Refactor validation before data switch
refactor the validation before data switch flow to be subId generic
instead of specific to opportunistic subId.
Bug: 244064524
Test: existing cts+atest, manual data during phone call
Merged-In: I0cbfaa195d42140426bea533fe83f1d73ac806e2
Change-Id: I0cbfaa195d42140426bea533fe83f1d73ac806e2
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
index e7b2c69..bad461a 100644
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
@@ -3636,7 +3636,7 @@
return SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
}
- return phoneSwitcher.getOpportunisticDataSubscriptionId();
+ return phoneSwitcher.getAutoSelectedDataSubId();
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
index cd81b0c..ee8d157 100644
--- a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
@@ -31,6 +31,7 @@
import static java.util.Arrays.copyOf;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -195,6 +196,7 @@
@VisibleForTesting
protected final CellularNetworkValidator mValidator;
private int mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID;
+ private int mLastAutoSelectedSwitchReason = -1;
private boolean mPendingSwitchNeedValidation;
@VisibleForTesting
public final CellularNetworkValidator.ValidationCallback mValidationCallback =
@@ -227,9 +229,12 @@
// Internet data if mOpptDataSubId is not set.
protected int mPrimaryDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- // mOpptDataSubId must be an active subscription. If it's set, it overrides mPrimaryDataSubId
- // to be used for Internet data.
- private int mOpptDataSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+ // The automatically suggested preferred data subId (by e.g. CBRS or auto data switch), a
+ // candidate for preferred data subId, which is eventually presided by
+ // updatePreferredDataPhoneId().
+ // If CBRS/auto switch feature selects the primary data subId as the preferred data subId,
+ // its value will be DEFAULT_SUBSCRIPTION_ID.
+ private int mAutoSelectedDataSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
// The phone ID that has an active voice call. If set, and its mobile data setting is on,
// it will become the mPreferredDataPhoneId.
@@ -1148,7 +1153,7 @@
if (VDBG) {
log("mPrimaryDataSubId = " + mPrimaryDataSubId);
- log("mOpptDataSubId = " + mOpptDataSubId);
+ log("mAutoSelectedDataSubId = " + mAutoSelectedDataSubId);
for (int i = 0; i < mActiveModemCount; i++) {
log(" phone[" + i + "] using sub[" + mPhoneSubscriptions[i] + "]");
}
@@ -1310,8 +1315,8 @@
}
private int getSubIdForDefaultNetworkRequests() {
- if (mSubscriptionController.isActiveSubId(mOpptDataSubId)) {
- return mOpptDataSubId;
+ if (mSubscriptionController.isActiveSubId(mAutoSelectedDataSubId)) {
+ return mAutoSelectedDataSubId;
} else {
return mPrimaryDataSubId;
}
@@ -1451,45 +1456,65 @@
*/
private void setOpportunisticDataSubscription(int subId, boolean needValidation,
ISetOpportunisticDataCallback callback) {
- if (!mSubscriptionController.isActiveSubId(subId)
- && subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
- log("Can't switch data to inactive subId " + subId);
+ validate(subId, needValidation,
+ DataSwitch.Reason.DATA_SWITCH_REASON_CBRS, callback);
+ }
+
+ /**
+ * Try setup a new internet connection on the subId that's pending validation. If the validation
+ * succeeds, this subId will be evaluated for being the preferred data subId; If fails, nothing
+ * happens.
+ * Callback will be updated with the validation result.
+ *
+ * @param subId Sub Id that's pending switch, awaiting validation.
+ * @param needValidation {@code false} if switch to the subId even if validation fails.
+ * @param switchReason The switch reason for this validation
+ * @param callback Optional - specific for external opportunistic sub validation request.
+ */
+ private void validate(int subId, boolean needValidation, int switchReason,
+ @Nullable ISetOpportunisticDataCallback callback) {
+ int subIdToValidate = (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)
+ ? mPrimaryDataSubId : subId;
+ if (!mSubscriptionController.isActiveSubId(subIdToValidate)) {
+ log("Can't switch data to inactive subId " + subIdToValidate);
+ if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+ // the default data sub is not selected yet, store the intent of switching to
+ // default subId once it becomes available.
+ mAutoSelectedDataSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+ }
sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
return;
}
- // Remove EVENT_NETWORK_VALIDATION_DONE. Don't handle validation result of previously subId
- // if queued.
- removeMessages(EVENT_NETWORK_VALIDATION_DONE);
- removeMessages(EVENT_NETWORK_AVAILABLE);
-
- int subIdToValidate = (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)
- ? mPrimaryDataSubId : subId;
-
- mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID;
-
if (mValidator.isValidating()) {
mValidator.stopValidation();
sendSetOpptCallbackHelper(mSetOpptSubCallback, SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
mSetOpptSubCallback = null;
}
- if (subId == mOpptDataSubId) {
+ // Remove EVENT_NETWORK_VALIDATION_DONE. Don't handle validation result of previous subId
+ // if queued.
+ removeMessages(EVENT_NETWORK_VALIDATION_DONE);
+ removeMessages(EVENT_NETWORK_AVAILABLE);
+
+ mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID;
+
+ if (subIdToValidate == mPreferredDataSubId.get()) {
sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS);
return;
}
- logDataSwitchEvent(subId == DEFAULT_SUBSCRIPTION_ID ? mPrimaryDataSubId : subId,
+ mLastAutoSelectedSwitchReason = switchReason;
+ logDataSwitchEvent(subIdToValidate,
TelephonyEvent.EventState.EVENT_STATE_START,
- DataSwitch.Reason.DATA_SWITCH_REASON_CBRS);
- registerDefaultNetworkChangeCallback(
- subId == DEFAULT_SUBSCRIPTION_ID ? mPrimaryDataSubId : subId,
- DataSwitch.Reason.DATA_SWITCH_REASON_CBRS);
+ switchReason);
+ registerDefaultNetworkChangeCallback(subIdToValidate,
+ switchReason);
// If validation feature is not supported, set it directly. Otherwise,
// start validation on the subscription first.
if (!mValidator.isValidationFeatureSupported()) {
- setOpportunisticSubscriptionInternal(subId);
+ setAutoSelectedDataSubIdInternal(subIdToValidate);
sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS);
return;
}
@@ -1531,12 +1556,15 @@
}
/**
- * Set opportunistic data subscription.
+ * Evaluate whether the specified sub Id can be set to be the preferred data sub Id.
+ *
+ * @param subId The subId that we tried to validate: could possibly be unvalidated if validation
+ * feature is not supported.
*/
- private void setOpportunisticSubscriptionInternal(int subId) {
- if (mOpptDataSubId != subId) {
- mOpptDataSubId = subId;
- onEvaluate(REQUESTS_UNCHANGED, "oppt data subId changed");
+ private void setAutoSelectedDataSubIdInternal(int subId) {
+ if (mAutoSelectedDataSubId != subId) {
+ mAutoSelectedDataSubId = subId;
+ onEvaluate(REQUESTS_UNCHANGED, switchReasonToString(mLastAutoSelectedSwitchReason));
}
}
@@ -1549,11 +1577,10 @@
} else if (!confirm) {
resultForCallBack = SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED;
} else {
- if (mSubscriptionController.isOpportunistic(subId)) {
- setOpportunisticSubscriptionInternal(subId);
+ if (subId == mPrimaryDataSubId) {
+ setAutoSelectedDataSubIdInternal(DEFAULT_SUBSCRIPTION_ID);
} else {
- // Switching data back to primary subscription.
- setOpportunisticSubscriptionInternal(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+ setAutoSelectedDataSubIdInternal(subId);
}
resultForCallBack = SET_OPPORTUNISTIC_SUB_SUCCESS;
}
@@ -1623,10 +1650,6 @@
? HAL_COMMAND_PREFERRED_DATA : HAL_COMMAND_ALLOW_DATA;
}
- public int getOpportunisticDataSubscriptionId() {
- return mOpptDataSubId;
- }
-
public int getPreferredDataPhoneId() {
return mPreferredDataPhoneId;
}
@@ -1708,6 +1731,13 @@
return mPreferredDataSubId.get();
}
+ /**
+ * @return The auto selected data subscription id.
+ */
+ public int getAutoSelectedDataSubId() {
+ return mAutoSelectedDataSubId;
+ }
+
// TODO (b/148396668): add an internal callback method to monitor phone capability change,
// and hook this call to that callback.
private void onPhoneCapabilityChanged(PhoneCapability capability) {
@@ -1732,7 +1762,7 @@
pw.println("DefaultDataPhoneId=" + mSubscriptionController.getPhoneId(
mSubscriptionController.getDefaultDataSubId()));
pw.println("mPrimaryDataSubId=" + mPrimaryDataSubId);
- pw.println("mOpptDataSubId=" + mOpptDataSubId);
+ pw.println("mAutoSelectedDataSubId=" + mAutoSelectedDataSubId);
pw.println("mIsRegisteredForImsRadioTechChange=" + mIsRegisteredForImsRadioTechChange);
pw.println("mPendingSwitchNeedValidation=" + mPendingSwitchNeedValidation);
pw.println("mMaxDataAttachModemCount=" + mMaxDataAttachModemCount);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
index 487f7e3..6465705 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
@@ -477,6 +477,65 @@
assertFalse(mDataAllowed[1]);
}
+ /**
+ * TestSetPreferredData in the event of different priorities.
+ * The following events can set preferred data subId with priority in the order of
+ * 1. Emergency call
+ * 2. Voice call (when data during call feature is enabled).
+ * 3. CBRS requests
+ */
+ @Test
+ @SmallTest
+ public void testSetPreferredDataCasePriority() throws Exception {
+ initialize();
+ setAllPhonesInactive();
+
+ // Phone 0 has sub 1, phone 1 has sub 2.
+ // Sub 1 is default data sub.
+ // Both are active subscriptions are active sub, as they are in both active slots.
+ setSlotIndexToSubId(0, 1);
+ setSlotIndexToSubId(1, 2);
+ setDefaultDataSubId(1);
+
+ // Notify phoneSwitcher about default data sub and default network request.
+ NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
+ // Phone 0 (sub 1) should be activated as it has default data sub.
+ assertEquals(1, mPhoneSwitcher.getActiveDataSubId());
+ assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(
+ new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(
+ new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+
+ // Set sub 2 as preferred sub should make phone 1 activated and phone 0 deactivated.
+ mPhoneSwitcher.trySetOpportunisticDataSubscription(2, false, null);
+ processAllMessages();
+ mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 2);
+ // A higher priority event occurring E.g. Phone1 has active IMS call on LTE.
+ doReturn(mImsPhone).when(mPhone).getImsPhone();
+ doReturn(true).when(mDataSettingsManager).isDataEnabled(ApnSetting.TYPE_DEFAULT);
+ mockImsRegTech(1, REGISTRATION_TECH_LTE);
+ notifyPhoneAsInCall(mPhone);
+
+ // switch shouldn't occur due to the higher priority event
+ assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(
+ new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(
+ new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ assertEquals(1, mPhoneSwitcher.getActiveDataSubId());
+ assertEquals(2, mPhoneSwitcher.getAutoSelectedDataSubId());
+
+ // The higher priority event ends, time to switch to auto selected subId.
+ notifyPhoneAsInactive(mPhone);
+
+ assertEquals(2, mPhoneSwitcher.getActiveDataSubId());
+ assertEquals(2, mPhoneSwitcher.getAutoSelectedDataSubId());
+ assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(
+ new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(
+ new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+
+ }
+
@Test
@SmallTest
public void testSetPreferredDataModemCommand() throws Exception {
@@ -1084,7 +1143,23 @@
setSlotIndexToSubId(1, 2);
setDefaultDataSubId(1);
+ // Switch to primary before a primary is selected/inactive.
+ setDefaultDataSubId(-1);
+ mPhoneSwitcher.trySetOpportunisticDataSubscription(
+ SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, mSetOpptDataCallback1);
+ processAllMessages();
+
+ assertEquals(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ mPhoneSwitcher.getAutoSelectedDataSubId());
+ verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
+
+ // once the primary is selected, it becomes the active sub.
+ setDefaultDataSubId(2);
+ assertEquals(2, mPhoneSwitcher.getActiveDataSubId());
+
+ setDefaultDataSubId(1);
// Validating on sub 10 which is inactive.
+ clearInvocations(mSetOpptDataCallback1);
mPhoneSwitcher.trySetOpportunisticDataSubscription(10, true, mSetOpptDataCallback1);
processAllMessages();
verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);