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

Commit 13647d75 authored by Wei Huang's avatar Wei Huang Committed by Beverly Tai
Browse files

Fix SystemUI mapping SIM state error issue



KeyguardUpdateMonitor#SimData#simState is updated from telephony
broadcast whose action is Intent#ACTION_SIM_STATE_CHANGED,
but the sim state mapping is inconsistent with telephony design.

Below are the telephony design of broadcast extra(SIM state and reason)
mapping matrix for action Intent#ACTION_SIM_STATE_CHANGED:
1. SIM card state unknown:
   a) Intent#EXTRA_SIM_STATE: Intent#SIM_STATE_UNKNOWN
   b) Intent#EXTRA_SIM_LOCKED_REASON: always null
2. SIM absent:
   a) Intent#EXTRA_SIM_STATE: Intent#SIM_STATE_ABSENT
   b) Intent#EXTRA_SIM_LOCKED_REASON: always null
3. SIM IO error three consecutive times:
   a) Intent#EXTRA_SIM_STATE: Intent#SIM_STATE_CARD_IO_ERROR
   b) Intent#EXTRA_SIM_LOCKED_REASON: Intent#SIM_STATE_CARD_IO_ERROR
4. SIM card is present but not usable due to carrier restrictions:
   a) Intent#EXTRA_SIM_STATE: Intent#SIM_STATE_CARD_RESTRICTED
   b) Intent#EXTRA_SIM_LOCKED_REASON: Intent#SIM_STATE_CARD_RESTRICTED
5. SIM locked:
   a) Intent#EXTRA_SIM_STATE: Intent#SIM_STATE_LOCKED
   b) Intent#EXTRA_SIM_LOCKED_REASON:
      - locked on PIN1: Intent#SIM_LOCKED_ON_PIN
      - locked on PUK1: Intent#SIM_LOCKED_ON_PUK
      - locked on network personalization: Intent#SIM_LOCKED_NETWORK
      - permanently disabled due to puk fails:
        Intent#SIM_ABSENT_ON_PERM_DISABLED
6. SIM applications are not ready:
   a) Intent#EXTRA_SIM_STATE: Intent#SIM_STATE_NOT_READY
   b) Intent#EXTRA_SIM_LOCKED_REASON: always null
7. SIM IMSI is ready in property, but currently it is never broadcasted:
   a) Intent#EXTRA_SIM_STATE: Intent#SIM_STATE_IMSI
   b) Intent#EXTRA_SIM_LOCKED_REASON: always null
8. SIM all applications are ready:
   a) Intent#EXTRA_SIM_STATE: Intent#SIM_STATE_READY
   b) Intent#EXTRA_SIM_LOCKED_REASON: always null
9. SIM all ICC records, including IMSI, are loaded:
   a) Intent#EXTRA_SIM_STATE: Intent#SIM_STATE_LOADED
   b) Intent#EXTRA_SIM_LOCKED_REASON: always null

Based on above, this patch fixes below points:
1. Upate KeyguardUpdateMonitor#SimData#fromIntent sim state, which
   follows telephony design.
2. Update CarrierTextManager#getStatusForIccState
   a) network locked mapping: TelephonyManager#SIM_STATE_NETWORK_LOCKED
      to CarrierTextManager#StatusMode#NetworkLocked.
   b) adds missed state CarrierTextManager#StatusMode#SimRestricted.
3. Add related automated unit tests to verify code logic

Bug: 265564214
Bug: 265440217
Test: Build and manual test on device.
Test: atest CarrierTextManagerTest KeyguardUpdateMonitorTest
Change-Id: I76eff7a66f2dac6f87072501dc6654e48c105e02
Signed-off-by: default avatarWei Huang <hwbest.v@gmail.com>
Signed-off-by: default avatarHonggang Luo <luo.loky@gmail.com>
Signed-off-by: default avatarChao Yuan <chaoyuanx@gmail.com>
parent 28227a3e
Loading
Loading
Loading
Loading
+15 −10
Original line number Diff line number Diff line
@@ -148,7 +148,8 @@ public class CarrierTextManager {
    /**
     * The status of this lock screen. Primarily used for widgets on LockScreen.
     */
    private enum StatusMode {
    @VisibleForTesting
    protected enum StatusMode {
        Normal, // Normal case (sim card present, it's not locked)
        NetworkLocked, // SIM card is 'network locked'.
        SimMissing, // SIM card is missing.
@@ -158,6 +159,7 @@ public class CarrierTextManager {
        SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure
        SimNotReady, // SIM is not ready yet. May never be on devices w/o a SIM.
        SimIoError, // SIM card is faulty
        SimRestricted, // SIM Card restricted, present but not usable due to carrier restrictions.
        SimUnknown // SIM card is unknown
    }

@@ -493,6 +495,7 @@ public class CarrierTextManager {
                        getContext().getText(R.string.keyguard_sim_error_message_short),
                        text);
                break;
            case SimRestricted: // fall through
            case SimUnknown:
                carrierText = null;
                break;
@@ -535,19 +538,19 @@ public class CarrierTextManager {
    /**
     * Determine the current status of the lock screen given the SIM state and other stuff.
     */
    private CarrierTextManager.StatusMode getStatusForIccState(int simState) {
        final boolean missingAndNotProvisioned =
                !mKeyguardUpdateMonitor.isDeviceProvisioned()
    @VisibleForTesting
    protected CarrierTextManager.StatusMode getStatusForIccState(int simState) {
        if (!mKeyguardUpdateMonitor.isDeviceProvisioned()
                && (simState == TelephonyManager.SIM_STATE_ABSENT
                        || simState == TelephonyManager.SIM_STATE_PERM_DISABLED);
                        || simState == TelephonyManager.SIM_STATE_PERM_DISABLED)) {
            return CarrierTextManager.StatusMode.SimMissingLocked;
        }

        // Assume we're NETWORK_LOCKED if not provisioned
        simState = missingAndNotProvisioned ? TelephonyManager.SIM_STATE_NETWORK_LOCKED : simState;
        switch (simState) {
            case TelephonyManager.SIM_STATE_ABSENT:
                return CarrierTextManager.StatusMode.SimMissing;
            case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
                return CarrierTextManager.StatusMode.SimMissingLocked;
                return CarrierTextManager.StatusMode.NetworkLocked;
            case TelephonyManager.SIM_STATE_NOT_READY:
                return CarrierTextManager.StatusMode.SimNotReady;
            case TelephonyManager.SIM_STATE_PIN_REQUIRED:
@@ -562,6 +565,8 @@ public class CarrierTextManager {
                return CarrierTextManager.StatusMode.SimUnknown;
            case TelephonyManager.SIM_STATE_CARD_IO_ERROR:
                return CarrierTextManager.StatusMode.SimIoError;
            case TelephonyManager.SIM_STATE_CARD_RESTRICTED:
                return CarrierTextManager.StatusMode.SimRestricted;
        }
        return CarrierTextManager.StatusMode.SimUnknown;
    }
+50 −22
Original line number Diff line number Diff line
@@ -2045,11 +2045,47 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    private final HashMap<Integer, Boolean> mIsUnlockWithFingerprintPossible = new HashMap<>();

    /**
     * When we receive a
     * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
     * When we receive a {@link android.content.Intent#ACTION_SIM_STATE_CHANGED} broadcast,
     * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
     * we need a single object to pass to the handler.  This class helps decode
     * the intent and provide a {@link SimData} result.
     *
     * Below is the Sim state mapping matrixs:
     * +---+-----------------------------------------------------+----------------------------+
     * |   |Telephony FWK broadcast with action                  |SystemUI mapping SIM state  |
     * |   |android.content.Intent#ACTION_SIM_STATE_CHANGED      |refer to android.telephony. |
     * |NO.+-------------------------+---------------------------+TelephonyManager#getSimState|
     * |   |EXTRA_SIM_STATE          |EXTRA_SIM_LOCKED_REASON    |                            |
     * |   |(Intent#XXX)             |(Intent#XXX)               |TelephonyManager#SimState   |
     * +===+=====================================================+============================+
     * |1  |SIM_STATE_UNKNOWN        |always null                |SIM_STATE_UNKNOWN           |
     * +---+-------------------------+---------------------------+----------------------------+
     * |2  |SIM_STATE_ABSENT         |always null                |SIM_STATE_ABSENT            |
     * +---+-------------------------+---------------------------+----------------------------+
     * |3  |SIM_STATE_CARD_IO_ERROR  |SIM_STATE_CARD_IO_ERROR    |SIM_STATE_CARD_IO_ERROR     |
     * +---+-------------------------+---------------------------+----------------------------+
     * |4  |SIM_STATE_CARD_RESTRICTED|SIM_STATE_CARD_RESTRICTED  |SIM_STATE_CARD_RESTRICTED   |
     * +---+-------------------------+---------------------------+----------------------------+
     * |5  |SIM_STATE_LOCKED         |SIM_LOCKED_ON_PIN          |SIM_STATE_PIN_REQUIRED      |
     * +---+-------------------------+---------------------------+----------------------------+
     * |6  |SIM_STATE_LOCKED         |SIM_LOCKED_ON_PUK          |SIM_STATE_PUK_REQUIRED      |
     * +---+-------------------------+---------------------------+----------------------------+
     * |7  |SIM_STATE_LOCKED         |SIM_LOCKED_NETWORK         |SIM_STATE_NETWORK_LOCKED    |
     * +---+-------------------------+---------------------------+----------------------------+
     * |8  |SIM_STATE_LOCKED         |SIM_ABSENT_ON_PERM_DISABLED|SIM_STATE_PERM_DISABLED     |
     * +---+-------------------------+---------------------------+----------------------------+
     * |9  |SIM_STATE_NOT_READY      |always null                |SIM_STATE_NOT_READY         |
     * +---+-------------------------+---------------------------+----------------------------+
     * |10 |SIM_STATE_IMSI           |always null                |SIM_STATE_READY             |
     * +---+-------------------------+---------------------------+----------------------------+
     * |11 |SIM_STATE_READY          |always null                |SIM_STATE_READY             |
     * +---+-------------------------+---------------------------+----------------------------+
     * |12 |SIM_STATE_LOADED         |always null                |SIM_STATE_READY             |
     * +---+-------------------------+---------------------------+----------------------------+
     *
     * Note that, it seems #10 imsi ready case(i.e. SIM_STATE_IMSI) is never triggered from
     * Android Pie(telephony FWK doesn't trigger this broadcast any more), but it is still
     * OK keep this mapping logic.
     */
    private static class SimData {
        public int simState;
@@ -2063,26 +2099,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        }

        static SimData fromIntent(Intent intent) {
            int state;
            if (!Intent.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
                throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
            }
            int state = TelephonyManager.SIM_STATE_UNKNOWN;
            String stateExtra = intent.getStringExtra(Intent.EXTRA_SIM_STATE);
            int slotId = intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0);
            int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
                    SubscriptionManager.INVALID_SUBSCRIPTION_ID);
            if (Intent.SIM_STATE_ABSENT.equals(stateExtra)) {
                final String absentReason = intent
                        .getStringExtra(Intent.EXTRA_SIM_LOCKED_REASON);

                if (Intent.SIM_ABSENT_ON_PERM_DISABLED.equals(
                        absentReason)) {
                    state = TelephonyManager.SIM_STATE_PERM_DISABLED;
                } else {
                state = TelephonyManager.SIM_STATE_ABSENT;
                }
            } else if (Intent.SIM_STATE_READY.equals(stateExtra)) {
                state = TelephonyManager.SIM_STATE_READY;
            } else if (Intent.SIM_STATE_LOCKED.equals(stateExtra)) {
                final String lockedReason = intent
                        .getStringExtra(Intent.EXTRA_SIM_LOCKED_REASON);
@@ -2090,22 +2116,24 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
                    state = TelephonyManager.SIM_STATE_PIN_REQUIRED;
                } else if (Intent.SIM_LOCKED_ON_PUK.equals(lockedReason)) {
                    state = TelephonyManager.SIM_STATE_PUK_REQUIRED;
                } else if (Intent.SIM_LOCKED_NETWORK.equals(lockedReason)) {
                    state = TelephonyManager.SIM_STATE_NETWORK_LOCKED;
                } else if (Intent.SIM_ABSENT_ON_PERM_DISABLED.equals(lockedReason)) {
                    state = TelephonyManager.SIM_STATE_PERM_DISABLED;
                } else {
                    state = TelephonyManager.SIM_STATE_UNKNOWN;
                }
            } else if (Intent.SIM_LOCKED_NETWORK.equals(stateExtra)) {
                state = TelephonyManager.SIM_STATE_NETWORK_LOCKED;
            } else if (Intent.SIM_STATE_CARD_IO_ERROR.equals(stateExtra)) {
                state = TelephonyManager.SIM_STATE_CARD_IO_ERROR;
            } else if (Intent.SIM_STATE_LOADED.equals(stateExtra)
            } else if (Intent.SIM_STATE_CARD_RESTRICTED.equals(stateExtra)) {
                state = TelephonyManager.SIM_STATE_CARD_RESTRICTED;
            } else if (Intent.SIM_STATE_NOT_READY.equals(stateExtra)) {
                state = TelephonyManager.SIM_STATE_NOT_READY;
            } else if (Intent.SIM_STATE_READY.equals(stateExtra)
                    || Intent.SIM_STATE_LOADED.equals(stateExtra)
                    || Intent.SIM_STATE_IMSI.equals(stateExtra)) {
                // This is required because telephony doesn't return to "READY" after
                // Mapping SIM_STATE_LOADED and SIM_STATE_IMSI to SIM_STATE_READY is required
                // because telephony doesn't return to "READY" after
                // these state transitions. See bug 7197471.
                state = TelephonyManager.SIM_STATE_READY;
            } else {
                state = TelephonyManager.SIM_STATE_UNKNOWN;
            }
            return new SimData(state, slotId, subId);
        }
+60 −0
Original line number Diff line number Diff line
@@ -561,6 +561,66 @@ public class CarrierTextManagerTest extends SysuiTestCase {
                captor.getValue().carrierText);
    }

    @Test
    public void testGetStatusForIccState() {
        when(mKeyguardUpdateMonitor.isDeviceProvisioned()).thenReturn(false);
        assertEquals(CarrierTextManager.StatusMode.SimMissingLocked,
                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_ABSENT));
        assertEquals(CarrierTextManager.StatusMode.NetworkLocked,
                mCarrierTextManager.getStatusForIccState(
                        TelephonyManager.SIM_STATE_NETWORK_LOCKED));
        assertEquals(CarrierTextManager.StatusMode.SimNotReady,
                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_NOT_READY));
        assertEquals(CarrierTextManager.StatusMode.SimLocked,
                mCarrierTextManager.getStatusForIccState(
                        TelephonyManager.SIM_STATE_PIN_REQUIRED));
        assertEquals(CarrierTextManager.StatusMode.SimPukLocked,
                mCarrierTextManager.getStatusForIccState(
                        TelephonyManager.SIM_STATE_PUK_REQUIRED));
        assertEquals(CarrierTextManager.StatusMode.Normal,
                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_READY));
        assertEquals(CarrierTextManager.StatusMode.SimMissingLocked,
                mCarrierTextManager.getStatusForIccState(
                        TelephonyManager.SIM_STATE_PERM_DISABLED));
        assertEquals(CarrierTextManager.StatusMode.SimUnknown,
                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_UNKNOWN));
        assertEquals(CarrierTextManager.StatusMode.SimIoError,
                mCarrierTextManager.getStatusForIccState(
                        TelephonyManager.SIM_STATE_CARD_IO_ERROR));
        assertEquals(CarrierTextManager.StatusMode.SimRestricted,
                mCarrierTextManager.getStatusForIccState(
                        TelephonyManager.SIM_STATE_CARD_RESTRICTED));

        when(mKeyguardUpdateMonitor.isDeviceProvisioned()).thenReturn(true);
        assertEquals(CarrierTextManager.StatusMode.SimMissing,
                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_ABSENT));
        assertEquals(CarrierTextManager.StatusMode.NetworkLocked,
                mCarrierTextManager.getStatusForIccState(
                        TelephonyManager.SIM_STATE_NETWORK_LOCKED));
        assertEquals(CarrierTextManager.StatusMode.SimNotReady,
                mCarrierTextManager.getStatusForIccState(
                        TelephonyManager.SIM_STATE_NOT_READY));
        assertEquals(CarrierTextManager.StatusMode.SimLocked,
                mCarrierTextManager.getStatusForIccState(
                        TelephonyManager.SIM_STATE_PIN_REQUIRED));
        assertEquals(CarrierTextManager.StatusMode.SimPukLocked,
                mCarrierTextManager.getStatusForIccState(
                        TelephonyManager.SIM_STATE_PUK_REQUIRED));
        assertEquals(CarrierTextManager.StatusMode.Normal,
                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_READY));
        assertEquals(CarrierTextManager.StatusMode.SimPermDisabled,
                mCarrierTextManager.getStatusForIccState(
                        TelephonyManager.SIM_STATE_PERM_DISABLED));
        assertEquals(CarrierTextManager.StatusMode.SimUnknown,
                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_UNKNOWN));
        assertEquals(CarrierTextManager.StatusMode.SimIoError,
                mCarrierTextManager.getStatusForIccState(
                        TelephonyManager.SIM_STATE_CARD_IO_ERROR));
        assertEquals(CarrierTextManager.StatusMode.SimRestricted,
                mCarrierTextManager.getStatusForIccState(
                        TelephonyManager.SIM_STATE_CARD_RESTRICTED));
    }

    private Context getContextSpyForStickyBroadcast(Intent returnVal) {
        Context contextSpy = spy(mContext);
        doReturn(returnVal).when(contextSpy).registerReceiver(eq(null), any(IntentFilter.class));
+131 −0
Original line number Diff line number Diff line
@@ -167,6 +167,7 @@ import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -671,6 +672,130 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        verify(mTestCallback, times(2)).onRefreshCarrierInfo();
    }

    @Test
    public void testHandleSimStateChange_Unknown() {
        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);
        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_UNKNOWN);
        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
                putPhoneInfo(intent, null, false));
        mTestableLooper.processAllMessages();
        Assert.assertEquals(TelephonyManager.SIM_STATE_UNKNOWN,
                mKeyguardUpdateMonitor.getCachedSimState());
    }

    @Test
    public void testHandleSimStateChange_Absent() {
        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);
        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_ABSENT);
        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
                putPhoneInfo(intent, null, false));
        mTestableLooper.processAllMessages();
        Assert.assertEquals(TelephonyManager.SIM_STATE_ABSENT,
                mKeyguardUpdateMonitor.getCachedSimState());
    }

    @Test
    public void testHandleSimStateChange_CardIOError() {
        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);
        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_CARD_IO_ERROR);
        intent.putExtra(Intent.EXTRA_SIM_LOCKED_REASON, Intent.SIM_STATE_CARD_IO_ERROR);
        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
                putPhoneInfo(intent, null, false));
        mTestableLooper.processAllMessages();
        Assert.assertEquals(TelephonyManager.SIM_STATE_CARD_IO_ERROR,
                mKeyguardUpdateMonitor.getCachedSimState());
    }

    @Test
    public void testHandleSimStateChange_CardRestricted() {
        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);
        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_CARD_RESTRICTED);
        intent.putExtra(Intent.EXTRA_SIM_LOCKED_REASON, Intent.SIM_STATE_CARD_RESTRICTED);
        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
                putPhoneInfo(intent, null, false));
        mTestableLooper.processAllMessages();
        Assert.assertEquals(TelephonyManager.SIM_STATE_CARD_RESTRICTED,
                mKeyguardUpdateMonitor.getCachedSimState());
    }

    @Test
    public void testHandleSimStateChange_Locked() {
        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);
        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_LOCKED);

        // locked on PIN1
        intent.putExtra(Intent.EXTRA_SIM_LOCKED_REASON, Intent.SIM_LOCKED_ON_PIN);
        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
                putPhoneInfo(intent, null, true));
        mTestableLooper.processAllMessages();
        Assert.assertEquals(TelephonyManager.SIM_STATE_PIN_REQUIRED,
                mKeyguardUpdateMonitor.getCachedSimState());

        // locked on PUK1
        intent.putExtra(Intent.EXTRA_SIM_LOCKED_REASON, Intent.SIM_LOCKED_ON_PUK);
        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
                putPhoneInfo(intent, null, true));
        mTestableLooper.processAllMessages();
        Assert.assertEquals(TelephonyManager.SIM_STATE_PUK_REQUIRED,
                mKeyguardUpdateMonitor.getCachedSimState());

        // locked on network personalization
        intent.putExtra(Intent.EXTRA_SIM_LOCKED_REASON, Intent.SIM_LOCKED_NETWORK);
        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
                putPhoneInfo(intent, null, true));
        mTestableLooper.processAllMessages();
        Assert.assertEquals(TelephonyManager.SIM_STATE_NETWORK_LOCKED,
                mKeyguardUpdateMonitor.getCachedSimState());

        // permanently disabled due to puk fails
        intent.putExtra(Intent.EXTRA_SIM_LOCKED_REASON, Intent.SIM_ABSENT_ON_PERM_DISABLED);
        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
                putPhoneInfo(intent, null, true));
        mTestableLooper.processAllMessages();
        Assert.assertEquals(TelephonyManager.SIM_STATE_PERM_DISABLED,
                mKeyguardUpdateMonitor.getCachedSimState());
    }

    @Test
    public void testHandleSimStateChange_NotReady() {
        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);
        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_NOT_READY);
        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
                putPhoneInfo(intent, null, false));
        mTestableLooper.processAllMessages();
        Assert.assertEquals(TelephonyManager.SIM_STATE_NOT_READY,
                mKeyguardUpdateMonitor.getCachedSimState());
    }

    @Test
    public void testHandleSimStateChange_Ready() {
        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);

        // ICC IMSI is ready in property
        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_IMSI);
        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
                putPhoneInfo(intent, null, false));
        mTestableLooper.processAllMessages();
        Assert.assertEquals(TelephonyManager.SIM_STATE_READY,
                mKeyguardUpdateMonitor.getCachedSimState());

        // ICC is ready to access
        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_READY);
        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
                putPhoneInfo(intent, null, false));
        mTestableLooper.processAllMessages();
        Assert.assertEquals(TelephonyManager.SIM_STATE_READY,
                mKeyguardUpdateMonitor.getCachedSimState());

        // all ICC records, including IMSI, are loaded
        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_LOADED);
        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
                putPhoneInfo(intent, null, true));
        mTestableLooper.processAllMessages();
        Assert.assertEquals(TelephonyManager.SIM_STATE_READY,
                mKeyguardUpdateMonitor.getCachedSimState());
    }

    @Test
    public void testTriesToAuthenticateFingerprint_whenKeyguard() {
        mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
@@ -3122,6 +3247,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {

    private class TestableKeyguardUpdateMonitor extends KeyguardUpdateMonitor {
        AtomicBoolean mSimStateChanged = new AtomicBoolean(false);
        AtomicInteger mCachedSimState = new AtomicInteger(-1);

        protected TestableKeyguardUpdateMonitor(Context context) {
            super(context, mUserTracker,
@@ -3144,9 +3270,14 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
            return mSimStateChanged.getAndSet(false);
        }

        public int getCachedSimState() {
            return mCachedSimState.getAndSet(-1);
        }

        @Override
        protected void handleSimStateChange(int subId, int slotId, int state) {
            mSimStateChanged.set(true);
            mCachedSimState.set(state);
            super.handleSimStateChange(subId, slotId, state);
        }