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

Commit dc652e24 authored by Amit Mahajan's avatar Amit Mahajan
Browse files

Determine the state to be broadcast in just one place.

Earlier it was done in multiple places leading to corner cases
and unexpected states.

Test: basic telephony sanity
Bug: 72513243
Change-Id: I129a9f69e523db8f11901f40a37164fb7ebf5282
parent df844ef5
Loading
Loading
Loading
Loading
+95 −90
Original line number Diff line number Diff line
@@ -222,56 +222,15 @@ public class UiccProfile extends Handler implements IccCard {
            return;
        }
        switch (msg.what) {
            case EVENT_NETWORK_LOCKED:
                mNetworkLockedRegistrants.notifyRegistrants();
                // intentional fall through
            case EVENT_RADIO_OFF_OR_UNAVAILABLE:
                updateExternalState();
                break;

            case EVENT_ICC_LOCKED:
                processLockedState();
                break;

            case EVENT_APP_READY:
                if (VDBG) log("EVENT_APP_READY");
                if (areAllApplicationsReady()) {
                    if (areAllRecordsLoaded() && areCarrierPriviligeRulesLoaded()) {
                        setExternalState(IccCardConstants.State.LOADED);
                    } else {
                        setExternalState(IccCardConstants.State.READY);
                    }
                }
                break;

            case EVENT_RECORDS_LOADED:
                if (VDBG) log("EVENT_RECORDS_LOADED");
                if (!areAllRecordsLoaded()) {
                    break;
                }
                // Update the MCC/MNC.
                if (mIccRecords != null) {
                    String operator = mIccRecords.getOperatorNumeric();
                    log("operator=" + operator + " mPhoneId=" + mPhoneId);

                    if (!TextUtils.isEmpty(operator)) {
                        mTelephonyManager.setSimOperatorNumericForPhone(mPhoneId, operator);
                        String countryCode = operator.substring(0, 3);
                        if (countryCode != null) {
                            mTelephonyManager.setSimCountryIsoForPhone(mPhoneId,
                                    MccTable.countryCodeForMcc(Integer.parseInt(countryCode)));
                        } else {
                            loge("EVENT_RECORDS_LOADED Country code is null");
                        }
                    } else {
                        loge("EVENT_RECORDS_LOADED Operator name is null");
                    }
                }
                if (areCarrierPriviligeRulesLoaded()) {
                    setExternalState(IccCardConstants.State.LOADED);
                }
                break;

            case EVENT_NETWORK_LOCKED:
                mNetworkLockedRegistrants.notifyRegistrants();
                setExternalState(IccCardConstants.State.NETWORK_LOCKED);
                if (VDBG) log("handleMessage: Received " + msg.what);
                updateExternalState();
                break;

            case EVENT_ICC_RECORD_EVENTS:
@@ -288,9 +247,7 @@ public class UiccProfile extends Handler implements IccCard {
            case EVENT_CARRIER_PRIVILEGES_LOADED:
                if (VDBG) log("EVENT_CARRIER_PRIVILEGES_LOADED");
                onCarrierPriviligesLoadedMessage();
                if (areAllRecordsLoaded()) {
                    setExternalState(IccCardConstants.State.LOADED);
                }
                updateExternalState();
                break;

            case EVENT_OPEN_LOGICAL_CHANNEL_DONE:
@@ -348,7 +305,7 @@ public class UiccProfile extends Handler implements IccCard {
    }

    private void updateExternalState() {

        // First check if card state is IO_ERROR or RESTRICTED
        if (mUiccCard.getCardState() == IccCardStatus.CardState.CARDSTATE_ERROR) {
            setExternalState(IccCardConstants.State.CARD_IO_ERROR);
            return;
@@ -359,13 +316,65 @@ public class UiccProfile extends Handler implements IccCard {
            return;
        }

        if (mUiccApplication == null || !areAllApplicationsReady()) {
        // By process of elimination, the UICC Card State = PRESENT and state needs to be decided
        // based on apps
        if (mUiccApplication == null) {
            loge("updateExternalState: setting state to NOT_READY because mUiccApplication is "
                    + "null");
            setExternalState(IccCardConstants.State.NOT_READY);
            return;
        }

        // Check if SIM is locked
        boolean cardLocked = false;
        IccCardConstants.State lockedState = null;
        IccCardApplicationStatus.AppState appState = mUiccApplication.getState();

        PinState pin1State = mUiccApplication.getPin1State();
        if (pin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) {
            if (VDBG) log("updateExternalState: PERM_DISABLED");
            cardLocked = true;
            lockedState = IccCardConstants.State.PERM_DISABLED;
        } else {
            if (appState == IccCardApplicationStatus.AppState.APPSTATE_PIN) {
                if (VDBG) log("updateExternalState: PIN_REQUIRED");
                cardLocked = true;
                lockedState = IccCardConstants.State.PIN_REQUIRED;
            } else if (appState == IccCardApplicationStatus.AppState.APPSTATE_PUK) {
                if (VDBG) log("updateExternalState: PUK_REQUIRED");
                cardLocked = true;
                lockedState = IccCardConstants.State.PUK_REQUIRED;
            } else if (appState == IccCardApplicationStatus.AppState.APPSTATE_SUBSCRIPTION_PERSO) {
                if (mUiccApplication.getPersoSubState()
                        == IccCardApplicationStatus.PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {
                    if (VDBG) log("updateExternalState: PERSOSUBSTATE_SIM_NETWORK");
                    cardLocked = true;
                    lockedState = IccCardConstants.State.NETWORK_LOCKED;
                }
            }
        }

        // If SIM is locked, broadcast state as NOT_READY/LOCKED depending on if records are loaded
        if (cardLocked) {
            if (mIccRecords != null && (mIccRecords.getLockedRecordsLoaded()
                    || mIccRecords.getNetworkLockedRecordsLoaded())) { // locked records loaded
                if (VDBG) {
                    log("updateExternalState: card locked and records loaded; "
                            + "setting state to locked");
                }
                setExternalState(lockedState);
            } else {
                if (VDBG) {
                    log("updateExternalState: card locked but records not loaded; "
                            + "setting state to NOT_READY");
                }
                setExternalState(IccCardConstants.State.NOT_READY);
            }
            return;
        }

        // By process of elimination, the UICC Card State = PRESENT
        switch (mUiccApplication.getState()) {
        // Check for remaining app states
        switch (appState) {
            case APPSTATE_UNKNOWN:
                /*
                 * APPSTATE_UNKNOWN is a catch-all state reported whenever the app
@@ -377,23 +386,29 @@ public class UiccProfile extends Handler implements IccCard {
                 * 2) There is no valid App on the SIM to load, which can be the case with an
                 *    eSIM/soft SIM.
                 */
                setExternalState(IccCardConstants.State.NOT_READY);
                break;
            case APPSTATE_SUBSCRIPTION_PERSO:
                if (mUiccApplication.getPersoSubState()
                        == IccCardApplicationStatus.PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {
                    setExternalState(IccCardConstants.State.NETWORK_LOCKED);
                if (VDBG) {
                    log("updateExternalState: app state is unknown; setting state to NOT_READY");
                }
                // Otherwise don't change external SIM state.
                setExternalState(IccCardConstants.State.NOT_READY);
                break;
            case APPSTATE_READY:
                if (areAllApplicationsReady()) {
                    if (areAllRecordsLoaded() && areCarrierPriviligeRulesLoaded()) {
                        if (VDBG) log("updateExternalState: setting state to LOADED");
                        setExternalState(IccCardConstants.State.LOADED);
                    } else {
                        if (VDBG) {
                            log("updateExternalState: setting state to READY; records loaded "
                                    + areAllRecordsLoaded() + ", carrier privilige rules loaded "
                                    + areCarrierPriviligeRulesLoaded());
                        }
                        setExternalState(IccCardConstants.State.READY);
                    }
                } else {
                    if (VDBG) {
                        log("updateExternalState: app state is READY but not for all apps; "
                                + "setting state to NOT_READY");
                    }
                    setExternalState(IccCardConstants.State.NOT_READY);
                }
                break;
@@ -471,41 +486,31 @@ public class UiccProfile extends Handler implements IccCard {
                return;
            }
            mExternalState = newState;
            log("setExternalState: set mPhoneId=" + mPhoneId + " mExternalState=" + mExternalState);
            mTelephonyManager.setSimStateForPhone(mPhoneId, getState().toString());
            if (mExternalState == IccCardConstants.State.LOADED) {
                // Update the MCC/MNC.
                if (mIccRecords != null) {
                    String operator = mIccRecords.getOperatorNumeric();
                    log("operator=" + operator + " mPhoneId=" + mPhoneId);

            broadcastInternalIccStateChangedIntent(getIccStateIntentString(mExternalState),
                    getIccStateReason(mExternalState));
                    if (!TextUtils.isEmpty(operator)) {
                        mTelephonyManager.setSimOperatorNumericForPhone(mPhoneId, operator);
                        String countryCode = operator.substring(0, 3);
                        if (countryCode != null) {
                            mTelephonyManager.setSimCountryIsoForPhone(mPhoneId,
                                    MccTable.countryCodeForMcc(Integer.parseInt(countryCode)));
                        } else {
                            loge("EVENT_RECORDS_LOADED Country code is null");
                        }
                    } else {
                        loge("EVENT_RECORDS_LOADED Operator name is null");
                    }

    private void processLockedState() {
        synchronized (mLock) {
            if (mUiccApplication == null) {
                //Don't need to do anything if non-existent application is locked
                return;
                }
            PinState pin1State = mUiccApplication.getPin1State();
            if (pin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) {
                setExternalState(IccCardConstants.State.PERM_DISABLED);
                return;
            }
            log("setExternalState: set mPhoneId=" + mPhoneId + " mExternalState=" + mExternalState);
            mTelephonyManager.setSimStateForPhone(mPhoneId, getState().toString());

            IccCardApplicationStatus.AppState appState = mUiccApplication.getState();
            switch (appState) {
                case APPSTATE_PIN:
                    setExternalState(IccCardConstants.State.PIN_REQUIRED);
                    break;
                case APPSTATE_PUK:
                    setExternalState(IccCardConstants.State.PUK_REQUIRED);
                    break;
                case APPSTATE_DETECTED:
                case APPSTATE_READY:
                case APPSTATE_SUBSCRIPTION_PERSO:
                case APPSTATE_UNKNOWN:
                    // Neither required
                    break;
            }
            broadcastInternalIccStateChangedIntent(getIccStateIntentString(mExternalState),
                    getIccStateReason(mExternalState));
        }
    }

+8 −25
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@
package com.android.internal.telephony.uicc;

import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -33,7 +32,6 @@ import android.os.HandlerThread;
import android.os.Message;
import android.test.suitebuilder.annotation.SmallTest;

import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.cat.CatService;
@@ -52,8 +50,6 @@ public class UiccProfileTest extends TelephonyTest {
    }

    private IccIoResult mIccIoResult;
    // Must match UiccProfile.EVENT_RADIO_ON
    private static final int EVENT_RADIO_ON = 2;
    // Must match UiccProfile.EVENT_APP_READY
    private static final int EVENT_APP_READY = 6;
    private static final int SCARY_SLEEP_MS = 200;
@@ -252,20 +248,9 @@ public class UiccProfileTest extends TelephonyTest {
        assertEquals(mUiccProfile.getState(), State.NOT_READY);
    }

    @Test
    @SmallTest
    public void testPowerOn() {
        mSimulatedCommands.setRadioPower(true, null);
        mUiccProfile.sendMessage(mUiccProfile.obtainMessage(EVENT_RADIO_ON));
        waitForMs(SCARY_SLEEP_MS);
        assertEquals(CommandsInterface.RadioState.RADIO_ON, mSimulatedCommands.getRadioState());
        assertEquals(mUiccProfile.getState(), State.NOT_READY);
    }

    @Test
    @SmallTest
    public void testUpdateUiccProfileApplicationNotReady() {
        mUiccProfile.sendMessage(mUiccProfile.obtainMessage(EVENT_RADIO_ON));
        /* update app status and index */
        IccCardApplicationStatus cdmaApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_CSIM,
@@ -298,7 +283,6 @@ public class UiccProfileTest extends TelephonyTest {
    @Test
    @SmallTest
    public void testUpdateUiccProfileApplicationAllReady() {
        mUiccProfile.sendMessage(mUiccProfile.obtainMessage(EVENT_RADIO_ON));
        /* update app status and index */
        IccCardApplicationStatus cdmaApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_CSIM,
@@ -333,21 +317,20 @@ public class UiccProfileTest extends TelephonyTest {
    @Test
    @SmallTest
    public void testUpdateUiccProfileApplicationAllSupportedAppsReady() {
        mUiccProfile.sendMessage(mUiccProfile.obtainMessage(EVENT_RADIO_ON));
        /* update app status and index */
        IccCardApplicationStatus cdmaApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_CSIM,
                IccCardApplicationStatus.AppState.APPSTATE_READY, "0xA0");
        IccCardApplicationStatus umtsApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_USIM,
                IccCardApplicationStatus.AppState.APPSTATE_READY, "0xA2");
        IccCardApplicationStatus imsApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_ISIM,
                IccCardApplicationStatus.AppState.APPSTATE_READY, "0xA1");
        IccCardApplicationStatus umtsApp = composeUiccApplicationStatus(
        IccCardApplicationStatus unknownApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_UNKNOWN,
                IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA2");
        mIccCardStatus.mApplications = new IccCardApplicationStatus[]{cdmaApp, imsApp, umtsApp};
        mIccCardStatus.mCdmaSubscriptionAppIndex = 0;
        mIccCardStatus.mImsSubscriptionAppIndex = 1;
        mIccCardStatus.mGsmUmtsSubscriptionAppIndex = 2;
        mIccCardStatus.mApplications = new IccCardApplicationStatus[]{imsApp, umtsApp, unknownApp};
        mIccCardStatus.mCdmaSubscriptionAppIndex = -1;
        mIccCardStatus.mImsSubscriptionAppIndex = 0;
        mIccCardStatus.mGsmUmtsSubscriptionAppIndex = 1;
        Message mProfileUpdate = mHandler.obtainMessage(UICCPROFILE_UPDATE_APPLICATION_EVENT);
        setReady(false);
        mProfileUpdate.sendToTarget();