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

Commit 34aaaec6 authored by Holly Jiuyu Sun's avatar Holly Jiuyu Sun Committed by android-build-merger
Browse files

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

am: b0136b8e

Change-Id: I3e8d54f6bffb6ed4a7f6aa1a08e38cb4cfdb2324
parents 4abd5467 b0136b8e
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,