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

Commit cdd84b30 authored by Malcolm Chen's avatar Malcolm Chen
Browse files

Fix bug that disabled pSIM stays inactive after unplugging.

The expected behavior is, for inactive pSIMs, once unplugged, we
mark uicc applications back to true. In handleSimAbsent we failed to
do that as by clearing the subinfo with phoneId, as disabled subInfo
doesn't have phoneId associated with it already.

Bug: 155985091
Test: manual unittest
Change-Id: Idf5be434882ed8e03064b72b9114442217401c46
parent 9e11310f
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ public class SubscriptionInfoUpdater extends Handler {
    @UnsupportedAppUsage

    protected static String[] sIccId = new String[SUPPORTED_MODEM_COUNT];
    private static String[] sInactiveIccIds = new String[SUPPORTED_MODEM_COUNT];
    private static int[] sSimCardState = new int[SUPPORTED_MODEM_COUNT];
    private static int[] sSimApplicationState = new int[SUPPORTED_MODEM_COUNT];
    private static boolean sIsSubInfoInitialized = false;
@@ -427,7 +428,12 @@ public class SubscriptionInfoUpdater extends Handler {
        boolean isFinalState = false;

        IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard();
        if (iccCard.isEmptyProfile() || areUiccAppsDisabledOnCard(phoneId)) {
        boolean uiccAppsDisabled = areUiccAppsDisabledOnCard(phoneId);
        if (iccCard.isEmptyProfile() || uiccAppsDisabled) {
            if (uiccAppsDisabled) {
                UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId);
                sInactiveIccIds[phoneId] = IccUtils.stripTrailingFs(slot.getIccId());
            }
            isFinalState = true;
            // ICC_NOT_READY is a terminal state for
            // 1) It's an empty profile as there's no uicc applications. Or
@@ -607,9 +613,9 @@ public class SubscriptionInfoUpdater extends Handler {
     * It could be INVALID if it was already inactive.
     */
    private void handleInactiveSlotIccStateChange(int phoneId, String iccId) {
        // If phoneId is valid, it means the physical slot was active in that phoneId. In this case,
        // we clear (mark inactive) the subscription in db on that phone.
        if (SubscriptionManager.isValidPhoneId(phoneId)) {
            // If phoneId is valid, it means the physical slot was previously active in that
            // phoneId. In this case, found the subId and set its phoneId to invalid.
            if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
                logd("Slot of SIM" + (phoneId + 1) + " becomes inactive");
            }
@@ -628,14 +634,16 @@ public class SubscriptionInfoUpdater extends Handler {

    private void cleanSubscriptionInPhone(int phoneId) {
        sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM;
        int[] subIds = SubscriptionController.getInstance().getSubId(phoneId);
        if (subIds != null && subIds.length > 0) {
        if (sInactiveIccIds[phoneId] != null) {
            // When a SIM is unplugged, mark uicc applications enabled. This is to make sure when
            // user unplugs and re-inserts the SIM card, we re-enable it.
            logd("cleanSubscriptionInPhone " + phoneId + " inactive iccid "
                    + sInactiveIccIds[phoneId]);
            ContentValues value = new ContentValues(1);
            value.put(SubscriptionManager.UICC_APPLICATIONS_ENABLED, true);
            sContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value,
                    SubscriptionController.getSelectionForSubIdList(subIds), null);
                    SubscriptionManager.ICC_ID + "=\'" + sInactiveIccIds[phoneId] + "\'", null);
            sInactiveIccIds[phoneId] = null;
        }
        updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
    }
+39 −7
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@
 */
package com.android.internal.telephony;

import static android.telephony.SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID;
import static android.telephony.SubscriptionManager.UICC_APPLICATIONS_ENABLED;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -192,12 +192,6 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
        verify(mConfigManager).updateConfigForPhoneId(eq(FAKE_SUB_ID_1),
                eq(IccCardConstants.INTENT_VALUE_ICC_ABSENT));
        verify(mSubscriptionController, times(1)).notifySubscriptionInfoChanged();
        ArgumentCaptor<ContentValues> valueCapture = ArgumentCaptor.forClass(ContentValues.class);
        verify(mContentProvider).update(any(), valueCapture.capture(),
                eq(UNIQUE_KEY_SUBSCRIPTION_ID + " IN (" + FAKE_SUB_ID_1 + ")"), any());
        boolean uiccApplicationsEnabled = valueCapture.getValue()
                .getAsBoolean(SubscriptionManager.UICC_APPLICATIONS_ENABLED);
        assertTrue(uiccApplicationsEnabled);
    }

    @Test
@@ -280,6 +274,44 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
                eq(IccCardConstants.INTENT_VALUE_ICC_NOT_READY));
    }

    @Test
    @SmallTest
    public void testSimNotReadyDisabledUiccApps() throws Exception {
        String iccId = "123456";
        doReturn(mIccCard).when(mPhone).getIccCard();
        doReturn(false).when(mIccCard).isEmptyProfile();
        doReturn(iccId).when(mUiccSlot).getIccId();
        doReturn(mSubInfo).when(mSubscriptionController).getSubInfoForIccId(iccId);
        doReturn(false).when(mSubInfo).areUiccApplicationsEnabled();

        mUpdater.updateInternalIccState(
                IccCardConstants.INTENT_VALUE_ICC_NOT_READY, null, FAKE_SUB_ID_1);

        processAllMessages();
        assertTrue(mUpdater.isSubInfoInitialized());
        // Sub info should be cleared and change should be notified.
        verify(mSubscriptionController).clearSubInfoRecord(eq(FAKE_SUB_ID_1));
        verify(mSubscriptionController).notifySubscriptionInfoChanged();
        // No new sub should be added.
        verify(mSubscriptionManager, never()).addSubscriptionInfoRecord(any(), anyInt());
        verify(mSubscriptionContent, never()).put(anyString(), any());
        CarrierConfigManager mConfigManager = (CarrierConfigManager)
                mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
        verify(mConfigManager).updateConfigForPhoneId(eq(FAKE_SUB_ID_1),
                eq(IccCardConstants.INTENT_VALUE_ICC_NOT_READY));

        // When becomes ABSENT, UICC_APPLICATIONS_ENABLED should be reset to true.
        mUpdater.updateInternalIccState(
                IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, FAKE_SUB_ID_1);
        processAllMessages();
        ArgumentCaptor<ContentValues> valueCapture = ArgumentCaptor.forClass(ContentValues.class);
        verify(mContentProvider).update(eq(SubscriptionManager.CONTENT_URI), valueCapture.capture(),
                eq(SubscriptionManager.ICC_ID + "=\'" + iccId + "\'"), eq(null));
        ContentValues contentValues = valueCapture.getValue();
        assertTrue(contentValues != null && contentValues.getAsBoolean(
                UICC_APPLICATIONS_ENABLED));
    }

    @Test
    @SmallTest
    public void testSimError() throws Exception {