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

Commit b0136b8e authored by Holly Jiuyu Sun's avatar Holly Jiuyu Sun Committed by Gerrit Code Review
Browse files

Merge "Get user consent first before checking profile metadata."

parents d097521e b1539585
Loading
Loading
Loading
Loading
+37 −35
Original line number Diff line number Diff line
@@ -343,13 +343,35 @@ public class EuiccController extends IEuiccController.Stub {
                        forceDeactivateSim, callingPackage, resolvedBundle, callbackIntent);
                return;
            }
            // Without WRITE_EMBEDDED_SUBSCRIPTIONS, the caller *must* be whitelisted per the
            // metadata of the profile to be downloaded, so check the metadata first.

            // Without WRITE_EMBEDDED_SUBSCRIPTIONS, we first check whether the caller can manage
            // subscription on the target SIM (see comments below). If yes, the caller *must* be
            // whitelisted per the metadata of the profile to be downloaded, so check the metadata;
            // If no, ask the user's consent before proceed.
            // On a multi-active SIM device, if the caller can manage the active subscription on the
            // target SIM, or there is no active subscription on the target SIM and the caller can
            // manage any active subscription on other SIMs, we perform the download silently.
            // 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
            // the download silently; if not, the user must provide consent.
            if (canManageSubscriptionOnTargetSim(cardId, callingPackage)) {
                mConnector.getDownloadableSubscriptionMetadata(cardId, subscription,
                    forceDeactivateSim,
                    new DownloadSubscriptionGetMetadataCommandCallback(token, subscription,
                        switchAfterDownload, callingPackage, forceDeactivateSim,
                        callbackIntent, false /* withUserConsent */));
            } else {
                Log.i(TAG, "Caller can't manage subscription on target SIM. "
                        + "Ask user's consent first");
                Intent extrasIntent = new Intent();
                addResolutionIntent(extrasIntent, EuiccService.ACTION_RESOLVE_NO_PRIVILEGES,
                        callingPackage,
                        0 /* resolvableErrors */,
                        false /* confirmationCodeRetried */,
                        EuiccOperation.forDownloadNoPrivilegesOrDeactivateSimCheckMetadata(token,
                                subscription, switchAfterDownload, callingPackage));
                sendResult(callbackIntent, RESOLVABLE_ERROR, extrasIntent);
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }
@@ -395,14 +417,14 @@ public class EuiccController extends IEuiccController.Stub {
                }
            } else { // !mWithUserConsent
                if (result.getResult() == EuiccService.RESULT_MUST_DEACTIVATE_SIM) {
                    // If we need to deactivate the current SIM to even check permissions, go ahead
                    // and require that the user resolve the stronger permission dialog.
                    // The caller can manage the target SIM. Ask the user's consent to deactivate
                    // the current SIM.
                    Intent extrasIntent = new Intent();
                    addResolutionIntent(extrasIntent, EuiccService.ACTION_RESOLVE_NO_PRIVILEGES,
                    addResolutionIntent(extrasIntent, EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM,
                            mCallingPackage,
                            0 /* resolvableErrors */,
                            false /* confirmationCodeRetried */,
                            EuiccOperation.forDownloadNoPrivilegesCheckMetadata(
                            EuiccOperation.forDownloadNoPrivilegesOrDeactivateSimCheckMetadata(
                                    mCallingToken, mSubscription, mSwitchAfterDownload,
                                    mCallingPackage));
                    sendResult(mCallbackIntent, RESOLVABLE_ERROR, extrasIntent);
@@ -416,32 +438,12 @@ public class EuiccController extends IEuiccController.Stub {
                }

                if (checkCarrierPrivilegeInMetadata(subscription, mCallingPackage)) {
                    // Caller can download this profile.
                    // On a multi-active SIM device, if the caller can manage the active
                    // subscription on the target SIM, or there is no active subscription on the
                    // target SIM and the caller can manage any active subscription on other SIMs,
                    // we perform the download silently. 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 the download silently; if not,
                    // the user must provide consent.
                    if (canManageSubscriptionOnTargetSim(cardId, mCallingPackage)) {
                    // Caller can download this profile per profile metadata. Also, caller can
                    // manage the subscription on the target SIM, which is already checked.
                    downloadSubscriptionPrivileged(cardId,
                                mCallingToken, subscription, mSwitchAfterDownload,
                                mForceDeactivateSim, mCallingPackage, null /* resolvedBundle */,
                            mCallingToken, subscription, mSwitchAfterDownload, mForceDeactivateSim,
                            mCallingPackage, null /* resolvedBundle */,
                            mCallbackIntent);
                        return;
                    }

                    // Download might still be permitted, but the user must consent first.
                    Intent extrasIntent = new Intent();
                    addResolutionIntent(extrasIntent, EuiccService.ACTION_RESOLVE_NO_PRIVILEGES,
                            mCallingPackage,
                            0 /* resolvableErrors */,
                            false /* confirmationCodeRetried */,
                            EuiccOperation.forDownloadNoPrivileges(
                                    mCallingToken, subscription, mSwitchAfterDownload,
                                    mCallingPackage));
                    sendResult(mCallbackIntent, RESOLVABLE_ERROR, extrasIntent);
                } else {
                    Log.e(TAG, "Caller is not permitted to download this profile per metadata");
                    sendResult(mCallbackIntent, ERROR, null /* extrasIntent */);
+14 −10
Original line number Diff line number Diff line
@@ -88,8 +88,11 @@ public class EuiccOperation implements Parcelable {
    @VisibleForTesting
    @Deprecated
    static final int ACTION_DOWNLOAD_CONFIRMATION_CODE = 8;
    /**
     * ACTION_DOWNLOAD_CHECK_METADATA can be used for either NO_PRIVILEGES or DEACTIVATE_SIM.
     */
    @VisibleForTesting
    static final int ACTION_DOWNLOAD_NO_PRIVILEGES_CHECK_METADATA = 9;
    static final int ACTION_DOWNLOAD_NO_PRIVILEGES_OR_DEACTIVATE_SIM_CHECK_METADATA = 9;

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public final @Action int mAction;
@@ -140,14 +143,15 @@ public class EuiccOperation implements Parcelable {
    }

    /**
     * {@link EuiccManager#downloadSubscription} failed because we cannot determine the
     * privileges without deactivating the current SIM first.
     * {@link EuiccManager#downloadSubscription} failed because the caller can't manage the target
     * SIM, or we cannot determine the privileges without deactivating the current SIM first.
     */
    static EuiccOperation forDownloadNoPrivilegesCheckMetadata(long callingToken,
    static EuiccOperation forDownloadNoPrivilegesOrDeactivateSimCheckMetadata(long callingToken,
            DownloadableSubscription subscription, boolean switchAfterDownload,
            String callingPackage) {
        return new EuiccOperation(ACTION_DOWNLOAD_NO_PRIVILEGES_CHECK_METADATA, callingToken,
            subscription,  0 /* subscriptionId */, switchAfterDownload, callingPackage);
        return new EuiccOperation(ACTION_DOWNLOAD_NO_PRIVILEGES_OR_DEACTIVATE_SIM_CHECK_METADATA,
                callingToken, subscription,  0 /* subscriptionId */,
                switchAfterDownload, callingPackage);
    }

    /**
@@ -280,8 +284,8 @@ public class EuiccOperation implements Parcelable {
                        resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT),
                        callbackIntent);
                break;
            case ACTION_DOWNLOAD_NO_PRIVILEGES_CHECK_METADATA:
                resolvedDownloadNoPrivilegesCheckMetadata(cardId,
            case ACTION_DOWNLOAD_NO_PRIVILEGES_OR_DEACTIVATE_SIM_CHECK_METADATA:
                resolvedDownloadNoPrivilegesOrDeactivateSimCheckMetadata(cardId,
                        resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT),
                        callbackIntent);
                break;
@@ -378,8 +382,8 @@ public class EuiccOperation implements Parcelable {
        }
    }

    private void resolvedDownloadNoPrivilegesCheckMetadata(int cardId, boolean consent,
            PendingIntent callbackIntent) {
    private void resolvedDownloadNoPrivilegesOrDeactivateSimCheckMetadata(int cardId,
            boolean consent, PendingIntent callbackIntent) {
        if (consent) {
            // User has consented; perform the download with full privileges.
            long token = Binder.clearCallingIdentity();
+75 −4
Original line number Diff line number Diff line
@@ -463,6 +463,20 @@ public class EuiccControllerTest extends TelephonyTest {
            throws Exception {
        setHasWriteEmbeddedPermission(false);
        prepareGetDownloadableSubscriptionMetadataCall(false /* complete */, null /* result */);
        callDownloadSubscription(SUBSCRIPTION, true /* switchAfterDownload */, true /* complete */,
                12345, 0 /* resolvableError */, PACKAGE_NAME /* callingPackage */);
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR,
                0 /* detailedCode */);
        verify(mMockConnector, never()).downloadSubscription(anyInt(),
                any(), anyBoolean(), anyBoolean(), any(), any());
    }

    @Test
    public void testDownloadSubscription_noPrivileges_getMetadata_serviceUnavailable_canManageSim()
            throws Exception {
        setHasWriteEmbeddedPermission(false);
        prepareGetDownloadableSubscriptionMetadataCall(false /* complete */, null /* result */);
        setCanManageSubscriptionOnTargetSim(true /* isTargetEuicc */, true /* hasPrivileges */);
        callDownloadSubscription(SUBSCRIPTION, true /* switchAfterDownload */, true /* complete */,
                12345, 0 /* resolvableError */, PACKAGE_NAME /* callingPackage */);
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR,
@@ -478,6 +492,22 @@ public class EuiccControllerTest extends TelephonyTest {
        GetDownloadableSubscriptionMetadataResult result =
                new GetDownloadableSubscriptionMetadataResult(42, null /* subscription */);
        prepareGetDownloadableSubscriptionMetadataCall(true /* complete */, result);
        callDownloadSubscription(SUBSCRIPTION, true /* switchAfterDownload */, true /* complete */,
                12345, 0 /* resolvableError */, PACKAGE_NAME /* callingPackage */);
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR,
                0 /* detailedCode */);
        verify(mMockConnector, never()).downloadSubscription(anyInt(),
                any(), anyBoolean(), anyBoolean(), any(), any());
    }

    @Test
    public void testDownloadSubscription_noPrivileges_getMetadata_error_canManageSim()
            throws Exception {
        setHasWriteEmbeddedPermission(false);
        GetDownloadableSubscriptionMetadataResult result =
                new GetDownloadableSubscriptionMetadataResult(42, null /* subscription */);
        prepareGetDownloadableSubscriptionMetadataCall(true /* complete */, result);
        setCanManageSubscriptionOnTargetSim(true /* isTargetEuicc */, true /* hasPrivileges */);
        callDownloadSubscription(SUBSCRIPTION, true /* switchAfterDownload */, true /* complete */,
                12345, 0 /* resolvableError */, PACKAGE_NAME /* callingPackage */);
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR,
@@ -501,7 +531,26 @@ public class EuiccControllerTest extends TelephonyTest {
        // In this case we go with the potentially stronger NO_PRIVILEGES consent dialog to avoid
        // double prompting.
        verifyResolutionIntent(EuiccService.ACTION_RESOLVE_NO_PRIVILEGES,
                EuiccOperation.ACTION_DOWNLOAD_NO_PRIVILEGES_CHECK_METADATA);
                EuiccOperation.ACTION_DOWNLOAD_NO_PRIVILEGES_OR_DEACTIVATE_SIM_CHECK_METADATA);
    }

    @Test
    public void testDownloadSubscription_noPrivileges_getMetadata_mustDeactivateSim_canManageSim()
            throws Exception {
        setHasWriteEmbeddedPermission(false);
        GetDownloadableSubscriptionMetadataResult result =
                new GetDownloadableSubscriptionMetadataResult(
                    EuiccService.RESULT_MUST_DEACTIVATE_SIM, null /* subscription */);
        prepareGetDownloadableSubscriptionMetadataCall(true /* complete */, result);
        setCanManageSubscriptionOnTargetSim(true /* isTargetEuicc */, true /* hasPrivileges */);
        callDownloadSubscription(SUBSCRIPTION, true /* switchAfterDownload */, true /* complete */,
                12345, 0 /* resolvableError */, PACKAGE_NAME /* callingPackage */);
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR,
                0 /* detailedCode */);
        // In this case we go with the potentially stronger NO_PRIVILEGES consent dialog to avoid
        // double prompting.
        verifyResolutionIntent(EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM,
                EuiccOperation.ACTION_DOWNLOAD_NO_PRIVILEGES_OR_DEACTIVATE_SIM_CHECK_METADATA);
    }

    @Test
@@ -554,7 +603,7 @@ public class EuiccControllerTest extends TelephonyTest {
        verify(mMockConnector, never()).downloadSubscription(anyInt(),
                any(), anyBoolean(), anyBoolean(), any(), any());
        verifyResolutionIntent(EuiccService.ACTION_RESOLVE_NO_PRIVILEGES,
                EuiccOperation.ACTION_DOWNLOAD_NO_PRIVILEGES);
                EuiccOperation.ACTION_DOWNLOAD_NO_PRIVILEGES_OR_DEACTIVATE_SIM_CHECK_METADATA);
    }

    @Test
@@ -574,7 +623,7 @@ public class EuiccControllerTest extends TelephonyTest {
        verify(mMockConnector, never()).downloadSubscription(anyInt(),
                any(), anyBoolean(), anyBoolean(), any(), any());
        verifyResolutionIntent(EuiccService.ACTION_RESOLVE_NO_PRIVILEGES,
                EuiccOperation.ACTION_DOWNLOAD_NO_PRIVILEGES);
                EuiccOperation.ACTION_DOWNLOAD_NO_PRIVILEGES_OR_DEACTIVATE_SIM_CHECK_METADATA);
    }

    @Test
@@ -594,7 +643,7 @@ public class EuiccControllerTest extends TelephonyTest {
        verify(mMockConnector, never()).downloadSubscription(anyInt(),
                any(), anyBoolean(), anyBoolean(), any(), any());
        verifyResolutionIntent(EuiccService.ACTION_RESOLVE_NO_PRIVILEGES,
                EuiccOperation.ACTION_DOWNLOAD_NO_PRIVILEGES);
                EuiccOperation.ACTION_DOWNLOAD_NO_PRIVILEGES_OR_DEACTIVATE_SIM_CHECK_METADATA);
    }

    @Test
@@ -608,6 +657,28 @@ public class EuiccControllerTest extends TelephonyTest {
        pi.packageName = PACKAGE_NAME;
        pi.signatures = new Signature[] { new Signature(new byte[] { 5, 4, 3, 2, 1 }) };
        when(mPackageManager.getPackageInfo(eq(PACKAGE_NAME), anyInt())).thenReturn(pi);
        callDownloadSubscription(SUBSCRIPTION, true /* switchAfterDownload */, true /* complete */,
                12345, 0 /* resolvableError */, PACKAGE_NAME /* callingPackage */);
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR,
                0 /* detailedCode */);
        verify(mTelephonyManager, never()).checkCarrierPrivilegesForPackage(PACKAGE_NAME);
        verify(mMockConnector, never()).downloadSubscription(anyInt(),
                any(), anyBoolean(), anyBoolean(), any(), any());
    }

    @Test
    public void testDownloadSubscription_noPrivileges_noCarrierPrivileges_canManagerTargetSim()
            throws Exception {
        setHasWriteEmbeddedPermission(false);
        GetDownloadableSubscriptionMetadataResult result =
                new GetDownloadableSubscriptionMetadataResult(
                    EuiccService.RESULT_OK, SUBSCRIPTION_WITH_METADATA);
        prepareGetDownloadableSubscriptionMetadataCall(true /* complete */, result);
        PackageInfo pi = new PackageInfo();
        pi.packageName = PACKAGE_NAME;
        pi.signatures = new Signature[] { new Signature(new byte[] { 5, 4, 3, 2, 1 }) };
        when(mPackageManager.getPackageInfo(eq(PACKAGE_NAME), anyInt())).thenReturn(pi);
        setCanManageSubscriptionOnTargetSim(true /* isTargetEuicc */, true /* hasPrivileges */);
        callDownloadSubscription(SUBSCRIPTION, true /* switchAfterDownload */, true /* complete */,
                12345, 0 /* resolvableError */, PACKAGE_NAME /* callingPackage */);
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR,