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

Commit 37f4517b authored by Jesse Melhuish's avatar Jesse Melhuish
Browse files

CarrierServiceBindHelper: Add flagged code to reset carrierNetworkChange

by phoneId

When enabled, the CarrierServiceBindHelper will be able to reset the
carrierNetworkChange state by phoneId when subscriptionId is not
present.

Bug: 333571417
Test: atest CtsTelephonyTestCases
Flag: com.android.internal.telephony.flags.cleanup_carrier_network_change_by_phoneid

Change-Id: I1ada8b9e259568cb667bbfc48f555764d911c980
parent bfe3ada6
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -41,3 +41,14 @@ flag {
      purpose: PURPOSE_BUGFIX
    }
}

# OWNER=melhuishj TARGET=25Q3
flag {
    name: "cleanup_carrier_network_change_by_phoneid"
    namespace: "telephony"
    description: "use phoneId to cleanup carrierNetworkChange status when carrier app is lost"
    bug:"333571417"
    metadata {
      purpose: PURPOSE_BUGFIX
    }
}
+14 −7
Original line number Diff line number Diff line
@@ -445,19 +445,26 @@ public class CarrierServiceBindHelper {
        }

        private void maybeDisableCarrierNetworkChangeNotification() {
            TelephonyRegistryManager telephonyRegistryManager =
                    mContext.getSystemService(TelephonyRegistryManager.class);
            // TODO(b/333571417): Consolidate to using the ForPhoneAndSubId variant during cleanup.
            int subscriptionId = SubscriptionManager.getSubscriptionId(mPhoneId);
            // TODO(b/117525047): switch to phoneId-based solution when available in
            // TelephonyRegistryManager to address SIM remove/disable case.
            if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            if (subscriptionId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
                telephonyRegistryManager.notifyCarrierNetworkChange(subscriptionId, false);
                return;
            }

            if (!Flags.cleanupCarrierNetworkChangeByPhoneid()) {
                logdWithLocalLog(
                        "No valid subscription found when trying to disable carrierNetworkChange"
                                + " for phoneId: "
                                + mPhoneId);
                return;
            } else {
                logdWithLocalLog(
                        "Disabling carrierNetworkChange for phoneId: " + mPhoneId);
                telephonyRegistryManager.notifyCarrierNetworkChange(
                        mPhoneId, subscriptionId, false);
            }
            TelephonyRegistryManager telephonyRegistryManager =
                    mContext.getSystemService(TelephonyRegistryManager.class);
            telephonyRegistryManager.notifyCarrierNetworkChange(subscriptionId, false);
        }

        @Override
+116 −43
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.internal.telephony;

import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -150,30 +152,22 @@ public class CarrierServiceBindHelperTest extends TelephonyTest {
        verify(mTelephonyManager, never()).unregisterCarrierPrivilegesCallback(eq(phone0Callback));
    }

    @Test
    public void testCarrierAppConnectionLost_resetsCarrierNetworkChange() {
        if (!Flags.disableCarrierNetworkChangeOnCarrierAppLost()) {
            return;
        }
        // Static test data
        String carrierServicePackageName = "android.test.package.carrier";
    private void setupCarrierServiceMocks(
            String carrierServicePackageName, String carrierServiceClassName) {
        String carrierServiceFullName = carrierServicePackageName + "." + carrierServiceClassName;
        ComponentName carrierServiceComponentName =
                new ComponentName("android.test.package", "carrier");
        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
                ArgumentCaptor.forClass(ServiceConnection.class);
                new ComponentName(carrierServicePackageName, carrierServiceClassName);

        ResolveInfo resolveInfo = new ResolveInfo();
        ServiceInfo serviceInfo = new ServiceInfo();
        serviceInfo.packageName = carrierServicePackageName;
        serviceInfo.name = "carrier";
        serviceInfo.packageName = carrierServiceFullName;
        serviceInfo.name = carrierServiceClassName;
        serviceInfo.metaData = new Bundle();
        serviceInfo.metaData.putBoolean("android.service.carrier.LONG_LIVED_BINDING", true);
        resolveInfo.serviceInfo = serviceInfo;

        // Set up expectations for construction/initialization.
        doReturn(carrierServicePackageName)
        doReturn(carrierServiceFullName)
                .when(mTelephonyManager)
                .getCarrierServicePackageNameForLogicalSlot(PHONE_ID_0);
        doReturn(1).when(mTelephonyManager).getActiveModemCount();
        doReturn(resolveInfo)
                .when(mPackageManager)
                .resolveService(any(), eq(PackageManager.GET_META_DATA));
@@ -181,9 +175,24 @@ public class CarrierServiceBindHelperTest extends TelephonyTest {
        mContextFixture.addService(
                CarrierService.CARRIER_SERVICE_INTERFACE,
                carrierServiceComponentName,
                carrierServicePackageName,
                carrierServiceFullName,
                carrierServiceInterface,
                serviceInfo);
    }

    @Test
    public void testCarrierAppConnectionLost_resetsCarrierNetworkChange_withSubId() {
        if (!Flags.disableCarrierNetworkChangeOnCarrierAppLost()) {
            return;
        }
        setupCarrierServiceMocks("android.test.package", "carrier");
        ComponentName carrierServiceComponentName =
                new ComponentName("android.test.package", "carrier");

        // Set up expectations for construction/initialization.
        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
                ArgumentCaptor.forClass(ServiceConnection.class);
        doReturn(1).when(mTelephonyManager).getActiveModemCount();

        mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext);
        processAllMessages();
@@ -202,43 +211,65 @@ public class CarrierServiceBindHelperTest extends TelephonyTest {

        // Test CarrierService disconnection
        serviceConnection.onServiceDisconnected(carrierServiceComponentName);
        verify(mTelephonyRegistryManager).notifyCarrierNetworkChange(PHONE_ID_0, false);
        verify(mTelephonyRegistryManager).notifyCarrierNetworkChange(
                PHONE_ID_0, false);
        verify(mTelephonyRegistryManager, never())
                .notifyCarrierNetworkChange(PHONE_ID_0, INVALID_SUBSCRIPTION_ID, false);
    }

    @Test
    public void testCarrierAppBindingLost_resetsCarrierNetworkChange() {
    public void testCarrierAppBindingLost_resetsCarrierNetworkChange_withSubId() {
        if (!Flags.disableCarrierNetworkChangeOnCarrierAppLost()) {
            return;
        }
        // Static test data
        String carrierServicePackageName = "android.test.package.carrier";
        setupCarrierServiceMocks("android.test.package", "carrier");
        ComponentName carrierServiceComponentName =
                new ComponentName("android.test.package", "carrier");

        // Set up expectations for construction/initialization.
        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
                ArgumentCaptor.forClass(ServiceConnection.class);
        ResolveInfo resolveInfo = new ResolveInfo();
        ServiceInfo serviceInfo = new ServiceInfo();
        serviceInfo.packageName = carrierServicePackageName;
        serviceInfo.name = "carrier";
        serviceInfo.metaData = new Bundle();
        serviceInfo.metaData.putBoolean("android.service.carrier.LONG_LIVED_BINDING", true);
        resolveInfo.serviceInfo = serviceInfo;
        doReturn(1).when(mTelephonyManager).getActiveModemCount();

        mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext);
        processAllMessages();

        CarrierPrivilegesCallback phoneCallback =
                expectRegisterCarrierPrivilegesCallback(PHONE_ID_0);
        assertNotNull(phoneCallback);
        phoneCallback.onCarrierServiceChanged(null, 0);
        processAllMessages();

        // Grab the ServiceConnection for CarrierService
        verify(mContext)
                .bindService(any(Intent.class), anyInt(), any(), serviceConnectionCaptor.capture());
        ServiceConnection serviceConnection = serviceConnectionCaptor.getAllValues().get(0);
        assertNotNull(serviceConnection);

        // Test CarrierService disconnection
        serviceConnection.onBindingDied(carrierServiceComponentName);
        verify(mTelephonyRegistryManager).notifyCarrierNetworkChange(
                PHONE_ID_0, false);
        verify(mTelephonyRegistryManager, never())
                .notifyCarrierNetworkChange(PHONE_ID_0, INVALID_SUBSCRIPTION_ID, false);
    }

    @Test
    public void testCarrierAppBindingLost_resetsCarrierNetworkChange_withPhoneId() {
        if (!Flags.disableCarrierNetworkChangeOnCarrierAppLost()) {
            return;
        }
        if (!Flags.cleanupCarrierNetworkChangeByPhoneid()) {
            return;
        }
        setupCarrierServiceMocks("android.test.package", "carrier");
        ComponentName carrierServiceComponentName =
                new ComponentName("android.test.package", "carrier");

        // Set up expectations for construction/initialization.
        doReturn(carrierServicePackageName)
                .when(mTelephonyManager)
                .getCarrierServicePackageNameForLogicalSlot(PHONE_ID_0);
        doReturn(1).when(mTelephonyManager).getActiveModemCount();
        doReturn(resolveInfo)
                .when(mPackageManager)
                .resolveService(any(), eq(PackageManager.GET_META_DATA));
        ICarrierService carrierServiceInterface = Mockito.mock(ICarrierService.class);
        mContextFixture.addService(
                CarrierService.CARRIER_SERVICE_INTERFACE,
                carrierServiceComponentName,
                carrierServicePackageName,
                carrierServiceInterface,
                serviceInfo);
        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
                ArgumentCaptor.forClass(ServiceConnection.class);
        Mockito.when(mTelephonyManager.getActiveModemCount()).thenReturn(1).thenReturn(0);

        mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext);
        processAllMessages();
@@ -257,7 +288,49 @@ public class CarrierServiceBindHelperTest extends TelephonyTest {

        // Test CarrierService disconnection
        serviceConnection.onBindingDied(carrierServiceComponentName);
        verify(mTelephonyRegistryManager).notifyCarrierNetworkChange(PHONE_ID_0, false);
        verify(mTelephonyRegistryManager, never()).notifyCarrierNetworkChange(
                PHONE_ID_0, false);
        verify(mTelephonyRegistryManager).notifyCarrierNetworkChange(
                PHONE_ID_0, INVALID_SUBSCRIPTION_ID, false);
    }

    @Test
    public void testCarrierAppConnectionLost_resetsCarrierNetworkChange_withPhoneId() {
        if (!Flags.disableCarrierNetworkChangeOnCarrierAppLost()) {
            return;
        }
        if (!Flags.cleanupCarrierNetworkChangeByPhoneid()) {
            return;
        }
        setupCarrierServiceMocks("android.test.package", "carrier");
        ComponentName carrierServiceComponentName =
                new ComponentName("android.test.package", "carrier");

        // Set up expectations for construction/initialization.
        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
                ArgumentCaptor.forClass(ServiceConnection.class);
        Mockito.when(mTelephonyManager.getActiveModemCount()).thenReturn(1).thenReturn(0);

        mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext);
        processAllMessages();

        CarrierPrivilegesCallback phoneCallback =
                expectRegisterCarrierPrivilegesCallback(PHONE_ID_0);
        assertNotNull(phoneCallback);
        phoneCallback.onCarrierServiceChanged(null, 0);
        processAllMessages();

        // Grab the ServiceConnection for CarrierService
        verify(mContext)
                .bindService(any(Intent.class), anyInt(), any(), serviceConnectionCaptor.capture());
        ServiceConnection serviceConnection = serviceConnectionCaptor.getAllValues().get(0);
        assertNotNull(serviceConnection);

        // Test CarrierService disconnection
        serviceConnection.onServiceDisconnected(carrierServiceComponentName);
        verify(mTelephonyRegistryManager, never()).notifyCarrierNetworkChange(PHONE_ID_0, false);
        verify(mTelephonyRegistryManager).notifyCarrierNetworkChange(
                PHONE_ID_0, INVALID_SUBSCRIPTION_ID, false);
    }
    // TODO (b/232461097): Add UT cases to cover more scenarios (user unlock, SIM state change...)
}
+168 −22
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ public class TelephonyRegistryTest extends TelephonyTest {
    private int mSrvccState = -1;
    private ServiceState mServiceState = null;
    private int mRadioPowerState = RADIO_POWER_UNAVAILABLE;
    private boolean mCarrierNetworkChange = false;
    private int mDataConnectionState = TelephonyManager.DATA_UNKNOWN;
    private int mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
    private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
@@ -206,11 +207,12 @@ public class TelephonyRegistryTest extends TelephonyTest {
                TelephonyCallback.EVENT_OUTGOING_EMERGENCY_SMS);
    }

    public class TelephonyCallbackWrapper extends TelephonyCallback implements
            TelephonyCallback.SrvccStateListener,
    public class TelephonyCallbackWrapper extends TelephonyCallback
            implements TelephonyCallback.SrvccStateListener,
                    TelephonyCallback.PhoneCapabilityListener,
                    TelephonyCallback.ActiveDataSubscriptionIdListener,
                    TelephonyCallback.RadioPowerStateListener,
                    TelephonyCallback.CarrierNetworkListener,
                    TelephonyCallback.PreciseDataConnectionStateListener,
                    TelephonyCallback.DataConnectionStateListener,
                    TelephonyCallback.DisplayInfoListener,
@@ -259,6 +261,13 @@ public class TelephonyRegistryTest extends TelephonyTest {
            invocationCount.incrementAndGet();
            mRadioPowerState = state;
        }

        @Override
        public void onCarrierNetworkChange(boolean active) {
            invocationCount.incrementAndGet();
            mCarrierNetworkChange = active;
        }

        @Override
        public void onPreciseDataConnectionStateChanged(PreciseDataConnectionState preciseState) {
            invocationCount.incrementAndGet();
@@ -502,6 +511,143 @@ public class TelephonyRegistryTest extends TelephonyTest {
        assertEquals(activeSubId, mActiveSubId);
    }

    @Test
    @SmallTest
    public void testCarrierNetworkChangeWithSubId_initialStateIsFalse() {
        int subId = 1;
        doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
        doReturn(0 /*slotIndex*/).when(mMockSubInfo).getSimSlotIndex();
        int[] events = {TelephonyCallback.EVENT_CARRIER_NETWORK_CHANGED};

        mTelephonyRegistry.listenWithEventList(
                false /*renounceFineLocationAccess*/,
                false /*renounceCoarseLocationAccess*/,
                subId,
                mContext.getOpPackageName(),
                mContext.getAttributionTag(),
                mTelephonyCallback.callback,
                events,
                true /*notifyNow*/);

        processAllMessages();
        assertFalse(mCarrierNetworkChange);
    }

    @Test
    @SmallTest
    public void testCarrierNetworkChangeWithSubId_notifyFalse() {
        int subId = 1;
        doReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS)
                .when(mTelephonyManager)
                .getCarrierPrivilegeStatus(anyInt());
        doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
        int phoneId = 0;
        doReturn(phoneId).when(mMockSubInfo).getSimSlotIndex();
        int[] events = {TelephonyCallback.EVENT_CARRIER_NETWORK_CHANGED};

        mTelephonyRegistry.listenWithEventList(
                false /*renounceFineLocationAccess*/,
                false /*renounceCoarseLocationAccess*/,
                subId,
                mContext.getOpPackageName(),
                mContext.getAttributionTag(),
                mTelephonyCallback.callback,
                events,
                true /*notifyNow*/);

        mTelephonyRegistry.notifyCarrierNetworkChangeForPhoneAndSubId(phoneId, subId, false);
        processAllMessages();
        assertFalse(mCarrierNetworkChange);
    }

    @Test
    @SmallTest
    public void testCarrierNetworkChangeWithSubId_notifyTrue() {
        int subId = 1;
        doReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS)
                .when(mTelephonyManager)
                .getCarrierPrivilegeStatus(anyInt());
        doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
        int phoneId = 0;
        doReturn(phoneId).when(mMockSubInfo).getSimSlotIndex();
        int[] events = {TelephonyCallback.EVENT_CARRIER_NETWORK_CHANGED};

        mTelephonyRegistry.listenWithEventList(
                false /*renounceFineLocationAccess*/,
                false /*renounceCoarseLocationAccess*/,
                subId,
                mContext.getOpPackageName(),
                mContext.getAttributionTag(),
                mTelephonyCallback.callback,
                events,
                true /*notifyNow*/);

        mTelephonyRegistry.notifyCarrierNetworkChangeForPhoneAndSubId(phoneId, subId, true);
        processAllMessages();
        assertTrue(mCarrierNetworkChange);
    }

    @Test
    @SmallTest
    public void testCarrierNetworkChangeForPhone_updatesOnRegistration() {
        int subId = 1;
        int phoneId = 0;
        doReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS)
                .when(mTelephonyManager)
                .getCarrierPrivilegeStatus(anyInt());
        doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
        doReturn(phoneId).when(mMockSubInfo).getSimSlotIndex();
        int[] events = {TelephonyCallback.EVENT_CARRIER_NETWORK_CHANGED};

        assertFalse(mCarrierNetworkChange);
        mTelephonyRegistry.notifyCarrierNetworkChangeForPhoneAndSubId(
                phoneId, INVALID_SUBSCRIPTION_ID, true);
        mTelephonyRegistry.listenWithEventList(
                false /*renounceFineLocationAccess*/,
                false /*renounceCoarseLocationAccess*/,
                subId,
                mContext.getOpPackageName(),
                mContext.getAttributionTag(),
                mTelephonyCallback.callback,
                events,
                true /*notifyNow*/);

        processAllMessages();
        assertTrue(mCarrierNetworkChange);
    }

    @Test
    @SmallTest
    public void testCarrierNetworkChangeForPhone_notifiesSubListener() {
        int subId = 1;
        int phoneId = 0;
        doReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS)
                .when(mTelephonyManager)
                .getCarrierPrivilegeStatus(anyInt());
        doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
        doReturn(phoneId).when(mMockSubInfo).getSimSlotIndex();
        int[] events = {TelephonyCallback.EVENT_CARRIER_NETWORK_CHANGED};

        mTelephonyRegistry.listenWithEventList(
                false /*renounceFineLocationAccess*/,
                false /*renounceCoarseLocationAccess*/,
                subId,
                mContext.getOpPackageName(),
                mContext.getAttributionTag(),
                mTelephonyCallback.callback,
                events,
                true /*notifyNow*/);

        mTelephonyRegistry.notifyCarrierNetworkChangeForPhoneAndSubId(phoneId, subId, true);
        processAllMessages();
        assertTrue(mCarrierNetworkChange);

        mTelephonyRegistry.notifyCarrierNetworkChangeForPhoneAndSubId(
                phoneId, INVALID_SUBSCRIPTION_ID, false);
        processAllMessages();
        assertFalse(mCarrierNetworkChange);
    }

    /**
     * Test that we first receive a callback when listen(...) is called that contains the latest
     * notify(...) response and then that the callback is called correctly when notify(...) is