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

Commit a74b8520 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 13350447 from 0bf5f4bd to 25Q3-release

Change-Id: Iee9a77d0c0ffb5724b40945dcaf0a1a0eac04f9e
parents ae859ed9 0bf5f4bd
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
package: "com.android.internal.telephony.flags"
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
flag {
  name: "slicing_additional_error_codes"
+12 −0
Original line number Diff line number Diff line
@@ -103,3 +103,15 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

# OWNER=amallampati TARGET=25Q3
flag {
    name: "satellite_improve_multi_thread_design"
    is_exported: false
    namespace: "telephony"
    description: "Improve multi-thread design in satellite module"
    bug:"398227332"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
 No newline at end of file
+103 −17
Original line number Diff line number Diff line
@@ -422,6 +422,10 @@ public class AutoDataSwitchController extends Handler {
     * sub to reduce unnecessary tracking.
     */
    private void onSubscriptionsChanged() {
        if (sFeatureFlags.autoDataPruneListener()) {
            boolean changed = updateListenerRegistrations();
            if (changed) logl("onSubscriptionChanged: " + Arrays.toString(mPhonesSignalStatus));
        } else {
            Set<Integer> activePhoneIds = Arrays.stream(mSubscriptionManagerService
                            .getActiveSubIdList(true /*visibleOnly*/))
                    .map(mSubscriptionManagerService::getPhoneId)
@@ -443,6 +447,80 @@ public class AutoDataSwitchController extends Handler {
            }
            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.
@@ -459,6 +537,7 @@ public class AutoDataSwitchController extends Handler {
            phone.getServiceStateTracker().registerForServiceStateChanged(this,
                    EVENT_SERVICE_STATE_CHANGED, phoneId);
            mPhonesSignalStatus[phoneId].mListeningForEvents = true;
            log("registerAllEventsForPhone: registered listeners for phone " + phoneId);
        } else {
            loge("Unexpected null phone " + phoneId + " when register all events");
        }
@@ -475,6 +554,7 @@ public class AutoDataSwitchController extends Handler {
            phone.getSignalStrengthController().unregisterForSignalStrengthChanged(this);
            phone.getServiceStateTracker().unregisterForServiceStateChanged(this);
            mPhonesSignalStatus[phoneId].mListeningForEvents = false;
            log("unregisterAllEventsForPhone: unregistered listeners for phone " + phoneId);
        } else {
            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()
                        : dataConfig.getAutoDataSwitchAvailabilityStabilityTimeThreshold());
        mAutoDataSwitchValidationMaxRetry =
                dataConfig.getAutoDataSwitchValidationMaxRetry();
        mAutoDataSwitchValidationMaxRetry = dataConfig.getAutoDataSwitchValidationMaxRetry();
    }

    @Override
@@ -664,7 +743,14 @@ public class AutoDataSwitchController extends Handler {
                ? STABILITY_CHECK_TIMER_MAP.get(STABILITY_CHECK_AVAILABILITY_SWITCH)
                << mAutoSwitchValidationFailedCount
                : 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),
                    delayMs);
        }
+184 −0
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {
            doReturn(mSignalStrength).when(phone).getSignalStrength();
            doReturn(mDataNetworkController).when(phone).getDataNetworkController();
            doReturn(mDataConfigManager).when(mDataNetworkController).getDataConfigManager();
            doReturn(mDataSettingsManager).when(phone).getDataSettingsManager();
            doAnswer(invocation -> phone.getSubId() == mDefaultDataSub)
                    .when(phone).isUserDataEnabled();
        }
@@ -195,6 +196,10 @@ public class AutoDataSwitchControllerTest extends TelephonyTest {
                "mEventsToAlarmListener", Map.class);
        mScheduledEventsToExtras = getPrivateField(mAutoDataSwitchControllerUT,
                "mScheduledEventsToExtras", Map.class);

        clearInvocations(mDisplayInfoController, mSignalStrengthController, mSST);

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

    @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
    public void testRatSignalStrengthSkipEvaluation() {
        // 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
        doReturn(true).when(mPhone2).getDataRoamingEnabled();
        doReturn(true).when(mDataSettingsManager).isDataEnabled();
        mDataEvaluation.addDataAllowedReason(DataEvaluation.DataAllowedReason.NORMAL);

        // 5. No default network