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

Commit a66e4a64 authored by Peter Wang's avatar Peter Wang Committed by Gerrit Code Review
Browse files

Merge "Add EuiccCardManager.ResetOption to eraseSubscriptions"

parents 655335f3 f6591267
Loading
Loading
Loading
Loading
+30 −2
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package com.android.internal.telephony.euicc;

import static android.telephony.euicc.EuiccCardManager.ResetOption;

import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;

import android.Manifest;
@@ -143,6 +145,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
    private static final int CMD_RETAIN_SUBSCRIPTIONS = 110;
    private static final int CMD_GET_OTA_STATUS = 111;
    private static final int CMD_START_OTA_IF_NECESSARY = 112;
    private static final int CMD_ERASE_SUBSCRIPTIONS_WITH_OPTIONS = 113;

    private static boolean isEuiccCommand(int what) {
        return what >= CMD_GET_EID;
@@ -302,7 +305,9 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
        void onUpdateNicknameComplete(int result);
    }

    /** Callback class for {@link #eraseSubscriptions}. */
    /**
     * Callback class for {@link #eraseSubscriptions} and {@link #eraseSubscriptionsWithOptions}.
     */
    @VisibleForTesting(visibility = PACKAGE)
    public interface EraseCommandCallback extends BaseEuiccCommandCallback {
        /** Called when the erase has completed (though it may have failed). */
@@ -496,12 +501,19 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
        sendMessage(CMD_UPDATE_SUBSCRIPTION_NICKNAME, cardId, 0 /* arg2 */, request);
    }

    /** Asynchronously erase all profiles on the eUICC. */
    /** Asynchronously erase operational profiles on the eUICC. */
    @VisibleForTesting(visibility = PACKAGE)
    public void eraseSubscriptions(int cardId, EraseCommandCallback callback) {
        sendMessage(CMD_ERASE_SUBSCRIPTIONS, cardId, 0 /* arg2 */, callback);
    }

    /** Asynchronously erase specific profiles on the eUICC. */
    @VisibleForTesting(visibility = PACKAGE)
    public void eraseSubscriptionsWithOptions(
            int cardId, @ResetOption int options, EraseCommandCallback callback) {
        sendMessage(CMD_ERASE_SUBSCRIPTIONS_WITH_OPTIONS, cardId, options, callback);
    }

    /** Asynchronously ensure that all profiles will be retained on the next factory reset. */
    @VisibleForTesting(visibility = PACKAGE)
    public void retainSubscriptions(int cardId, RetainSubscriptionsCommandCallback callback) {
@@ -845,6 +857,21 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
                                    });
                            break;
                        }
                        case CMD_ERASE_SUBSCRIPTIONS_WITH_OPTIONS: {
                            mEuiccService.eraseSubscriptionsWithOptions(slotId,
                                    message.arg2 /* options */,
                                    new IEraseSubscriptionsCallback.Stub() {
                                        @Override
                                        public void onComplete(int result) {
                                            sendMessage(CMD_COMMAND_COMPLETE, (Runnable) () -> {
                                                ((EraseCommandCallback) callback)
                                                        .onEraseComplete(result);
                                                onCommandEnd(callback);
                                            });
                                        }
                                    });
                            break;
                        }
                        case CMD_RETAIN_SUBSCRIPTIONS: {
                            mEuiccService.retainSubscriptionsForFactoryReset(slotId,
                                    new IRetainSubscriptionsForFactoryResetCallback.Stub() {
@@ -936,6 +963,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
            case CMD_GET_EUICC_PROFILE_INFO_LIST:
            case CMD_GET_EUICC_INFO:
            case CMD_ERASE_SUBSCRIPTIONS:
            case CMD_ERASE_SUBSCRIPTIONS_WITH_OPTIONS:
            case CMD_RETAIN_SUBSCRIPTIONS:
            case CMD_GET_OTA_STATUS:
            case CMD_START_OTA_IF_NECESSARY:
+45 −1
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.telephony.TelephonyManager;
import android.telephony.UiccAccessRule;
import android.telephony.UiccCardInfo;
import android.telephony.euicc.DownloadableSubscription;
import android.telephony.euicc.EuiccCardManager.ResetOption;
import android.telephony.euicc.EuiccInfo;
import android.telephony.euicc.EuiccManager;
import android.telephony.euicc.EuiccManager.OtaStatus;
@@ -957,7 +958,50 @@ public class EuiccController extends IEuiccController.Stub {
        }
        long token = Binder.clearCallingIdentity();
        try {
            mConnector.eraseSubscriptions(cardId, new EuiccConnector.EraseCommandCallback() {
            mConnector.eraseSubscriptions(
                    cardId, new EuiccConnector.EraseCommandCallback() {
                        @Override
                        public void onEraseComplete(int result) {
                            Intent extrasIntent = new Intent();
                            final int resultCode;
                            switch (result) {
                                case EuiccService.RESULT_OK:
                                    resultCode = OK;
                                    refreshSubscriptionsAndSendResult(
                                            callbackIntent, resultCode, extrasIntent);
                                    return;
                                default:
                                    resultCode = ERROR;
                                    extrasIntent.putExtra(
                                            EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
                                            result);
                                    break;
                            }

                            sendResult(callbackIntent, resultCode, extrasIntent);
                        }

                        @Override
                        public void onEuiccServiceUnavailable() {
                            sendResult(callbackIntent, ERROR, null /* extrasIntent */);
                        }
                    });
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @Override
    public void eraseSubscriptionsWithOptions(
            int cardId, @ResetOption int options, PendingIntent callbackIntent) {
        if (!callerCanWriteEmbeddedSubscriptions()) {
            throw new SecurityException(
                    "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to erase subscriptions");
        }
        long token = Binder.clearCallingIdentity();
        try {
            mConnector.eraseSubscriptionsWithOptions(
                    cardId, options, new EuiccConnector.EraseCommandCallback() {
                @Override
                public void onEraseComplete(int result) {
                    Intent extrasIntent = new Intent();
+51 −2
Original line number Diff line number Diff line
@@ -15,6 +15,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 org.junit.Assert.assertEquals;
@@ -984,8 +985,7 @@ public class EuiccControllerTest extends TelephonyTest {
    public void testEraseSubscriptions_error() throws Exception {
        setHasWriteEmbeddedPermission(true);
        callEraseSubscriptions(true /* complete */, 42 /* result */);
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR,
                42 /* detailedCode */);
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR, 42 /* detailedCode */);
    }

    @Test
@@ -996,6 +996,36 @@ public class EuiccControllerTest extends TelephonyTest {
        assertTrue(mController.mCalledRefreshSubscriptionsAndSendResult);
    }

    @Test(expected = SecurityException.class)
    public void testEraseSubscriptionsWithOptions_noPrivileges() throws Exception {
        setHasWriteEmbeddedPermission(false);
        callEraseSubscriptionsWithOptions(false /* complete */, 0 /* result */);
    }

    @Test
    public void testEraseSubscriptionsWithOptions_serviceUnavailable() throws Exception {
        setHasWriteEmbeddedPermission(true);
        callEraseSubscriptionsWithOptions(false /* complete */, 0 /* result */);
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR,
                0 /* detailedCode */);
        verify(mMockConnector).eraseSubscriptionsWithOptions(anyInt(), anyInt(), any());
    }

    @Test
    public void testEraseSubscriptionsWithOptions_error() throws Exception {
        setHasWriteEmbeddedPermission(true);
        callEraseSubscriptionsWithOptions(true /* complete */, 42 /* result */);
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR, 42 /* detailedCode */);
    }

    @Test
    public void testEraseSubscriptionsWithOptions_success() throws Exception {
        setHasWriteEmbeddedPermission(true);
        callEraseSubscriptionsWithOptions(true /* complete */, EuiccService.RESULT_OK);
        verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK, 0 /* detailedCode */);
        assertTrue(mController.mCalledRefreshSubscriptionsAndSendResult);
    }

    @Test(expected = SecurityException.class)
    public void testRetainSubscriptionsForFactoryReset_noPrivileges() throws Exception {
        setHasMasterClearPermission(false);
@@ -1318,6 +1348,25 @@ public class EuiccControllerTest extends TelephonyTest {
        mController.eraseSubscriptions(CARD_ID, resultCallback);
    }

    private void callEraseSubscriptionsWithOptions(final boolean complete, final int result) {
        PendingIntent resultCallback = PendingIntent.getBroadcast(mContext, 0, new Intent(), 0);
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Exception {
                EuiccConnector.EraseCommandCallback cb = invocation
                        .getArgument(2 /* resultCallback */);
                if (complete) {
                    cb.onEraseComplete(result);
                } else {
                    cb.onEuiccServiceUnavailable();
                }
                return null;
            }
        }).when(mMockConnector).eraseSubscriptionsWithOptions(anyInt(), anyInt(), any());
        mController.eraseSubscriptionsWithOptions(CARD_ID,
                RESET_OPTION_DELETE_OPERATIONAL_PROFILES, resultCallback);
    }

    private void callRetainSubscriptionsForFactoryReset(final boolean complete, final int result) {
        PendingIntent resultCallback = PendingIntent.getBroadcast(mContext, 0, new Intent(), 0);
        doAnswer(new Answer<Void>() {