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

Commit 7b0c7c82 authored by Jack Yu's avatar Jack Yu Committed by Gerrit Code Review
Browse files

Merge changes from topic "ignore gid difference"

* changes:
  Refactor validation before data switch
  Add auto_data_switch_availability_stability_time_threshold to control auto data switch
  Merge similar data profile - ignore gid difference
parents 2ae9a8a8 3f87f6e1
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);
        }
+3 −2
Original line number Diff line number Diff line
@@ -966,6 +966,9 @@ public class DataProfileManager extends Handler {
                ? apn1.getMtuV4() : apn2.getMtuV4());
        apnBuilder.setMtuV6(apn2.getMtuV6() <= ApnSetting.UNSET_MTU
                ? apn1.getMtuV6() : apn2.getMtuV6());
        // legacy properties that don't matter
        apnBuilder.setMvnoType(apn1.getMvnoType());
        apnBuilder.setMvnoMatchData(apn1.getMvnoMatchData());

        // The following fields in apn1 and apn2 should be the same, otherwise ApnSetting.similar()
        // should fail earlier.
@@ -980,8 +983,6 @@ public class DataProfileManager extends Handler {
        apnBuilder.setMaxConns(apn1.getMaxConns());
        apnBuilder.setWaitTime(apn1.getWaitTime());
        apnBuilder.setMaxConnsTime(apn1.getMaxConnsTime());
        apnBuilder.setMvnoType(apn1.getMvnoType());
        apnBuilder.setMvnoMatchData(apn1.getMvnoMatchData());
        apnBuilder.setApnSetId(apn1.getApnSetId());
        apnBuilder.setCarrierId(apn1.getCarrierId());
        apnBuilder.setSkip464Xlat(apn1.getSkip464Xlat());
+110 −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;
@@ -53,6 +54,7 @@ import android.os.PersistableBundle;
import android.os.Registrant;
import android.os.RegistrantList;
import android.os.RemoteException;
import android.provider.DeviceConfig;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
@@ -65,6 +67,7 @@ import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsRegistrationAttributes;
import android.telephony.ims.RegistrationManager;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.LocalLog;

@@ -109,6 +112,9 @@ import java.util.concurrent.CompletableFuture;
 */
public class PhoneSwitcher extends Handler {
    private static final String LOG_TAG = "PhoneSwitcher";
    /** DeviceConfig key of the time threshold in ms for defining a network status to be stable. **/
    private static final String KEY_AUTO_DATA_SWITCH_AVAILABILITY_STABILITY_TIME_THRESHOLD =
            "auto_data_switch_availability_stability_time_threshold";
    protected static final boolean VDBG = false;

    private static final int DEFAULT_NETWORK_CHANGE_TIMEOUT_MS = 5000;
@@ -190,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 =
@@ -222,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.
@@ -294,6 +304,7 @@ public class PhoneSwitcher extends Handler {
    private static final int EVENT_PROCESS_SIM_STATE_CHANGE       = 119;
    @VisibleForTesting
    public static final int EVENT_IMS_RADIO_TECH_CHANGED          = 120;
    public static final int EVENT_DEVICE_CONFIG_CHANGED           = 121;

    // List of events triggers re-evaluations
    private static final String EVALUATION_REASON_RADIO_ON = "EVENT_RADIO_ON";
@@ -320,6 +331,13 @@ public class PhoneSwitcher extends Handler {

    private List<Set<CommandException.Error>> mCurrentDdsSwitchFailure;

    /**
     * Time threshold in ms to define a internet connection status to be stable(e.g. out of service,
     * in service, wifi is the default active network.etc), while -1 indicates auto switch
     * feature disabled.
     */
    private long mAutoDataSwitchAvailabilityStabilityTimeThreshold = -1;

    /** Data settings manager callback. Key is the phone id. */
    private final @NonNull Map<Integer, DataSettingsManagerCallback> mDataSettingsManagerCallbacks =
            new ArrayMap<>();
@@ -569,6 +587,17 @@ public class PhoneSwitcher extends Handler {
        // we want to see all requests
        networkFactory.registerIgnoringScore();

        // Register for device config update
        DeviceConfig.addOnPropertiesChangedListener(
                DeviceConfig.NAMESPACE_TELEPHONY, this::post,
                properties -> {
                    if (TextUtils.equals(DeviceConfig.NAMESPACE_TELEPHONY,
                            properties.getNamespace())) {
                        sendEmptyMessage(EVENT_DEVICE_CONFIG_CHANGED);
                    }
                });
        updateDeviceConfig();

        updateHalCommandToUse();

        log("PhoneSwitcher started");
@@ -840,9 +869,23 @@ public class PhoneSwitcher extends Handler {
                }
                break;
            }
            case EVENT_DEVICE_CONFIG_CHANGED: {
                updateDeviceConfig();
                break;
            }
        }
    }

    /** Update local properties from {@link DeviceConfig} */
    private void updateDeviceConfig() {
        DeviceConfig.Properties properties = //read all telephony properties
                DeviceConfig.getProperties(DeviceConfig.NAMESPACE_TELEPHONY);

        mAutoDataSwitchAvailabilityStabilityTimeThreshold = properties.getInt(
                KEY_AUTO_DATA_SWITCH_AVAILABILITY_STABILITY_TIME_THRESHOLD, -1);

    }

    private synchronized void onMultiSimConfigChanged(int activeModemCount) {
        // No change.
        if (mActiveModemCount == activeModemCount) return;
@@ -1110,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] + "]");
                    }
@@ -1272,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;
        }
@@ -1413,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();
@@ -1436,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;
        }
@@ -1493,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));
        }
    }

@@ -1511,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;
        }
@@ -1585,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;
    }
@@ -1670,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) {
@@ -1694,13 +1762,15 @@ 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);
        pw.println("mActiveModemCount=" + mActiveModemCount);
        pw.println("mPhoneIdInVoiceCall=" + mPhoneIdInVoiceCall);
        pw.println("mCurrentDdsSwitchFailure=" + mCurrentDdsSwitchFailure);
        pw.println("mAutoDataSwitchAvailabilityStabilityTimeThreshold="
                + mAutoDataSwitchAvailabilityStabilityTimeThreshold);
        pw.println("Local logs:");
        pw.increaseIndent();
        mLocalLog.dump(fd, pw, args);
+4 −0
Original line number Diff line number Diff line
@@ -931,6 +931,8 @@ public class DataProfileManagerTest extends TelephonyTest {
                        .setProtocol(ApnSetting.PROTOCOL_IPV4V6)
                        .setRoamingProtocol(ApnSetting.PROTOCOL_IPV4V6)
                        .setCarrierEnabled(true)
                        .setMvnoMatchData("1")
                        .setMvnoType(1)
                        .build())
                .build();

@@ -945,6 +947,8 @@ public class DataProfileManagerTest extends TelephonyTest {
                        .setProtocol(ApnSetting.PROTOCOL_IPV4V6)
                        .setRoamingProtocol(ApnSetting.PROTOCOL_IPV4V6)
                        .setCarrierEnabled(true)
                        .setMvnoMatchData("2")
                        .setMvnoType(2)
                        .build())
                .build();

+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);