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

Commit 9ec9d708 authored by Jordan Liu's avatar Jordan Liu Committed by Gerrit Code Review
Browse files

Merge "EuiccController/Connector support multiple eUICCs"

parents bdefc6b3 8ad00f7a
Loading
Loading
Loading
Loading
+49 −28
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@ import android.service.euicc.IRetainSubscriptionsForFactoryResetCallback;
import android.service.euicc.ISwitchToSubscriptionCallback;
import android.service.euicc.IUpdateSubscriptionNicknameCallback;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccCardInfo;
import android.telephony.euicc.DownloadableSubscription;
import android.telephony.euicc.EuiccInfo;
import android.telephony.euicc.EuiccManager;
@@ -219,7 +221,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
    @VisibleForTesting(visibility = PACKAGE)
    public interface GetMetadataCommandCallback extends BaseEuiccCommandCallback {
        /** Called when the metadata lookup has completed (though it may have failed). */
        void onGetMetadataComplete(GetDownloadableSubscriptionMetadataResult result);
        void onGetMetadataComplete(int cardId, GetDownloadableSubscriptionMetadataResult result);
    }

    static class DownloadRequest {
@@ -394,37 +396,38 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {

    /** Asynchronously fetch the EID. */
    @VisibleForTesting(visibility = PACKAGE)
    public void getEid(GetEidCommandCallback callback) {
        sendMessage(CMD_GET_EID, callback);
    public void getEid(int cardId, GetEidCommandCallback callback) {
        sendMessage(CMD_GET_EID, cardId, 0 /* arg2 */, callback);
    }

    /** Asynchronously get OTA status. */
    @VisibleForTesting(visibility = PACKAGE)
    public void getOtaStatus(GetOtaStatusCommandCallback callback) {
        sendMessage(CMD_GET_OTA_STATUS, callback);
    public void getOtaStatus(int cardId, GetOtaStatusCommandCallback callback) {
        sendMessage(CMD_GET_OTA_STATUS, cardId, 0 /* arg2 */, callback);
    }

    /** Asynchronously perform OTA update. */
    @VisibleForTesting(visibility = PACKAGE)
    public void startOtaIfNecessary(OtaStatusChangedCallback callback) {
        sendMessage(CMD_START_OTA_IF_NECESSARY, callback);
    public void startOtaIfNecessary(int cardId, OtaStatusChangedCallback callback) {
        sendMessage(CMD_START_OTA_IF_NECESSARY, cardId, 0 /* arg2 */, callback);
    }

    /** Asynchronously fetch metadata for the given downloadable subscription. */
    @VisibleForTesting(visibility = PACKAGE)
    public void getDownloadableSubscriptionMetadata(DownloadableSubscription subscription,
    public void getDownloadableSubscriptionMetadata(int cardId,
            DownloadableSubscription subscription,
            boolean forceDeactivateSim, GetMetadataCommandCallback callback) {
        GetMetadataRequest request =
                new GetMetadataRequest();
        request.mSubscription = subscription;
        request.mForceDeactivateSim = forceDeactivateSim;
        request.mCallback = callback;
        sendMessage(CMD_GET_DOWNLOADABLE_SUBSCRIPTION_METADATA, request);
        sendMessage(CMD_GET_DOWNLOADABLE_SUBSCRIPTION_METADATA, cardId, 0 /* arg2 */, request);
    }

    /** Asynchronously download the given subscription. */
    @VisibleForTesting(visibility = PACKAGE)
    public void downloadSubscription(DownloadableSubscription subscription,
    public void downloadSubscription(int cardId, DownloadableSubscription subscription,
            boolean switchAfterDownload, boolean forceDeactivateSim,
            Bundle resolvedBundle, DownloadCommandCallback callback) {
        DownloadRequest request = new DownloadRequest();
@@ -433,7 +436,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
        request.mForceDeactivateSim = forceDeactivateSim;
        request.mResolvedBundle = resolvedBundle;
        request.mCallback = callback;
        sendMessage(CMD_DOWNLOAD_SUBSCRIPTION, request);
        sendMessage(CMD_DOWNLOAD_SUBSCRIPTION, cardId, 0 /* arg2 */, request);
    }

    void getEuiccProfileInfoList(int cardId, GetEuiccProfileInfoListCommandCallback callback) {
@@ -442,61 +445,61 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {

    /** Asynchronously fetch the default downloadable subscription list. */
    @VisibleForTesting(visibility = PACKAGE)
    public void getDefaultDownloadableSubscriptionList(
    public void getDefaultDownloadableSubscriptionList(int cardId,
            boolean forceDeactivateSim, GetDefaultListCommandCallback callback) {
        GetDefaultListRequest request = new GetDefaultListRequest();
        request.mForceDeactivateSim = forceDeactivateSim;
        request.mCallback = callback;
        sendMessage(CMD_GET_DEFAULT_DOWNLOADABLE_SUBSCRIPTION_LIST, request);
        sendMessage(CMD_GET_DEFAULT_DOWNLOADABLE_SUBSCRIPTION_LIST, cardId, 0 /* arg2 */, request);
    }

    /** Asynchronously fetch the {@link EuiccInfo}. */
    @VisibleForTesting(visibility = PACKAGE)
    public void getEuiccInfo(GetEuiccInfoCommandCallback callback) {
        sendMessage(CMD_GET_EUICC_INFO, callback);
    public void getEuiccInfo(int cardId, GetEuiccInfoCommandCallback callback) {
        sendMessage(CMD_GET_EUICC_INFO, cardId, 0 /* arg2 */, callback);
    }

    /** Asynchronously delete the given subscription. */
    @VisibleForTesting(visibility = PACKAGE)
    public void deleteSubscription(String iccid, DeleteCommandCallback callback) {
    public void deleteSubscription(int cardId, String iccid, DeleteCommandCallback callback) {
        DeleteRequest request = new DeleteRequest();
        request.mIccid = iccid;
        request.mCallback = callback;
        sendMessage(CMD_DELETE_SUBSCRIPTION, request);
        sendMessage(CMD_DELETE_SUBSCRIPTION, cardId, 0 /* arg2 */, request);
    }

    /** Asynchronously switch to the given subscription. */
    @VisibleForTesting(visibility = PACKAGE)
    public void switchToSubscription(@Nullable String iccid, boolean forceDeactivateSim,
    public void switchToSubscription(int cardId, @Nullable String iccid, boolean forceDeactivateSim,
            SwitchCommandCallback callback) {
        SwitchRequest request = new SwitchRequest();
        request.mIccid = iccid;
        request.mForceDeactivateSim = forceDeactivateSim;
        request.mCallback = callback;
        sendMessage(CMD_SWITCH_TO_SUBSCRIPTION, request);
        sendMessage(CMD_SWITCH_TO_SUBSCRIPTION, cardId, 0 /* arg2 */, request);
    }

    /** Asynchronously update the nickname of the given subscription. */
    @VisibleForTesting(visibility = PACKAGE)
    public void updateSubscriptionNickname(
    public void updateSubscriptionNickname(int cardId,
            String iccid, String nickname, UpdateNicknameCommandCallback callback) {
        UpdateNicknameRequest request = new UpdateNicknameRequest();
        request.mIccid = iccid;
        request.mNickname = nickname;
        request.mCallback = callback;
        sendMessage(CMD_UPDATE_SUBSCRIPTION_NICKNAME, request);
        sendMessage(CMD_UPDATE_SUBSCRIPTION_NICKNAME, cardId, 0 /* arg2 */, request);
    }

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

    /** Asynchronously ensure that all profiles will be retained on the next factory reset. */
    @VisibleForTesting(visibility = PACKAGE)
    public void retainSubscriptions(RetainSubscriptionsCommandCallback callback) {
        sendMessage(CMD_RETAIN_SUBSCRIPTIONS, callback);
    public void retainSubscriptions(int cardId, RetainSubscriptionsCommandCallback callback) {
        sendMessage(CMD_RETAIN_SUBSCRIPTIONS, cardId, 0 /* arg2 */, callback);
    }

    /**
@@ -671,8 +674,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
            } else if (isEuiccCommand(message.what)) {
                final BaseEuiccCommandCallback callback = getCallback(message);
                onCommandStart(callback);
                // TODO(b/36260308): Plumb through an actual SIM slot ID.
                int slotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
                final int slotId = getSlotIdFromCardId(message.arg1);
                try {
                    switch (message.what) {
                        case CMD_GET_EID: {
@@ -700,7 +702,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
                                                GetDownloadableSubscriptionMetadataResult result) {
                                            sendMessage(CMD_COMMAND_COMPLETE, (Runnable) () -> {
                                                ((GetMetadataCommandCallback) callback)
                                                        .onGetMetadataComplete(result);
                                                        .onGetMetadataComplete(slotId, result);
                                                onCommandEnd(callback);
                                            });
                                        }
@@ -946,6 +948,25 @@ public class EuiccConnector extends StateMachine implements ServiceConnection {
        }
    }

    /**
     * Gets the slot ID from the card ID.
     */
    private int getSlotIdFromCardId(int cardId) {
        TelephonyManager tm = (TelephonyManager)
                mContext.getSystemService(Context.TELEPHONY_SERVICE);
        UiccCardInfo[] infos = tm.getUiccCardsInfo();
        if (infos == null) {
            return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
        }
        int slotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
        for (UiccCardInfo info : infos) {
            if (info.getCardId() == cardId) {
                slotId = info.getSlotIndex();
            }
        }
        return slotId;
    }

    /** Call this at the beginning of the execution of any command. */
    private void onCommandStart(BaseEuiccCommandCallback callback) {
        mActiveCommandCallbacks.add(callback);
+74 −56

File changed.

Preview size limit exceeded, changes collapsed.

+35 −22
Original line number Diff line number Diff line
@@ -245,7 +245,8 @@ public class EuiccOperation implements Parcelable {
     *     {@link EuiccManager#continueOperation}.
     * @param callbackIntent The callback intent to trigger after the operation completes.
     */
    public void continueOperation(Bundle resolutionExtras, PendingIntent callbackIntent) {
    public void continueOperation(int cardId, Bundle resolutionExtras,
            PendingIntent callbackIntent) {
        // Restore the identity of the caller. We should err on the side of caution and redo any
        // permission checks before continuing with the operation in case the caller state has
        // changed. Resolution flows can re-clear the identity if required.
@@ -253,40 +254,40 @@ public class EuiccOperation implements Parcelable {

        switch (mAction) {
            case ACTION_GET_METADATA_DEACTIVATE_SIM:
                resolvedGetMetadataDeactivateSim(
                resolvedGetMetadataDeactivateSim(cardId,
                        resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT),
                        callbackIntent);
                break;
            case ACTION_DOWNLOAD_DEACTIVATE_SIM:
                resolvedDownloadDeactivateSim(
                resolvedDownloadDeactivateSim(cardId,
                        resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT),
                        callbackIntent);
                break;
            case ACTION_DOWNLOAD_NO_PRIVILEGES:
                resolvedDownloadNoPrivileges(
                resolvedDownloadNoPrivileges(cardId,
                        resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT),
                        callbackIntent);
                break;
            case ACTION_DOWNLOAD_CONFIRMATION_CODE: // Deprecated case
                resolvedDownloadConfirmationCode(
                resolvedDownloadConfirmationCode(cardId,
                        resolutionExtras.getString(EuiccService.EXTRA_RESOLUTION_CONFIRMATION_CODE),
                        callbackIntent);
                break;
            case ACTION_DOWNLOAD_RESOLVABLE_ERRORS:
                resolvedDownloadResolvableErrors(resolutionExtras, callbackIntent);
                resolvedDownloadResolvableErrors(cardId, resolutionExtras, callbackIntent);
                break;
            case ACTION_GET_DEFAULT_LIST_DEACTIVATE_SIM:
                resolvedGetDefaultListDeactivateSim(
                resolvedGetDefaultListDeactivateSim(cardId,
                        resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT),
                        callbackIntent);
                break;
            case ACTION_SWITCH_DEACTIVATE_SIM:
                resolvedSwitchDeactivateSim(
                resolvedSwitchDeactivateSim(cardId,
                        resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT),
                        callbackIntent);
                break;
            case ACTION_SWITCH_NO_PRIVILEGES:
                resolvedSwitchNoPrivileges(
                resolvedSwitchNoPrivileges(cardId,
                        resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT),
                        callbackIntent);
                break;
@@ -296,12 +297,13 @@ public class EuiccOperation implements Parcelable {
        }
    }

    private void resolvedGetMetadataDeactivateSim(
            boolean consent, PendingIntent callbackIntent) {
    private void resolvedGetMetadataDeactivateSim(int cardId, boolean consent,
            PendingIntent callbackIntent) {
        if (consent) {
            // User has consented; perform the lookup, but this time, tell the LPA to deactivate any
            // required active SIMs.
            EuiccController.get().getDownloadableSubscriptionMetadata(
                    cardId,
                    mDownloadableSubscription,
                    true /* forceDeactivateSim */,
                    mCallingPackage,
@@ -312,12 +314,13 @@ public class EuiccOperation implements Parcelable {
        }
    }

    private void resolvedDownloadDeactivateSim(
            boolean consent, PendingIntent callbackIntent) {
    private void resolvedDownloadDeactivateSim(int cardId, boolean consent,
            PendingIntent callbackIntent) {
        if (consent) {
            // User has consented; perform the download, but this time, tell the LPA to deactivate
            // any required active SIMs.
            EuiccController.get().downloadSubscription(
                    cardId,
                    mDownloadableSubscription,
                    mSwitchAfterDownload,
                    mCallingPackage,
@@ -330,7 +333,8 @@ public class EuiccOperation implements Parcelable {
        }
    }

    private void resolvedDownloadNoPrivileges(boolean consent, PendingIntent callbackIntent) {
    private void resolvedDownloadNoPrivileges(int cardId, boolean consent,
            PendingIntent callbackIntent) {
        if (consent) {
            // User has consented; perform the download with full privileges.
            long token = Binder.clearCallingIdentity();
@@ -340,6 +344,7 @@ public class EuiccOperation implements Parcelable {
                // the privilege prompt makes it clear that we're switching from the current
                // carrier.
                EuiccController.get().downloadSubscriptionPrivileged(
                        cardId,
                        token,
                        mDownloadableSubscription,
                        mSwitchAfterDownload,
@@ -361,13 +366,14 @@ public class EuiccOperation implements Parcelable {
     * {@link #resolvedDownloadResolvableErrors(Bundle, PendingIntent)} from Q.
     */
    @Deprecated
    private void resolvedDownloadConfirmationCode(String confirmationCode,
    private void resolvedDownloadConfirmationCode(int cardId, String confirmationCode,
            PendingIntent callbackIntent) {
        if (TextUtils.isEmpty(confirmationCode)) {
            fail(callbackIntent);
        } else {
            mDownloadableSubscription.setConfirmationCode(confirmationCode);
            EuiccController.get().downloadSubscription(
                    cardId,
                    mDownloadableSubscription,
                    mSwitchAfterDownload,
                    mCallingPackage,
@@ -377,7 +383,7 @@ public class EuiccOperation implements Parcelable {
        }
    }

    private void resolvedDownloadResolvableErrors(Bundle resolvedBundle,
    private void resolvedDownloadResolvableErrors(int cardId, Bundle resolvedBundle,
            PendingIntent callbackIntent) {
        boolean pass = true;
        String confirmationCode = null;
@@ -401,6 +407,7 @@ public class EuiccOperation implements Parcelable {
        } else {
            mDownloadableSubscription.setConfirmationCode(confirmationCode);
            EuiccController.get().downloadSubscription(
                    cardId,
                    mDownloadableSubscription,
                    mSwitchAfterDownload,
                    mCallingPackage,
@@ -410,25 +417,29 @@ public class EuiccOperation implements Parcelable {
        }
    }

    private void resolvedGetDefaultListDeactivateSim(
            boolean consent, PendingIntent callbackIntent) {
    private void resolvedGetDefaultListDeactivateSim(int cardId, boolean consent,
            PendingIntent callbackIntent) {
        if (consent) {
            // User has consented; perform the lookup, but this time, tell the LPA to deactivate any
            // required active SIMs.
            EuiccController.get().getDefaultDownloadableSubscriptionList(
                    true /* forceDeactivateSim */, mCallingPackage, callbackIntent);
                    cardId,
                    true /* forceDeactivateSim */,
                    mCallingPackage,
                    callbackIntent);
        } else {
            // User has not consented; fail the operation.
            fail(callbackIntent);
        }
    }

    private void resolvedSwitchDeactivateSim(
            boolean consent, PendingIntent callbackIntent) {
    private void resolvedSwitchDeactivateSim(int cardId, boolean consent,
            PendingIntent callbackIntent) {
        if (consent) {
            // User has consented; perform the switch, but this time, tell the LPA to deactivate any
            // required active SIMs.
            EuiccController.get().switchToSubscription(
                    cardId,
                    mSubscriptionId,
                    true /* forceDeactivateSim */,
                    mCallingPackage,
@@ -439,7 +450,8 @@ public class EuiccOperation implements Parcelable {
        }
    }

    private void resolvedSwitchNoPrivileges(boolean consent, PendingIntent callbackIntent) {
    private void resolvedSwitchNoPrivileges(int cardId, boolean consent,
            PendingIntent callbackIntent) {
        if (consent) {
            // User has consented; perform the switch with full privileges.
            long token = Binder.clearCallingIdentity();
@@ -451,6 +463,7 @@ public class EuiccOperation implements Parcelable {
                // even reach this point, because we cannot fetch the metadata needed to check the
                // privileges without doing so.
                EuiccController.get().switchToSubscriptionPrivileged(
                        cardId,
                        token,
                        mSubscriptionId,
                        true /* forceDeactivateSim */,
+2 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;

@@ -82,7 +83,7 @@ public class EuiccCardControllerTest extends TelephonyTest {
        mOtaStarted = false;
        mOtaLatch = new CountDownLatch(1);

        when(mEuiccController.getOtaStatus()).thenReturn(EuiccManager.EUICC_OTA_SUCCEEDED);
        when(mEuiccController.getOtaStatus(anyInt())).thenReturn(EuiccManager.EUICC_OTA_SUCCEEDED);
        doAnswer(new Answer<Void>() {
                @Override
                public Void answer(InvocationOnMock invocation) throws Throwable {
+11 −8
Original line number Diff line number Diff line
@@ -67,6 +67,8 @@ public class EuiccConnectorTest extends TelephonyTest {
    private EuiccConnector mConnector;
    @Mock private IEuiccService.Stub mEuiccService;

    private static final int CARD_ID = 15;

    @Before
    public void setUp() throws Exception {
        super.setUp("EuiccConnectorTest");
@@ -114,7 +116,7 @@ public class EuiccConnectorTest extends TelephonyTest {
                false /* hasPriority */);
        mConnector = new EuiccConnector(mContext, mLooper.getLooper());
        final AtomicBoolean called = new AtomicBoolean(false);
        mConnector.getEid(new EuiccConnector.GetEidCommandCallback() {
        mConnector.getEid(CARD_ID, new EuiccConnector.GetEidCommandCallback() {
            @Override
            public void onGetEidComplete(String eid) {
                fail("Command should have failed");
@@ -135,7 +137,8 @@ public class EuiccConnectorTest extends TelephonyTest {
                false /* hasPriority */);
        mConnector = new EuiccConnector(mContext, mLooper.getLooper());
        final AtomicBoolean called = new AtomicBoolean(false);
        mConnector.switchToSubscription("12345", true, new EuiccConnector.SwitchCommandCallback() {
        mConnector.switchToSubscription(CARD_ID, "12345", true, new
                EuiccConnector.SwitchCommandCallback() {
            @Override
            public void onSwitchComplete(int result) {
                fail("Command should have failed");
@@ -210,7 +213,7 @@ public class EuiccConnectorTest extends TelephonyTest {
            }
        }).when(mEuiccService).getEid(anyInt(), Mockito.<IGetEidCallback>any());
        final AtomicReference<String> eidRef = new AtomicReference<>();
        mConnector.getEid(new EuiccConnector.GetEidCommandCallback() {
        mConnector.getEid(CARD_ID, new EuiccConnector.GetEidCommandCallback() {
            @Override
            public void onGetEidComplete(String eid) {
                if (eidRef.get() != null) {
@@ -236,7 +239,7 @@ public class EuiccConnectorTest extends TelephonyTest {
        doThrow(new RemoteException("failure"))
                .when(mEuiccService).getEid(anyInt(), Mockito.<IGetEidCallback>any());
        final AtomicBoolean called = new AtomicBoolean(false);
        mConnector.getEid(new EuiccConnector.GetEidCommandCallback() {
        mConnector.getEid(CARD_ID, new EuiccConnector.GetEidCommandCallback() {
            @Override
            public void onGetEidComplete(String eid) {
                fail("Command should have failed");
@@ -258,7 +261,7 @@ public class EuiccConnectorTest extends TelephonyTest {
                true /* hasPriority */);
        mConnector = new EuiccConnector(mContext, mLooper.getLooper());
        final AtomicBoolean called = new AtomicBoolean(false);
        mConnector.getEid(new EuiccConnector.GetEidCommandCallback() {
        mConnector.getEid(CARD_ID, new EuiccConnector.GetEidCommandCallback() {
            @Override
            public void onGetEidComplete(String eid) {
                fail("Unexpected command success callback");
@@ -288,7 +291,7 @@ public class EuiccConnectorTest extends TelephonyTest {
        ArgumentCaptor<IGetEidCallback> callbackCaptor =
                ArgumentCaptor.forClass(IGetEidCallback.class);
        doNothing().when(mEuiccService).getEid(anyInt(), callbackCaptor.capture());
        mConnector.getEid(new EuiccConnector.GetEidCommandCallback() {
        mConnector.getEid(CARD_ID, new EuiccConnector.GetEidCommandCallback() {
            @Override public void onGetEidComplete(String eid) {}
            @Override public void onEuiccServiceUnavailable() {}
        });
@@ -316,11 +319,11 @@ public class EuiccConnectorTest extends TelephonyTest {
        ArgumentCaptor<IGetEidCallback> callbackCaptor =
                ArgumentCaptor.forClass(IGetEidCallback.class);
        doNothing().when(mEuiccService).getEid(anyInt(), callbackCaptor.capture());
        mConnector.getEid(new EuiccConnector.GetEidCommandCallback() {
        mConnector.getEid(CARD_ID, new EuiccConnector.GetEidCommandCallback() {
            @Override public void onGetEidComplete(String eid) {}
            @Override public void onEuiccServiceUnavailable() {}
        });
        mConnector.getEid(new EuiccConnector.GetEidCommandCallback() {
        mConnector.getEid(CARD_ID, new EuiccConnector.GetEidCommandCallback() {
            @Override public void onGetEidComplete(String eid) {}
            @Override public void onEuiccServiceUnavailable() {}
        });
Loading