Merge "Refactor simState & activeSubscriptionInfo"
diff --git a/src/java/com/android/internal/telephony/PhoneConfigurationModels.java b/src/java/com/android/internal/telephony/PhoneConfigurationModels.java
index fb8cc5e..aca4955 100644
--- a/src/java/com/android/internal/telephony/PhoneConfigurationModels.java
+++ b/src/java/com/android/internal/telephony/PhoneConfigurationModels.java
@@ -40,7 +40,7 @@
List<ModemInfo> logicalModemList = new ArrayList<>();
logicalModemList.add(modemInfo1);
logicalModemList.add(modemInfo2);
- DSDS_CAPABILITY = new PhoneCapability(1, 2, 0, logicalModemList, false);
+ DSDS_CAPABILITY = new PhoneCapability(1, 2, 0, logicalModemList, true);
logicalModemList = new ArrayList<>();
logicalModemList.add(modemInfo1);
diff --git a/src/java/com/android/internal/telephony/PhoneSwitcher.java b/src/java/com/android/internal/telephony/PhoneSwitcher.java
index 2d4426e..4aff9ca 100644
--- a/src/java/com/android/internal/telephony/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/PhoneSwitcher.java
@@ -22,6 +22,9 @@
import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
import static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER;
+import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS;
+import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -42,6 +45,7 @@
import android.os.Registrant;
import android.os.RegistrantList;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
import android.telephony.PreciseCallState;
@@ -113,13 +117,15 @@
private int mPhoneIdInCall = SubscriptionManager.INVALID_PHONE_INDEX;
+ private ISetOpportunisticDataCallback mSetOpptSubCallback;
+
private static final int EVENT_DEFAULT_SUBSCRIPTION_CHANGED = 101;
private static final int EVENT_SUBSCRIPTION_CHANGED = 102;
private static final int EVENT_REQUEST_NETWORK = 103;
private static final int EVENT_RELEASE_NETWORK = 104;
private static final int EVENT_EMERGENCY_TOGGLE = 105;
private static final int EVENT_RADIO_CAPABILITY_CHANGED = 106;
- private static final int EVENT_PREFERRED_SUBSCRIPTION_CHANGED = 107;
+ private static final int EVENT_CHANGE_PREFERRED_SUBSCRIPTION = 107;
private static final int EVENT_RADIO_AVAILABLE = 108;
private static final int EVENT_PHONE_IN_CALL_CHANGED = 109;
private static final int EVENT_NETWORK_VALIDATION_DONE = 110;
@@ -349,9 +355,16 @@
resendRilCommands(msg);
break;
}
- case EVENT_PREFERRED_SUBSCRIPTION_CHANGED: {
- onEvaluate(REQUESTS_UNCHANGED, "preferredDataSubscriptionIdChanged");
- registerDefaultNetworkChangeCallback();
+ case EVENT_CHANGE_PREFERRED_SUBSCRIPTION: {
+ int subId = msg.arg1;
+ boolean needValidation = (msg.arg2 == 1);
+ ISetOpportunisticDataCallback callback =
+ (ISetOpportunisticDataCallback) msg.obj;
+ if (SubscriptionManager.isUsableSubscriptionId(subId)) {
+ setOpportunisticDataSubscription(subId, needValidation, callback);
+ } else {
+ unsetOpportunisticDataSubscription(callback);
+ }
break;
}
case EVENT_RADIO_AVAILABLE: {
@@ -779,20 +792,34 @@
* subscription. It has to be an active subscription, and PhoneSwitcher will try to validate
* it first if needed.
*/
- public void setOpportunisticDataSubscription(int subId) {
+ private void setOpportunisticDataSubscription(int subId, boolean needValidation,
+ ISetOpportunisticDataCallback callback) {
if (!mSubscriptionController.isActiveSubId(subId)) {
log("Can't switch data to inactive subId " + subId);
+ sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER);
return;
}
- logDataSwitchEvent(TelephonyEvent.EventState.START, DataSwitch.Reason.CBRS);
+ if (mValidator.isValidating()
+ && (!needValidation || subId != mValidator.getSubIdInValidation())) {
+ mValidator.stopValidation();
+ }
+
+ if (subId == mPreferredDataSubId) {
+ sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS);
+ return;
+ }
+
// If validation feature is not supported, set it directly. Otherwise,
// start validation on the subscription first.
- if (!CellularNetworkValidator.isValidationFeatureSupported()) {
- setPreferredDataSubscriptionId(subId);
- } else {
+ if (CellularNetworkValidator.isValidationFeatureSupported() && needValidation) {
+ logDataSwitchEvent(TelephonyEvent.EventState.START, DataSwitch.Reason.CBRS);
+ mSetOpptSubCallback = callback;
mValidator.validate(subId, DEFAULT_VALIDATION_EXPIRATION_TIME,
false, mValidationCallback);
+ } else {
+ setPreferredSubscription(subId);
+ sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS);
}
}
@@ -800,32 +827,66 @@
* Unset opportunistic data subscription. It's an indication to switch Internet data back
* from opportunistic subscription to primary subscription.
*/
- public void unsetOpportunisticDataSubscription() {
- logDataSwitchEvent(TelephonyEvent.EventState.START, DataSwitch.Reason.CBRS);
- if (CellularNetworkValidator.isValidationFeatureSupported()
- && mValidator.isValidating()) {
+ private void unsetOpportunisticDataSubscription(ISetOpportunisticDataCallback callback) {
+ if (mValidator.isValidating()) {
mValidator.stopValidation();
}
// Set mPreferredDataSubId back to DEFAULT_SUBSCRIPTION_ID. This will trigger
// data switch to mDefaultDataSubId.
- setPreferredDataSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+ setPreferredSubscription(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+ sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS);
+ }
+
+ private void sendSetOpptCallbackHelper(ISetOpportunisticDataCallback callback, int result) {
+ if (callback == null) return;
+ try {
+ callback.onComplete(result);
+ } catch (RemoteException exception) {
+ log("RemoteException " + exception);
+ }
+ }
+
+ /**
+ * Set opportunistic data subscription.
+ */
+ private void setPreferredSubscription(int subId) {
+ if (mPreferredDataSubId != subId) {
+ mPreferredDataSubId = subId;
+ logDataSwitchEvent(TelephonyEvent.EventState.START, DataSwitch.Reason.CBRS);
+ onEvaluate(REQUESTS_UNCHANGED, "preferredDataSubscriptionIdChanged");
+ notifyPreferredDataSubIdChanged();
+ registerDefaultNetworkChangeCallback();
+ }
}
private void onValidationDone(int subId, boolean passed) {
log("Network validation " + (passed ? "passed" : "failed")
+ " on subId " + subId);
- mValidator.stopValidation();
- if (passed) setPreferredDataSubscriptionId(subId);
+ if (passed) setPreferredSubscription(subId);
+
+ // Trigger callback if needed
+ sendSetOpptCallbackHelper(mSetOpptSubCallback, passed ? SET_OPPORTUNISTIC_SUB_SUCCESS
+ : SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
+ mSetOpptSubCallback = null;
}
// TODO b/123598154: rename preferredDataSub to opportunisticSubId.
- private void setPreferredDataSubscriptionId(int subId) {
- if (mPreferredDataSubId != subId) {
- log("setPreferredDataSubscriptionId subId changed to " + subId);
- mPreferredDataSubId = subId;
- Message msg = PhoneSwitcher.this.obtainMessage(EVENT_PREFERRED_SUBSCRIPTION_CHANGED);
- msg.sendToTarget();
+ public void trySetPreferredSubscription(int subId, boolean needValidation,
+ ISetOpportunisticDataCallback callback) {
+ log("Try set preferred subscription to subId " + subId
+ + (needValidation ? " with " : " without ") + "validation");
+ PhoneSwitcher.this.obtainMessage(EVENT_CHANGE_PREFERRED_SUBSCRIPTION,
+ subId, needValidation ? 1 : 0, callback).sendToTarget();
+ }
+
+ private void notifyPreferredDataSubIdChanged() {
+ ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
+ "telephony.registry"));
+ try {
+ tr.notifyPreferredDataSubIdChanged(mPreferredDataSubId);
+ } catch (RemoteException ex) {
+ // Should never happen because TelephonyRegistry service should always be available.
}
}
@@ -843,6 +904,10 @@
? HAL_COMMAND_PREFERRED_DATA : HAL_COMMAND_ALLOW_DATA;
}
+ public int getPreferredDataSubscriptionId() {
+ return mPreferredDataSubId;
+ }
+
private void log(String l) {
Rlog.d(LOG_TAG, l);
mLocalLog.log(l);
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
index f89ba4d..12e5845 100644
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
@@ -2690,16 +2690,14 @@
}
@Override
- public void setPreferredDataSubscriptionId(int subId) {
+ public void setPreferredDataSubscriptionId(int subId, boolean needValidation,
+ ISetOpportunisticDataCallback callback) {
enforceModifyPhoneState("setPreferredDataSubscriptionId");
final long token = Binder.clearCallingIdentity();
try {
- if (SubscriptionManager.isUsableSubscriptionId(subId)) {
- PhoneSwitcher.getInstance().setOpportunisticDataSubscription(subId);
- } else {
- PhoneSwitcher.getInstance().unsetOpportunisticDataSubscription();
- }
+ PhoneSwitcher.getInstance().trySetPreferredSubscription(
+ subId, needValidation, callback);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -2708,17 +2706,12 @@
@Override
public int getPreferredDataSubscriptionId() {
enforceReadPrivilegedPhoneState("getPreferredDataSubscriptionId");
- return mPreferredDataSubId;
- }
+ final long token = Binder.clearCallingIdentity();
- private void notifyPreferredDataSubIdChanged() {
- ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
- "telephony.registry"));
try {
- if (DBG) logd("notifyPreferredDataSubIdChanged:");
- tr.notifyPreferredDataSubIdChanged(mPreferredDataSubId);
- } catch (RemoteException ex) {
- // Should never happen because its always available.
+ return PhoneSwitcher.getInstance().getPreferredDataSubscriptionId();
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java
index 7746bd5..de47da1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java
@@ -386,13 +386,14 @@
assertTrue(mDataAllowed[0]);
// Set sub 2 as preferred sub should make phone 1 activated and phone 0 deactivated.
- mPhoneSwitcher.setOpportunisticDataSubscription(2);
+ mPhoneSwitcher.trySetPreferredSubscription(2, false, null);
waitABit();
assertFalse(mDataAllowed[0]);
assertTrue(mDataAllowed[1]);
// Unset preferred sub should make default data sub (phone 0 / sub 1) activated again.
- mPhoneSwitcher.unsetOpportunisticDataSubscription();
+ mPhoneSwitcher.trySetPreferredSubscription(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ false, null);
waitABit();
assertTrue(mDataAllowed[0]);
assertFalse(mDataAllowed[1]);
@@ -441,7 +442,7 @@
assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 1));
// Set sub 2 as preferred sub should make phone 1 preferredDataModem
- mPhoneSwitcher.setOpportunisticDataSubscription(2);
+ mPhoneSwitcher.trySetPreferredSubscription(2, false, null);
waitABit();
verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
@@ -454,7 +455,8 @@
clearInvocations(mActivePhoneSwitchHandler);
// Unset preferred sub should make phone0 preferredDataModem again.
- mPhoneSwitcher.unsetOpportunisticDataSubscription();
+ mPhoneSwitcher.trySetPreferredSubscription(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ false, null);
waitABit();
verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsManagerTest.java
index dff75b0..294c5bb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsManagerTest.java
@@ -61,10 +61,14 @@
private static final boolean VT_IMS_ENABLE_DEFAULT_VAL = true;
private static final boolean WFC_IMS_EDITABLE_VAL = true;
private static final boolean WFC_IMS_NOT_EDITABLE_VAL = false;
+ private static final boolean WFC_IMS_ROAMING_EDITABLE_VAL = true;
+ private static final boolean WFC_IMS_ROAMING_NOT_EDITABLE_VAL = false;
private static final int WFC_IMS_MODE_DEFAULT_VAL =
ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
private static final int WFC_IMS_ROAMING_MODE_DEFAULT_VAL =
ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED;
+ private static final boolean WFC_USE_HOME_MODE_FOR_ROAMING_VAL = true;
+ private static final boolean WFC_NOT_USE_HOME_MODE_FOR_ROAMING_VAL = false;
PersistableBundle mBundle;
@Mock IBinder mBinder;
@@ -107,6 +111,8 @@
ENHANCED_4G_MODE_EDITABLE);
mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL,
WFC_IMS_EDITABLE_VAL);
+ mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL,
+ WFC_IMS_ROAMING_EDITABLE_VAL);
mBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL,
WFC_IMS_ENABLE_DEFAULT_VAL);
mBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL,
@@ -118,6 +124,9 @@
mBundle.putBoolean(CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL,
ENHANCED_4G_MODE_DEFAULT_VAL);
mBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL, true);
+ mBundle.putBoolean(
+ CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL,
+ WFC_NOT_USE_HOME_MODE_FOR_ROAMING_VAL);
}
@Test @SmallTest
@@ -653,6 +662,98 @@
eq(WFC_IMS_MODE_DEFAULT_VAL));
}
+ /**
+ * Tests the operation of getWfcMode when the configuration to use the home network mode when
+ * roaming for WFC is false. First, it checks that the user setting for WFC_IMS_ROAMING_MODE is
+ * returned when WFC roaming is set to editable. Then, it switches the WFC roaming mode to not
+ * editable and ensures that the default WFC roaming mode is returned.
+ *
+ * Preconditions:
+ * - CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL = false
+ */
+ @Test @SmallTest
+ public void getWfcMode_useWfcHomeModeConfigFalse_shouldUseWfcRoamingMode() {
+ // Set some values that are different than the defaults for WFC mode.
+ doReturn(String.valueOf(ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY))
+ .when(mSubscriptionController).getSubscriptionProperty(
+ anyInt(),
+ eq(SubscriptionManager.WFC_IMS_MODE),
+ anyString());
+ doReturn(String.valueOf(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED))
+ .when(mSubscriptionController).getSubscriptionProperty(
+ anyInt(),
+ eq(SubscriptionManager.WFC_IMS_ROAMING_MODE),
+ anyString());
+
+ ImsManager imsManager = getImsManagerAndInitProvisionedValues();
+
+ // Check that use the WFC roaming network mode.
+ assertEquals(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED,
+ imsManager.getWfcMode(true));
+ verify(mSubscriptionController, times(1)).getSubscriptionProperty(
+ anyInt(),
+ eq(SubscriptionManager.WFC_IMS_ROAMING_MODE),
+ anyString());
+
+ // Set WFC roaming network mode to not editable.
+ mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL,
+ WFC_IMS_ROAMING_NOT_EDITABLE_VAL);
+
+ // Check that use the default WFC roaming network mode.
+ assertEquals(WFC_IMS_ROAMING_MODE_DEFAULT_VAL, imsManager.getWfcMode(true));
+ verify(mSubscriptionController, times(1)).getSubscriptionProperty(
+ anyInt(),
+ eq(SubscriptionManager.WFC_IMS_ROAMING_MODE),
+ anyString());
+ }
+
+ /**
+ * Tests the operation of getWfcMode when the configuration to use the home network mode when
+ * roaming for WFC is true independent of whether or not the WFC roaming mode is editable.
+ *
+ * Preconditions:
+ * - CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL = true
+ */
+ @Test @SmallTest
+ public void getWfcMode_useWfcHomeModeConfigTrue_shouldUseWfcHomeMode() {
+ // Set some values that are different than the defaults for WFC mode.
+ doReturn(String.valueOf(ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY))
+ .when(mSubscriptionController).getSubscriptionProperty(
+ anyInt(),
+ eq(SubscriptionManager.WFC_IMS_MODE),
+ anyString());
+ doReturn(String.valueOf(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED))
+ .when(mSubscriptionController).getSubscriptionProperty(
+ anyInt(),
+ eq(SubscriptionManager.WFC_IMS_ROAMING_MODE),
+ anyString());
+
+ // Set to use WFC home network mode in roaming network.
+ mBundle.putBoolean(
+ CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL,
+ WFC_USE_HOME_MODE_FOR_ROAMING_VAL);
+
+ ImsManager imsManager = getImsManagerAndInitProvisionedValues();
+
+ // Check that use the WFC home network mode.
+ assertEquals(ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY, imsManager.getWfcMode(true));
+ verify(mSubscriptionController, times(1)).getSubscriptionProperty(
+ anyInt(),
+ eq(SubscriptionManager.WFC_IMS_MODE),
+ anyString());
+
+ // Set WFC home network mode to not editable.
+ mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL,
+ WFC_IMS_NOT_EDITABLE_VAL);
+
+ // Check that use the default WFC home network mode.
+ assertEquals(WFC_IMS_MODE_DEFAULT_VAL, imsManager.getWfcMode(true));
+ verify(mSubscriptionController, times(1)).getSubscriptionProperty(
+ anyInt(),
+ eq(SubscriptionManager.WFC_IMS_MODE),
+ anyString());
+ }
+
private ImsManager getImsManagerAndInitProvisionedValues() {
when(mImsConfigImplBaseMock.getConfigInt(anyInt()))
.thenAnswer(invocation -> {