Merge "Improve UI for PIN2/PUK2 authentication on FDN setting"
diff --git a/res/xml/carrier_ss_string.xml b/res/xml/carrier_ss_string.xml
index 29de13a..b7771cd 100644
--- a/res/xml/carrier_ss_string.xml
+++ b/res/xml/carrier_ss_string.xml
@@ -146,4 +146,32 @@
<entry key="status_code" definition="ok">7</entry>
</command_result>
</feature>
+ <feature name="callwaiting">
+ <command name="query"><!--For example: *#102#-->
+ <service_code>102</service_code>
+ <action_code>*#</action_code>
+ <response_format number ="1"><!--For example: 120*4#-->
+ <entry position="4" key="status_code"/>
+ </response_format>
+ </command>
+ <command name="activate"><!--For example: *102#-->
+ <service_code>102</service_code>
+ <action_code>*</action_code>
+ <response_format number="1"><!--For example: 102*5#-->
+ <entry position="4" key="status_code"/>
+ </response_format>
+ </command>
+ <command name="deactivate"><!--For example: #102#-->
+ <service_code>102</service_code>
+ <action_code>#</action_code>
+ <response_format number="1"><!--For example: 148*4#-->
+ <entry position="4" key="status_code"/>
+ </response_format>
+ </command>
+ <command_result number="3">
+ <entry key="status_code" definition="activate">5</entry>
+ <entry key="status_code" definition="deactivate">4</entry>
+ <entry key="status_code" definition="unregister">0</entry>
+ </command_result>
+ </feature>
</resources>
diff --git a/res/xml/carrier_ss_string_850.xml b/res/xml/carrier_ss_string_850.xml
index 01eeee5..ed31fae 100644
--- a/res/xml/carrier_ss_string_850.xml
+++ b/res/xml/carrier_ss_string_850.xml
@@ -94,4 +94,32 @@
<entry key="status_code" definition="ok">7</entry>
</command_result>
</feature>
+ <feature name="callwaiting">
+ <command name="query"><!--For example: *#102#-->
+ <service_code>102</service_code>
+ <action_code>*#</action_code>
+ <response_format number ="1"><!--For example: 120*4#-->
+ <entry position="4" key="status_code"/>
+ </response_format>
+ </command>
+ <command name="activate"><!--For example: *102#-->
+ <service_code>102</service_code>
+ <action_code>*</action_code>
+ <response_format number="1"><!--For example: 102*5#-->
+ <entry position="4" key="status_code"/>
+ </response_format>
+ </command>
+ <command name="deactivate"><!--For example: #102#-->
+ <service_code>102</service_code>
+ <action_code>#</action_code>
+ <response_format number="1"><!--For example: 148*4#-->
+ <entry position="4" key="status_code"/>
+ </response_format>
+ </command>
+ <command_result number="3">
+ <entry key="status_code" definition="activate">5</entry>
+ <entry key="status_code" definition="deactivate">4</entry>
+ <entry key="status_code" definition="unregister">0</entry>
+ </command_result>
+ </feature>
</resources>
diff --git a/src/com/android/phone/CallWaitingSwitchPreference.java b/src/com/android/phone/CallWaitingSwitchPreference.java
index 41442fe..01dd3b2 100644
--- a/src/com/android/phone/CallWaitingSwitchPreference.java
+++ b/src/com/android/phone/CallWaitingSwitchPreference.java
@@ -1,18 +1,21 @@
package com.android.phone;
+import static com.android.phone.TimeConsumingPreferenceActivity.EXCEPTION_ERROR;
import static com.android.phone.TimeConsumingPreferenceActivity.RESPONSE_ERROR;
import android.content.Context;
-import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.preference.SwitchPreference;
+import android.telephony.TelephonyManager;
import android.util.AttributeSet;
import android.util.Log;
-import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.Phone;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
public class CallWaitingSwitchPreference extends SwitchPreference {
private static final String LOG_TAG = "CallWaitingSwitchPreference";
private final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
@@ -20,6 +23,11 @@
private final MyHandler mHandler = new MyHandler();
private Phone mPhone;
private TimeConsumingPreferenceListener mTcpListener;
+ private Executor mExecutor;
+ private TelephonyManager mTelephonyManager;
+ private boolean mIsDuringUpdateProcess = false;
+ private int mUpdateStatus = TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR;
+ private int mQueryStatus = TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR;
public CallWaitingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
@@ -37,101 +45,84 @@
TimeConsumingPreferenceListener listener, boolean skipReading, Phone phone) {
mPhone = phone;
mTcpListener = listener;
+ mExecutor = Executors.newSingleThreadExecutor();
+ mTelephonyManager = getContext().getSystemService(
+ TelephonyManager.class).createForSubscriptionId(phone.getSubId());
if (!skipReading) {
- mPhone.getCallWaiting(mHandler.obtainMessage(MyHandler.MESSAGE_GET_CALL_WAITING,
- MyHandler.MESSAGE_GET_CALL_WAITING, MyHandler.MESSAGE_GET_CALL_WAITING));
+ Log.d(LOG_TAG, "init getCallWaitingStatus");
+ mTelephonyManager.getCallWaitingStatus(mExecutor, this::queryStatusCallBack);
if (mTcpListener != null) {
mTcpListener.onStarted(this, true);
}
}
}
+ private void queryStatusCallBack(int result) {
+ Log.d(LOG_TAG, "queryStatusCallBack: CW state " + result);
+ mQueryStatus = result;
+ mHandler.sendMessage(mHandler.obtainMessage(MyHandler.MESSAGE_UPDATE_CALL_WAITING));
+ }
+
+ private void updateStatusCallBack(int result) {
+ Log.d(LOG_TAG, "updateStatusCallBack: CW state " + result + ", and re get");
+ mUpdateStatus = result;
+ mTelephonyManager.getCallWaitingStatus(mExecutor, this::queryStatusCallBack);
+ }
+
@Override
protected void onClick() {
super.onClick();
-
- mPhone.setCallWaiting(isChecked(),
- mHandler.obtainMessage(MyHandler.MESSAGE_SET_CALL_WAITING));
+ mTelephonyManager.setCallWaitingEnabled(isChecked(), mExecutor, this::updateStatusCallBack);
if (mTcpListener != null) {
+ mIsDuringUpdateProcess = true;
mTcpListener.onStarted(this, false);
}
}
private class MyHandler extends Handler {
- static final int MESSAGE_GET_CALL_WAITING = 0;
- static final int MESSAGE_SET_CALL_WAITING = 1;
+ static final int MESSAGE_UPDATE_CALL_WAITING = 0;
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MESSAGE_GET_CALL_WAITING:
- handleGetCallWaitingResponse(msg);
- break;
- case MESSAGE_SET_CALL_WAITING:
- handleSetCallWaitingResponse(msg);
+ case MESSAGE_UPDATE_CALL_WAITING:
+ updateUi();
break;
}
}
- private void handleGetCallWaitingResponse(Message msg) {
- AsyncResult ar = (AsyncResult) msg.obj;
-
+ private void updateUi() {
if (mTcpListener != null) {
- if (msg.arg2 == MESSAGE_SET_CALL_WAITING) {
+ if (mIsDuringUpdateProcess) {
mTcpListener.onFinished(CallWaitingSwitchPreference.this, false);
} else {
mTcpListener.onFinished(CallWaitingSwitchPreference.this, true);
}
}
- if (ar.exception instanceof CommandException) {
- if (DBG) {
- Log.d(LOG_TAG, "handleGetCallWaitingResponse: CommandException=" +
- ar.exception);
- }
+ if (mIsDuringUpdateProcess && (
+ mUpdateStatus == TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED
+ || mUpdateStatus
+ == TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR)) {
+ Log.d(LOG_TAG, "handleSetCallWaitingResponse: Exception");
if (mTcpListener != null) {
- mTcpListener.onException(CallWaitingSwitchPreference.this,
- (CommandException)ar.exception);
+ mTcpListener.onError(CallWaitingSwitchPreference.this, EXCEPTION_ERROR);
}
- } else if (ar.userObj instanceof Throwable || ar.exception != null) {
- // Still an error case but just not a CommandException.
- if (DBG) {
- Log.d(LOG_TAG, "handleGetCallWaitingResponse: Exception" + ar.exception);
- }
+ } else if (mQueryStatus == TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED
+ || mQueryStatus == TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR) {
+ Log.d(LOG_TAG, "handleGetCallWaitingResponse: Exception");
if (mTcpListener != null) {
mTcpListener.onError(CallWaitingSwitchPreference.this, RESPONSE_ERROR);
}
} else {
- if (DBG) {
- Log.d(LOG_TAG, "handleGetCallWaitingResponse: CW state successfully queried.");
- }
- int[] cwArray = (int[])ar.result;
- // If cwArray[0] is = 1, then cwArray[1] must follow,
- // with the TS 27.007 service class bit vector of services
- // for which call waiting is enabled.
- try {
- setChecked(((cwArray[0] == 1) && ((cwArray[1] & 0x01) == 0x01)));
- } catch (ArrayIndexOutOfBoundsException e) {
- Log.e(LOG_TAG, "handleGetCallWaitingResponse: improper result: err ="
- + e.getMessage());
+ if (mQueryStatus == TelephonyManager.CALL_WAITING_STATUS_ENABLED) {
+ setChecked(true);
+ } else {
+ setChecked(false);
}
}
- }
-
- private void handleSetCallWaitingResponse(Message msg) {
- AsyncResult ar = (AsyncResult) msg.obj;
-
- if (ar.exception != null) {
- if (DBG) {
- Log.d(LOG_TAG, "handleSetCallWaitingResponse: ar.exception=" + ar.exception);
- }
- //setEnabled(false);
- }
- if (DBG) Log.d(LOG_TAG, "handleSetCallWaitingResponse: re get");
-
- mPhone.getCallWaiting(obtainMessage(MESSAGE_GET_CALL_WAITING,
- MESSAGE_SET_CALL_WAITING, MESSAGE_SET_CALL_WAITING, ar.exception));
+ mIsDuringUpdateProcess = false;
}
}
}
diff --git a/src/com/android/phone/CallWaitingUssdResultReceiver.java b/src/com/android/phone/CallWaitingUssdResultReceiver.java
new file mode 100644
index 0000000..b9049e9
--- /dev/null
+++ b/src/com/android/phone/CallWaitingUssdResultReceiver.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.telephony.TelephonyManager;
+import android.telephony.UssdResponse;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.telephony.IIntegerConsumer;
+
+import java.util.HashMap;
+
+/**
+ * Handling the call waiting USSD result.
+ */
+public class CallWaitingUssdResultReceiver extends ResultReceiver {
+ private static final String LOG_TAG = "CwUssdResultReceiver";
+
+ private IIntegerConsumer mCallback;
+ private CarrierXmlParser mCarrierXmlParser;
+ private CarrierXmlParser.SsEntry.SSAction mSsAction;
+
+ CallWaitingUssdResultReceiver(Handler handler, IIntegerConsumer callback,
+ CarrierXmlParser carrierXmlParser, CarrierXmlParser.SsEntry.SSAction action) {
+ super(handler);
+ mCallback = callback;
+ mCarrierXmlParser = carrierXmlParser;
+ mSsAction = action;
+ }
+
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle ussdResponse) {
+ log("USSD:" + resultCode);
+ checkNotNull(ussdResponse, "ussdResponse cannot be null.");
+ UssdResponse response = ussdResponse.getParcelable(
+ TelephonyManager.USSD_RESPONSE);
+
+ if (resultCode == TelephonyManager.USSD_RETURN_SUCCESS) {
+ int callWaitingStatus = getStatusFromResponse(response);
+ try {
+ mCallback.accept(callWaitingStatus);
+ } catch (RemoteException e) {
+ log("Fail to notify getCallWaitingStatus due to " + e);
+ }
+ } else {
+ try {
+ mCallback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
+ } catch (RemoteException e) {
+ log("Fail to notify getCallWaitingStatus due to " + e);
+ }
+ }
+ }
+
+ private int getStatusFromResponse(UssdResponse response) {
+ int callWaitingStatus = TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR;
+
+ CarrierXmlParser.SsFeature callWaitingFeature = mCarrierXmlParser.getFeature(
+ CarrierXmlParser.FEATURE_CALL_WAITING);
+ if (callWaitingFeature == null) {
+ return callWaitingStatus;
+ }
+
+ HashMap<String, String> analysisResult = callWaitingFeature
+ .getResponseSet(mSsAction, response.getReturnMessage().toString());
+ if (analysisResult.get(CarrierXmlParser.TAG_RESPONSE_STATUS_ERROR) != null) {
+ return callWaitingStatus;
+ }
+
+ if (analysisResult != null && analysisResult.size() != 0) {
+ String tmpStatusStr = analysisResult.get(
+ CarrierXmlParser.TAG_RESPONSE_STATUS);
+
+ if (!TextUtils.isEmpty(tmpStatusStr)) {
+ if (tmpStatusStr.equals(
+ CarrierXmlParser.TAG_COMMAND_RESULT_DEFINITION_ACTIVATE)) {
+ callWaitingStatus =
+ TelephonyManager.CALL_WAITING_STATUS_ENABLED;
+ } else if (tmpStatusStr.equals(
+ CarrierXmlParser.TAG_COMMAND_RESULT_DEFINITION_DEACTIVATE)) {
+ callWaitingStatus =
+ TelephonyManager.CALL_WAITING_STATUS_DISABLED;
+ }
+ }
+ }
+ return callWaitingStatus;
+ }
+
+ private static void log(String msg) {
+ Log.d(LOG_TAG, msg);
+ }
+}
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 4ff7316..d5b697a 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -36,6 +36,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.Process;
@@ -55,6 +56,7 @@
import android.util.LocalLog;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.ICarrierConfigLoader;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.Phone;
@@ -166,6 +168,7 @@
private static final int EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT = 21;
// Fetching config timed out from the default app for no SIM config.
private static final int EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT = 22;
+ // NOTE: any new EVENT_* values must be added to method eventToString().
private static final int BIND_TIMEOUT_MILLIS = 30000;
@@ -201,10 +204,14 @@
// 3. clearing config (e.g. due to sim removal)
// 4. encountering bind or IPC error
private class ConfigHandler extends Handler {
+ ConfigHandler(@NonNull Looper looper) {
+ super(looper);
+ }
+
@Override
public void handleMessage(Message msg) {
final int phoneId = msg.arg1;
- logdWithLocalLog("mHandler: " + msg.what + " phoneId: " + phoneId);
+ logdWithLocalLog("mHandler: " + eventToString(msg.what) + " phoneId: " + phoneId);
if (!SubscriptionManager.isValidPhoneId(phoneId)
&& msg.what != EVENT_MULTI_SIM_CONFIG_CHANGED) {
return;
@@ -314,13 +321,13 @@
@Override
public void onReceiveResult(int resultCode, Bundle resultData) {
unbindIfBound(mContext, conn, phoneId);
+ removeMessages(EVENT_FETCH_DEFAULT_TIMEOUT,
+ getMessageToken(phoneId));
// If new service connection has been created, this is stale.
if (mServiceConnection[phoneId] != conn) {
loge("Received response for stale request.");
return;
}
- removeMessages(EVENT_FETCH_DEFAULT_TIMEOUT,
- getMessageToken(phoneId));
if (resultCode == RESULT_ERROR || resultData == null) {
// On error, abort config fetching.
loge("Failed to get carrier config");
@@ -444,13 +451,13 @@
@Override
public void onReceiveResult(int resultCode, Bundle resultData) {
unbindIfBound(mContext, conn, phoneId);
+ removeMessages(EVENT_FETCH_CARRIER_TIMEOUT,
+ getMessageToken(phoneId));
// If new service connection has been created, this is stale.
if (mServiceConnection[phoneId] != conn) {
loge("Received response for stale request.");
return;
}
- removeMessages(EVENT_FETCH_CARRIER_TIMEOUT,
- getMessageToken(phoneId));
if (resultCode == RESULT_ERROR || resultData == null) {
// On error, abort config fetching.
loge("Failed to get carrier config from carrier app: "
@@ -666,11 +673,13 @@
* Constructs a CarrierConfigLoader, registers it as a service, and registers a broadcast
* receiver for relevant events.
*/
- private CarrierConfigLoader(Context context) {
+ @VisibleForTesting
+ /* package */ CarrierConfigLoader(Context context,
+ SubscriptionInfoUpdater subscriptionInfoUpdater, @NonNull Looper looper) {
mContext = context;
mPlatformCarrierConfigPackage =
mContext.getString(R.string.platform_carrier_config_package);
- mHandler = new ConfigHandler();
+ mHandler = new ConfigHandler(looper);
IntentFilter bootFilter = new IntentFilter();
bootFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
@@ -701,7 +710,7 @@
TelephonyFrameworkInitializer
.getTelephonyServiceManager().getCarrierConfigServiceRegisterer().register(this);
logd("CarrierConfigLoader has started");
- mSubscriptionInfoUpdater = PhoneFactory.getSubscriptionInfoUpdater();
+ mSubscriptionInfoUpdater = subscriptionInfoUpdater;
mHandler.sendEmptyMessage(EVENT_CHECK_SYSTEM_UPDATE);
}
@@ -710,11 +719,11 @@
*
* This is only done once, at startup, from {@link com.android.phone.PhoneApp#onCreate}.
*/
- /* package */
- static CarrierConfigLoader init(Context context) {
+ /* package */ static CarrierConfigLoader init(Context context) {
synchronized (CarrierConfigLoader.class) {
if (sInstance == null) {
- sInstance = new CarrierConfigLoader(context);
+ sInstance = new CarrierConfigLoader(context,
+ PhoneFactory.getSubscriptionInfoUpdater(), Looper.myLooper());
} else {
Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
}
@@ -722,7 +731,8 @@
}
}
- private void clearConfigForPhone(int phoneId, boolean fetchNoSimConfig) {
+ @VisibleForTesting
+ /* package */ void clearConfigForPhone(int phoneId, boolean fetchNoSimConfig) {
/* Ignore clear configuration request if device is being shutdown. */
Phone phone = PhoneFactory.getPhone(phoneId);
if (phone != null) {
@@ -844,7 +854,8 @@
}
}
- private CarrierIdentifier getCarrierIdentifierForPhoneId(int phoneId) {
+ @VisibleForTesting
+ /* package */ CarrierIdentifier getCarrierIdentifierForPhoneId(int phoneId) {
String mcc = "";
String mnc = "";
String imsi = "";
@@ -1000,12 +1011,14 @@
}
}
- private void saveConfigToXml(String packageName, @NonNull String extraString, int phoneId,
+ @VisibleForTesting
+ /* package */ void saveConfigToXml(String packageName, @NonNull String extraString, int phoneId,
CarrierIdentifier carrierId, PersistableBundle config) {
saveConfigToXml(packageName, extraString, phoneId, carrierId, config, false);
}
- private void saveNoSimConfigToXml(String packageName, PersistableBundle config) {
+ @VisibleForTesting
+ /* package */ void saveNoSimConfigToXml(String packageName, PersistableBundle config) {
saveConfigToXml(packageName, "", -1, null, config, true);
}
@@ -1166,20 +1179,20 @@
@Override
@NonNull
- public PersistableBundle getConfigForSubId(int subId, String callingPackage) {
- return getConfigForSubIdWithFeature(subId, callingPackage, null);
+ public PersistableBundle getConfigForSubId(int subscriptionId, String callingPackage) {
+ return getConfigForSubIdWithFeature(subscriptionId, callingPackage, null);
}
@Override
@NonNull
- public PersistableBundle getConfigForSubIdWithFeature(int subId, String callingPackage,
+ public PersistableBundle getConfigForSubIdWithFeature(int subscriptionId, String callingPackage,
String callingFeatureId) {
- if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId, callingPackage,
- callingFeatureId, "getCarrierConfig")) {
+ if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subscriptionId,
+ callingPackage, callingFeatureId, "getCarrierConfig")) {
return new PersistableBundle();
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subscriptionId);
PersistableBundle retConfig = CarrierConfigManager.getDefaultConfig();
if (SubscriptionManager.isValidPhoneId(phoneId)) {
PersistableBundle config = mConfigFromDefaultApp[phoneId];
@@ -1223,7 +1236,8 @@
int phoneId = SubscriptionManager.getPhoneId(subscriptionId);
if (!SubscriptionManager.isValidPhoneId(phoneId)) {
logd("Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId);
- return;
+ throw new IllegalArgumentException(
+ "Invalid phoneId " + phoneId + " for subId " + subscriptionId);
}
// Post to run on handler thread on which all states should be confined.
mHandler.post(() -> {
@@ -1262,17 +1276,18 @@
}
@Override
- public void notifyConfigChangedForSubId(int subId) {
- int phoneId = SubscriptionManager.getPhoneId(subId);
- if (!SubscriptionManager.isValidPhoneId(phoneId)) {
- logd("Ignore invalid phoneId: " + phoneId + " for subId: " + subId);
- return;
- }
-
+ public void notifyConfigChangedForSubId(int subscriptionId) {
// Requires the calling app to be either a carrier privileged app for this subId or
// system privileged app with MODIFY_PHONE_STATE permission.
- TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mContext, subId,
- "Require carrier privileges or MODIFY_PHONE_STATE permission.");
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mContext,
+ subscriptionId, "Require carrier privileges or MODIFY_PHONE_STATE permission.");
+
+ int phoneId = SubscriptionManager.getPhoneId(subscriptionId);
+ if (!SubscriptionManager.isValidPhoneId(phoneId)) {
+ logd("Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId);
+ throw new IllegalArgumentException(
+ "Invalid phoneId " + phoneId + " for subId " + subscriptionId);
+ }
// This method should block until deleting has completed, so that an error which prevents us
// from clearing the cache is passed back to the carrier app. With the files successfully
@@ -1289,7 +1304,7 @@
android.Manifest.permission.MODIFY_PHONE_STATE, null);
logdWithLocalLog("Update config for phoneId: " + phoneId + " simState: " + simState);
if (!SubscriptionManager.isValidPhoneId(phoneId)) {
- return;
+ throw new IllegalArgumentException("Invalid phoneId: " + phoneId);
}
// requires Java 7 for switch on string.
switch (simState) {
@@ -1315,6 +1330,31 @@
return mPlatformCarrierConfigPackage;
}
+ @VisibleForTesting
+ /* package */ Handler getHandler() {
+ return mHandler;
+ }
+
+ @VisibleForTesting
+ /* package */ PersistableBundle getConfigFromDefaultApp(int phoneId) {
+ return mConfigFromDefaultApp[phoneId];
+ }
+
+ @VisibleForTesting
+ /* package */ PersistableBundle getConfigFromCarrierApp(int phoneId) {
+ return mConfigFromCarrierApp[phoneId];
+ }
+
+ @VisibleForTesting
+ /* package */ PersistableBundle getNoSimConfig() {
+ return mNoSimConfig;
+ }
+
+ @VisibleForTesting
+ /* package */ PersistableBundle getOverrideConfig(int phoneId) {
+ return mOverrideConfigs[phoneId];
+ }
+
private void unbindIfBound(Context context, CarrierServiceConnection conn,
int phoneId) {
if (mServiceBound[phoneId]) {
@@ -1614,6 +1654,56 @@
}
}
+ // Get readable string for the message code supported in this class.
+ private static String eventToString(int code) {
+ switch (code) {
+ case EVENT_CLEAR_CONFIG:
+ return "EVENT_CLEAR_CONFIG";
+ case EVENT_CONNECTED_TO_DEFAULT:
+ return "EVENT_CONNECTED_TO_DEFAULT";
+ case EVENT_CONNECTED_TO_CARRIER:
+ return "EVENT_CONNECTED_TO_CARRIER";
+ case EVENT_FETCH_DEFAULT_DONE:
+ return "EVENT_FETCH_DEFAULT_DONE";
+ case EVENT_FETCH_CARRIER_DONE:
+ return "EVENT_FETCH_CARRIER_DONE";
+ case EVENT_DO_FETCH_DEFAULT:
+ return "EVENT_DO_FETCH_DEFAULT";
+ case EVENT_DO_FETCH_CARRIER:
+ return "EVENT_DO_FETCH_CARRIER";
+ case EVENT_PACKAGE_CHANGED:
+ return "EVENT_PACKAGE_CHANGED";
+ case EVENT_BIND_DEFAULT_TIMEOUT:
+ return "EVENT_BIND_DEFAULT_TIMEOUT";
+ case EVENT_BIND_CARRIER_TIMEOUT:
+ return "EVENT_BIND_CARRIER_TIMEOUT";
+ case EVENT_CHECK_SYSTEM_UPDATE:
+ return "EVENT_CHECK_SYSTEM_UPDATE";
+ case EVENT_SYSTEM_UNLOCKED:
+ return "EVENT_SYSTEM_UNLOCKED";
+ case EVENT_FETCH_DEFAULT_TIMEOUT:
+ return "EVENT_FETCH_DEFAULT_TIMEOUT";
+ case EVENT_FETCH_CARRIER_TIMEOUT:
+ return "EVENT_FETCH_CARRIER_TIMEOUT";
+ case EVENT_SUBSCRIPTION_INFO_UPDATED:
+ return "EVENT_SUBSCRIPTION_INFO_UPDATED";
+ case EVENT_MULTI_SIM_CONFIG_CHANGED:
+ return "EVENT_MULTI_SIM_CONFIG_CHANGED";
+ case EVENT_DO_FETCH_DEFAULT_FOR_NO_SIM_CONFIG:
+ return "EVENT_DO_FETCH_DEFAULT_FOR_NO_SIM_CONFIG";
+ case EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE:
+ return "EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE";
+ case EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG:
+ return "EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG";
+ case EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT:
+ return "EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT";
+ case EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT:
+ return "EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT";
+ default:
+ return "UNKNOWN(" + code + ")";
+ }
+ }
+
private void logd(String msg) {
Log.d(LOG_TAG, msg);
}
diff --git a/src/com/android/phone/CarrierXmlParser.java b/src/com/android/phone/CarrierXmlParser.java
index 18602c9..6e01b43 100644
--- a/src/com/android/phone/CarrierXmlParser.java
+++ b/src/com/android/phone/CarrierXmlParser.java
@@ -67,6 +67,7 @@
// To define feature's item name in xml
public static final String FEATURE_CALL_FORWARDING = "callforwarding";
+ public static final String FEATURE_CALL_WAITING = "callwaiting";
public static final String FEATURE_CALLER_ID = "callerid";
// COMMAND_NAME is xml's command name.
diff --git a/src/com/android/phone/ImsRcsController.java b/src/com/android/phone/ImsRcsController.java
index ad33302..bd6ba6b 100644
--- a/src/com/android/phone/ImsRcsController.java
+++ b/src/com/android/phone/ImsRcsController.java
@@ -104,7 +104,7 @@
*/
@Override
public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "registerImsRegistrationCallback");
final long token = Binder.clearCallingIdentity();
try {
@@ -122,7 +122,7 @@
*/
@Override
public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "unregisterImsRegistrationCallback");
final long token = Binder.clearCallingIdentity();
try {
@@ -139,7 +139,7 @@
*/
@Override
public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getImsRcsRegistrationState");
final long token = Binder.clearCallingIdentity();
try {
@@ -161,7 +161,7 @@
*/
@Override
public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getImsRcsRegistrationTransportType");
final long token = Binder.clearCallingIdentity();
try {
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 9a1e275..98b540c 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -209,6 +209,7 @@
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
@@ -1152,7 +1153,6 @@
}
break;
}
-
case EVENT_PERFORM_NETWORK_SCAN_DONE:
ar = (AsyncResult) msg.obj;
request = (MainThreadRequest) ar.userObj;
@@ -3678,7 +3678,7 @@
@Override
public int getNetworkSelectionMode(int subId) {
TelephonyPermissions
- .enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ .enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getNetworkSelectionMode");
final long identity = Binder.clearCallingIdentity();
try {
@@ -3715,7 +3715,7 @@
@Override
public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback c)
throws RemoteException {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "registerImsRegistrationCallback");
if (!ImsManager.isImsSupportedOnDevice(mApp)) {
@@ -3741,7 +3741,7 @@
*/
@Override
public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback c) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "unregisterImsRegistrationCallback");
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
@@ -3798,7 +3798,7 @@
*/
@Override
public void getImsMmTelRegistrationTransportType(int subId, IIntegerConsumer consumer) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getImsMmTelRegistrationTransportType");
if (!ImsManager.isImsSupportedOnDevice(mApp)) {
throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
@@ -3838,7 +3838,7 @@
@Override
public void registerMmTelCapabilityCallback(int subId, IImsCapabilityCallback c)
throws RemoteException {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "registerMmTelCapabilityCallback");
if (!ImsManager.isImsSupportedOnDevice(mApp)) {
throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
@@ -3863,7 +3863,7 @@
*/
@Override
public void unregisterMmTelCapabilityCallback(int subId, IImsCapabilityCallback c) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "unregisterMmTelCapabilityCallback");
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
@@ -3963,7 +3963,7 @@
*/
@Override
public boolean isAdvancedCallingSettingEnabled(int subId) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isAdvancedCallingSettingEnabled");
// TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
@@ -4000,7 +4000,7 @@
*/
@Override
public boolean isVtSettingEnabled(int subId) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isVtSettingEnabled");
final long identity = Binder.clearCallingIdentity();
try {
@@ -4034,7 +4034,7 @@
*/
@Override
public boolean isVoWiFiSettingEnabled(int subId) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isVoWiFiSettingEnabled");
final long identity = Binder.clearCallingIdentity();
try {
@@ -4069,7 +4069,7 @@
*/
@Override
public boolean isVoWiFiRoamingSettingEnabled(int subId) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isVoWiFiRoamingSettingEnabled");
final long identity = Binder.clearCallingIdentity();
try {
@@ -4121,7 +4121,7 @@
*/
@Override
public int getVoWiFiModeSetting(int subId) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getVoWiFiModeSetting");
final long identity = Binder.clearCallingIdentity();
try {
@@ -4203,7 +4203,7 @@
*/
@Override
public boolean isTtyOverVolteEnabled(int subId) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isTtyOverVolteEnabled");
final long identity = Binder.clearCallingIdentity();
try {
@@ -5595,7 +5595,7 @@
@ImsFeature.FeatureType int featureType) {
int[] subIds = SubscriptionManager.getSubId(slotId);
TelephonyPermissions
- .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, (subIds != null ? subIds[0] : SubscriptionManager.INVALID_SUBSCRIPTION_ID),
"getBoundImsServicePackage");
@@ -5732,7 +5732,7 @@
@Override
public String getManualNetworkSelectionPlmn(int subId) {
TelephonyPermissions
- .enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ .enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getManualNetworkSelectionPlmn");
final long identity = Binder.clearCallingIdentity();
@@ -5879,10 +5879,9 @@
*/
@Override
public void getCallWaitingStatus(int subId, IIntegerConsumer callback) {
- enforceReadPrivilegedPermission("getCallForwarding");
+ enforceReadPrivilegedPermission("getCallWaitingStatus");
long identity = Binder.clearCallingIdentity();
try {
-
Phone phone = getPhone(subId);
if (phone == null) {
try {
@@ -5892,11 +5891,35 @@
}
return;
}
-
- Consumer<Integer> argument = FunctionalUtils.ignoreRemoteException(callback::accept);
+ CarrierConfigManager configManager = new CarrierConfigManager(phone.getContext());
+ PersistableBundle c = configManager.getConfigForSubId(subId);
+ boolean requireUssd = c.getBoolean(
+ CarrierConfigManager.KEY_USE_CALL_WAITING_USSD_BOOL, false);
if (DBG) log("getCallWaitingStatus: subId " + subId);
- sendRequestAsync(CMD_GET_CALL_WAITING, argument, phone, null);
+ if (requireUssd) {
+ CarrierXmlParser carrierXmlParser = new CarrierXmlParser(phone.getContext(),
+ getSubscriptionCarrierId(subId));
+ String newUssdCommand = "";
+ try {
+ newUssdCommand = carrierXmlParser.getFeature(
+ CarrierXmlParser.FEATURE_CALL_WAITING)
+ .makeCommand(CarrierXmlParser.SsEntry.SSAction.QUERY, null);
+ } catch (NullPointerException e) {
+ loge("Failed to generate USSD number" + e);
+ }
+ ResultReceiver wrappedCallback = new CallWaitingUssdResultReceiver(
+ mMainThreadHandler, callback, carrierXmlParser,
+ CarrierXmlParser.SsEntry.SSAction.QUERY);
+ final String ussdCommand = newUssdCommand;
+ Executors.newSingleThreadExecutor().execute(() -> {
+ handleUssdRequest(subId, ussdCommand, wrappedCallback);
+ });
+ } else {
+ Consumer<Integer> argument = FunctionalUtils.ignoreRemoteException(
+ callback::accept);
+ sendRequestAsync(CMD_GET_CALL_WAITING, argument, phone, null);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -5922,10 +5945,38 @@
return;
}
- Pair<Boolean, Consumer<Integer>> arguments = Pair.create(enable,
- FunctionalUtils.ignoreRemoteException(callback::accept));
+ CarrierConfigManager configManager = new CarrierConfigManager(phone.getContext());
+ PersistableBundle c = configManager.getConfigForSubId(subId);
+ boolean requireUssd = c.getBoolean(
+ CarrierConfigManager.KEY_USE_CALL_WAITING_USSD_BOOL, false);
- sendRequestAsync(CMD_SET_CALL_WAITING, arguments, phone, null);
+ if (DBG) log("getCallWaitingStatus: subId " + subId);
+ if (requireUssd) {
+ CarrierXmlParser carrierXmlParser = new CarrierXmlParser(phone.getContext(),
+ getSubscriptionCarrierId(subId));
+ CarrierXmlParser.SsEntry.SSAction ssAction =
+ enable ? CarrierXmlParser.SsEntry.SSAction.UPDATE_ACTIVATE
+ : CarrierXmlParser.SsEntry.SSAction.UPDATE_DEACTIVATE;
+ String newUssdCommand = "";
+ try {
+ newUssdCommand = carrierXmlParser.getFeature(
+ CarrierXmlParser.FEATURE_CALL_WAITING)
+ .makeCommand(ssAction, null);
+ } catch (NullPointerException e) {
+ loge("Failed to generate USSD number" + e);
+ }
+ ResultReceiver wrappedCallback = new CallWaitingUssdResultReceiver(
+ mMainThreadHandler, callback, carrierXmlParser, ssAction);
+ final String ussdCommand = newUssdCommand;
+ Executors.newSingleThreadExecutor().execute(() -> {
+ handleUssdRequest(subId, ussdCommand, wrappedCallback);
+ });
+ } else {
+ Pair<Boolean, Consumer<Integer>> arguments = Pair.create(enable,
+ FunctionalUtils.ignoreRemoteException(callback::accept));
+
+ sendRequestAsync(CMD_SET_CALL_WAITING, arguments, phone, null);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -6032,7 +6083,7 @@
@Override
public int getAllowedNetworkTypesBitmask(int subId) {
TelephonyPermissions
- .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getAllowedNetworkTypesBitmask");
final long identity = Binder.clearCallingIdentity();
@@ -6057,7 +6108,7 @@
@Override
public long getAllowedNetworkTypesForReason(int subId,
@TelephonyManager.AllowedNetworkTypesReason int reason) {
- TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getAllowedNetworkTypesForReason");
final long identity = Binder.clearCallingIdentity();
try {
@@ -6110,7 +6161,7 @@
@Override
public boolean isNrDualConnectivityEnabled(int subId) {
TelephonyPermissions
- .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isNRDualConnectivityEnabled");
if (!isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE)) {
@@ -6918,7 +6969,7 @@
Phone phone = PhoneFactory.getPhone(phoneId);
try {
TelephonyPermissions
- .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, phone.getSubId(), "getRadioAccessFamily");
} catch (SecurityException e) {
EventLog.writeEvent(0x534e4554, "150857259", -1, "Missing Permission");
@@ -6931,7 +6982,7 @@
final long identity = Binder.clearCallingIdentity();
try {
TelephonyPermissions
- .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, phone.getSubId(), "getRadioAccessFamily");
raf = ProxyController.getInstance().getRadioAccessFamily(phoneId);
} finally {
@@ -8090,7 +8141,7 @@
mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
null);
} catch (Exception e) {
- TelephonyPermissions.enforeceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isDataRoamingEnabled");
}
@@ -8135,7 +8186,7 @@
@Override
public boolean isManualNetworkSelectionAllowed(int subId) {
TelephonyPermissions
- .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isManualNetworkSelectionAllowed");
boolean isAllowed = true;
@@ -8421,7 +8472,7 @@
@Override
public int getCdmaRoamingMode(int subId) {
TelephonyPermissions
- .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getCdmaRoamingMode");
final long identity = Binder.clearCallingIdentity();
@@ -8448,7 +8499,7 @@
@Override
public int getCdmaSubscriptionMode(int subId) {
TelephonyPermissions
- .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getCdmaSubscriptionMode");
final long identity = Binder.clearCallingIdentity();
@@ -8502,7 +8553,7 @@
final Phone defaultPhone = getDefaultPhone();
if (!exactMatch) {
TelephonyPermissions
- .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, defaultPhone.getSubId(), "isEmergencyNumber(Potential)");
}
final long identity = Binder.clearCallingIdentity();
@@ -8968,7 +9019,7 @@
@Override
public List<RadioAccessSpecifier> getSystemSelectionChannels(int subId) {
TelephonyPermissions
- .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getSystemSelectionChannels");
WorkSource workSource = getWorkSource(Binder.getCallingUid());
final long identity = Binder.clearCallingIdentity();
diff --git a/src/com/android/phone/RcsProvisioningMonitor.java b/src/com/android/phone/RcsProvisioningMonitor.java
index 6fdde78..18c8c0b 100644
--- a/src/com/android/phone/RcsProvisioningMonitor.java
+++ b/src/com/android/phone/RcsProvisioningMonitor.java
@@ -539,8 +539,15 @@
*/
public boolean isRcsVolteSingleRegistrationEnabled(int subId) {
if (mRcsProvisioningInfos.containsKey(subId)) {
- return mRcsProvisioningInfos.get(subId).getSingleRegistrationCapability()
- == ProvisioningManager.STATUS_CAPABLE;
+ if (mRcsProvisioningInfos.get(subId).getSingleRegistrationCapability()
+ == ProvisioningManager.STATUS_CAPABLE) {
+ try {
+ RcsConfig rcsConfig = new RcsConfig(getConfig(subId));
+ return rcsConfig.isRcsVolteSingleRegistrationSupported();
+ } catch (IllegalArgumentException e) {
+ logd("fail to get rcs config for sub:" + subId);
+ }
+ }
}
return false;
}
@@ -838,10 +845,9 @@
}
void unregisterRcsFeatureListener(RcsProvisioningInfo info) {
- int slotId = SubscriptionManager.getSlotIndex(info.getSubId());
- RcsFeatureListener cb = mRcsFeatureListeners.get(slotId);
- if (cb != null) {
- cb.removeRcsProvisioningInfo(info);
+ // make sure the info to be removed in any case, even the slotId changed or invalid.
+ for (int i = 0; i < mRcsFeatureListeners.size(); i++) {
+ mRcsFeatureListeners.valueAt(i).removeRcsProvisioningInfo(info);
}
}
diff --git a/src/com/android/phone/SimPhonebookProvider.java b/src/com/android/phone/SimPhonebookProvider.java
index 6a27130..4a15950 100644
--- a/src/com/android/phone/SimPhonebookProvider.java
+++ b/src/com/android/phone/SimPhonebookProvider.java
@@ -818,15 +818,15 @@
int efid;
if (efName != null) {
switch (efName) {
- case ElementaryFiles.EF_ADN_PATH_SEGMENT:
+ case ElementaryFiles.PATH_SEGMENT_EF_ADN:
efType = ElementaryFiles.EF_ADN;
efid = IccConstants.EF_ADN;
break;
- case ElementaryFiles.EF_FDN_PATH_SEGMENT:
+ case ElementaryFiles.PATH_SEGMENT_EF_FDN:
efType = ElementaryFiles.EF_FDN;
efid = IccConstants.EF_FDN;
break;
- case ElementaryFiles.EF_SDN_PATH_SEGMENT:
+ case ElementaryFiles.PATH_SEGMENT_EF_SDN:
efType = ElementaryFiles.EF_SDN;
efid = IccConstants.EF_SDN;
break;
diff --git a/src/com/android/services/telephony/rcs/MessageTransportStateTracker.java b/src/com/android/services/telephony/rcs/MessageTransportStateTracker.java
index c42472d..daafeb2 100644
--- a/src/com/android/services/telephony/rcs/MessageTransportStateTracker.java
+++ b/src/com/android/services/telephony/rcs/MessageTransportStateTracker.java
@@ -190,7 +190,7 @@
* dialog be released as the SIP dialog is now closed.
*/
@Override
- public void closeDialog(String callId) {
+ public void cleanupSession(String callId) {
long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() -> {
@@ -202,7 +202,7 @@
try {
// TODO track the SIP Dialogs created/destroyed on the associated
// SipDelegate.
- mSipDelegate.closeDialog(callId);
+ mSipDelegate.cleanupSession(callId);
} catch (RemoteException e) {
logw("SipDelegate not available when closeDialog was called "
+ "for call id: " + callId);
diff --git a/testapps/TestRcsApp/TestApp/Android.bp b/testapps/TestRcsApp/TestApp/Android.bp
index 4496a8e..cda7d17 100644
--- a/testapps/TestRcsApp/TestApp/Android.bp
+++ b/testapps/TestRcsApp/TestApp/Android.bp
@@ -21,6 +21,8 @@
"libphonenumber-platform"
],
+ libs: ["org.apache.http.legacy"],
+
certificate: "platform",
privileged: true,
product_specific: true,
diff --git a/testapps/TestRcsApp/TestApp/AndroidManifest.xml b/testapps/TestRcsApp/TestApp/AndroidManifest.xml
index 52dd427..7538df7 100644
--- a/testapps/TestRcsApp/TestApp/AndroidManifest.xml
+++ b/testapps/TestRcsApp/TestApp/AndroidManifest.xml
@@ -19,8 +19,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.sample.rcsclient"
- android:versionCode="11"
- android:versionName="1.0.10">
+ android:versionCode="13"
+ android:versionName="1.0.12">
<uses-sdk
android:minSdkVersion="30"
diff --git a/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java b/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java
index 3bc1c24..b9078f8 100644
--- a/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java
+++ b/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java
@@ -156,6 +156,7 @@
Log.i(TAG, "FileTransferController null");
return;
}
+ mUploadResult.setText("");
Futures.addCallback(
fileTransferController.uploadFile(UUID.randomUUID().toString(),
mFile),
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/FileUploadController.java b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/FileUploadController.java
index d8e38e0..0d45828 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/FileUploadController.java
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/FileUploadController.java
@@ -34,10 +34,11 @@
import com.google.common.util.concurrent.MoreExecutors;
import org.apache.http.Header;
-import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AUTH;
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.MalformedChallengeException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.AuthPolicy;
@@ -96,7 +97,7 @@
ListenableFuture<HttpResponse> initialResponseFuture = sendEmptyPost(httpClient);
BasicHttpContext httpContext = new BasicHttpContext();
- ListenableFuture<Void> prepareAuthFuture =
+ ListenableFuture<AuthScheme> prepareAuthFuture =
Futures.transform(
initialResponseFuture,
initialResponse -> {
@@ -117,17 +118,16 @@
// Override nonce and realm in the HTTP context.
RFC2617Scheme authScheme = createAuthScheme(initialResponse);
httpContext.setAttribute(ATTRIBUTE_PREEMPTIVE_AUTH, authScheme);
-
- return null;
+ return authScheme;
},
executor);
// Executing the post with credentials.
return Futures.transformAsync(
prepareAuthFuture,
- unused ->
+ authScheme ->
executeAuthenticatedPost(
- httpClient, httpContext, transactionId, file),
+ httpClient, httpContext, authScheme, transactionId, file),
executor);
}
@@ -141,27 +141,12 @@
String scheme = authHeader.getValue();
if (scheme.contains(AuthPolicy.DIGEST)) {
- HeaderElement[] elements = authHeader.getElements();
-
- if (elements == null || elements.length == 0) {
- throw new IllegalArgumentException(
- "Unable to find header elements. Cannot perform Digest authentication.");
- }
-
DigestScheme digestScheme = new DigestScheme();
- for (HeaderElement element : elements) {
- // TODO(b/180601658): Add checks for the realm, which should start with
- // 3GPP-bootstrapping@.
- if (element.getName().contains(PARAM_REALM)) {
- digestScheme.overrideParamter(PARAM_REALM, element.getValue());
- Log.i(TAG, "Realm: " + element.getValue());
- }
- if (element.getName().contains(PARAM_NONCE)) {
- digestScheme.overrideParamter(PARAM_NONCE, element.getValue());
- Log.i(TAG, "Nonce: " + element.getValue());
- }
+ try {
+ digestScheme.processChallenge(authHeader);
+ } catch (MalformedChallengeException e) {
+ throw new IllegalArgumentException(e);
}
-
return digestScheme;
} else {
throw new IllegalArgumentException("Unable to create authentication scheme " + scheme);
@@ -195,13 +180,14 @@
private ListenableFuture<String> executeAuthenticatedPost(
DefaultHttpClient httpClient,
HttpContext context,
+ AuthScheme authScheme,
String transactionId,
File file)
throws IOException {
Part[] parts = {
new StringPart(TRANSFER_ID_PART_NAME, transactionId),
- new FilePart(file.getName(), file)
+ new FilePart(FILE_PART_NAME, file)
};
MultipartEntity entity = new MultipartEntity(parts);
@@ -211,7 +197,8 @@
Log.i(TAG, "Created file upload POST:" + contentServerUri);
ListenableFuture<HttpResponse> responseFuture =
- requestExecutor.executeAuthenticatedRequest(httpClient, context, postRequest);
+ requestExecutor.executeAuthenticatedRequest(httpClient, context, postRequest,
+ authScheme);
Futures.addCallback(
responseFuture,
@@ -227,7 +214,7 @@
@Override
public void onFailure(Throwable t) {
- Log.i(TAG, "onFailure");
+ Log.e(TAG, "onFailure", t);
throw new IllegalArgumentException(t);
}
},
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaAuthenticationProvider.java b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaAuthenticationProvider.java
index 55608e0..008fb76 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaAuthenticationProvider.java
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaAuthenticationProvider.java
@@ -25,6 +25,7 @@
import android.util.Log;
import com.google.auto.value.AutoValue;
+import com.google.common.io.BaseEncoding;
import com.google.common.util.concurrent.SettableFuture;
import org.apache.http.auth.Credentials;
@@ -61,13 +62,14 @@
int cipherSuite = carrierConfig.getInt(
CarrierConfigManager.KEY_GBA_UA_TLS_CIPHER_SUITE_INT);
Log.i(TAG, "organization:" + organization + ", protocol:" + protocol + ", cipherSuite:"
- + cipherSuite);
+ + cipherSuite + ", contentServerUrl:" + contentServerUrl);
- builder.setOrg(UaSecurityProtocolIdentifier.ORG_3GPP)
- .setProtocol(
- UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT);
+ builder.setOrg(organization)
+ .setProtocol(protocol);
if (cipherSuite == TlsParams.TLS_NULL_WITH_NULL_NULL) {
builder.setTlsCipherSuite(TlsParams.TLS_RSA_WITH_AES_128_CBC_SHA);
+ } else {
+ builder.setTlsCipherSuite(cipherSuite);
}
} catch (IllegalArgumentException e) {
Log.e(TAG, e.getMessage());
@@ -79,7 +81,8 @@
new TelephonyManager.BootstrapAuthenticationCallback() {
@Override
public void onKeysAvailable(byte[] gbaKey, String btId) {
- Log.i(TAG, "onKeysAvailable: key:[" + new String(gbaKey) + "] btid:[" + btId
+ Log.i(TAG, "onKeysAvailable: String key:[" + new String(gbaKey) + "] btid:["
+ + btId + "]" + "Base64 key:[" + BaseEncoding.base64().encode(gbaKey)
+ "]");
credentialsFuture.set(GbaCredentials.create(btId, gbaKey));
}
@@ -108,7 +111,7 @@
public static GbaCredentials create(String btId, byte[] gbaKey) {
return new AutoValue_GbaAuthenticationProvider_GbaCredentials(
- GbaPrincipal.create(btId), new String(gbaKey));
+ GbaPrincipal.create(btId), BaseEncoding.base64().encode(gbaKey));
}
@Override
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaRequestExecutor.java b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaRequestExecutor.java
index 856fec1..83d5a8a 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaRequestExecutor.java
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaRequestExecutor.java
@@ -24,9 +24,12 @@
import com.google.common.util.concurrent.MoreExecutors;
import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.AuthState;
import org.apache.http.auth.Credentials;
import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HttpContext;
@@ -48,7 +51,8 @@
@Override
@SuppressWarnings("CheckReturnValue")
public ListenableFuture<HttpResponse> executeAuthenticatedRequest(
- DefaultHttpClient httpClient, HttpContext context, HttpRequestBase request) {
+ DefaultHttpClient httpClient, HttpContext context, HttpRequestBase request,
+ AuthScheme authScheme) {
// Set authentication for the client.
ListenableFuture<Credentials> credentialsFuture =
@@ -61,8 +65,13 @@
Log.i(TAG,
"Obtained credentialsFuture, making the POST with credentials"
+ ".");
- httpClient.getCredentialsProvider().setCredentials(AuthScope.ANY,
- credentials);
+ httpClient.addRequestInterceptor((req, ctx) -> {
+ AuthState authState = (AuthState) context.getAttribute(
+ ClientContext.TARGET_AUTH_STATE);
+ authState.setAuthScope(AuthScope.ANY);
+ authState.setAuthScheme(authScheme);
+ authState.setCredentials(credentials);
+ }, /* index= */ 0);
// Make the first request.
return executor.submit(() -> httpClient.execute(request, context));
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/HttpRequestExecutor.java b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/HttpRequestExecutor.java
index 59a3aa9..0026790 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/HttpRequestExecutor.java
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/HttpRequestExecutor.java
@@ -19,6 +19,7 @@
import com.google.common.util.concurrent.ListenableFuture;
import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthScheme;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HttpContext;
@@ -29,6 +30,7 @@
public interface HttpRequestExecutor {
ListenableFuture<HttpResponse> executeAuthenticatedRequest(
- DefaultHttpClient httpClient, HttpContext context, HttpRequestBase request)
+ DefaultHttpClient httpClient, HttpContext context, HttpRequestBase request,
+ AuthScheme authScheme)
throws IOException;
}
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/MessageConverter.java b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/MessageConverter.java
index 75eb48d..e3a091d 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/MessageConverter.java
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/MessageConverter.java
@@ -88,7 +88,7 @@
return (Message)
method.invoke(
new StringMsgParser(),
- message.getEncodedMessage(),
+ message.toEncodedMessage(),
true,
false,
(ParseExceptionListener)
@@ -98,7 +98,7 @@
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
try {
method = StringMsgParser.class.getDeclaredMethod("parseSIPMessage", byte[].class);
- return (Message) method.invoke(new StringMsgParser(), message.getEncodedMessage());
+ return (Message) method.invoke(new StringMsgParser(), message.toEncodedMessage());
} catch (IllegalAccessException | InvocationTargetException
| NoSuchMethodException ex) {
ex.printStackTrace();
diff --git a/tests/src/com/android/TestContext.java b/tests/src/com/android/TestContext.java
index 9d712d3..fc5ee4c 100644
--- a/tests/src/com/android/TestContext.java
+++ b/tests/src/com/android/TestContext.java
@@ -24,6 +24,8 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.Binder;
import android.os.Handler;
import android.os.PersistableBundle;
import android.telecom.TelecomManager;
@@ -32,16 +34,22 @@
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsManager;
import android.test.mock.MockContext;
+import android.util.Log;
import android.util.SparseArray;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
+import java.util.HashSet;
import java.util.concurrent.Executor;
public class TestContext extends MockContext {
+ private static final String TAG = "TestContext";
+ // Stub used to grant all permissions
+ public static final String STUB_PERMISSION_ENABLE_ALL = "stub_permission_enable_all";
+
@Mock CarrierConfigManager mMockCarrierConfigManager;
@Mock TelecomManager mMockTelecomManager;
@Mock TelephonyManager mMockTelephonyManager;
@@ -50,6 +58,8 @@
private SparseArray<PersistableBundle> mCarrierConfigs = new SparseArray<>();
+ private final HashSet<String> mPermissionTable = new HashSet<>();
+
public TestContext() {
MockitoAnnotations.initMocks(this);
doAnswer((Answer<PersistableBundle>) invocation -> {
@@ -161,4 +171,67 @@
}
return b;
}
+
+ @Override
+ public void enforceCallingOrSelfPermission(String permission, String message) {
+ if (checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException(permission + " denied: " + message);
+ }
+ }
+
+ @Override
+ public void enforcePermission(String permission, int pid, int uid, String message) {
+ enforceCallingOrSelfPermission(permission, message);
+ }
+
+ @Override
+ public void enforceCallingPermission(String permission, String message) {
+ enforceCallingOrSelfPermission(permission, message);
+ }
+
+ @Override
+ public int checkCallingOrSelfPermission(String permission) {
+ return checkPermission(permission, Binder.getCallingPid(), Binder.getCallingUid());
+ }
+
+ @Override
+ public int checkPermission(String permission, int pid, int uid) {
+ synchronized (mPermissionTable) {
+ if (mPermissionTable.contains(permission)
+ || mPermissionTable.contains(STUB_PERMISSION_ENABLE_ALL)) {
+ logd("checkCallingOrSelfPermission: " + permission + " return GRANTED");
+ return PackageManager.PERMISSION_GRANTED;
+ } else {
+ logd("checkCallingOrSelfPermission: " + permission + " return DENIED");
+ return PackageManager.PERMISSION_DENIED;
+ }
+ }
+ }
+
+ public void grantPermission(String permission) {
+ synchronized (mPermissionTable) {
+ if (mPermissionTable != null && permission != null) {
+ mPermissionTable.remove(STUB_PERMISSION_ENABLE_ALL);
+ mPermissionTable.add(permission);
+ }
+ }
+ }
+
+ public void revokePermission(String permission) {
+ synchronized (mPermissionTable) {
+ if (mPermissionTable != null && permission != null) {
+ mPermissionTable.remove(permission);
+ }
+ }
+ }
+
+ public void revokeAllPermissions() {
+ synchronized (mPermissionTable) {
+ mPermissionTable.clear();
+ }
+ }
+
+ private static void logd(String s) {
+ Log.d(TAG, s);
+ }
}
diff --git a/tests/src/com/android/phone/CarrierConfigLoaderTest.java b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
new file mode 100644
index 0000000..f58e6cc
--- /dev/null
+++ b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import static com.android.TestContext.STUB_PERMISSION_ENABLE_ALL;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.os.Build;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.os.UserHandle;
+import android.service.carrier.CarrierIdentifier;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.testing.TestableLooper;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.SubscriptionInfoUpdater;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.List;
+
+/**
+ * Unit Test for CarrierConfigLoader.
+ */
+@RunWith(AndroidJUnit4.class)
+public class CarrierConfigLoaderTest extends TelephonyTestBase {
+
+ private static final int DEFAULT_PHONE_ID = 0;
+ private static final int DEFAULT_SUB_ID = SubscriptionManager.getDefaultSubscriptionId();
+ private static final String PLATFORM_CARRIER_CONFIG_PACKAGE = "com.android.carrierconfig";
+ private static final long PLATFORM_CARRIER_CONFIG_PACKAGE_VERSION_CODE = 1;
+ private static final String CARRIER_CONFIG_EXAMPLE_KEY =
+ CarrierConfigManager.KEY_CARRIER_USSD_METHOD_INT;
+ private static final int CARRIER_CONFIG_EXAMPLE_VALUE =
+ CarrierConfigManager.USSD_OVER_CS_PREFERRED;
+
+ @Mock Resources mResources;
+ @Mock PackageManager mPackageManager;
+ @Mock PackageInfo mPackageInfo;
+ @Mock SubscriptionInfoUpdater mSubscriptionInfoUpdater;
+ @Mock SharedPreferences mSharedPreferences;
+
+ private TelephonyManager mTelephonyManager;
+ private CarrierConfigLoader mCarrierConfigLoader;
+ private Handler mHandler;
+ private HandlerThread mHandlerThread;
+ private TestableLooper mTestableLooper;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ doReturn(mSharedPreferences).when(mContext).getSharedPreferences(anyString(), anyInt());
+ doReturn(Build.FINGERPRINT).when(mSharedPreferences).getString(eq("build_fingerprint"),
+ any());
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(mResources).when(mContext).getResources();
+ doReturn(InstrumentationRegistry.getTargetContext().getFilesDir()).when(
+ mContext).getFilesDir();
+ doReturn(PLATFORM_CARRIER_CONFIG_PACKAGE).when(mResources).getString(
+ eq(R.string.platform_carrier_config_package));
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+ doReturn(1).when(mTelephonyManager).getSupportedModemCount();
+ doReturn(1).when(mTelephonyManager).getActiveModemCount();
+ doReturn("spn").when(mTelephonyManager).getSimOperatorNameForPhone(anyInt());
+ doReturn("310260").when(mTelephonyManager).getSimOperatorNumericForPhone(anyInt());
+ doReturn(mPackageInfo).when(mPackageManager).getPackageInfo(
+ eq(PLATFORM_CARRIER_CONFIG_PACKAGE), eq(0) /*flags*/);
+ doReturn(PLATFORM_CARRIER_CONFIG_PACKAGE_VERSION_CODE).when(
+ mPackageInfo).getLongVersionCode();
+
+ mHandlerThread = new HandlerThread("CarrierConfigLoaderTest");
+ mHandlerThread.start();
+
+ mTestableLooper = new TestableLooper(mHandlerThread.getLooper());
+ mCarrierConfigLoader = new CarrierConfigLoader(mContext, mSubscriptionInfoUpdater,
+ mTestableLooper.getLooper());
+ mHandler = mCarrierConfigLoader.getHandler();
+
+ // Clear all configs to have the same starting point.
+ mCarrierConfigLoader.clearConfigForPhone(DEFAULT_PHONE_ID, false);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mContext.revokeAllPermissions();
+ mTestableLooper.destroy();
+ super.tearDown();
+ }
+
+ /**
+ * Verifies that SecurityException should throw when call #updateConfigForPhoneId() without
+ * MODIFY_PHONE_STATE permission.
+ */
+ @Test
+ public void testUpdateConfigForPhoneId_noPermission() throws Exception {
+ assertThrows(SecurityException.class,
+ () -> mCarrierConfigLoader.updateConfigForPhoneId(DEFAULT_PHONE_ID,
+ IccCardConstants.INTENT_VALUE_ICC_ABSENT));
+ }
+
+ /**
+ * Verifies that IllegalArgumentException should throw when call #updateConfigForPhoneId() with
+ * invalid phoneId.
+ */
+ @Test
+ public void testUpdateConfigForPhoneId_invalidPhoneId() throws Exception {
+ mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+
+ assertThrows(IllegalArgumentException.class,
+ () -> mCarrierConfigLoader.updateConfigForPhoneId(
+ SubscriptionManager.INVALID_PHONE_INDEX,
+ IccCardConstants.INTENT_VALUE_ICC_ABSENT));
+ }
+
+ /**
+ * Verifies that when call #updateConfigForPhoneId() with SIM absence, both carrier config from
+ * default app and carrier should be cleared but no-sim config should be loaded.
+ */
+ @Test
+ public void testUpdateConfigForPhoneId_simAbsent() throws Exception {
+ // Bypass case if default subId is not supported by device to reduce flakiness
+ if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
+ return;
+ }
+ mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+ doNothing().when(mContext).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class));
+
+ // Prepare a cached config to fetch from xml
+ PersistableBundle config = getTestConfig();
+ mCarrierConfigLoader.saveNoSimConfigToXml(PLATFORM_CARRIER_CONFIG_PACKAGE, config);
+ mCarrierConfigLoader.updateConfigForPhoneId(DEFAULT_PHONE_ID,
+ IccCardConstants.INTENT_VALUE_ICC_ABSENT);
+ mTestableLooper.processAllMessages();
+
+ assertThat(mCarrierConfigLoader.getConfigFromDefaultApp(DEFAULT_PHONE_ID)).isNull();
+ assertThat(mCarrierConfigLoader.getConfigFromCarrierApp(DEFAULT_PHONE_ID)).isNull();
+ assertThat(mCarrierConfigLoader.getNoSimConfig().getInt(CARRIER_CONFIG_EXAMPLE_KEY))
+ .isEqualTo(CARRIER_CONFIG_EXAMPLE_VALUE);
+ verify(mContext).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class));
+ }
+
+ /**
+ * Verifies that with cached config in XML, calling #updateConfigForPhoneId() with SIM loaded
+ * will return the right config in the XML.
+ */
+ @Test
+ public void testUpdateConfigForPhoneId_simLoaded_withCachedConfigInXml() throws Exception {
+ // Bypass case if default subId is not supported by device to reduce flakiness
+ if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
+ return;
+ }
+ mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+
+ // Prepare to make sure we can save the config into the XML file which used as cache
+ List<String> carrierPackages = List.of(PLATFORM_CARRIER_CONFIG_PACKAGE);
+ doReturn(carrierPackages).when(mTelephonyManager).getCarrierPackageNamesForIntentAndPhone(
+ nullable(Intent.class), anyInt());
+
+ // Save the sample config into the XML file
+ PersistableBundle config = getTestConfig();
+ CarrierIdentifier carrierId = mCarrierConfigLoader.getCarrierIdentifierForPhoneId(
+ DEFAULT_PHONE_ID);
+ mCarrierConfigLoader.saveConfigToXml(PLATFORM_CARRIER_CONFIG_PACKAGE, "",
+ DEFAULT_PHONE_ID, carrierId, config);
+ mCarrierConfigLoader.updateConfigForPhoneId(DEFAULT_PHONE_ID,
+ IccCardConstants.INTENT_VALUE_ICC_LOADED);
+ mTestableLooper.processAllMessages();
+
+ assertThat(mCarrierConfigLoader.getConfigFromDefaultApp(DEFAULT_PHONE_ID).getInt(
+ CARRIER_CONFIG_EXAMPLE_KEY)).isEqualTo(CARRIER_CONFIG_EXAMPLE_VALUE);
+
+ }
+
+ /**
+ * Verifies that SecurityException should throw if call #overrideConfig() without
+ * MODIFY_PHONE_STATE permission.
+ */
+ @Test
+ public void testOverrideConfig_noPermission() throws Exception {
+ assertThrows(SecurityException.class,
+ () -> mCarrierConfigLoader.overrideConfig(DEFAULT_SUB_ID, PersistableBundle.EMPTY,
+ false));
+ }
+
+ /**
+ * Verifies IllegalArgumentException should throw if call #overrideConfig() with invalid subId.
+ */
+ @Test
+ public void testOverrideConfig_invalidSubId() throws Exception {
+ mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+
+ assertThrows(IllegalArgumentException.class, () -> mCarrierConfigLoader.overrideConfig(
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID, new PersistableBundle(), false));
+ }
+
+ /**
+ * Verifies that override config is not null when calling #overrideConfig with null bundle.
+ */
+ @Test
+ public void testOverrideConfig_withNullBundle() throws Exception {
+ // Bypass case if default subId is not supported by device to reduce flakiness
+ if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
+ return;
+ }
+ mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+
+ mCarrierConfigLoader.overrideConfig(DEFAULT_SUB_ID, null /*overrides*/,
+ false/*persistent*/);
+ mTestableLooper.processAllMessages();
+
+ assertThat(mCarrierConfigLoader.getOverrideConfig(DEFAULT_PHONE_ID).isEmpty()).isTrue();
+ verify(mSubscriptionInfoUpdater).updateSubscriptionByCarrierConfigAndNotifyComplete(
+ eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
+ any(PersistableBundle.class), any(Message.class));
+ }
+
+ /**
+ * Verifies that override config is not null when calling #overrideConfig with non-null bundle.
+ */
+ @Test
+ public void testOverrideConfig_withNonNullBundle() throws Exception {
+ // Bypass case if default subId is not supported by device to reduce flakiness
+ if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
+ return;
+ }
+ mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+
+ PersistableBundle config = getTestConfig();
+ mCarrierConfigLoader.overrideConfig(DEFAULT_SUB_ID, config /*overrides*/,
+ false/*persistent*/);
+ mTestableLooper.processAllMessages();
+
+ assertThat(mCarrierConfigLoader.getOverrideConfig(DEFAULT_PHONE_ID).getInt(
+ CARRIER_CONFIG_EXAMPLE_KEY)).isEqualTo(CARRIER_CONFIG_EXAMPLE_VALUE);
+ verify(mSubscriptionInfoUpdater).updateSubscriptionByCarrierConfigAndNotifyComplete(
+ eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
+ any(PersistableBundle.class), any(Message.class));
+ }
+
+ /**
+ * Verifies that IllegalArgumentException should throw when calling
+ * #notifyConfigChangedForSubId() with invalid subId.
+ */
+ @Test
+ public void testNotifyConfigChangedForSubId_invalidSubId() throws Exception {
+ mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+
+ assertThrows(IllegalArgumentException.class,
+ () -> mCarrierConfigLoader.notifyConfigChangedForSubId(
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID));
+ }
+
+ // TODO(b/184040111): Enable test case when support disabling carrier privilege
+ // Phone/System UID always has carrier privilege (TelephonyPermission#getCarrierPrivilegeStatus)
+ // when running the test here.
+ /**
+ * Verifies that SecurityException should throw when calling notifyConfigChangedForSubId without
+ * MODIFY_PHONE_STATE permission.
+ */
+ @Ignore
+ public void testNotifyConfigChangedForSubId_noPermission() throws Exception {
+ setCarrierPrivilegesForSubId(false, DEFAULT_SUB_ID);
+
+ assertThrows(SecurityException.class,
+ () -> mCarrierConfigLoader.notifyConfigChangedForSubId(DEFAULT_SUB_ID));
+ }
+
+ /**
+ * Verifies that SecurityException should throw when calling getDefaultCarrierServicePackageName
+ * without READ_PRIVILEGED_PHONE_STATE permission.
+ */
+ @Test
+ public void testGetDefaultCarrierServicePackageName_noPermission() {
+ assertThrows(SecurityException.class,
+ () -> mCarrierConfigLoader.getDefaultCarrierServicePackageName());
+ }
+
+ /**
+ * Verifies that the right default carrier service package name is return when calling
+ * getDefaultCarrierServicePackageName with permission.
+ */
+ @Test
+ public void testGetDefaultCarrierServicePackageName_withPermission() {
+ mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+
+ assertThat(mCarrierConfigLoader.getDefaultCarrierServicePackageName())
+ .isEqualTo(PLATFORM_CARRIER_CONFIG_PACKAGE);
+ }
+
+ // TODO(b/184040111): Enable test case when support disabling carrier privilege
+ // Phone/System UID always has carrier privilege (TelephonyPermission#getCarrierPrivilegeStatus)
+ // when running the test here.
+ /**
+ * Verifies that without permission, #getConfigForSubId will return an empty PersistableBundle.
+ */
+ @Ignore
+ public void testGetConfigForSubId_noPermission() {
+ // Bypass case if default subId is not supported by device to reduce flakiness
+ if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
+ return;
+ }
+ setCarrierPrivilegesForSubId(false, DEFAULT_SUB_ID);
+
+ assertThat(mCarrierConfigLoader.getConfigForSubId(DEFAULT_SUB_ID,
+ PLATFORM_CARRIER_CONFIG_PACKAGE)).isEqualTo(PersistableBundle.EMPTY);
+ }
+
+ /**
+ * Verifies that when have no DUMP permission, the #dump() method shows permission denial.
+ */
+ @Test
+ public void testDump_noPermission() {
+ StringWriter stringWriter = new StringWriter();
+ mCarrierConfigLoader.dump(new FileDescriptor(), new PrintWriter(stringWriter),
+ new String[0]);
+ stringWriter.flush();
+
+ assertThat(stringWriter.toString()).contains("Permission Denial:");
+ }
+
+ /**
+ * Verifies that when have DUMP permission, the #dump() method can dump the CarrierConfigLoader.
+ */
+ @Test
+ public void testDump_withPermission() {
+ mContext.grantPermission(android.Manifest.permission.DUMP);
+
+ StringWriter stringWriter = new StringWriter();
+ mCarrierConfigLoader.dump(new FileDescriptor(), new PrintWriter(stringWriter),
+ new String[0]);
+ stringWriter.flush();
+
+ String dumpContent = stringWriter.toString();
+ assertThat(dumpContent).contains("CarrierConfigLoader:");
+ assertThat(dumpContent).doesNotContain("Permission Denial:");
+ }
+
+ private static PersistableBundle getTestConfig() {
+ PersistableBundle config = new PersistableBundle();
+ config.putInt(CARRIER_CONFIG_EXAMPLE_KEY, CARRIER_CONFIG_EXAMPLE_VALUE);
+ return config;
+ }
+
+ private void setCarrierPrivilegesForSubId(boolean hasCarrierPrivileges, int subId) {
+ TelephonyManager mockTelephonyManager = Mockito.mock(TelephonyManager.class);
+ doReturn(mockTelephonyManager).when(mTelephonyManager).createForSubscriptionId(subId);
+ doReturn(hasCarrierPrivileges ? TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
+ : TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS).when(
+ mockTelephonyManager).getCarrierPrivilegeStatus(anyInt());
+ }
+}
diff --git a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
index 54333bb..c7d0c8f 100644
--- a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
+++ b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
@@ -85,7 +85,7 @@
*/
public class RcsProvisioningMonitorTest {
private static final String TAG = "RcsProvisioningMonitorTest";
- private static final String SAMPLE_CONFIG = "<RCSConfig>\n"
+ private static final String CONFIG_DEFAULT = "<RCSConfig>\n"
+ "\t<rcsVolteSingleRegistration>1</rcsVolteSingleRegistration>\n"
+ "\t<SERVICES>\n"
+ "\t\t<SupportedRCSProfileVersions>UP_2.0</SupportedRCSProfileVersions>\n"
@@ -104,6 +104,9 @@
+ "\t\t</Ext>\n"
+ "\t</SERVICES>\n"
+ "</RCSConfig>";
+ private static final String CONFIG_SINGLE_REGISTRATION_DISABLED = "<RCSConfig>\n"
+ + "\t<rcsVolteSingleRegistration>0</rcsVolteSingleRegistration>\n"
+ + "</RCSConfig>";
private static final int FAKE_SUB_ID_BASE = 0x0FFFFFF0;
private static final String DEFAULT_MESSAGING_APP1 = "DMA1";
private static final String DEFAULT_MESSAGING_APP2 = "DMA2";
@@ -252,7 +255,7 @@
when(mCursor.moveToFirst()).thenReturn(true);
when(mCursor.getColumnIndexOrThrow(any())).thenReturn(1);
when(mCursor.getBlob(anyInt())).thenReturn(
- RcsConfig.compressGzip(SAMPLE_CONFIG.getBytes()));
+ RcsConfig.compressGzip(CONFIG_DEFAULT.getBytes()));
mHandlerThread = new HandlerThread("RcsProvisioningMonitorTest");
mHandlerThread.start();
@@ -278,7 +281,7 @@
createMonitor(3);
for (int i = 0; i < 3; i++) {
- assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(),
+ assertTrue(Arrays.equals(CONFIG_DEFAULT.getBytes(),
mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE + i)));
}
@@ -312,7 +315,7 @@
ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
for (int i = 0; i < 3; i++) {
- assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(),
+ assertTrue(Arrays.equals(CONFIG_DEFAULT.getBytes(),
mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE + i)));
}
verify(mPhone, times(3)).sendBroadcast(captorIntent.capture(), any());
@@ -358,7 +361,7 @@
processAllMessages();
byte[] configCached = mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE);
- assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(), configCached));
+ assertTrue(Arrays.equals(CONFIG_DEFAULT.getBytes(), configCached));
verify(mIImsConfig, times(1)).notifyRcsAutoConfigurationRemoved();
// The api should be called 2 times, one happens when monitor is initilized,
// Another happens when DMS is changed.
@@ -421,12 +424,12 @@
createMonitor(1);
final ArgumentCaptor<byte[]> argumentBytes = ArgumentCaptor.forClass(byte[].class);
- mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, SAMPLE_CONFIG.getBytes(), false);
+ mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, CONFIG_DEFAULT.getBytes(), false);
processAllMessages();
verify(mIImsConfig, atLeastOnce()).notifyRcsAutoConfigurationReceived(
argumentBytes.capture(), eq(false));
- assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(), argumentBytes.getValue()));
+ assertTrue(Arrays.equals(CONFIG_DEFAULT.getBytes(), argumentBytes.getValue()));
}
@Test
@@ -447,13 +450,15 @@
createMonitor(1);
when(mPackageManager.hasSystemFeature(
- eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(true);
+ eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(false);
mBundle.putBoolean(
- CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
+ CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
processAllMessages();
- assertTrue(mRcsProvisioningMonitor.isRcsVolteSingleRegistrationEnabled(FAKE_SUB_ID_BASE));
+ assertFalse(mRcsProvisioningMonitor.isRcsVolteSingleRegistrationEnabled(FAKE_SUB_ID_BASE));
+ when(mPackageManager.hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(true);
mBundle.putBoolean(
CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
@@ -468,6 +473,27 @@
broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
processAllMessages();
assertFalse(mRcsProvisioningMonitor.isRcsVolteSingleRegistrationEnabled(FAKE_SUB_ID_BASE));
+
+ when(mPackageManager.hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(true);
+ mBundle.putBoolean(
+ CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
+ broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
+ processAllMessages();
+ assertTrue(mRcsProvisioningMonitor.isRcsVolteSingleRegistrationEnabled(FAKE_SUB_ID_BASE));
+
+ mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, null, false);
+ processAllMessages();
+ assertFalse(mRcsProvisioningMonitor.isRcsVolteSingleRegistrationEnabled(FAKE_SUB_ID_BASE));
+
+ mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, CONFIG_DEFAULT.getBytes(), false);
+ processAllMessages();
+ assertTrue(mRcsProvisioningMonitor.isRcsVolteSingleRegistrationEnabled(FAKE_SUB_ID_BASE));
+
+ mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE,
+ CONFIG_SINGLE_REGISTRATION_DISABLED.getBytes(), false);
+ processAllMessages();
+ assertFalse(mRcsProvisioningMonitor.isRcsVolteSingleRegistrationEnabled(FAKE_SUB_ID_BASE));
}
@Test
@@ -594,12 +620,12 @@
verify(mCursor, times(1)).getBlob(anyInt());
assertNull(mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE));
- mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, SAMPLE_CONFIG.getBytes(), false);
+ mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, CONFIG_DEFAULT.getBytes(), false);
processAllMessages();
//config cahced in monitor should be updated, but db should not
assertNull(mProvider.getContentValues());
- assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(),
+ assertTrue(Arrays.equals(CONFIG_DEFAULT.getBytes(),
mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE)));
//verify if monitor goes back to normal mode
@@ -609,12 +635,12 @@
verify(mCursor, times(2)).getBlob(anyInt());
assertNull(mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE));
- mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, SAMPLE_CONFIG.getBytes(), false);
+ mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, CONFIG_DEFAULT.getBytes(), false);
processAllMessages();
- assertTrue(Arrays.equals(SAMPLE_CONFIG.getBytes(),
+ assertTrue(Arrays.equals(CONFIG_DEFAULT.getBytes(),
mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE)));
- assertTrue(Arrays.equals(RcsConfig.compressGzip(SAMPLE_CONFIG.getBytes()),
+ assertTrue(Arrays.equals(RcsConfig.compressGzip(CONFIG_DEFAULT.getBytes()),
(byte[]) mProvider.getContentValues().get(SimInfo.COLUMN_RCS_CONFIG)));
}
diff --git a/tests/src/com/android/services/telephony/rcs/MessageTransportStateTrackerTest.java b/tests/src/com/android/services/telephony/rcs/MessageTransportStateTrackerTest.java
index 5e05085..f69b9a8 100644
--- a/tests/src/com/android/services/telephony/rcs/MessageTransportStateTrackerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/MessageTransportStateTrackerTest.java
@@ -173,12 +173,12 @@
@SmallTest
@Test
- public void testDelegateConnectionCloseDialog() throws Exception {
+ public void testDelegateConnectionCloseSession() throws Exception {
MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
Runnable::run, mDelegateMessageCallback);
tracker.openTransport(mISipDelegate, Collections.emptySet());
- tracker.getDelegateConnection().closeDialog("testCallId");
- verify(mISipDelegate).closeDialog("testCallId");
+ tracker.getDelegateConnection().cleanupSession("testCallId");
+ verify(mISipDelegate).cleanupSession("testCallId");
}
@SmallTest