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

Commit f08175e5 authored by Jordan Liu's avatar Jordan Liu
Browse files

EuiccController/Connector support multiple eUICCs

This is done using cardId, which is then converted into the slotId. The
reason for the conversion is that the EuiccService API was already
defined using the slot index, and we can't change the existing API
without deprectating all the functions.

Bug: 80097562
Test: manual
Change-Id: I6087f26b90960fd26bc989fb71b534d3d92f48e0
parent 9f2235e9
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);
Loading