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

Commit 73a55a65 authored by Muralidhar Reddy Mule's avatar Muralidhar Reddy Mule Committed by Android (Google) Code Review
Browse files

Merge "isSimPortAvailable API should return true if the calling app can...

Merge "isSimPortAvailable API should return true if the calling app can activate a new profile on the selected port without any user consent or deactivate dialog."
parents 8bedc899 f41702d2
Loading
Loading
Loading
Loading
+63 −47
Original line number Diff line number Diff line
@@ -1894,8 +1894,6 @@ public class EuiccController extends IEuiccController.Stub {
            boolean hasActiveEmbeddedSubscription = subInfoList.stream().anyMatch(
                    subInfo -> subInfo.isEmbedded() && subInfo.getCardId() == cardId
                            && (!usePortIndex || subInfo.getPortIndex() == targetPortIndex));
            Log.d(TAG, "canManageSubscriptionOnTargetSim hasActiveEmbeddedSubscriptions: "
                    + hasActiveEmbeddedSubscription);
            if (hasActiveEmbeddedSubscription) {
                // hasActiveEmbeddedSubscription is true if there is an active embedded subscription
                // on the target port(in case of usePortIndex is true) or if there is an active
@@ -1952,13 +1950,14 @@ public class EuiccController extends IEuiccController.Stub {

    @Override
    public boolean isSimPortAvailable(int cardId, int portIndex, String callingPackage) {
        List<UiccCardInfo> cardInfos;
        mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
        // In the event that this check is coming from ONS, WRITE_EMBEDDED_SUBSCRIPTIONS will be
        // required for the case where a port is inactive but could trivially be enabled without
        // requiring user consent.
        boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions();
        final long token = Binder.clearCallingIdentity();
        try {
            cardInfos = mTelephonyManager.getUiccCardsInfo();
        } finally {
            Binder.restoreCallingIdentity(token);
        }
            List<UiccCardInfo> cardInfos = mTelephonyManager.getUiccCardsInfo();
            for (UiccCardInfo info : cardInfos) {
                if (info == null || info.getCardId() != cardId) {
                    continue;
@@ -1973,9 +1972,23 @@ public class EuiccController extends IEuiccController.Stub {
                    if (portInfo == null || portInfo.getPortIndex() != portIndex) {
                        continue;
                    }
                // Return false if port is not active.
                    if (!portInfo.isActive()) {
                    return false;
                        // port is inactive, check whether the caller can activate a new profile
                        // seamlessly. This is possible in below condition:
                        // 1. Device in DSDS Mode(P+E).
                        // 2. pSIM slot is active but no active subscription.
                        // 3. Caller has carrier privileges on any phone or has
                        // WRITE_EMBEDDED_SUBSCRIPTIONS. The latter covers calls from ONS
                        // which does not have carrier privileges.
                        boolean hasActiveRemovableNonEuiccSlot = getRemovableNonEuiccSlot() != null
                                && getRemovableNonEuiccSlot().isActive();
                        boolean hasCarrierPrivileges = mTelephonyManager
                                .checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
                                == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
                        return mTelephonyManager.isMultiSimEnabled()
                                && hasActiveRemovableNonEuiccSlot
                                && !isRemovalNonEuiccSlotHasActiveSubscription()
                                && (hasCarrierPrivileges || callerCanWriteEmbeddedSubscriptions);
                    }
                    // A port is available if it has no profiles enabled on it or calling app has
                    // Carrier privilege over the profile installed on the selected port.
@@ -2006,6 +2019,9 @@ public class EuiccController extends IEuiccController.Stub {
                            == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
                }
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }
        return false;
    }

+133 −0
Original line number Diff line number Diff line
@@ -65,6 +65,8 @@ import android.telephony.euicc.EuiccManager;

import androidx.test.runner.AndroidJUnit4;

import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.euicc.EuiccConnector.GetOtaStatusCommandCallback;
import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;
@@ -89,6 +91,7 @@ import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@RunWith(AndroidJUnit4.class)
public class EuiccControllerTest extends TelephonyTest {
@@ -128,6 +131,7 @@ public class EuiccControllerTest extends TelephonyTest {
    private static final int SUBSCRIPTION_ID = 12345;
    private static final String ICC_ID = "54321";
    private static final int CARD_ID = 25;
    private static final int REMOVABLE_CARD_ID = 26;

    // Mocked classes
    private EuiccConnector mMockConnector;
@@ -1290,6 +1294,135 @@ public class EuiccControllerTest extends TelephonyTest {
                SWITCH_WITHOUT_PORT_INDEX_EXCEPTION_ON_DISABLE));
    }

    @Test
    public void testIsSimPortAvailable_invalidCase() {
        setUiccCardInfos(false, true, true);
        // assert non euicc card id
        assertFalse(mController.isSimPortAvailable(REMOVABLE_CARD_ID, 0, PACKAGE_NAME));

        // assert invalid port index
        assertFalse(mController.isSimPortAvailable(CARD_ID, 5 /* portIndex */, PACKAGE_NAME));
    }

    @Test
    public void testIsSimPortAvailable_port_active() throws Exception {
        setUiccCardInfos(false, true, true);

        // port has empty iccid
        assertTrue(mController.isSimPortAvailable(CARD_ID, 0, PACKAGE_NAME));

        // Set port is active, has valid iccid(may be boot profile) and UiccProfile is empty
        setUiccCardInfos(false, true, false);
        when(mUiccController.getUiccPortForSlot(anyInt(), anyInt())).thenReturn(mUiccPort);
        when(mUiccPort.getUiccProfile()).thenReturn(mUiccProfile);
        when(mUiccProfile.isEmptyProfile()).thenReturn(true);
        assertTrue(mController.isSimPortAvailable(CARD_ID, 0, PACKAGE_NAME));

        // port is active, valid iccid, not empty profile but Phone object is null
        when(mUiccPort.getUiccProfile()).thenReturn(mUiccProfile);
        when(mUiccProfile.isEmptyProfile()).thenReturn(false);
        replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone});
        // logicalSlotIndex of port#0 is 1, Phone object should be null
        assertFalse(mController.isSimPortAvailable(CARD_ID, 0, PACKAGE_NAME));

        // port is active, valid iccid, not empty profile but no carrier privileges
        when(mUiccPort.getUiccProfile()).thenReturn(mUiccProfile);
        when(mUiccProfile.isEmptyProfile()).thenReturn(false);
        replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone, mPhone});
        when(mPhone.getCarrierPrivilegesTracker()).thenReturn(null);
        assertFalse(mController.isSimPortAvailable(CARD_ID, 0, PACKAGE_NAME));
        when(mPhone.getCarrierPrivilegesTracker()).thenReturn(mCarrierPrivilegesTracker);
        when(mCarrierPrivilegesTracker.getCarrierPrivilegeStatusForPackage(PACKAGE_NAME))
                .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
        assertFalse(mController.isSimPortAvailable(CARD_ID, 0, PACKAGE_NAME));

        // port is active, valid iccid, not empty profile and has carrier privileges
        when(mCarrierPrivilegesTracker.getCarrierPrivilegeStatusForPackage(PACKAGE_NAME))
                .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
        assertTrue(mController.isSimPortAvailable(CARD_ID, 0, PACKAGE_NAME));
    }

    @Test
    public void testIsSimPortAvailable_port_inActive() {
        setUiccCardInfos(false, false, true);
        when(mUiccController.getUiccSlots()).thenReturn(new UiccSlot[]{mUiccSlot});
        when(mUiccSlot.isRemovable()).thenReturn(true);

        // Check getRemovableNonEuiccSlot null case
        when(mUiccSlot.isEuicc()).thenReturn(true);
        assertFalse(mController.isSimPortAvailable(CARD_ID, 0, PACKAGE_NAME));

        // Check getRemovableNonEuiccSlot isActive() false case
        when(mUiccSlot.isEuicc()).thenReturn(false);
        when(mUiccSlot.isActive()).thenReturn(false);
        assertFalse(mController.isSimPortAvailable(CARD_ID, 0, PACKAGE_NAME));

        // assert false,multisim is not enabled
        when(mUiccSlot.isEuicc()).thenReturn(false);
        when(mUiccSlot.isActive()).thenReturn(true);
        when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(PACKAGE_NAME)).thenReturn(
                TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
        when(mTelephonyManager.isMultiSimEnabled()).thenReturn(false);
        assertFalse(mController.isSimPortAvailable(CARD_ID, 0, PACKAGE_NAME));

        // assert false, caller does not have carrier privileges
        setHasWriteEmbeddedPermission(false);
        when(mTelephonyManager.isMultiSimEnabled()).thenReturn(true);
        when(mUiccSlot.getPortList()).thenReturn(new int[] {0});
        when(mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(anyInt())).thenReturn(
                new SubscriptionInfo.Builder().build());
        when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(PACKAGE_NAME)).thenReturn(
                TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
        assertFalse(mController.isSimPortAvailable(CARD_ID, 0, PACKAGE_NAME));

        // assert true, caller does not have carrier privileges but has write_embedded permission
        setHasWriteEmbeddedPermission(true);
        assertTrue(mController.isSimPortAvailable(CARD_ID, 0, PACKAGE_NAME));

        // assert true, caller has carrier privileges
        setHasWriteEmbeddedPermission(false);
        when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(PACKAGE_NAME)).thenReturn(
                TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
        assertTrue(mController.isSimPortAvailable(CARD_ID, 0, PACKAGE_NAME));
    }


    private void setUiccCardInfos(boolean isMepSupported, boolean isPortActive,
            boolean isEmptyPort) {
        List<UiccPortInfo> euiccPortInfoList;
        if (isMepSupported) {
            euiccPortInfoList = Arrays.asList(
                    new UiccPortInfo(isEmptyPort ? "" : ICC_ID /* iccId */, 0 /* portIdx */,
                            isPortActive ? 1 : -1 /* logicalSlotIdx */,
                            isPortActive /* isActive */),
                    new UiccPortInfo(isEmptyPort ? "" : ICC_ID /* iccId */, 1 /* portIdx */,
                            -1 /* logicalSlotIdx */,
                            isPortActive /* isActive */));
        } else {
            euiccPortInfoList = Collections.singletonList(
                    new UiccPortInfo(isEmptyPort ? "" : ICC_ID /* iccId */, 0 /* portIdx */,
                            isPortActive ? 1 : -1 /* logicalSlotIdx */,
                            isPortActive /* isActive */)
                    );
        }

        UiccCardInfo cardInfo1 = new UiccCardInfo(true, CARD_ID, "", 0,
                false /* isRemovable */,
                isMepSupported /* isMultipleEnabledProfileSupported */,
                euiccPortInfoList);
        UiccCardInfo cardInfo2 = new UiccCardInfo(false /* isEuicc */,
                REMOVABLE_CARD_ID /* cardId */,
                "", 0, true /* isRemovable */,
                false /* isMultipleEnabledProfileSupported */,
                Collections.singletonList(
                        new UiccPortInfo("" /* iccId */, 0 /* portIdx */,
                                0 /* logicalSlotIdx */, true /* isActive */)));
        ArrayList<UiccCardInfo> cardInfos = new ArrayList<>();
        cardInfos.add(cardInfo1);
        cardInfos.add(cardInfo2);
        when(mTelephonyManager.getUiccCardsInfo()).thenReturn(cardInfos);
    }

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