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

Commit 4dd94641 authored by Ling Ma's avatar Ling Ma
Browse files

Separate user enabled and user allowed

When the preferred data on backup phone,
- before the change, due to service state change race condition, if service state change event reaches switch controller first, the phone will immediately switch back to the default because it thought data is now allowed due to non-service state change reason.
- after the change, we ensure only immediately switch back when user
  disabled the settings. For other environment related reasons, we allow
a stability check.

Also, this change remove the ratss flag which is 100% rolled out to
prune branches

Fix: 338552223
Test: voice call + data browsing
Test: atest rameworks/opt/telephony/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java

Change-Id: Ib413236991f7d64043973c355ff88779543dee9e
parent 29ce646b
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -25,10 +25,13 @@ flag {

# OWNER=linggm TARGET=24Q3
flag {
  name: "auto_data_switch_rat_ss"
  name: "auto_data_switch_uses_data_enabled"
  namespace: "telephony"
  description: "Whether switch for better rat and signal strength"
  bug:"260928808"
  description: "Separately consider the backup phone's data allowed and data enabled."
  bug: "338552223"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}

# OWNER=linggm TARGET=24Q2
+2 −2
Original line number Diff line number Diff line
@@ -4922,8 +4922,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    /**
     * @return The data settings manager
     */
    public @Nullable DataSettingsManager getDataSettingsManager() {
        if (mDataNetworkController == null) return null;
    @NonNull
    public DataSettingsManager getDataSettingsManager() {
        return mDataNetworkController.getDataSettingsManager();
    }

+72 −84
Original line number Diff line number Diff line
@@ -473,6 +473,7 @@ public class AutoDataSwitchController extends Handler {
    @Override
    public void handleMessage(@NonNull Message msg) {
        AsyncResult ar;
        Object obj;
        int phoneId;
        switch (msg.what) {
            case EVENT_SERVICE_STATE_CHANGED:
@@ -491,20 +492,14 @@ public class AutoDataSwitchController extends Handler {
                onSignalStrengthChanged(phoneId);
                break;
            case EVENT_EVALUATE_AUTO_SWITCH:
                if (sFeatureFlags.autoDataSwitchRatSs()) {
                    Object obj = mScheduledEventsToExtras.get(EVENT_EVALUATE_AUTO_SWITCH);
                obj = mScheduledEventsToExtras.get(EVENT_EVALUATE_AUTO_SWITCH);
                if (obj instanceof EvaluateEventExtra extra) {
                    mScheduledEventsToExtras.remove(EVENT_EVALUATE_AUTO_SWITCH);
                    onEvaluateAutoDataSwitch(extra.evaluateReason);
                }
                } else {
                    int reason = (int) msg.obj;
                    onEvaluateAutoDataSwitch(reason);
                }
                break;
            case EVENT_STABILITY_CHECK_PASSED:
                if (sFeatureFlags.autoDataSwitchRatSs()) {
                    Object obj = mScheduledEventsToExtras.get(EVENT_STABILITY_CHECK_PASSED);
                obj = mScheduledEventsToExtras.get(EVENT_STABILITY_CHECK_PASSED);
                if (obj instanceof StabilityEventExtra extra) {
                    int targetPhoneId = extra.targetPhoneId;
                    boolean needValidation = extra.needValidation;
@@ -513,13 +508,6 @@ public class AutoDataSwitchController extends Handler {
                    mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED);
                    mPhoneSwitcherCallback.onRequireValidation(targetPhoneId, needValidation);
                }
                } else {
                    int targetPhoneId = msg.arg1;
                    boolean needValidation = msg.arg2 == 1;
                    log("require validation on phone " + targetPhoneId
                            + (needValidation ? "" : " no") + " need to pass");
                    mPhoneSwitcherCallback.onRequireValidation(targetPhoneId, needValidation);
                }
                break;
            case EVENT_SUBSCRIPTIONS_CHANGED:
                onSubscriptionsChanged();
@@ -643,16 +631,10 @@ public class AutoDataSwitchController extends Handler {
                ? mAutoDataSwitchAvailabilityStabilityTimeThreshold
                << mAutoSwitchValidationFailedCount
                : 0;
        if (sFeatureFlags.autoDataSwitchRatSs()) {
        if (!mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) {
            scheduleEventWithTimer(EVENT_EVALUATE_AUTO_SWITCH, new EvaluateEventExtra(reason),
                    delayMs);
        }
        } else {
            if (!hasMessages(EVENT_EVALUATE_AUTO_SWITCH)) {
                sendMessageDelayed(obtainMessage(EVENT_EVALUATE_AUTO_SWITCH, reason), delayMs);
            }
        }
    }

    /**
@@ -700,13 +682,33 @@ public class AutoDataSwitchController extends Handler {
                return;
            }

            DataEvaluation internetEvaluation;
            if (sFeatureFlags.autoDataSwitchUsesDataEnabled()) {
                if (!defaultDataPhone.isUserDataEnabled()) {
                    mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX,
                            EVALUATION_REASON_DATA_SETTINGS_CHANGED);
                    log(debugMessage.append(
                            ", immediately back to default as user turns off default").toString());
                    return;
                } else if (!(internetEvaluation = backupDataPhone.getDataNetworkController()
                        .getInternetEvaluation(false/*ignoreExistingNetworks*/))
                        .isSubsetOf(DataEvaluation.DataDisallowedReason.NOT_IN_SERVICE)) {
                    mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(
                            DEFAULT_PHONE_INDEX, EVALUATION_REASON_DATA_SETTINGS_CHANGED);
                    log(debugMessage.append(
                                    ", immediately back to default because backup ")
                            .append(internetEvaluation).toString());
                    return;
                }
            } else {
                if (!defaultDataPhone.isUserDataEnabled() || !backupDataPhone.isDataAllowed()) {
                    mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX,
                            EVALUATION_REASON_DATA_SETTINGS_CHANGED);
                log(debugMessage.append(", immediately back to default as user turns off settings")
                        .toString());
                    log(debugMessage.append(
                            ", immediately back to default as user turns off settings").toString());
                    return;
                }
            }

            boolean backToDefault = false;
            boolean isForPerformance = false;
@@ -915,12 +917,15 @@ public class AutoDataSwitchController extends Handler {
            }

            if (secondaryDataPhone != null) {
                // check auto switch feature enabled
                if (secondaryDataPhone.isDataAllowed()) {
                // check internet data is allowed on the candidate
                DataEvaluation internetEvaluation = secondaryDataPhone.getDataNetworkController()
                        .getInternetEvaluation(false/*ignoreExistingNetworks*/);
                if (!internetEvaluation.containsDisallowedReasons()) {
                    return new StabilityEventExtra(phoneId,
                            isForPerformance, mRequirePingTestBeforeSwitch);
                } else {
                    debugMessage.append(", but candidate's data is not allowed");
                    debugMessage.append(", but candidate's data is not allowed ")
                            .append(internetEvaluation);
                }
            }
        }
@@ -932,8 +937,7 @@ public class AutoDataSwitchController extends Handler {
     * @return {@code true} If the feature of switching base on RAT and signal strength is enabled.
     */
    private boolean isRatSignalStrengthBasedSwitchEnabled() {
        return sFeatureFlags.autoDataSwitchRatSs() && mScoreTolerance >= 0
                && mAutoDataSwitchPerformanceStabilityTimeThreshold >= 0;
        return mScoreTolerance >= 0 && mAutoDataSwitchPerformanceStabilityTimeThreshold >= 0;
    }

    /**
@@ -953,8 +957,6 @@ public class AutoDataSwitchController extends Handler {
     */
    private void startStabilityCheck(int targetPhoneId, boolean isForPerformance,
            boolean needValidation) {
        String combinationIdentifier = targetPhoneId + "" + needValidation;
        if (sFeatureFlags.autoDataSwitchRatSs()) {
        StabilityEventExtra eventExtras = (StabilityEventExtra)
                mScheduledEventsToExtras.getOrDefault(EVENT_STABILITY_CHECK_PASSED,
                        new StabilityEventExtra(INVALID_PHONE_INDEX, false /*need validation*/,
@@ -976,16 +978,6 @@ public class AutoDataSwitchController extends Handler {
        log("startStabilityCheck: "
                + (delayMs != -1 ? "scheduling " : "already scheduled ")
                + eventExtras);
        } else if (!hasEqualMessages(EVENT_STABILITY_CHECK_PASSED, combinationIdentifier)) {
            removeMessages(EVENT_STABILITY_CHECK_PASSED);
            sendMessageDelayed(obtainMessage(EVENT_STABILITY_CHECK_PASSED, targetPhoneId,
                            needValidation ? 1 : 0,
                            combinationIdentifier),
                    mAutoDataSwitchAvailabilityStabilityTimeThreshold);
            log("startStabilityCheck: targetPhoneId=" + targetPhoneId
                    + " isForPerformance=" + isForPerformance
                    + " needValidation=" + needValidation);
        }
    }

    /**
@@ -1075,7 +1067,6 @@ public class AutoDataSwitchController extends Handler {
    private void cancelAnyPendingSwitch() {
        mSelectedTargetPhoneId = INVALID_PHONE_INDEX;
        resetFailedCount();
        if (sFeatureFlags.autoDataSwitchRatSs()) {
        if (mScheduledEventsToExtras.containsKey(EVENT_STABILITY_CHECK_PASSED)) {
            if (mEventsToAlarmListener.containsKey(EVENT_STABILITY_CHECK_PASSED)) {
                mAlarmManager.cancel(mEventsToAlarmListener.get(EVENT_STABILITY_CHECK_PASSED));
@@ -1085,9 +1076,6 @@ public class AutoDataSwitchController extends Handler {
            removeMessages(EVENT_STABILITY_CHECK_PASSED);
            mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED);
        }
        } else {
            removeMessages(EVENT_STABILITY_CHECK_PASSED);
        }
        mPhoneSwitcherCallback.onRequireCancelAnyPendingAutoSwitchValidation();
    }

+22 −7
Original line number Diff line number Diff line
@@ -1481,6 +1481,19 @@ public class DataNetworkController extends Handler {
     * still allowed in this case.
     */
    public boolean isInternetDataAllowed(boolean ignoreExistingNetworks) {
        return !getInternetEvaluation(ignoreExistingNetworks).containsDisallowedReasons();
    }

    /**
     * @param ignoreExistingNetworks {@code true} to skip the existing network check.
     * @return The internet evaluation result.
     * For example, if SIM is absent, or airplane mode is on, then data is NOT allowed.
     * This API does not reflect the currently internet data network status. It's possible there is
     * no internet data due to weak cellular signal or network side issue, but internet data is
     * still allowed in this case.
     */
    @NonNull
    public DataEvaluation getInternetEvaluation(boolean ignoreExistingNetworks) {
        TelephonyNetworkRequest internetRequest = new TelephonyNetworkRequest(
                new NetworkRequest.Builder()
                        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
@@ -1492,7 +1505,7 @@ public class DataNetworkController extends Handler {
                && mDataNetworkList.stream().anyMatch(
                        dataNetwork -> internetRequest.canBeSatisfiedBy(
                                dataNetwork.getNetworkCapabilities()))) {
            return true;
            return new DataEvaluation(DataEvaluationReason.EXTERNAL_QUERY);
        }

        // If no existing network can satisfy the request, then check if we can possibly setup
@@ -1500,17 +1513,19 @@ public class DataNetworkController extends Handler {

        DataEvaluation evaluation = evaluateNetworkRequest(internetRequest,
                DataEvaluationReason.EXTERNAL_QUERY);
        if (evaluation.containsOnly(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK)) {
            // If the only failed reason is only single network allowed, then check if the request
            // can trump the current network.
            return internetRequest.getPriority() > mDataNetworkList.stream()
        if (evaluation.containsOnly(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK)
                && internetRequest.getPriority() > mDataNetworkList.stream()
                .map(DataNetwork::getPriority)
                .max(Comparator.comparing(Integer::valueOf))
                    .orElse(0);
                .orElse(0)) {
            // If the only failed reason is only single network allowed, then check if the request
            // can trump the current network.
            evaluation.addDataAllowedReason(DataAllowedReason.NORMAL);
        }
        return !evaluation.containsDisallowedReasons();
        return evaluation;
    }


    /**
     * @return {@code true} if internet is unmetered.
     */
+28 −10
Original line number Diff line number Diff line
@@ -93,8 +93,10 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {
    private TelephonyDisplayInfo mGoodTelephonyDisplayInfo;
    private TelephonyDisplayInfo mBadTelephonyDisplayInfo;
    private int mDefaultDataSub;
    private DataEvaluation mDataEvaluation;
    private AutoDataSwitchController mAutoDataSwitchControllerUT;
    private Map<Integer, AlarmManager.OnAlarmListener> mEventsToAlarmListener;
    private Map<Integer, Object> mScheduledEventsToExtras;
    @Before
    public void setUp() throws Exception {
        super.setUp(getClass().getSimpleName());
@@ -137,6 +139,8 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {
            doAnswer(invocation -> phone.getSubId() == mDefaultDataSub)
                    .when(phone).isUserDataEnabled();
        }
        mDataEvaluation = new DataEvaluation(DataEvaluation.DataEvaluationReason.EXTERNAL_QUERY);
        doReturn(mDataEvaluation).when(mDataNetworkController).getInternetEvaluation(anyBoolean());
        doReturn(new int[]{SUB_1, SUB_2}).when(mSubscriptionManagerService)
                .getActiveSubIdList(true);
        doAnswer(invocation -> {
@@ -184,9 +188,12 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {
                mAutoDataSwitchControllerUT, mMockedAlarmManager);
        mEventsToAlarmListener = getPrivateField(mAutoDataSwitchControllerUT,
                "mEventsToAlarmListener", Map.class);
        mScheduledEventsToExtras = getPrivateField(mAutoDataSwitchControllerUT,
                "mScheduledEventsToExtras", Map.class);

        doReturn(true).when(mFeatureFlags).autoDataSwitchAllowRoaming();
        doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag();
        doReturn(true).when(mFeatureFlags).autoDataSwitchUsesDataEnabled();
    }

    @After
@@ -240,7 +247,10 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {
        prepareIdealUsesNonDdsCondition();
        processAllFutureMessages();
        clearInvocations(mMockedPhoneSwitcherCallback);
        doReturn(false).when(mPhone2).isDataAllowed();
        mDataEvaluation.addDataDisallowedReason(DataEvaluation.DataDisallowedReason
                .NO_SUITABLE_DATA_PROFILE);
        doReturn(mDataEvaluation)
                .when(mDataNetworkController).getInternetEvaluation(anyBoolean());
        mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED);
        processAllFutureMessages();

@@ -350,7 +360,6 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {

    @Test
    public void testRoaming_same_roaming_condition_uses_rat_signalStrength() {
        doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs();
        // On primary phone
        // 1. Both roaming, user allow roaming on both phone, uses RAT score to decide switch.
        prepareIdealUsesNonDdsCondition();
@@ -375,7 +384,6 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {

    @Test
    public void testCancelSwitch_onPrimary_rat_signalStrength() {
        doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs();
        // 4.1.1 Display info and signal strength on secondary phone became bad,
        // but primary is still OOS, so still switch to the secondary.
        prepareIdealUsesNonDdsCondition();
@@ -467,7 +475,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {
        prepareIdealUsesNonDdsCondition();
        // 2.2 Auto switch feature is disabled, no need validation
        clearInvocations(mCellularNetworkValidator);
        doReturn(false).when(mPhone2).isDataAllowed();
        mDataEvaluation.addDataDisallowedReason(DataEvaluation.DataDisallowedReason.DATA_DISABLED);
        mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED);
        processAllFutureMessages();

@@ -483,11 +491,13 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {

        verify(mMockedPhoneSwitcherCallback).onRequireValidation(DEFAULT_PHONE_INDEX,
                false/*needValidation*/);

        clearInvocations(mMockedPhoneSwitcherCallback);
        prepareIdealUsesNonDdsCondition();
    }

    @Test
    public void testOnNonDdsSwitchBackToPrimary_rat_signalStrength() {
        doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs();
        prepareIdealUsesNonDdsCondition();
        processAllFutureMessages();
        doReturn(PHONE_2).when(mPhoneSwitcher).getPreferredDataPhoneId();
@@ -536,10 +546,16 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {

    @Test
    public void testStabilityCheckOverride_basic() {
        // Disable RAT + signalStrength base switching.
        doReturn(-1).when(mDataConfigManager).getAutoDataSwitchScoreTolerance();
        mAutoDataSwitchControllerUT = new AutoDataSwitchController(mContext, Looper.myLooper(),
                mPhoneSwitcher, mFeatureFlags, mMockedPhoneSwitcherCallback);

        // Starting stability check for switching to non-DDS
        prepareIdealUsesNonDdsCondition();
        processAllMessages();
        processAllFutureMessages();

        clearInvocations(mMockedPhoneSwitcherCallback);
        // Switch success, but the previous stability check is still pending
        doReturn(PHONE_2).when(mPhoneSwitcher).getPreferredDataPhoneId();

@@ -557,7 +573,6 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {

    @Test
    public void testStabilityCheckOverride_uses_rat_signalStrength() {
        doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs();
        // Switching due to availability first.
        prepareIdealUsesNonDdsCondition();

@@ -578,6 +593,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {
    public void testValidationFailedRetry() {
        prepareIdealUsesNonDdsCondition();

        clearInvocations(mMockedPhoneSwitcherCallback);
        for (int i = 0; i < MAX_RETRY; i++) {
            mAutoDataSwitchControllerUT.evaluateRetryOnValidationFailed();
            processAllFutureMessages();
@@ -730,7 +746,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {

        // 4.2 Auto switch feature is enabled
        doReturn(true).when(mPhone2).getDataRoamingEnabled();
        doReturn(true).when(mPhone2).isDataAllowed();
        mDataEvaluation.addDataAllowedReason(DataEvaluation.DataAllowedReason.NORMAL);

        // 5. No default network
        mAutoDataSwitchControllerUT.updateDefaultNetworkCapabilities(null /*networkCapabilities*/);
@@ -783,10 +799,12 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {

    @Override
    public void processAllFutureMessages() {
        if (mFeatureFlags.autoDataSwitchRatSs()
                && mEventsToAlarmListener.containsKey(EVENT_STABILITY_CHECK_PASSED)) {
        if (mScheduledEventsToExtras.containsKey(EVENT_STABILITY_CHECK_PASSED)) {
            mEventsToAlarmListener.get(EVENT_STABILITY_CHECK_PASSED).onAlarm();
        }
        if (mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) {
            mEventsToAlarmListener.get(EVENT_EVALUATE_AUTO_SWITCH).onAlarm();
        }
        super.processAllFutureMessages();
    }
}
Loading