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

Commit a2e62f42 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Unregister listeners when settings disabled or connect to wifi" into main

parents e590f4e2 43514d27
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
package: "com.android.internal.telephony.flags"
package: "com.android.internal.telephony.flags"
container: "system"
container: "system"


# OWNER=linggm TARGET=25Q3
flag {
  name: "auto_data_prune_listener"
  namespace: "telephony"
  description: "Unregister listeners when user disable settings or connect to wifi."
  bug:"389591869"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}

# OWNER=sarahchin TARGET=24Q3
# OWNER=sarahchin TARGET=24Q3
flag {
flag {
  name: "slicing_additional_error_codes"
  name: "slicing_additional_error_codes"
+103 −17
Original line number Original line Diff line number Diff line
@@ -422,6 +422,10 @@ public class AutoDataSwitchController extends Handler {
     * sub to reduce unnecessary tracking.
     * sub to reduce unnecessary tracking.
     */
     */
    private void onSubscriptionsChanged() {
    private void onSubscriptionsChanged() {
        if (sFeatureFlags.autoDataPruneListener()) {
            boolean changed = updateListenerRegistrations();
            if (changed) logl("onSubscriptionChanged: " + Arrays.toString(mPhonesSignalStatus));
        } else {
            Set<Integer> activePhoneIds = Arrays.stream(mSubscriptionManagerService
            Set<Integer> activePhoneIds = Arrays.stream(mSubscriptionManagerService
                            .getActiveSubIdList(true /*visibleOnly*/))
                            .getActiveSubIdList(true /*visibleOnly*/))
                    .map(mSubscriptionManagerService::getPhoneId)
                    .map(mSubscriptionManagerService::getPhoneId)
@@ -443,6 +447,80 @@ public class AutoDataSwitchController extends Handler {
            }
            }
            if (changed) logl("onSubscriptionChanged: " + Arrays.toString(mPhonesSignalStatus));
            if (changed) logl("onSubscriptionChanged: " + Arrays.toString(mPhonesSignalStatus));
        }
        }
    }

    /**
     * Updates network event listener registrations based on conditions.
     *
     * Unregisters listeners for *all* phones if:
     * 1. <2 active subscriptions (auto-switching requires 2+).
     * 2. Non-cellular default network (auto-switching not relevant).
     * 3. Default data disabled (no need to monitor for switching).
     * 4. No eligible auto-switch candidates (all other phones' data
     *    disabled, preventing switching).
     *
     * Registers listeners if none of the above apply and a phone's
     * listeners are currently unregistered.
     *
     * @return `true` if any registration changed; `false` otherwise.
     */
    private boolean updateListenerRegistrations() {
        if (!sFeatureFlags.autoDataPruneListener()) {
            return false;
        }
        boolean shouldUnregister = false;
        String reason = "";

        if (mSubscriptionManagerService.getActiveSubIdList(true).length < 2) {
            shouldUnregister = true;
            reason = "only have one active subscription";
        } else if (mDefaultNetworkIsOnNonCellular) {
            shouldUnregister = true;
            reason = "default network is on non-cellular network";
        } else {
            int defaultDataPhoneId = mSubscriptionManagerService.getPhoneId(
                    mSubscriptionManagerService.getDefaultDataSubId());
            Phone defaultDataPhone = PhoneFactory.getPhone(defaultDataPhoneId);

            if (defaultDataPhone != null && !defaultDataPhone.isUserDataEnabled()) {
                shouldUnregister = true;
                reason = "default data is disabled";
            } else {
                boolean anyCandidateEnabled = false;
                for (int phoneId = 0; phoneId < mPhonesSignalStatus.length; phoneId++) {
                    if (phoneId != defaultDataPhoneId) {
                        Phone phone = PhoneFactory.getPhone(phoneId);
                        if (phone != null && phone.getDataSettingsManager().isDataEnabled()) {
                            anyCandidateEnabled = true;
                            break;
                        }
                    }
                }

                if (!anyCandidateEnabled) {
                    shouldUnregister = true;
                    reason = "no candidate enabled auto data switch feature";
                }
            }
        }

        if (shouldUnregister) {
            log("updateListenerRegistrations: " + reason);
        }

        // Register or unregister as needed
        boolean changed = false;
        for (int phoneId = 0; phoneId < mPhonesSignalStatus.length; phoneId++) {
            if (shouldUnregister && mPhonesSignalStatus[phoneId].mListeningForEvents) {
                unregisterAllEventsForPhone(phoneId);
                changed = true;
            } else if (!shouldUnregister && !mPhonesSignalStatus[phoneId].mListeningForEvents) {
                registerAllEventsForPhone(phoneId);
                changed = true;
            }
        }
        return changed;
    }


    /**
    /**
     * Register all tracking events for a phone.
     * Register all tracking events for a phone.
@@ -459,6 +537,7 @@ public class AutoDataSwitchController extends Handler {
            phone.getServiceStateTracker().registerForServiceStateChanged(this,
            phone.getServiceStateTracker().registerForServiceStateChanged(this,
                    EVENT_SERVICE_STATE_CHANGED, phoneId);
                    EVENT_SERVICE_STATE_CHANGED, phoneId);
            mPhonesSignalStatus[phoneId].mListeningForEvents = true;
            mPhonesSignalStatus[phoneId].mListeningForEvents = true;
            log("registerAllEventsForPhone: registered listeners for phone " + phoneId);
        } else {
        } else {
            loge("Unexpected null phone " + phoneId + " when register all events");
            loge("Unexpected null phone " + phoneId + " when register all events");
        }
        }
@@ -475,6 +554,7 @@ public class AutoDataSwitchController extends Handler {
            phone.getSignalStrengthController().unregisterForSignalStrengthChanged(this);
            phone.getSignalStrengthController().unregisterForSignalStrengthChanged(this);
            phone.getServiceStateTracker().unregisterForServiceStateChanged(this);
            phone.getServiceStateTracker().unregisterForServiceStateChanged(this);
            mPhonesSignalStatus[phoneId].mListeningForEvents = false;
            mPhonesSignalStatus[phoneId].mListeningForEvents = false;
            log("unregisterAllEventsForPhone: unregistered listeners for phone " + phoneId);
        } else {
        } else {
            loge("Unexpected out of bound phone " + phoneId + " when unregister all events");
            loge("Unexpected out of bound phone " + phoneId + " when unregister all events");
        }
        }
@@ -497,8 +577,7 @@ public class AutoDataSwitchController extends Handler {
                dataConfig.getAutoDataSwitchAvailabilitySwitchbackStabilityTimeThreshold() >= 0
                dataConfig.getAutoDataSwitchAvailabilitySwitchbackStabilityTimeThreshold() >= 0
                        ? dataConfig.getAutoDataSwitchAvailabilitySwitchbackStabilityTimeThreshold()
                        ? dataConfig.getAutoDataSwitchAvailabilitySwitchbackStabilityTimeThreshold()
                        : dataConfig.getAutoDataSwitchAvailabilityStabilityTimeThreshold());
                        : dataConfig.getAutoDataSwitchAvailabilityStabilityTimeThreshold());
        mAutoDataSwitchValidationMaxRetry =
        mAutoDataSwitchValidationMaxRetry = dataConfig.getAutoDataSwitchValidationMaxRetry();
                dataConfig.getAutoDataSwitchValidationMaxRetry();
    }
    }


    @Override
    @Override
@@ -664,7 +743,14 @@ public class AutoDataSwitchController extends Handler {
                ? STABILITY_CHECK_TIMER_MAP.get(STABILITY_CHECK_AVAILABILITY_SWITCH)
                ? STABILITY_CHECK_TIMER_MAP.get(STABILITY_CHECK_AVAILABILITY_SWITCH)
                << mAutoSwitchValidationFailedCount
                << mAutoSwitchValidationFailedCount
                : 0;
                : 0;
        if (!mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) {
        if (reason == EVALUATION_REASON_DATA_SETTINGS_CHANGED
                || reason == EVALUATION_REASON_DEFAULT_NETWORK_CHANGED) {
            // In some conditions, listeners are paused to reduce unnecessary tracking.
            updateListenerRegistrations();
            // Always reevaluate with those critical condition change.
            scheduleEventWithTimer(EVENT_EVALUATE_AUTO_SWITCH, new EvaluateEventExtra(reason),
                    delayMs);
        } else if (!mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) {
            scheduleEventWithTimer(EVENT_EVALUATE_AUTO_SWITCH, new EvaluateEventExtra(reason),
            scheduleEventWithTimer(EVENT_EVALUATE_AUTO_SWITCH, new EvaluateEventExtra(reason),
                    delayMs);
                    delayMs);
        }
        }
+184 −0
Original line number Original line Diff line number Diff line
@@ -138,6 +138,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {
            doReturn(mSignalStrength).when(phone).getSignalStrength();
            doReturn(mSignalStrength).when(phone).getSignalStrength();
            doReturn(mDataNetworkController).when(phone).getDataNetworkController();
            doReturn(mDataNetworkController).when(phone).getDataNetworkController();
            doReturn(mDataConfigManager).when(mDataNetworkController).getDataConfigManager();
            doReturn(mDataConfigManager).when(mDataNetworkController).getDataConfigManager();
            doReturn(mDataSettingsManager).when(phone).getDataSettingsManager();
            doAnswer(invocation -> phone.getSubId() == mDefaultDataSub)
            doAnswer(invocation -> phone.getSubId() == mDefaultDataSub)
                    .when(phone).isUserDataEnabled();
                    .when(phone).isUserDataEnabled();
        }
        }
@@ -195,6 +196,10 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {
                "mEventsToAlarmListener", Map.class);
                "mEventsToAlarmListener", Map.class);
        mScheduledEventsToExtras = getPrivateField(mAutoDataSwitchControllerUT,
        mScheduledEventsToExtras = getPrivateField(mAutoDataSwitchControllerUT,
                "mScheduledEventsToExtras", Map.class);
                "mScheduledEventsToExtras", Map.class);

        clearInvocations(mDisplayInfoController, mSignalStrengthController, mSST);

        doReturn(true).when(mFeatureFlags).autoDataPruneListener();
    }
    }


    @After
    @After
@@ -721,6 +726,184 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {
        }
        }
    }
    }


    @Test
    public void testDataSettingsChangedUpdateListener() {
        setDefaultDataSubId(SUB_1); // Phone 1 is default
        int modemCount = mPhones.length; // Should be 2

        // Pre-condition: Assume listeners are registered initially (cleared invocations in setUp)

        // --- Scenario 1: Disable Default Phone User Data ---
        logd("Scenario 1: Disable Default Phone User Data");
        doReturn(false).when(mPhone).isUserDataEnabled();

        mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED);
        processAllMessages();

        // Verify unregister calls for *both* phones
        verify(mDisplayInfoController, times(modemCount))
                .unregisterForTelephonyDisplayInfoChanged(any());
        verify(mSignalStrengthController, times(modemCount)).unregisterForSignalStrengthChanged(
                any());
        verify(mSST, times(modemCount)).unregisterForServiceStateChanged(any());
        // Verify register calls were NOT made
        verify(mDisplayInfoController, never()).registerForTelephonyDisplayInfoChanged(
                any(), anyInt(), any());
        verify(mSignalStrengthController, never()).registerForSignalStrengthChanged(
                any(), anyInt(), any());
        verify(mSST, never()).registerForServiceStateChanged(any(), anyInt(), any());
        clearInvocations(mDisplayInfoController, mSignalStrengthController, mSST);

        // --- Scenario 2: Re-enable Default Phone User Data ---
        logd("Scenario 2: Re-enable Default Phone User Data");
        doReturn(true).when(mPhone).isUserDataEnabled();

        mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED);
        processAllMessages();

        // Verify register calls for *both* phones
        verify(mDisplayInfoController, times(modemCount)).registerForTelephonyDisplayInfoChanged(
                any(), eq(EVENT_DISPLAY_INFO_CHANGED), any());
        verify(mSignalStrengthController, times(modemCount)).registerForSignalStrengthChanged(
                any(), eq(EVENT_SIGNAL_STRENGTH_CHANGED), any());
        verify(mSST, times(modemCount)).registerForServiceStateChanged(
                any(), eq(EVENT_SERVICE_STATE_CHANGED), any());
        // Verify unregister calls were NOT made
        verify(mDisplayInfoController, never()).unregisterForTelephonyDisplayInfoChanged(any());
        verify(mSignalStrengthController, never()).unregisterForSignalStrengthChanged(any());
        verify(mSST, never()).unregisterForServiceStateChanged(any());
        clearInvocations(mDisplayInfoController, mSignalStrengthController, mSST); // Reset

        // --- Scenario 3: Disable *Only* Candidate Phone Data Setting ---
        logd("Scenario 3: Disable *Only* Candidate Phone Data Setting");
        doReturn(true).when(mPhone).isUserDataEnabled(); // Ensure default is enabled
        doReturn(false).when(mDataSettingsManager).isDataEnabled(); // Disable candidate

        mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED);
        processAllMessages();

        // Verify unregister calls for *both* phones (as no candidates left)
        verify(mDisplayInfoController, times(modemCount))
                .unregisterForTelephonyDisplayInfoChanged(any());
        verify(mSignalStrengthController, times(modemCount))
                .unregisterForSignalStrengthChanged(any());
        verify(mSST, times(modemCount)).unregisterForServiceStateChanged(any());
        // Verify register calls were NOT made
        verify(mDisplayInfoController, never())
                .registerForTelephonyDisplayInfoChanged(any(), anyInt(), any());
        verify(mSignalStrengthController, never())
                .registerForSignalStrengthChanged(any(), anyInt(), any());
        verify(mSST, never()).registerForServiceStateChanged(any(), anyInt(), any());
        clearInvocations(mDisplayInfoController, mSignalStrengthController, mSST); // Reset

        // --- Scenario 4: Re-enable Candidate Phone Data Setting ---
        logd("Scenario 4: Re-enable Candidate Phone Data Setting");
        doReturn(true).when(mDataSettingsManager).isDataEnabled();

        mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED);
        processAllMessages();

        // Verify register calls for *both* phones
        verify(mDisplayInfoController, times(modemCount)).registerForTelephonyDisplayInfoChanged(
                any(), eq(EVENT_DISPLAY_INFO_CHANGED), any());
        verify(mSignalStrengthController, times(modemCount)).registerForSignalStrengthChanged(
                any(), eq(EVENT_SIGNAL_STRENGTH_CHANGED), any());
        verify(mSST, times(modemCount)).registerForServiceStateChanged(
                any(), eq(EVENT_SERVICE_STATE_CHANGED), any());
        // Verify unregister calls were NOT made
        verify(mDisplayInfoController, never()).unregisterForTelephonyDisplayInfoChanged(any());
        verify(mSignalStrengthController, never()).unregisterForSignalStrengthChanged(any());
        verify(mSST, never()).unregisterForServiceStateChanged(any());
    }

    @Test
    public void testDefaultNetworkChangedUpdateListener() {
        setDefaultDataSubId(SUB_1); // Phone 1 is default
        int modemCount = mPhones.length; // Should be 2

        // Pre-condition: Assume listeners are registered initially (cleared invocations in setUp)

        // --- Scenario 1: Default network becomes non-cellular (WIFI) ---
        logd("Scenario 1: Default network becomes WIFI");
        NetworkCapabilities wifiCapabilities = new NetworkCapabilities();
        wifiCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
        mAutoDataSwitchControllerUT.updateDefaultNetworkCapabilities(wifiCapabilities);
        mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(AutoDataSwitchController
                .EVALUATION_REASON_DEFAULT_NETWORK_CHANGED);
        processAllMessages();

        // Verify unregister calls for *both* phones
        verify(mDisplayInfoController, times(modemCount))
                .unregisterForTelephonyDisplayInfoChanged(any());
        verify(mSignalStrengthController, times(modemCount))
                .unregisterForSignalStrengthChanged(any());
        verify(mSST, times(modemCount)).unregisterForServiceStateChanged(any());
        // Verify register calls were NOT made
        verify(mDisplayInfoController, never()).registerForTelephonyDisplayInfoChanged(
                any(), anyInt(), any());
        verify(mSignalStrengthController, never()).registerForSignalStrengthChanged(
                any(), anyInt(), any());
        verify(mSST, never()).registerForServiceStateChanged(any(), anyInt(), any());
        clearInvocations(mDisplayInfoController, mSignalStrengthController, mSST); // Reset

        // --- Scenario 2: Default network becomes cellular ---
        logd("Scenario 2: Default network becomes CELLULAR");
        NetworkCapabilities cellularCapabilities = new NetworkCapabilities();
        cellularCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
        mAutoDataSwitchControllerUT.updateDefaultNetworkCapabilities(cellularCapabilities);
        mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(AutoDataSwitchController
                .EVALUATION_REASON_DEFAULT_NETWORK_CHANGED);
        processAllMessages();

        // Verify register calls for *both* phones
        verify(mDisplayInfoController, times(modemCount)).registerForTelephonyDisplayInfoChanged(
                any(), eq(EVENT_DISPLAY_INFO_CHANGED), any());
        verify(mSignalStrengthController, times(modemCount)).registerForSignalStrengthChanged(any(),
                eq(EVENT_SIGNAL_STRENGTH_CHANGED), any());
        verify(mSST, times(modemCount)).registerForServiceStateChanged(any(),
                eq(EVENT_SERVICE_STATE_CHANGED), any());
        // Verify unregister calls were NOT made
        verify(mDisplayInfoController, never()).unregisterForTelephonyDisplayInfoChanged(any());
        verify(mSignalStrengthController, never()).unregisterForSignalStrengthChanged(any());
        verify(mSST, never()).unregisterForServiceStateChanged(any());
        clearInvocations(mDisplayInfoController, mSignalStrengthController, mSST); // Reset

        // --- Scenario 3: Default network lost (null) ---
        logd("Scenario 3: Default network lost (null)");
        // First switch to non-cellular to ensure listeners are off
        mAutoDataSwitchControllerUT.updateDefaultNetworkCapabilities(wifiCapabilities);
        mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(AutoDataSwitchController
                .EVALUATION_REASON_DEFAULT_NETWORK_CHANGED);
        processAllMessages();

        verify(mDisplayInfoController, times(modemCount))
                .unregisterForTelephonyDisplayInfoChanged(any());
        verify(mSignalStrengthController, times(modemCount))
                .unregisterForSignalStrengthChanged(any());
        verify(mSST, times(modemCount))
                .unregisterForServiceStateChanged(any());
        clearInvocations(mDisplayInfoController, mSignalStrengthController, mSST);

        // Now lose the network
        mAutoDataSwitchControllerUT.updateDefaultNetworkCapabilities(null);
        mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(AutoDataSwitchController
                .EVALUATION_REASON_DEFAULT_NETWORK_CHANGED);
        processAllMessages();

        // Verify register calls for *both* phones (null network means cellular is possible)
        verify(mDisplayInfoController, times(modemCount)).registerForTelephonyDisplayInfoChanged(
                any(), eq(EVENT_DISPLAY_INFO_CHANGED), any());
        verify(mSignalStrengthController, times(modemCount)).registerForSignalStrengthChanged(any(),
                eq(EVENT_SIGNAL_STRENGTH_CHANGED), any());
        verify(mSST, times(modemCount)).registerForServiceStateChanged(any(),
                eq(EVENT_SERVICE_STATE_CHANGED), any());

        verify(mDisplayInfoController, never())
                .unregisterForTelephonyDisplayInfoChanged(any());
        verify(mSignalStrengthController, never()).unregisterForSignalStrengthChanged(any());
        verify(mSST, never()).unregisterForServiceStateChanged(any());
    }

    @Test
    @Test
    public void testRatSignalStrengthSkipEvaluation() {
    public void testRatSignalStrengthSkipEvaluation() {
        // Verify the secondary phone is OOS and its score(0) is too low to justify the evaluation
        // Verify the secondary phone is OOS and its score(0) is too low to justify the evaluation
@@ -764,6 +947,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {


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


        // 5. No default network
        // 5. No default network