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

Commit 56e1297a authored by SongFerngWang's avatar SongFerngWang
Browse files

Unable to enable the removable esim

When the user enable the removable esim, the settings select wrong
slot(esim slot). The slot shold be the removable + esim slot and the
UiccCardInfo's cardId is the same as the removable esim's cardId.

Bug: 233170453
Bug: 233338345
Test: atest UiccSlotUtilTest
Change-Id: Ibd324b781c84318c994e3742bb82e1d1393b94e4
Merged-In: Ibd324b781c84318c994e3742bb82e1d1393b94e4
parent 887bb592
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -475,7 +475,7 @@ public class SubscriptionUtil {
                .stream()
                .filter(subInfo -> subInfo.getSubscriptionId() == subId)
                .findFirst()
                .get();
                .orElse(null);
    }

    /**
+67 −18
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import android.app.PendingIntent;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.UiccCardInfo;
import android.telephony.UiccPortInfo;
import android.telephony.UiccSlotInfo;
import android.telephony.UiccSlotMapping;
import android.telephony.euicc.EuiccManager;
import android.util.Log;
@@ -28,6 +30,8 @@ import android.util.Log;
import com.android.settings.SidecarFragment;
import com.android.settings.network.telephony.EuiccOperationSidecar;

import com.google.common.collect.ImmutableList;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
@@ -44,6 +48,7 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
    private int mPort;
    private SubscriptionInfo mRemovedSubInfo;
    private boolean mIsDuringSimSlotMapping;
    private List<SubscriptionInfo> mActiveSubInfos;

    /** Returns a SwitchToEuiccSubscriptionSidecar sidecar instance. */
    public static SwitchToEuiccSubscriptionSidecar get(FragmentManager fm) {
@@ -87,6 +92,10 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
        setState(State.RUNNING, Substate.UNUSED);
        mCallbackIntent = createCallbackIntent();
        mSubId = subscriptionId;
        SubscriptionManager subscriptionManager = getContext().getSystemService(
                SubscriptionManager.class);
        mActiveSubInfos = SubscriptionUtil.getActiveSubscriptions(subscriptionManager);

        int targetSlot = getTargetSlot();
        if (targetSlot < 0) {
            Log.d(TAG, "There is no esim, the TargetSlot is " + targetSlot);
@@ -99,15 +108,29 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
        mPort = (port < 0) ? getTargetPortId(targetSlot, removedSubInfo) : port;
        mRemovedSubInfo = removedSubInfo;
        Log.d(TAG,
                String.format("set esim into the SubId%d Slot%d:Port%d",
                String.format("set esim into the SubId%d Physical Slot%d:Port%d",
                        mSubId, targetSlot, mPort));

        if (mTelephonyManager.isMultiSimEnabled() && removedSubInfo != null
                && removedSubInfo.isEmbedded()) {
            // In DSDS mode+MEP, if the replaced esim is active, then it should be disabled esim
            // profile before changing SimSlotMapping process.
            // Use INVALID_SUBSCRIPTION_ID to disable the esim profile.
            // The SimSlotMapping is ready, then to execute activate/inactivate esim.
        if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            // If the subId is INVALID_SUBSCRIPTION_ID, disable the esim (the default esim slot
            // which is selected by the framework).
            switchToSubscription();
        } else if ((mTelephonyManager.isMultiSimEnabled() && removedSubInfo != null
                && removedSubInfo.isEmbedded())
                || isEsimEnabledAtTargetSlotPort(targetSlot, mPort)) {
            // Case1: In DSDS mode+MEP, if the replaced esim is active, then the replaced esim
            // should be disabled before changing SimSlotMapping process.
            //
            // Case2: If the user enables the esimA on the target slot:port and the target
            // slot:port is active and there is an active esimB on target slot:port, then the
            // settings disables the esimB before the settings enables the esimA on the
            // target slot:port.
            //
            // Step:
            // 1. disables the replaced esim.
            // 2. switches the SimSlotMapping if the target slot port is not active.
            // 3. enables the target esim.
            // Note: Use INVALID_SUBSCRIPTION_ID to disable the esim profile.
            Log.d(TAG, "disable the enabled esim before the settings enables the target esim");
            mIsDuringSimSlotMapping = true;
            mEuiccManager.switchToSubscription(SubscriptionManager.INVALID_SUBSCRIPTION_ID, mPort,
                    mCallbackIntent);
@@ -117,8 +140,8 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
    }

    private int getTargetPortId(int physicalEsimSlotIndex, SubscriptionInfo removedSubInfo) {
        if (!isMultipleEnabledProfilesSupported()) {
            Log.d(TAG, "The device is no MEP, port is 0");
        if (!isMultipleEnabledProfilesSupported(physicalEsimSlotIndex)) {
            Log.d(TAG, "The slotId" + physicalEsimSlotIndex + " is no MEP, port is 0");
            return 0;
        }

@@ -150,11 +173,12 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
        // port is 0.

        int port = 0;
        SubscriptionManager subscriptionManager = getContext().getSystemService(
                SubscriptionManager.class);
        if(mActiveSubInfos == null){
            Log.d(TAG, "mActiveSubInfos is null.");
            return port;
        }
        List<SubscriptionInfo> activeEsimSubInfos =
                SubscriptionUtil.getActiveSubscriptions(subscriptionManager)
                        .stream()
                mActiveSubInfos.stream()
                        .filter(i -> i.isEmbedded())
                        .sorted(Comparator.comparingInt(SubscriptionInfo::getPortIndex))
                        .collect(Collectors.toList());
@@ -167,7 +191,31 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
    }

    private int getTargetSlot() {
        return UiccSlotUtil.getEsimSlotId(getContext());
        return UiccSlotUtil.getEsimSlotId(getContext(), mSubId);
    }

    private boolean isEsimEnabledAtTargetSlotPort(int physicalSlotIndex, int portIndex) {
        int logicalSlotId = getLogicalSlotIndex(physicalSlotIndex, portIndex);
        if (logicalSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
            return false;
        }
        return mActiveSubInfos != null
                && mActiveSubInfos.stream()
                .anyMatch(i -> i.isEmbedded() && i.getSimSlotIndex() == logicalSlotId);
    }

    private int getLogicalSlotIndex(int physicalSlotIndex, int portIndex) {
        ImmutableList<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(mTelephonyManager);
        if (slotInfos != null && physicalSlotIndex >= 0 && physicalSlotIndex < slotInfos.size()
                && slotInfos.get(physicalSlotIndex) != null) {
            for (UiccPortInfo portInfo : slotInfos.get(physicalSlotIndex).getPorts()) {
                if (portInfo.getPortIndex() == portIndex) {
                    return portInfo.getLogicalSlotIndex();
                }
            }
        }

        return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
    }

    private void onSwitchSlotSidecarStateChange() {
@@ -185,14 +233,15 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
        }
    }

    private boolean isMultipleEnabledProfilesSupported() {
    private boolean isMultipleEnabledProfilesSupported(int physicalEsimSlotIndex) {
        List<UiccCardInfo> cardInfos = mTelephonyManager.getUiccCardsInfo();
        if (cardInfos == null) {
            Log.w(TAG, "UICC cards info list is empty.");
            return false;
        }
        return cardInfos.stream().anyMatch(
                cardInfo -> cardInfo.isMultipleEnabledProfilesSupported());
        return cardInfos.stream()
                .anyMatch(cardInfo -> cardInfo.getPhysicalSlotIndex() == physicalEsimSlotIndex
                        && cardInfo.isMultipleEnabledProfilesSupported());
    }

    private void switchToSubscription() {
+22 −1
Original line number Diff line number Diff line
@@ -22,11 +22,13 @@ import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccCardInfo;
import android.telephony.UiccSlotInfo;
import android.telephony.UiccSlotMapping;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.uicc.UiccController;
import com.android.settingslib.utils.ThreadUtils;

import com.google.common.collect.ImmutableList;
@@ -36,6 +38,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -183,9 +186,27 @@ public class UiccSlotUtil {
     * @param context the application context.
     * @return the esim slot. If the value is -1, there is not the esim.
     */
    public static int getEsimSlotId(Context context) {
    public static int getEsimSlotId(Context context, int subId) {
        TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
        List<UiccCardInfo> uiccCardInfos = telMgr.getUiccCardsInfo();
        ImmutableList<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(telMgr);
        SubscriptionManager subscriptionManager = context.getSystemService(
                SubscriptionManager.class);
        SubscriptionInfo subInfo = SubscriptionUtil.getSubById(subscriptionManager, subId);

        // checking whether this is the removable esim. If it is, then return the removable slot id.
        if (subInfo != null && subInfo.isEmbedded()) {
            for (UiccCardInfo uiccCardInfo : uiccCardInfos) {
                if (uiccCardInfo.getCardId() == subInfo.getCardId()
                        && uiccCardInfo.getCardId() > TelephonyManager.UNSUPPORTED_CARD_ID
                        && uiccCardInfo.isEuicc()
                        && uiccCardInfo.isRemovable()) {
                    Log.d(TAG, "getEsimSlotId: This subInfo is removable esim.");
                    return uiccCardInfo.getPhysicalSlotIndex();
                }
            }
        }

        int firstEsimSlot = IntStream.range(0, slotInfos.size())
                .filter(
                        index -> {
+69 −8
Original line number Diff line number Diff line
@@ -25,7 +25,9 @@ import static org.mockito.Mockito.when;

import android.content.Context;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccCardInfo;
import android.telephony.UiccPortInfo;
import android.telephony.UiccSlotInfo;
import android.telephony.UiccSlotMapping;
@@ -53,16 +55,24 @@ public class UiccSlotUtilTest {
    private Context mContext;
    @Mock
    private TelephonyManager mTelephonyManager;
    @Mock
    private SubscriptionManager mSubscriptionManager;

    private static final int ESIM_PHYSICAL_SLOT = 0;
    private static final int PSIM_PHYSICAL_SLOT = 1;

    private List<SubscriptionInfo> mSubscriptionInfoList = new ArrayList<>();
    private List<UiccCardInfo> mUiccCardInfo = new ArrayList<>();
    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);

        mContext = spy(ApplicationProvider.getApplicationContext());
        when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
        when(mTelephonyManager.getUiccCardsInfo()).thenReturn(mUiccCardInfo);

        when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
        when(mSubscriptionManager.getAllSubscriptionInfoList()).thenReturn(mSubscriptionInfoList);
    }

    @Test
@@ -88,15 +98,35 @@ public class UiccSlotUtilTest {
    public void getEsimSlotId_twoSimSlotsDeviceAndEsimIsSlot0_returnTheCorrectEsimSlot() {
        when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
                twoSimSlotsDeviceActiveEsimActivePsim());
        int testSlot = UiccSlotUtil.getEsimSlotId(mContext);
        int testSlot = UiccSlotUtil.getEsimSlotId(mContext,0);

        assertThat(testSlot).isEqualTo(0);
    }

    @Test
    public void getEsimSlotId_simIsRemovableEsimAndRemovableEsimIsSlot1_returnRemovableEsimSlot1() {
        int subId = 0;
        int cardId = 0;
        mSubscriptionInfoList.add(createSubscriptionInfo(subId,-1, -1, true, cardId));
        mUiccCardInfo.add(createUiccCardInfo(true, 3, 0, false, -1, -1));
        mUiccCardInfo.add(createUiccCardInfo(true, cardId, 1, true, -1, -1));
        when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
                twoSimSlotsDeviceActiveEsimActiveRemovableEsim());
        int testSlot = UiccSlotUtil.getEsimSlotId(mContext, subId);

        assertThat(testSlot).isEqualTo(1);
    }

    @Test
    public void getEsimSlotId_twoSimSlotsDeviceAndRemovableEsimIsSlot1_returnTheCorrectEsimSlot() {
    public void getEsimSlotId_simIsRemovableEsimAndTwoRemovableSlots_returnRemovableEsimSlot1() {
        int subId = 0;
        int cardId = 0;
        mSubscriptionInfoList.add(createSubscriptionInfo(subId,-1, -1, true, cardId));
        mUiccCardInfo.add(createUiccCardInfo(false, 4, 0, true, -1, -1));
        mUiccCardInfo.add(createUiccCardInfo(true, cardId, 1, true, -1, -1));
        when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
                twoSimSlotsDeviceActivePsimActiveRemovableEsim());
        int testSlot = UiccSlotUtil.getEsimSlotId(mContext);
        int testSlot = UiccSlotUtil.getEsimSlotId(mContext, subId);

        assertThat(testSlot).isEqualTo(1);
    }
@@ -105,7 +135,7 @@ public class UiccSlotUtilTest {
    public void getEsimSlotId_twoSimSlotsDeviceAndEsimIsSlot1_returnTheCorrectEsimSlot() {
        when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
                twoSimSlotsDeviceActivePsimActiveEsim());
        int testSlot = UiccSlotUtil.getEsimSlotId(mContext);
        int testSlot = UiccSlotUtil.getEsimSlotId(mContext,0);

        assertThat(testSlot).isEqualTo(1);
    }
@@ -114,7 +144,7 @@ public class UiccSlotUtilTest {
    public void getEsimSlotId_noEimSlotDevice_returnTheCorrectEsimSlot() {
        when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
                oneSimSlotDeviceActivePsim());
        int testSlot = UiccSlotUtil.getEsimSlotId(mContext);
        int testSlot = UiccSlotUtil.getEsimSlotId(mContext,0);

        assertThat(testSlot).isEqualTo(-1);
    }
@@ -620,13 +650,38 @@ public class UiccSlotUtilTest {
    }

    private SubscriptionInfo createSubscriptionInfo(int logicalSlotIndex, int portIndex) {
        return createSubscriptionInfo(0, logicalSlotIndex, portIndex, true, 25);
    }

    private SubscriptionInfo createSubscriptionInfo(int subId, int logicalSlotIndex, int portIndex,
            boolean isEmbedded, int cardId) {
        return new SubscriptionInfo(
                0, "", logicalSlotIndex, "", "", 0, 0, "", 0, null, "", "", "",
                true /* isEmbedded */,
                null, "", 25,
                subId, "",
                logicalSlotIndex, "", "", 0, 0, "", 0, null, "", "", "",
                isEmbedded /* isEmbedded */,
                null, "",
                cardId,
                false, null, false, 0, 0, 0, null, null, true, portIndex);
    }

    private UiccCardInfo createUiccCardInfo(boolean isEuicc, int cardId, int physicalSlotIndex,
            boolean isRemovable, int logicalSlotIndex, int portIndex) {
        return new UiccCardInfo(
                isEuicc /* isEuicc */,
                cardId /* cardId */,
                null /* eid */,
                physicalSlotIndex /* physicalSlotIndex */,
                isRemovable /* isRemovable */,
                false /* isMultipleEnabledProfileSupported */,
                Collections.singletonList(
                        new UiccPortInfo(
                                "123451234567890" /* iccId */,
                                portIndex /* portIdx */,
                                logicalSlotIndex /* logicalSlotIdx */,
                                true /* isActive */)
                ));
    }

    private List<SubscriptionInfo> createActiveSubscriptionInfoListOneSim(int logicalSlotIndex,
            int portIndex) {
        List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>();
@@ -737,6 +792,12 @@ public class UiccSlotUtilTest {
                createUiccSlotInfo(true, false, 1, true)};
    }

    private UiccSlotInfo[] twoSimSlotsDeviceActiveEsimActiveRemovableEsim() {
        return new UiccSlotInfo[]{
                createUiccSlotInfo(true, false, 0, true),
                createUiccSlotInfo(true, true, 1, true)};
    }

    private UiccSlotInfo[] twoSimSlotsDeviceActivePsimActiveRemovableEsim() {
        return new UiccSlotInfo[]{
                createUiccSlotInfo(false, true, 0, true),