Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f87f6e1 authored by Ling Ma's avatar Ling Ma Committed by Jack Yu
Browse files

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
parent 42505a8d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3636,7 +3636,7 @@ public class SubscriptionController extends ISub.Stub {
                return SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
            }

            return phoneSwitcher.getOpportunisticDataSubscriptionId();
            return phoneSwitcher.getAutoSelectedDataSubId();
        } finally {
            Binder.restoreCallingIdentity(token);
        }
+70 −40
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TE
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 @@ public class PhoneSwitcher extends Handler {
    @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 @@ public class PhoneSwitcher extends Handler {
    // 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 @@ public class PhoneSwitcher extends Handler {

                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 @@ public class PhoneSwitcher extends Handler {
    }

    private int getSubIdForDefaultNetworkRequests() {
        if (mSubscriptionController.isActiveSubId(mOpptDataSubId)) {
            return mOpptDataSubId;
        if (mSubscriptionController.isActiveSubId(mAutoSelectedDataSubId)) {
            return mAutoSelectedDataSubId;
        } else {
            return mPrimaryDataSubId;
        }
@@ -1451,22 +1456,35 @@ public class PhoneSwitcher extends Handler {
     */
    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);
            sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
            return;
        validate(subId, needValidation,
                DataSwitch.Reason.DATA_SWITCH_REASON_CBRS, callback);
    }

        // Remove EVENT_NETWORK_VALIDATION_DONE. Don't handle validation result of previously subId
        // if queued.
        removeMessages(EVENT_NETWORK_VALIDATION_DONE);
        removeMessages(EVENT_NETWORK_AVAILABLE);

    /**
     * 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;

        mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID;
        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;
        }

        if (mValidator.isValidating()) {
            mValidator.stopValidation();
@@ -1474,22 +1492,29 @@ public class PhoneSwitcher extends Handler {
            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 @@ public class PhoneSwitcher extends Handler {
    }

    /**
     * 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 @@ public class PhoneSwitcher extends Handler {
        } 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 @@ public class PhoneSwitcher extends Handler {
                ? HAL_COMMAND_PREFERRED_DATA : HAL_COMMAND_ALLOW_DATA;
    }

    public int getOpportunisticDataSubscriptionId() {
        return mOpptDataSubId;
    }

    public int getPreferredDataPhoneId() {
        return mPreferredDataPhoneId;
    }
@@ -1708,6 +1731,13 @@ public class PhoneSwitcher extends Handler {
        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 @@ public class PhoneSwitcher extends Handler {
        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);
+75 −0
Original line number Diff line number Diff line
@@ -477,6 +477,65 @@ public class PhoneSwitcherTest extends TelephonyTest {
        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 @@ public class PhoneSwitcherTest extends TelephonyTest {
        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);