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

Commit 9fc39674 authored by Peter Wang's avatar Peter Wang
Browse files

Add EuiccCardManager.ResetOption to eraseSubscriptions

Bug: 139474431
Test: on device
Change-Id: I9d5945e8f3f2e4e1cca09350c9027b532004c623
parent 8e8e6c19
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;
@@ -144,6 +146,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;
@@ -303,7 +306,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). */
@@ -492,12 +497,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) {
@@ -839,6 +851,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() {
@@ -930,6 +957,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>() {