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

Commit 55ad74c1 authored by Jack Yu's avatar Jack Yu
Browse files

Fixed eSIM switch issue

When switching between eSIM profile, there will not be
SIM absent event. We need to mark the previous active
subscription inactive to prevent both old and new subscriptions
active.

Fix: 269429990
Test: atest SubscriptionManagerServiceTest
Test: Basic phone functionality test
Change-Id: I9ca6562659a426dbf5ba324118b9f4bb14512f3b
parent d5210a5d
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -729,6 +729,7 @@ public class SubscriptionDatabaseManager extends Handler {
        if (uri != null && uri.getLastPathSegment() != null) {
            int subId = Integer.parseInt(uri.getLastPathSegment());
            if (SubscriptionManager.isValidSubscriptionId(subId)) {
                logv("insertNewRecordIntoDatabaseSync: contentValues=" + contentValues);
                logl("insertNewRecordIntoDatabaseSync: Successfully added subscription. subId="
                        + uri.getLastPathSegment());
                return subId;
@@ -1836,6 +1837,8 @@ public class SubscriptionDatabaseManager extends Handler {

                logl("Loaded " + mAllSubscriptionInfoInternalCache.size()
                        + " records from the subscription database.");
                mAllSubscriptionInfoInternalCache.forEach(
                        (subId, subInfo) -> log("  " + subInfo.toString()));
            } finally {
                mReadWriteLock.writeLock().unlock();
            }
+13 −1
Original line number Diff line number Diff line
@@ -923,7 +923,6 @@ public class SubscriptionManagerService extends ISub.Stub {
                .forEach(subInfo -> {
                    mSubscriptionDatabaseManager.setSimSlotIndex(subInfo.getSubscriptionId(),
                            SubscriptionManager.INVALID_SIM_SLOT_INDEX);
                    mSlotIndexToSubId.remove(simSlotIndex);
                });
        updateGroupDisabled();
        logl("markSubscriptionsInactive: " + slotMappingToString());
@@ -1268,6 +1267,19 @@ public class SubscriptionManagerService extends ISub.Stub {
        }

        String iccId = getIccId(phoneId);
        log("updateSubscriptions: Found iccId=" + SubscriptionInfo.givePrintableIccid(iccId)
                + " on phone " + phoneId);

        // For eSIM switching, SIM absent will not happen. Below is to exam if we find ICCID
        // mismatch on the SIM slot, we need to mark all subscriptions on that logical slot invalid
        // first. The correct subscription will be assigned the correct slot later.
        if (mSubscriptionDatabaseManager.getAllSubscriptions().stream()
                .anyMatch(subInfo -> subInfo.getSimSlotIndex() == phoneId
                        && !iccId.equals(subInfo.getIccId()))) {
            log("updateSubscriptions: iccId changed for phone " + phoneId);
            markSubscriptionsInactive(phoneId);
        }

        if (!TextUtils.isEmpty(iccId)) {
            // Check if the subscription already existed.
            SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
+2 −0
Original line number Diff line number Diff line
@@ -355,6 +355,8 @@ public class SubscriptionDatabaseManagerTest extends TelephonyTest {
    public void setUp() throws Exception {
        logd("SubscriptionDatabaseManagerTest +Setup!");
        super.setUp(getClass().getSimpleName());
        mContextFixture.putBooleanResource(com.android.internal.R.bool
                .config_subscription_database_async_update, true);
        mSubscriptionDatabaseManagerCallback =
                Mockito.mock(SubscriptionDatabaseManagerCallback.class);
        doAnswer(invocation -> {
+55 −10
Original line number Diff line number Diff line
@@ -144,7 +144,8 @@ public class SubscriptionManagerServiceTest extends TelephonyTest {
    public void setUp() throws Exception {
        logd("SubscriptionManagerServiceTest +Setup!");
        super.setUp(getClass().getSimpleName());

        mContextFixture.putBooleanResource(com.android.internal.R.bool
                .config_subscription_database_async_update, true);
        mContextFixture.putIntArrayResource(com.android.internal.R.array.sim_colors, new int[0]);

        mContextFixture.addSystemFeature(PackageManager.FEATURE_TELEPHONY_EUICC);
@@ -158,6 +159,7 @@ public class SubscriptionManagerServiceTest extends TelephonyTest {
                SubscriptionManagerServiceCallback.class);
        doReturn(FAKE_ICCID1).when(mUiccCard).getCardId();
        doReturn(FAKE_ICCID1).when(mUiccPort).getIccId();
        doReturn(true).when(mUiccSlot).isActive();

        doReturn(new int[0]).when(mSubscriptionManager).getCompleteActiveSubscriptionIdList();

@@ -167,6 +169,7 @@ public class SubscriptionManagerServiceTest extends TelephonyTest {
        mSubscriptionManagerServiceUT = new SubscriptionManagerService(mContext, Looper.myLooper());

        monitorTestableLooper(new TestableLooper(getBackgroundHandler().getLooper()));
        monitorTestableLooper(new TestableLooper(getSubscriptionDatabaseManager().getLooper()));

        doAnswer(invocation -> {
            ((Runnable) invocation.getArguments()[0]).run();
@@ -211,6 +214,13 @@ public class SubscriptionManagerServiceTest extends TelephonyTest {
        return (Handler) field.get(mSubscriptionManagerServiceUT);
    }

    private SubscriptionDatabaseManager getSubscriptionDatabaseManager() throws Exception {
        Field field = SubscriptionManagerService.class.getDeclaredField(
                "mSubscriptionDatabaseManager");
        field.setAccessible(true);
        return (SubscriptionDatabaseManager) field.get(mSubscriptionManagerServiceUT);
    }

    /**
     * Insert the subscription info to the database.
     *
@@ -222,21 +232,14 @@ public class SubscriptionManagerServiceTest extends TelephonyTest {
            mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
            subInfo = new SubscriptionInfoInternal.Builder(subInfo)
                    .setId(SubscriptionManager.INVALID_SUBSCRIPTION_ID).build();

            Field field = SubscriptionManagerService.class.getDeclaredField(
                    "mSubscriptionDatabaseManager");
            field.setAccessible(true);
            SubscriptionDatabaseManager sdbm =
                    (SubscriptionDatabaseManager) field.get(mSubscriptionManagerServiceUT);

            int subId = sdbm.insertSubscriptionInfo(subInfo);
            int subId = getSubscriptionDatabaseManager().insertSubscriptionInfo(subInfo);

            // Insertion is sync, but the onSubscriptionChanged callback is handled by the handler.
            processAllMessages();

            Class<?> WatchedMapClass = Class.forName("com.android.internal.telephony.subscription"
                    + ".SubscriptionManagerService$WatchedMap");
            field = SubscriptionManagerService.class.getDeclaredField("mSlotIndexToSubId");
            Field field = SubscriptionManagerService.class.getDeclaredField("mSlotIndexToSubId");
            field.setAccessible(true);
            Object map = field.get(mSubscriptionManagerServiceUT);
            Class[] cArgs = new Class[2];
@@ -1858,4 +1861,46 @@ public class SubscriptionManagerServiceTest extends TelephonyTest {
        // The original eSIM becomes removed pSIM ¯\_(ツ)_/¯
        assertThat(mSubscriptionManagerServiceUT.getSubscriptionInfo(2).isEmbedded()).isFalse();
    }

    @Test
    public void testEsimSwitch() {
        setIdentifierAccess(true);
        mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
        insertSubscription(FAKE_SUBSCRIPTION_INFO1);

        EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID2)
                .setIccid(FAKE_ICCID2)
                .setNickname(FAKE_CARRIER_NAME2)
                .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
                .setCarrierIdentifier(new CarrierIdentifier(FAKE_MCC2, FAKE_MNC2, null, null, null,
                        null, FAKE_CARRIER_ID2, FAKE_CARRIER_ID2))
                .setUiccAccessRule(Arrays.asList(UiccAccessRule.decodeRules(
                        FAKE_NATIVE_ACCESS_RULES2)))
                .build();

        GetEuiccProfileInfoListResult result = new GetEuiccProfileInfoListResult(
                EuiccService.RESULT_OK, new EuiccProfileInfo[]{profileInfo1}, false);
        doReturn(result).when(mEuiccController).blockingGetEuiccProfileInfoList(eq(1));
        doReturn(FAKE_ICCID2).when(mUiccCard).getCardId();
        doReturn(FAKE_ICCID2).when(mUiccController).convertToCardString(eq(1));
        doReturn(FAKE_ICCID2).when(mUiccPort).getIccId();

        mSubscriptionManagerServiceUT.updateEmbeddedSubscriptions(List.of(1), null);
        processAllMessages();

        mSubscriptionManagerServiceUT.updateSimState(
                0, TelephonyManager.SIM_STATE_READY, null, null);
        processAllMessages();

        mSubscriptionManagerServiceUT.updateSimState(
                0, TelephonyManager.SIM_STATE_LOADED, null, null);
        processAllMessages();

        List<SubscriptionInfo> subInfoList = mSubscriptionManagerServiceUT
                .getActiveSubscriptionInfoList(CALLING_PACKAGE, CALLING_FEATURE);

        assertThat(subInfoList).hasSize(1);
        assertThat(subInfoList.get(0).isActive()).isTrue();
        assertThat(subInfoList.get(0).getIccId()).isEqualTo(FAKE_ICCID2);
    }
}