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

Commit 4d389357 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge changes from topics "MEP_addPortIndex", "mep_switchToSubscription" am:...

Merge changes from topics "MEP_addPortIndex", "mep_switchToSubscription" am: b9f93b22 am: 458f1763

Original change: https://android-review.googlesource.com/c/platform/frameworks/opt/telephony/+/2042786



Change-Id: I5e29c3651924fa6fd2087daf438733ec9ac7bb43
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 31097775 458f1763
Loading
Loading
Loading
Loading
+216 −13
Original line number Original line Diff line number Diff line
@@ -57,6 +57,7 @@ import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;
import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.telephony.uicc.UiccPort;
import com.android.internal.telephony.uicc.UiccPort;
import com.android.internal.telephony.uicc.UiccSlot;
import com.android.internal.telephony.util.ArrayUtils;
import com.android.internal.telephony.util.ArrayUtils;


import java.io.FileDescriptor;
import java.io.FileDescriptor;
@@ -180,12 +181,11 @@ public class EuiccController extends IEuiccController.Stub {
            PendingIntent callbackIntent =
            PendingIntent callbackIntent =
                    resolutionIntent.getParcelableExtra(
                    resolutionIntent.getParcelableExtra(
                            EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT);
                            EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT);
            int portIndex = resolutionIntent.getIntExtra(
                    EuiccService.EXTRA_RESOLUTION_PORT_INDEX, 0);
            resolutionExtras.putInt(EuiccService.EXTRA_RESOLUTION_PORT_INDEX, portIndex);
            boolean usePortIndex = resolutionIntent.getBooleanExtra(
            boolean usePortIndex = resolutionIntent.getBooleanExtra(
                    EuiccService.EXTRA_RESOLUTION_USE_PORT_INDEX, false);
                    EuiccService.EXTRA_RESOLUTION_USE_PORT_INDEX, false);
            resolutionExtras.putBoolean(EuiccService.EXTRA_RESOLUTION_USE_PORT_INDEX, usePortIndex);
            resolutionExtras.putBoolean(EuiccService.EXTRA_RESOLUTION_USE_PORT_INDEX, usePortIndex);
            Log.i(TAG, " continueOperation portIndex: " + resolutionExtras.getInt(
                    EuiccService.EXTRA_RESOLUTION_PORT_INDEX) + " usePortIndex: " + usePortIndex);
            op.continueOperation(cardId, resolutionExtras, callbackIntent);
            op.continueOperation(cardId, resolutionExtras, callbackIntent);
        } finally {
        } finally {
            Binder.restoreCallingIdentity(token);
            Binder.restoreCallingIdentity(token);
@@ -211,7 +211,8 @@ public class EuiccController extends IEuiccController.Stub {
        long token = Binder.clearCallingIdentity();
        long token = Binder.clearCallingIdentity();
        try {
        try {
            if (!callerCanReadPhoneStatePrivileged
            if (!callerCanReadPhoneStatePrivileged
                    && !canManageSubscriptionOnTargetSim(cardId, callingPackage)) {
                    && !canManageSubscriptionOnTargetSim(cardId, callingPackage, false,
                    TelephonyManager.INVALID_PORT_INDEX)) {
                throw new SecurityException(
                throw new SecurityException(
                        "Must have carrier privileges on subscription to read EID for cardId="
                        "Must have carrier privileges on subscription to read EID for cardId="
                                + cardId);
                                + cardId);
@@ -564,7 +565,8 @@ public class EuiccController extends IEuiccController.Stub {
            // Otherwise, the user must provide consent. If it's a single-active SIM device,
            // Otherwise, the user must provide consent. If it's a single-active SIM device,
            // determine whether the caller can manage the current profile; if so, we can perform
            // determine whether the caller can manage the current profile; if so, we can perform
            // the download silently; if not, the user must provide consent.
            // the download silently; if not, the user must provide consent.
            if (canManageSubscriptionOnTargetSim(cardId, callingPackage)) {
            if (canManageSubscriptionOnTargetSim(cardId, callingPackage, false,
                    TelephonyManager.INVALID_PORT_INDEX)) {
                mConnector.getDownloadableSubscriptionMetadata(cardId, subscription,
                mConnector.getDownloadableSubscriptionMetadata(cardId, subscription,
                    forceDeactivateSim,
                    forceDeactivateSim,
                    new DownloadSubscriptionGetMetadataCommandCallback(token, subscription,
                    new DownloadSubscriptionGetMetadataCommandCallback(token, subscription,
@@ -1005,9 +1007,11 @@ public class EuiccController extends IEuiccController.Stub {
            }
            }
            final String iccid;
            final String iccid;
            boolean passConsent = false;
            boolean passConsent = false;
            boolean isConsentNeededToResolvePortIndex = false;
            if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
                if (callerCanWriteEmbeddedSubscriptions
                if (callerCanWriteEmbeddedSubscriptions
                        || canManageActiveSubscriptionOnTargetSim(cardId, callingPackage)) {
                        || canManageActiveSubscriptionOnTargetSim(cardId, callingPackage,
                        usePortIndex, portIndex)) {
                    passConsent = true;
                    passConsent = true;
                } else {
                } else {
                    Log.e(TAG, "Not permitted to switch to empty subscription");
                    Log.e(TAG, "Not permitted to switch to empty subscription");
@@ -1031,14 +1035,34 @@ public class EuiccController extends IEuiccController.Stub {
                        return;
                        return;
                    }
                    }


                    if (canManageSubscriptionOnTargetSim(cardId, callingPackage)) {
                    if (canManageSubscriptionOnTargetSim(cardId, callingPackage, usePortIndex,
                            portIndex)) {
                        passConsent = true;
                        passConsent = true;
                    }
                    }
                }
                }
                iccid = sub.getIccId();
                iccid = sub.getIccId();
                if (usePortIndex) {
                    boolean hasValidPortIndex = isTargetPortIndexValid(cardId, portIndex);
                    if (!hasValidPortIndex) {
                        // Return permanent error.
                        Log.e(TAG, "Not permitted to switch to invalid portIndex");
                        Intent extrasIntent = new Intent();
                        extrasIntent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE,
                                EuiccManager.ERROR_INVALID_PORT);
                        sendResult(callbackIntent, ERROR, extrasIntent /* extrasIntent */);
                        return;
                    }
                    }

                } else {
            if (!passConsent) {
                    // Resolve the portIndex internally if apps are calling switchToSubscription
                    // API without portIndex.
                    portIndex = getResolvedPortIndexForSubscriptionSwitch(cardId);
                    isConsentNeededToResolvePortIndex = (portIndex
                            == TelephonyManager.INVALID_PORT_INDEX);
                    usePortIndex = true;
                    Log.d(TAG, " Resolved portIndex: " + portIndex);
                }
            }
            if (!passConsent || isConsentNeededToResolvePortIndex) {
                // Switch needs consent.
                // Switch needs consent.
                Intent extrasIntent = new Intent();
                Intent extrasIntent = new Intent();
                addResolutionIntent(extrasIntent,
                addResolutionIntent(extrasIntent,
@@ -1060,6 +1084,171 @@ public class EuiccController extends IEuiccController.Stub {
        }
        }
    }
    }


    /**
     * Returns the resolved portIndex or {@link TelephonyManager#INVALID_PORT_INDEX} if no port
     * is available without user consent.
     */
    private int getResolvedPortIndexForSubscriptionSwitch(int cardId) {
        int slotIndex = getSlotIndexFromCardId(cardId);
        // Euicc Slot
        UiccSlot slot = UiccController.getInstance().getUiccSlot(slotIndex);
        if (!slot.isMultipleEnabledProfileSupported()) {
            Log.d(TAG, "Multiple enabled profiles is not supported, return default port index");
            return TelephonyManager.DEFAULT_PORT_INDEX;
        }
        boolean isPsimHasActiveSub = isRemovalNonEuiccSlotHasActiveSubscription();
        if (mTelephonyManager.getActiveModemCount() == 1) {
            // SS Mode
            if (isPsimHasActiveSub) {
                // In case of SS Mode and pSim has active subscription, return default port index
                // for two reasons.
                // 1. If psim and esim share the same carrier privilege, then users wouldn't need
                // to consent, the switch should be seamless.
                // 2. If psim and esim doesn't share the same carrier privilege, then permission
                // check dialog will be shown anyway.
                return TelephonyManager.DEFAULT_PORT_INDEX;
            }
            // If esim port is active, return the active portIndex irrespective of whether port is
            // empty or has active subscription.
            for (int portIndex : slot.getPortList()) {
                if (slot.isPortActive(portIndex)) {
                    return portIndex;
                }
            }
        } else {
            // DSDS Mode
            for (int portIndex : slot.getPortList()) {
                if (slot.isPortActive(portIndex)
                        && mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(
                        slot.getPhoneIdFromPortIndex(portIndex)) == null) {
                    // If the port is active and empty, return the portIndex.
                    return portIndex;
                }
            }
            // Check whether the pSim is active and empty
            boolean isPsimEmpty = getRemovableNonEuiccSlot() != null
                    && getRemovableNonEuiccSlot().isActive()
                    && !isPsimHasActiveSub;
            if (isPsimEmpty) {
                // This logic will execute only if below two conditions are true.
                // 1. pSim is active and empty
                // 2. eSim has active subscription
                // Return the next available inactive eSim portIndex.
                return getNextAvailableInActivePortIndex(slot);
            }
        }
        return TelephonyManager.INVALID_PORT_INDEX;
    }

    /**
     * Returns true if the target port index is valid.
     * 1. Port index is valid if it is non-negative and less than the total port count.
     * 2. In SS Mode, port index is invalid if the embedded slot already has an active empty port
     * with different port index than the target port index.
     * 3. In DSDS mode, port index is invalid if the pSim slot is active and the embedded slot
     * already has an active empty port with different port index than the target port index.
     */
    private boolean isTargetPortIndexValid(int cardId, int targetPortIndex) {
        if (targetPortIndex < 0) {
            Log.e(TAG, "Invalid portIndex: " + targetPortIndex);
            return false;
        }
        int slotIndex = getSlotIndexFromCardId(cardId);
        UiccSlot slot = UiccController.getInstance().getUiccSlot(slotIndex);
        if (slot == null || slot.getPortList().length == 0
                || targetPortIndex >= slot.getPortList().length) {
            Log.e(TAG, "Invalid portIndex");
            return false;
        }

        if (mTelephonyManager.getActiveModemCount() == 1) {
            // SS Mode
            for (int portIndex : slot.getPortList()) {
                if (slot.isPortActive(portIndex) && portIndex != targetPortIndex) {
                    // if there is an active esim port, should not try to enable the
                    // profile on other inactive port.
                    Log.e(TAG, "In SS Mode, slot already has active port on portIndex " + portIndex
                            + " , reject the switch request to portIndex " + targetPortIndex);
                    return false;
                }
            }
        } else if (mTelephonyManager.getActiveModemCount() > 1) {
            // DSDS Mode
            // If physical slot has active subscription and eSim has active port (without active
            // subscription), should not try to enable the profile on other inactive port.
            boolean isPsimActive = isRemovalNonEuiccSlotHasActiveSubscription();
            if (isPsimActive) {
                for (int portIndex : slot.getPortList()) {
                    if (slot.isPortActive(portIndex)
                            && mSubscriptionManager
                            .getActiveSubscriptionInfoForSimSlotIndex(
                                    slot.getPhoneIdFromPortIndex(portIndex)) == null
                            && portIndex != targetPortIndex) {
                        Log.e(TAG, "In DSDS Mode, pSim has active subscription, eSim has empty"
                                + " active port on portIndex " + portIndex
                                + " , reject the switch request to portIndex " + targetPortIndex);
                        return false;
                    }
                }
            }
        }
        return true;
    }

    private int getNextAvailableInActivePortIndex(UiccSlot slot) {
        if (slot != null) {
            for (int portIndex : slot.getPortList()) {
                if (!slot.isPortActive(portIndex)) {
                    return portIndex;
                }
            }
        }
        return TelephonyManager.INVALID_PORT_INDEX;
    }

    /**
     * Gets the slot index from the card ID.
     */
    private int getSlotIndexFromCardId(int cardId) {
        List<UiccCardInfo> infos = mTelephonyManager.getUiccCardsInfo();
        if (infos == null || infos.size() == 0) {
            return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
        }
        for (UiccCardInfo info : infos) {
            if (info.getCardId() == cardId) {
                return info.getPhysicalSlotIndex();
            }
        }
        return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
    }

    private boolean isRemovalNonEuiccSlotHasActiveSubscription() {
        UiccSlot uiccSlot = getRemovableNonEuiccSlot();
        if (uiccSlot != null) {
            for (int portIndex : uiccSlot.getPortList()) {
                if (uiccSlot.isPortActive(portIndex)
                        && mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(
                                uiccSlot.getPhoneIdFromPortIndex(portIndex)) != null) {
                    return true;
                }
            }
        }
        return false;
    }

    private UiccSlot getRemovableNonEuiccSlot() {
        UiccSlot[] uiccSlots = UiccController.getInstance().getUiccSlots();
        if (uiccSlots != null) {
            for (int i = 0; i < uiccSlots.length; i++) {
                if (uiccSlots[i] != null && uiccSlots[i].isRemovable()
                        && !uiccSlots[i].isEuicc()) {
                    return uiccSlots[i];
                }
            }
        }
        return null;
    }

    void switchToSubscriptionPrivileged(int cardId, int portIndex, final long callingToken,
    void switchToSubscriptionPrivileged(int cardId, int portIndex, final long callingToken,
            int subscriptionId, boolean forceDeactivateSim, final String callingPackage,
            int subscriptionId, boolean forceDeactivateSim, final String callingPackage,
            final PendingIntent callbackIntent, boolean usePortIndex) {
            final PendingIntent callbackIntent, boolean usePortIndex) {
@@ -1512,7 +1701,10 @@ public class EuiccController extends IEuiccController.Stub {


    // Checks whether the caller can manage the active embedded subscription on the SIM with the
    // Checks whether the caller can manage the active embedded subscription on the SIM with the
    // given cardId.
    // given cardId.
    private boolean canManageActiveSubscriptionOnTargetSim(int cardId, String callingPackage) {
    // From Android T, if usePortIndex is true then should check if the calling app has carrier
    // privilege over the subscription on the target port index.
    private boolean canManageActiveSubscriptionOnTargetSim(int cardId, String callingPackage,
            boolean usePortIndex, int targetPortIndex) {
        List<SubscriptionInfo> subInfoList = mSubscriptionManager
        List<SubscriptionInfo> subInfoList = mSubscriptionManager
                .getActiveSubscriptionInfoList(/* userVisibleOnly */false);
                .getActiveSubscriptionInfoList(/* userVisibleOnly */false);
        if (subInfoList == null || subInfoList.size() == 0) {
        if (subInfoList == null || subInfoList.size() == 0) {
@@ -1526,6 +1718,7 @@ public class EuiccController extends IEuiccController.Stub {
            // subscription on any eSIM. That's the best we can do here.
            // subscription on any eSIM. That's the best we can do here.
            if ((cardId == TelephonyManager.UNSUPPORTED_CARD_ID || subInfo.getCardId() == cardId)
            if ((cardId == TelephonyManager.UNSUPPORTED_CARD_ID || subInfo.getCardId() == cardId)
                    && subInfo.isEmbedded()
                    && subInfo.isEmbedded()
                    && (!usePortIndex || subInfo.getPortIndex() == targetPortIndex)
                    && mSubscriptionManager.canManageSubscription(subInfo, callingPackage)) {
                    && mSubscriptionManager.canManageSubscription(subInfo, callingPackage)) {
                return true;
                return true;
            }
            }
@@ -1540,7 +1733,10 @@ public class EuiccController extends IEuiccController.Stub {
    // other SIM. The target SIM should be an eUICC.
    // other SIM. The target SIM should be an eUICC.
    // For a single-active subscription phone, checks whether the caller can manage any active
    // For a single-active subscription phone, checks whether the caller can manage any active
    // embedded subscription.
    // embedded subscription.
    private boolean canManageSubscriptionOnTargetSim(int cardId, String callingPackage) {
    // From Android T, If embedded slot supports Multiple Enabled Profiles then should check if
    // the calling app has carrier privilege over the subscription on the target port index.
    private boolean canManageSubscriptionOnTargetSim(int cardId, String callingPackage,
            boolean usePortIndex, int targetPortIndex) {
        List<SubscriptionInfo> subInfoList = mSubscriptionManager
        List<SubscriptionInfo> subInfoList = mSubscriptionManager
                .getActiveSubscriptionInfoList(false /* userVisibleonly */);
                .getActiveSubscriptionInfoList(false /* userVisibleonly */);
        // No active subscription on any SIM.
        // No active subscription on any SIM.
@@ -1558,9 +1754,11 @@ public class EuiccController extends IEuiccController.Stub {
                return false;
                return false;
            }
            }
            boolean isEuicc = false;
            boolean isEuicc = false;
            boolean isMultipleEnabledProfilesSupported = false;
            for (UiccCardInfo info : cardInfos) {
            for (UiccCardInfo info : cardInfos) {
                if (info != null && info.getCardId() == cardId && info.isEuicc()) {
                if (info != null && info.getCardId() == cardId && info.isEuicc()) {
                    isEuicc = true;
                    isEuicc = true;
                    isMultipleEnabledProfilesSupported = info.isMultipleEnabledProfilesSupported();
                    break;
                    break;
                }
                }
            }
            }
@@ -1573,8 +1771,13 @@ public class EuiccController extends IEuiccController.Stub {
            // false. If the caller can manage the active embedded subscription on the target SIM,
            // false. If the caller can manage the active embedded subscription on the target SIM,
            // return true directly.
            // return true directly.
            for (SubscriptionInfo subInfo : subInfoList) {
            for (SubscriptionInfo subInfo : subInfoList) {
                // subInfo.isEmbedded() can only be true for the target SIM.
                // 1. subInfo.isEmbedded() can only be true for the target SIM.
                if (subInfo.isEmbedded() && subInfo.getCardId() == cardId) {
                // 2. Check whether the caller can manage subscription on the target portIndex
                // (i.e. subInfo.getPortIndex() == targetPortIndex condition) only in case if
                // isMultipleEnabledProfilesSupported and usePortIndex both are true.
                if (subInfo.isEmbedded() && subInfo.getCardId() == cardId
                        && (!isMultipleEnabledProfilesSupported || !usePortIndex
                        || subInfo.getPortIndex() == targetPortIndex)) {
                    return mSubscriptionManager.canManageSubscription(subInfo, callingPackage);
                    return mSubscriptionManager.canManageSubscription(subInfo, callingPackage);
                }
                }
            }
            }
+16 −0
Original line number Original line Diff line number Diff line
@@ -66,6 +66,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.euicc.EuiccConnector.GetOtaStatusCommandCallback;
import com.android.internal.telephony.euicc.EuiccConnector.GetOtaStatusCommandCallback;
import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;
import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;
import com.android.internal.telephony.uicc.UiccSlot;


import org.junit.After;
import org.junit.After;
import org.junit.Before;
import org.junit.Before;
@@ -121,6 +122,7 @@ public class EuiccControllerTest extends TelephonyTest {
    private static final int PORT_INDEX = 0;
    private static final int PORT_INDEX = 0;


    @Mock private EuiccConnector mMockConnector;
    @Mock private EuiccConnector mMockConnector;
    @Mock private UiccSlot mUiccSlot;
    private TestEuiccController mController;
    private TestEuiccController mController;
    private int mSavedEuiccProvisionedValue;
    private int mSavedEuiccProvisionedValue;


@@ -786,6 +788,7 @@ public class EuiccControllerTest extends TelephonyTest {
    public void testSwitchToSubscription_serviceUnavailable() throws Exception {
    public void testSwitchToSubscription_serviceUnavailable() throws Exception {
        setHasWriteEmbeddedPermission(true);
        setHasWriteEmbeddedPermission(true);
        prepareOperationSubscription(false /* hasPrivileges */);
        prepareOperationSubscription(false /* hasPrivileges */);
        setUpUiccSlotData();
        callSwitchToSubscription(
        callSwitchToSubscription(
                SUBSCRIPTION_ID, ICC_ID, false /* complete */, 0 /* result */,
                SUBSCRIPTION_ID, ICC_ID, false /* complete */, 0 /* result */,
                "whatever" /* callingPackage */);
                "whatever" /* callingPackage */);
@@ -799,6 +802,7 @@ public class EuiccControllerTest extends TelephonyTest {
    public void testSwitchToSubscription_error() throws Exception {
    public void testSwitchToSubscription_error() throws Exception {
        setHasWriteEmbeddedPermission(true);
        setHasWriteEmbeddedPermission(true);
        prepareOperationSubscription(false /* hasPrivileges */);
        prepareOperationSubscription(false /* hasPrivileges */);
        setUpUiccSlotData();
        callSwitchToSubscription(
        callSwitchToSubscription(
                SUBSCRIPTION_ID, ICC_ID, true /* complete */, 42 /* result */,
                SUBSCRIPTION_ID, ICC_ID, true /* complete */, 42 /* result */,
                "whatever" /* callingPackage */);
                "whatever" /* callingPackage */);
@@ -810,6 +814,7 @@ public class EuiccControllerTest extends TelephonyTest {
    public void testSwitchToSubscription_success() throws Exception {
    public void testSwitchToSubscription_success() throws Exception {
        setHasWriteEmbeddedPermission(true);
        setHasWriteEmbeddedPermission(true);
        prepareOperationSubscription(false /* hasPrivileges */);
        prepareOperationSubscription(false /* hasPrivileges */);
        setUpUiccSlotData();
        callSwitchToSubscription(
        callSwitchToSubscription(
                SUBSCRIPTION_ID, ICC_ID, true /* complete */, EuiccService.RESULT_OK,
                SUBSCRIPTION_ID, ICC_ID, true /* complete */, EuiccService.RESULT_OK,
                "whatever" /* callingPackage */);
                "whatever" /* callingPackage */);
@@ -842,6 +847,7 @@ public class EuiccControllerTest extends TelephonyTest {
    public void testSwitchToSubscription_hasCarrierPrivileges() throws Exception {
    public void testSwitchToSubscription_hasCarrierPrivileges() throws Exception {
        setHasWriteEmbeddedPermission(false);
        setHasWriteEmbeddedPermission(false);
        prepareOperationSubscription(true /* hasPrivileges */);
        prepareOperationSubscription(true /* hasPrivileges */);
        setUpUiccSlotData();
        when(mTelephonyManager.getPhoneCount()).thenReturn(1);
        when(mTelephonyManager.getPhoneCount()).thenReturn(1);
        setHasCarrierPrivilegesOnActiveSubscription(true);
        setHasCarrierPrivilegesOnActiveSubscription(true);
        callSwitchToSubscription(
        callSwitchToSubscription(
@@ -853,6 +859,7 @@ public class EuiccControllerTest extends TelephonyTest {
    public void testSwitchToSubscription_hasCarrierPrivileges_multiSim() throws Exception {
    public void testSwitchToSubscription_hasCarrierPrivileges_multiSim() throws Exception {
        setHasWriteEmbeddedPermission(false);
        setHasWriteEmbeddedPermission(false);
        prepareOperationSubscription(true /* hasPrivileges */);
        prepareOperationSubscription(true /* hasPrivileges */);
        setUpUiccSlotData();
        when(mTelephonyManager.getPhoneCount()).thenReturn(2);
        when(mTelephonyManager.getPhoneCount()).thenReturn(2);
        setCanManageSubscriptionOnTargetSim(true /* isTargetEuicc */, true /* hasPrivileges */);
        setCanManageSubscriptionOnTargetSim(true /* isTargetEuicc */, true /* hasPrivileges */);
        callSwitchToSubscription(
        callSwitchToSubscription(
@@ -864,6 +871,7 @@ public class EuiccControllerTest extends TelephonyTest {
    public void testSwitchToSubscription_hasCarrierPrivileges_needsConsent() throws Exception {
    public void testSwitchToSubscription_hasCarrierPrivileges_needsConsent() throws Exception {
        setHasWriteEmbeddedPermission(false);
        setHasWriteEmbeddedPermission(false);
        prepareOperationSubscription(true /* hasPrivileges */);
        prepareOperationSubscription(true /* hasPrivileges */);
        setUpUiccSlotData();
        setHasCarrierPrivilegesOnActiveSubscription(false);
        setHasCarrierPrivilegesOnActiveSubscription(false);
        when(mTelephonyManager.getPhoneCount()).thenReturn(1);
        when(mTelephonyManager.getPhoneCount()).thenReturn(1);
        callSwitchToSubscription(
        callSwitchToSubscription(
@@ -881,6 +889,7 @@ public class EuiccControllerTest extends TelephonyTest {
            throws Exception {
            throws Exception {
        setHasWriteEmbeddedPermission(false);
        setHasWriteEmbeddedPermission(false);
        prepareOperationSubscription(true /* hasPrivileges */);
        prepareOperationSubscription(true /* hasPrivileges */);
        setUpUiccSlotData();
        when(mTelephonyManager.getPhoneCount()).thenReturn(2);
        when(mTelephonyManager.getPhoneCount()).thenReturn(2);
        setCanManageSubscriptionOnTargetSim(true /* isTargetEuicc */, false /* hasPrivileges */);
        setCanManageSubscriptionOnTargetSim(true /* isTargetEuicc */, false /* hasPrivileges */);
        callSwitchToSubscription(
        callSwitchToSubscription(
@@ -898,6 +907,7 @@ public class EuiccControllerTest extends TelephonyTest {
            throws Exception {
            throws Exception {
        setHasWriteEmbeddedPermission(false);
        setHasWriteEmbeddedPermission(false);
        prepareOperationSubscription(true /* hasPrivileges */);
        prepareOperationSubscription(true /* hasPrivileges */);
        setUpUiccSlotData();
        when(mTelephonyManager.getPhoneCount()).thenReturn(2);
        when(mTelephonyManager.getPhoneCount()).thenReturn(2);
        setCanManageSubscriptionOnTargetSim(false /* isTargetEuicc */, true /* hasPrivileges */);
        setCanManageSubscriptionOnTargetSim(false /* isTargetEuicc */, true /* hasPrivileges */);
        callSwitchToSubscription(
        callSwitchToSubscription(
@@ -1129,6 +1139,12 @@ public class EuiccControllerTest extends TelephonyTest {
                EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE, -1), 0x345678);
                EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE, -1), 0x345678);
    }
    }


    private void setUpUiccSlotData() {
        when(mUiccController.getUiccSlot(anyInt())).thenReturn(mUiccSlot);
        // TODO(b/199559633): Add test cases for isMultipleEnabledProfileSupported true case
        when(mUiccSlot.isMultipleEnabledProfileSupported()).thenReturn(false);
    }

    private void setGetEidPermissions(
    private void setGetEidPermissions(
            boolean hasPhoneStatePrivileged, boolean hasCarrierPrivileges) throws Exception {
            boolean hasPhoneStatePrivileged, boolean hasCarrierPrivileges) throws Exception {
        doReturn(hasPhoneStatePrivileged
        doReturn(hasPhoneStatePrivileged