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

Commit 80a8a630 authored by junyulai's avatar junyulai
Browse files

Skip RAT type listener registration if IMSI is not available

Currently, if SIM is inserted but IMSI is not available, such
as SIM PIN locked state. Information of such SIM will still
be available but IMSI is not. Which makes
NetworkStatsSubscriptionMonitor failed to store IMSI locally
for later RAT type query. Hence, NETWORK_TYPE_UNKNOWN is
always returned for such SIM.

Skip the registration until the IMSI is available. This is safe
since there will be another onSubscriptionsChanged event when
that happens.

Test: enable SIM PIN and manually test
Test: atest NetworkStatsSubscriptionsMonitorTest#testSubscriberIdUnavailable
Test: ./out/host/linux-x86/bin/statsd_testdrive 10082
Bug: 160941101
Change-Id: I408379b3c432d9e62e0837d6b4f6551cc7838e29
parent 5fed70ab
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -100,11 +100,16 @@ public class NetworkStatsSubscriptionsMonitor extends
            if (match != null) continue;

            // Create listener for every newly added sub. Also store subscriberId into it to
            // prevent binder call to telephony when querying RAT.
            // prevent binder call to telephony when querying RAT. If the subscriberId is empty
            // for any reason, such as SIM PIN locked, skip registration.
            // SubscriberId will be unavailable again if 1. modem crashed 2. reboot
            // 3. re-insert SIM. If that happens, the listeners will be eventually synchronized
            // with active sub list once all subscriberIds are ready.
            final String subscriberId = mTeleManager.getSubscriberId(subId);
            if (TextUtils.isEmpty(subscriberId)) {
                Log.wtf(NetworkStatsService.TAG,
                        "Empty subscriberId for newly added sub: " + subId);
                Log.d(NetworkStatsService.TAG, "Empty subscriberId for newly added sub "
                        + subId + ", skip listener registration");
                continue;
            }
            final RatTypeListener listener =
                    new RatTypeListener(mExecutor, this, subId, subscriberId);
@@ -113,6 +118,7 @@ public class NetworkStatsSubscriptionsMonitor extends
            // Register listener to the telephony manager that associated with specific sub.
            mTeleManager.createForSubscriptionId(subId)
                    .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE);
            Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + subId);
        }

        for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
@@ -165,6 +171,7 @@ public class NetworkStatsSubscriptionsMonitor extends
    private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) {
        mTeleManager.createForSubscriptionId(listener.mSubId)
                .listen(listener, PhoneStateListener.LISTEN_NONE);
        Log.d(NetworkStatsService.TAG, "RAT type listener unregistered for sub " + listener.mSubId);
        mRatListeners.remove(listener);

        // Removal of subscriptions doesn't generate RAT changed event, fire it for every
+56 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.net.NetworkTemplate;
import android.os.test.TestLooper;
@@ -135,6 +136,11 @@ public final class NetworkStatsSubscriptionsMonitorTest {
        mMonitor.onSubscriptionsChanged();
    }

    private void updateSubscriberIdForTestSub(int subId, @Nullable final String subscriberId) {
        when(mTelephonyManager.getSubscriberId(subId)).thenReturn(subscriberId);
        mMonitor.onSubscriptionsChanged();
    }

    private void removeTestSub(int subId) {
        // Remove subId from TestSubList.
        mTestSubList.removeIf(it -> it == subId);
@@ -268,4 +274,54 @@ public final class NetworkStatsSubscriptionsMonitorTest {
        listener.onServiceStateChanged(serviceState);
        assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR);
    }

    @Test
    public void testSubscriberIdUnavailable() {
        final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor =
                ArgumentCaptor.forClass(RatTypeListener.class);

        mMonitor.start();
        // Insert sim1, set subscriberId to null which is normal in SIM PIN locked case.
        // Verify RAT type is NETWORK_TYPE_UNKNOWN and service will not perform listener
        // registration.
        addTestSub(TEST_SUBID1, null);
        verify(mTelephonyManager, never()).listen(any(), anyInt());
        assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);

        // Set IMSI for sim1, verify the listener will be registered.
        updateSubscriberIdForTestSub(TEST_SUBID1, TEST_IMSI1);
        verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(),
                eq(PhoneStateListener.LISTEN_SERVICE_STATE));
        reset(mTelephonyManager);
        when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);

        // Set RAT type of sim1 to UMTS. Verify RAT type of sim1 is changed.
        setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
                TelephonyManager.NETWORK_TYPE_UMTS);
        assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
        reset(mDelegate);

        // Set IMSI to null again to simulate somehow IMSI is not available, such as
        // modem crash. Verify service should not unregister listener.
        updateSubscriberIdForTestSub(TEST_SUBID1, null);
        verify(mTelephonyManager, never()).listen(any(), anyInt());
        assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
        reset(mDelegate);

        // Set RAT type of sim1 to LTE. Verify RAT type of sim1 is still changed even if the IMSI
        // is not available. The monitor keeps the listener even if the IMSI disappears because
        // the IMSI can never change for any given subId, therefore even if the IMSI is updated
        // to null, the monitor should continue accepting updates of the RAT type. However,
        // telephony is never actually supposed to do this, if the IMSI disappears there should
        // not be updates, but it's still the right thing to do theoretically.
        setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
                TelephonyManager.NETWORK_TYPE_LTE);
        assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_LTE);
        reset(mDelegate);

        mMonitor.stop();
        verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor.getValue()),
                eq(PhoneStateListener.LISTEN_NONE));
        assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
    }
}