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

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

Merge "[MEP] Resolve port index in case apps are calling...

Merge "[MEP] Resolve port index in case apps are calling switchToSubscription(without portIndex) API for disable operation."
parents 810fdfb7 7c33d7f5
Loading
Loading
Loading
Loading
+68 −10
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.app.compat.CompatChanges;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -988,7 +989,8 @@ public class EuiccController extends IEuiccController.Stub {
        boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions();
        mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
        Log.d(TAG, " subId: " + subscriptionId + " portIndex: " + portIndex
                + " forceDeactivateSim: " + forceDeactivateSim + " usePortIndex: " + usePortIndex);
                + " forceDeactivateSim: " + forceDeactivateSim + " usePortIndex: " + usePortIndex
                + " callingPackage: " + callingPackage);
        long token = Binder.clearCallingIdentity();
        try {
            if (callerCanWriteEmbeddedSubscriptions) {
@@ -998,19 +1000,23 @@ public class EuiccController extends IEuiccController.Stub {
                forceDeactivateSim = true;
            }

            // if the caller is not privileged caller and does not have the carrier privilege over
            // any active subscription, do not continue.
            if (!callerCanWriteEmbeddedSubscriptions && usePortIndex
                    && (mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
                    != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS)) {
                Log.e(TAG, "Not permitted to use switchToSubscription with portIndex");
                throw new SecurityException(
                        "Must have carrier privileges to use switchToSubscription with portIndex");
            }
            final String iccid;
            boolean passConsent = false;
            boolean isConsentNeededToResolvePortIndex = false;
            if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
                if (!usePortIndex) {
                    // Resolve the portIndex internally if apps are calling switchToSubscription
                    // API without portIndex and subscription id is invalid.
                    portIndex = getResolvedPortIndexForDisableSubscription(cardId, callingPackage,
                            callerCanWriteEmbeddedSubscriptions);
                    if (portIndex == TelephonyManager.INVALID_PORT_INDEX) {
                        Log.e(TAG, "Disable is not permitted: no active subscription or cannot"
                                + " manage subscription");
                        sendResult(callbackIntent, ERROR, null /* extrasIntent */);
                        return;
                    }
                    usePortIndex = true;
                }
                if (callerCanWriteEmbeddedSubscriptions
                        || canManageActiveSubscriptionOnTargetSim(cardId, callingPackage,
                        usePortIndex, portIndex)) {
@@ -1086,6 +1092,34 @@ public class EuiccController extends IEuiccController.Stub {
        }
    }

    /**
     * Returns the resolved portIndex or {@link TelephonyManager#INVALID_PORT_INDEX} if calling
     * cannot manage any active subscription.
     */
    private int getResolvedPortIndexForDisableSubscription(int cardId, String callingPackage,
            boolean callerCanWriteEmbeddedSubscriptions) {
        List<SubscriptionInfo> subInfoList = mSubscriptionManager
                .getActiveSubscriptionInfoList(/* userVisibleOnly */false);
        if (subInfoList == null || subInfoList.size() == 0) {
            // No active subscription on any SIM.
            return TelephonyManager.INVALID_PORT_INDEX;
        }
        // Return the portIndex of the first active subscription managed by the calling app.
        for (SubscriptionInfo subInfo : subInfoList) {
            // If cardId == TelephonyManager.UNSUPPORTED_CARD_ID, we assume it does not support
            // multiple eSIMs. There are older multi-active SIM devices which do not implement HAL
            // 1.2 and if they have multiple eSIMs, we let it pass if the app can manage an active
            // subscription on any eSIM. That's the best we can do here.
            if ((cardId == TelephonyManager.UNSUPPORTED_CARD_ID || subInfo.getCardId() == cardId)
                    && subInfo.isEmbedded()
                    && (callerCanWriteEmbeddedSubscriptions
                    || mSubscriptionManager.canManageSubscription(subInfo, callingPackage))) {
                return subInfo.getPortIndex();
            }
        }
        return TelephonyManager.INVALID_PORT_INDEX;
    }

    /**
     * Returns the resolved portIndex or {@link TelephonyManager#INVALID_PORT_INDEX} if no port
     * is available without user consent.
@@ -1858,4 +1892,28 @@ public class EuiccController extends IEuiccController.Stub {
        }
        return false;
    }

    @Override
    public boolean hasCarrierPrivilegesForPackageOnAnyPhone(String callingPackage) {
        final long token = Binder.clearCallingIdentity();
        try {
            // checkCarrierPrivilegesForPackageAnyPhone API requires READ_PHONE_STATE permission,
            // hence cannot call directly from EuiccManager switchToSubscription
            return mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
                    == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public boolean isCompatChangeEnabled(String callingPackage, long changeId) {
        // Platform compat framework kills the callingPackage app to ensure that the change
        // takes affect immediately. So the corresponding compat checking is moved to controller.
        boolean changeEnabled = CompatChanges.isChangeEnabled(changeId, callingPackage,
                Binder.getCallingUserHandle());
        Log.i(TAG, "isCompatChangeEnabled changeId: " + changeId
                + " changeEnabled: " + changeEnabled);
        return changeEnabled;
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ android_test {
        "services.net",
        "truth-prebuilt",
        "testables",
        "platform-compat-test-rules"
    ],

    jarjar_rules: ":jarjar-rules-telephony-tests",
+40 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package com.android.internal.telephony.euicc;

import static android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES;
import static android.telephony.euicc.EuiccManager.EUICC_OTA_STATUS_UNAVAILABLE;
import static android.telephony.euicc.EuiccManager.SWITCH_WITHOUT_PORT_INDEX_EXCEPTION_ON_DISABLE;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -39,6 +40,7 @@ import static org.mockito.Mockito.when;
import android.Manifest;
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.compat.testing.PlatformCompatChangeRule;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
@@ -68,9 +70,14 @@ import com.android.internal.telephony.euicc.EuiccConnector.GetOtaStatusCommandCa
import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;
import com.android.internal.telephony.uicc.UiccSlot;

import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
@@ -86,11 +93,14 @@ import java.util.Collections;

@RunWith(AndroidJUnit4.class)
public class EuiccControllerTest extends TelephonyTest {
    @Rule
    public TestRule compatChangeRule = new PlatformCompatChangeRule();
    private static final DownloadableSubscription SUBSCRIPTION =
            DownloadableSubscription.forActivationCode("abcde");

    private static final String PACKAGE_NAME = "test.package";
    private static final String CARRIER_NAME = "test name";
    private static final String TEST_PACKAGE_NAME = "com.android.frameworks.telephonytests";
    private static final byte[] SIGNATURE_BYTES = new byte[] {1, 2, 3, 4, 5};

    private static final UiccAccessRule ACCESS_RULE;
@@ -821,9 +831,22 @@ public class EuiccControllerTest extends TelephonyTest {
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK, 0 /* detailedCode */);
    }

    @Test
    public void testSwitchToSubscription_emptySubscription_noActiveSubscription() throws Exception {
        setHasWriteEmbeddedPermission(true);
        callSwitchToSubscription(
                SubscriptionManager.INVALID_SUBSCRIPTION_ID, null /* iccid */, true /* complete */,
                EuiccService.RESULT_OK, "whatever" /* callingPackage */);
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR,
                0 /* detailedCode */);
        verify(mMockConnector, never()).switchToSubscription(anyInt(), anyInt(), anyString(),
                anyBoolean(), any(), anyBoolean());
    }

    @Test
    public void testSwitchToSubscription_emptySubscription_success() throws Exception {
        setHasWriteEmbeddedPermission(true);
        setHasCarrierPrivilegesOnActiveSubscription(false);
        callSwitchToSubscription(
                SubscriptionManager.INVALID_SUBSCRIPTION_ID, null /* iccid */, true /* complete */,
                EuiccService.RESULT_OK, "whatever" /* callingPackage */);
@@ -1139,6 +1162,20 @@ public class EuiccControllerTest extends TelephonyTest {
                EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE, -1), 0x345678);
    }

    @Test
    @DisableCompatChanges({SWITCH_WITHOUT_PORT_INDEX_EXCEPTION_ON_DISABLE})
    public void testIsCompactChangeEnabled_disable() {
        assertFalse(mController.isCompatChangeEnabled(TEST_PACKAGE_NAME,
                SWITCH_WITHOUT_PORT_INDEX_EXCEPTION_ON_DISABLE));
    }

    @Test
    @EnableCompatChanges({SWITCH_WITHOUT_PORT_INDEX_EXCEPTION_ON_DISABLE})
    public void testIsCompactChangeEnabled_enable() {
        assertTrue(mController.isCompatChangeEnabled(TEST_PACKAGE_NAME,
                SWITCH_WITHOUT_PORT_INDEX_EXCEPTION_ON_DISABLE));
    }

    private void setUpUiccSlotData() {
        when(mUiccController.getUiccSlot(anyInt())).thenReturn(mUiccSlot);
        // TODO(b/199559633): Add test cases for isMultipleEnabledProfileSupported true case
@@ -1173,7 +1210,7 @@ public class EuiccControllerTest extends TelephonyTest {
        SubscriptionInfo subInfo = new SubscriptionInfo(
                0, "", 0, "", "", 0, 0, "", 0, null, "", "", "", true /* isEmbedded */,
                hasPrivileges ? new UiccAccessRule[] { ACCESS_RULE } : null, "", CARD_ID,
                false, null, false, 0, 0, 0, null, null, true, -1);
                false, null, false, 0, 0, 0, null, null, true, 0);
        when(mSubscriptionManager.canManageSubscription(subInfo, PACKAGE_NAME)).thenReturn(
                hasPrivileges);
        when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(
@@ -1202,11 +1239,11 @@ public class EuiccControllerTest extends TelephonyTest {
        SubscriptionInfo subInfo1 = new SubscriptionInfo(
                0, "", 0, "", "", 0, 0, "", 0, null, "", "", "", true /* isEmbedded */,
                hasPrivileges ? new UiccAccessRule[] { ACCESS_RULE } : null, "", CARD_ID,
                false, null, false, 0, 0, 0, null, null, true, -1);
                false, null, false, 0, 0, 0, null, null, true, 0);
        SubscriptionInfo subInfo2 = new SubscriptionInfo(
                0, "", 0, "", "", 0, 0, "", 0, null, "", "", "", true /* isEmbedded */,
                hasPrivileges ? new UiccAccessRule[] { ACCESS_RULE } : null, "",
                1 /* cardId */, false, null, false, 0, 0, 0, null, null, true, -1);
                1 /* cardId */, false, null, false, 0, 0, 0, null, null, true, 0);
        when(mSubscriptionManager.canManageSubscription(subInfo1, PACKAGE_NAME)).thenReturn(
                hasPrivileges);
        when(mSubscriptionManager.canManageSubscription(subInfo2, PACKAGE_NAME)).thenReturn(