Home | History | Annotate | Download | only in euicc
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.telephony.euicc;
     18 
     19 import android.annotation.Nullable;
     20 import android.app.AppOpsManager;
     21 import android.content.BroadcastReceiver;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.IntentFilter;
     25 import android.content.SharedPreferences;
     26 import android.content.pm.ComponentInfo;
     27 import android.os.Binder;
     28 import android.os.Handler;
     29 import android.os.RemoteException;
     30 import android.os.ServiceManager;
     31 import android.preference.PreferenceManager;
     32 import android.provider.Settings;
     33 import android.service.euicc.EuiccProfileInfo;
     34 import android.telephony.TelephonyManager;
     35 import android.telephony.euicc.EuiccCardManager;
     36 import android.telephony.euicc.EuiccNotification;
     37 import android.telephony.euicc.EuiccRulesAuthTable;
     38 import android.text.TextUtils;
     39 import android.util.Log;
     40 
     41 import com.android.internal.annotations.VisibleForTesting;
     42 import com.android.internal.telephony.SubscriptionController;
     43 import com.android.internal.telephony.uicc.UiccController;
     44 import com.android.internal.telephony.uicc.UiccSlot;
     45 import com.android.internal.telephony.uicc.euicc.EuiccCard;
     46 import com.android.internal.telephony.uicc.euicc.EuiccCardErrorException;
     47 import com.android.internal.telephony.uicc.euicc.async.AsyncResultCallback;
     48 
     49 import java.io.FileDescriptor;
     50 import java.io.PrintWriter;
     51 
     52 /** Backing implementation of {@link EuiccCardManager}. */
     53 public class EuiccCardController extends IEuiccCardController.Stub {
     54     private static final String TAG = "EuiccCardController";
     55     private static final String KEY_LAST_BOOT_COUNT = "last_boot_count";
     56 
     57     private final Context mContext;
     58     private AppOpsManager mAppOps;
     59     private String mCallingPackage;
     60     private ComponentInfo mBestComponent;
     61     private Handler mEuiccMainThreadHandler;
     62     private SimSlotStatusChangedBroadcastReceiver mSimSlotStatusChangeReceiver;
     63     private EuiccController mEuiccController;
     64     private UiccController mUiccController;
     65 
     66     private static EuiccCardController sInstance;
     67 
     68     private class SimSlotStatusChangedBroadcastReceiver extends BroadcastReceiver {
     69         @Override
     70         public void onReceive(Context context, Intent intent) {
     71             if (TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED.equals(intent.getAction())) {
     72                 if (isEmbeddedSlotActivated()) {
     73                     mEuiccController.startOtaUpdatingIfNecessary();
     74                 }
     75                 mContext.unregisterReceiver(mSimSlotStatusChangeReceiver);
     76             }
     77         }
     78     }
     79 
     80     /** Initialize the instance. Should only be called once. */
     81     public static EuiccCardController init(Context context) {
     82         synchronized (EuiccCardController.class) {
     83             if (sInstance == null) {
     84                 sInstance = new EuiccCardController(context);
     85             } else {
     86                 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
     87             }
     88         }
     89         return sInstance;
     90     }
     91 
     92     /** Get an instance. Assumes one has already been initialized with {@link #init}. */
     93     public static EuiccCardController get() {
     94         if (sInstance == null) {
     95             synchronized (EuiccCardController.class) {
     96                 if (sInstance == null) {
     97                     throw new IllegalStateException("get() called before init()");
     98                 }
     99             }
    100         }
    101         return sInstance;
    102     }
    103 
    104     private EuiccCardController(Context context) {
    105         this(context, new Handler(), EuiccController.get(), UiccController.getInstance());
    106         ServiceManager.addService("euicc_card_controller", this);
    107     }
    108 
    109     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    110     public EuiccCardController(
    111             Context context,
    112             Handler handler,
    113             EuiccController euiccController,
    114             UiccController uiccController) {
    115         mContext = context;
    116         mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
    117 
    118         mEuiccMainThreadHandler = handler;
    119         mUiccController = uiccController;
    120         mEuiccController = euiccController;
    121 
    122         if (isBootUp(mContext)) {
    123             mSimSlotStatusChangeReceiver = new SimSlotStatusChangedBroadcastReceiver();
    124             mContext.registerReceiver(
    125                     mSimSlotStatusChangeReceiver,
    126                     new IntentFilter(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
    127         }
    128     }
    129 
    130     /**
    131      * Check whether the restored boot count is the same as current one. If not, update the restored
    132      * one.
    133      */
    134     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    135     public static boolean isBootUp(Context context) {
    136         int bootCount = Settings.Global.getInt(
    137                 context.getContentResolver(), Settings.Global.BOOT_COUNT, -1);
    138         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
    139         int lastBootCount = sp.getInt(KEY_LAST_BOOT_COUNT, -1);
    140         if (bootCount == -1 || lastBootCount == -1 || bootCount != lastBootCount) {
    141             sp.edit().putInt(KEY_LAST_BOOT_COUNT, bootCount).apply();
    142             return true;
    143         }
    144         return false;
    145     }
    146 
    147     /** Whether embedded slot is activated or not. */
    148     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    149     public boolean isEmbeddedSlotActivated() {
    150         UiccSlot[] slots = mUiccController.getUiccSlots();
    151         if (slots == null) {
    152             return false;
    153         }
    154         for (int i = 0; i < slots.length; ++i) {
    155             UiccSlot slotInfo = slots[i];
    156             if (slotInfo.isEuicc() && slotInfo.isActive()) {
    157                 return true;
    158             }
    159         }
    160         return false;
    161     }
    162 
    163     private void checkCallingPackage(String callingPackage) {
    164         // Check the caller is LPA.
    165         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
    166         mCallingPackage = callingPackage;
    167         mBestComponent = EuiccConnector.findBestComponent(mContext.getPackageManager());
    168         if (mBestComponent == null
    169                 || !TextUtils.equals(mCallingPackage, mBestComponent.packageName)) {
    170             throw new SecurityException("The calling package can only be LPA.");
    171         }
    172     }
    173 
    174     private EuiccCard getEuiccCard(String cardId) {
    175         UiccController controller = UiccController.getInstance();
    176         int slotId = controller.getUiccSlotForCardId(cardId);
    177         if (slotId != UiccController.INVALID_SLOT_ID) {
    178             UiccSlot slot = controller.getUiccSlot(slotId);
    179             if (slot.isEuicc()) {
    180                 return (EuiccCard) controller.getUiccCardForSlot(slotId);
    181             }
    182         }
    183         loge("EuiccCard is null. CardId : " + cardId);
    184         return null;
    185     }
    186 
    187     private int getResultCode(Throwable e) {
    188         if (e instanceof EuiccCardErrorException) {
    189             return ((EuiccCardErrorException) e).getErrorCode();
    190         }
    191         return EuiccCardManager.RESULT_UNKNOWN_ERROR;
    192     }
    193 
    194     @Override
    195     public void getAllProfiles(String callingPackage, String cardId,
    196             IGetAllProfilesCallback callback) {
    197         checkCallingPackage(callingPackage);
    198 
    199         EuiccCard card = getEuiccCard(cardId);
    200         if (card == null) {
    201             try {
    202                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    203             } catch (RemoteException exception) {
    204                 loge("getAllProfiles callback failure.", exception);
    205             }
    206             return;
    207         }
    208 
    209         AsyncResultCallback<EuiccProfileInfo[]> cardCb =
    210                 new AsyncResultCallback<EuiccProfileInfo[]>() {
    211             @Override
    212             public void onResult(EuiccProfileInfo[] result) {
    213                 try {
    214                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
    215                 } catch (RemoteException exception) {
    216                     loge("getAllProfiles callback failure.", exception);
    217                 }
    218             }
    219 
    220             @Override
    221             public void onException(Throwable e) {
    222                 try {
    223                     loge("getAllProfiles callback onException: ", e);
    224                     callback.onComplete(getResultCode(e), null);
    225                 } catch (RemoteException exception) {
    226                     loge("getAllProfiles callback failure.", exception);
    227                 }
    228             }
    229         };
    230 
    231         card.getAllProfiles(cardCb, mEuiccMainThreadHandler);
    232     }
    233 
    234     @Override
    235     public void getProfile(String callingPackage, String cardId, String iccid,
    236             IGetProfileCallback callback) {
    237         checkCallingPackage(callingPackage);
    238 
    239         EuiccCard card = getEuiccCard(cardId);
    240         if (card == null) {
    241             try {
    242                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    243             } catch (RemoteException exception) {
    244                 loge("getProfile callback failure.", exception);
    245             }
    246             return;
    247         }
    248 
    249         AsyncResultCallback<EuiccProfileInfo> cardCb = new AsyncResultCallback<EuiccProfileInfo>() {
    250                     @Override
    251                     public void onResult(EuiccProfileInfo result) {
    252                         try {
    253                             callback.onComplete(EuiccCardManager.RESULT_OK, result);
    254                         } catch (RemoteException exception) {
    255                             loge("getProfile callback failure.", exception);
    256                         }
    257                     }
    258 
    259                     @Override
    260                     public void onException(Throwable e) {
    261                         try {
    262                             loge("getProfile callback onException: ", e);
    263                             callback.onComplete(getResultCode(e), null);
    264                         } catch (RemoteException exception) {
    265                             loge("getProfile callback failure.", exception);
    266                         }
    267                     }
    268                 };
    269 
    270         card.getProfile(iccid, cardCb, mEuiccMainThreadHandler);
    271     }
    272 
    273     @Override
    274     public void disableProfile(String callingPackage, String cardId, String iccid, boolean refresh,
    275             IDisableProfileCallback callback) {
    276         checkCallingPackage(callingPackage);
    277 
    278         EuiccCard card = getEuiccCard(cardId);
    279         if (card == null) {
    280             try {
    281                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND);
    282             } catch (RemoteException exception) {
    283                 loge("disableProfile callback failure.", exception);
    284             }
    285             return;
    286         }
    287 
    288         AsyncResultCallback<Void> cardCb = new AsyncResultCallback<Void>() {
    289             @Override
    290             public void onResult(Void result) {
    291                 try {
    292                     callback.onComplete(EuiccCardManager.RESULT_OK);
    293                 } catch (RemoteException exception) {
    294                     loge("disableProfile callback failure.", exception);
    295                 }
    296             }
    297 
    298             @Override
    299             public void onException(Throwable e) {
    300                 try {
    301                     loge("disableProfile callback onException: ", e);
    302                     callback.onComplete(getResultCode(e));
    303                 } catch (RemoteException exception) {
    304                     loge("disableProfile callback failure.", exception);
    305                 }
    306             }
    307         };
    308 
    309         card.disableProfile(iccid, refresh, cardCb, mEuiccMainThreadHandler);
    310     }
    311 
    312     @Override
    313     public void switchToProfile(String callingPackage, String cardId, String iccid, boolean refresh,
    314             ISwitchToProfileCallback callback) {
    315         checkCallingPackage(callingPackage);
    316 
    317         EuiccCard card = getEuiccCard(cardId);
    318         if (card == null) {
    319             try {
    320                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    321             } catch (RemoteException exception) {
    322                 loge("switchToProfile callback failure.", exception);
    323             }
    324             return;
    325         }
    326 
    327         AsyncResultCallback<EuiccProfileInfo> profileCb =
    328                 new AsyncResultCallback<EuiccProfileInfo>() {
    329             @Override
    330             public void onResult(EuiccProfileInfo profile) {
    331                 AsyncResultCallback<Void> switchCb = new AsyncResultCallback<Void>() {
    332                     @Override
    333                     public void onResult(Void result) {
    334                         try {
    335                             callback.onComplete(EuiccCardManager.RESULT_OK, profile);
    336                         } catch (RemoteException exception) {
    337                             loge("switchToProfile callback failure.", exception);
    338                         }
    339                     }
    340 
    341                     @Override
    342                     public void onException(Throwable e) {
    343                         try {
    344                             loge("switchToProfile callback onException: ", e);
    345                             callback.onComplete(getResultCode(e), profile);
    346                         } catch (RemoteException exception) {
    347                             loge("switchToProfile callback failure.", exception);
    348                         }
    349                     }
    350                 };
    351 
    352                 card.switchToProfile(iccid, refresh, switchCb, mEuiccMainThreadHandler);
    353             }
    354 
    355             @Override
    356             public void onException(Throwable e) {
    357                 try {
    358                     loge("getProfile in switchToProfile callback onException: ", e);
    359                     callback.onComplete(getResultCode(e), null);
    360                 } catch (RemoteException exception) {
    361                     loge("switchToProfile callback failure.", exception);
    362                 }
    363             }
    364         };
    365 
    366         card.getProfile(iccid, profileCb, mEuiccMainThreadHandler);
    367     }
    368 
    369     @Override
    370     public void setNickname(String callingPackage, String cardId, String iccid, String nickname,
    371             ISetNicknameCallback callback) {
    372         checkCallingPackage(callingPackage);
    373 
    374         EuiccCard card = getEuiccCard(cardId);
    375         if (card == null) {
    376             try {
    377                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND);
    378             } catch (RemoteException exception) {
    379                 loge("setNickname callback failure.", exception);
    380             }
    381             return;
    382         }
    383 
    384         AsyncResultCallback<Void> cardCb = new AsyncResultCallback<Void>() {
    385             @Override
    386             public void onResult(Void result) {
    387                 try {
    388                     callback.onComplete(EuiccCardManager.RESULT_OK);
    389                 } catch (RemoteException exception) {
    390                     loge("setNickname callback failure.", exception);
    391                 }
    392             }
    393 
    394             @Override
    395             public void onException(Throwable e) {
    396                 try {
    397                     loge("setNickname callback onException: ", e);
    398                     callback.onComplete(getResultCode(e));
    399                 } catch (RemoteException exception) {
    400                     loge("setNickname callback failure.", exception);
    401                 }
    402             }
    403         };
    404 
    405         card.setNickname(iccid, nickname, cardCb, mEuiccMainThreadHandler);
    406     }
    407 
    408     @Override
    409     public void deleteProfile(String callingPackage, String cardId, String iccid,
    410             IDeleteProfileCallback callback) {
    411         checkCallingPackage(callingPackage);
    412 
    413         EuiccCard card = getEuiccCard(cardId);
    414         if (card == null) {
    415             try {
    416                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND);
    417             } catch (RemoteException exception) {
    418                 loge("deleteProfile callback failure.", exception);
    419             }
    420             return;
    421         }
    422 
    423         AsyncResultCallback<Void> cardCb = new AsyncResultCallback<Void>() {
    424             @Override
    425             public void onResult(Void result) {
    426                 Log.i(TAG, "Request subscription info list refresh after delete.");
    427                 SubscriptionController.getInstance().requestEmbeddedSubscriptionInfoListRefresh();
    428                 try {
    429                     callback.onComplete(EuiccCardManager.RESULT_OK);
    430                 } catch (RemoteException exception) {
    431                     loge("deleteProfile callback failure.", exception);
    432                 }
    433             };
    434 
    435             @Override
    436             public void onException(Throwable e) {
    437                 try {
    438                     loge("deleteProfile callback onException: ", e);
    439                     callback.onComplete(getResultCode(e));
    440                 } catch (RemoteException exception) {
    441                     loge("deleteProfile callback failure.", exception);
    442                 }
    443             }
    444         };
    445 
    446         card.deleteProfile(iccid, cardCb, mEuiccMainThreadHandler);
    447     }
    448 
    449     @Override
    450     public void resetMemory(String callingPackage, String cardId,
    451             @EuiccCardManager.ResetOption int options, IResetMemoryCallback callback) {
    452         checkCallingPackage(callingPackage);
    453 
    454         EuiccCard card = getEuiccCard(cardId);
    455         if (card == null) {
    456             try {
    457                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND);
    458             } catch (RemoteException exception) {
    459                 loge("resetMemory callback failure.", exception);
    460             }
    461             return;
    462         }
    463 
    464         AsyncResultCallback<Void> cardCb = new AsyncResultCallback<Void>() {
    465             @Override
    466             public void onResult(Void result) {
    467                 Log.i(TAG, "Request subscription info list refresh after reset memory.");
    468                 SubscriptionController.getInstance().requestEmbeddedSubscriptionInfoListRefresh();
    469                 try {
    470                     callback.onComplete(EuiccCardManager.RESULT_OK);
    471                 } catch (RemoteException exception) {
    472                     loge("resetMemory callback failure.", exception);
    473                 }
    474             }
    475 
    476             @Override
    477             public void onException(Throwable e) {
    478                 try {
    479                     loge("resetMemory callback onException: ", e);
    480                     callback.onComplete(getResultCode(e));
    481                 } catch (RemoteException exception) {
    482                     loge("resetMemory callback failure.", exception);
    483                 }
    484             }
    485         };
    486 
    487         card.resetMemory(options, cardCb, mEuiccMainThreadHandler);
    488     }
    489 
    490     @Override
    491     public void getDefaultSmdpAddress(String callingPackage, String cardId,
    492             IGetDefaultSmdpAddressCallback callback) {
    493         checkCallingPackage(callingPackage);
    494 
    495         EuiccCard card = getEuiccCard(cardId);
    496         if (card == null) {
    497             try {
    498                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    499             } catch (RemoteException exception) {
    500                 loge("getDefaultSmdpAddress callback failure.", exception);
    501             }
    502             return;
    503         }
    504 
    505         AsyncResultCallback<String> cardCb = new AsyncResultCallback<String>() {
    506             @Override
    507             public void onResult(String result) {
    508                 try {
    509                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
    510                 } catch (RemoteException exception) {
    511                     loge("getDefaultSmdpAddress callback failure.", exception);
    512                 }
    513             }
    514 
    515             @Override
    516             public void onException(Throwable e) {
    517                 try {
    518                     loge("getDefaultSmdpAddress callback onException: ", e);
    519                     callback.onComplete(getResultCode(e), null);
    520                 } catch (RemoteException exception) {
    521                     loge("getDefaultSmdpAddress callback failure.", exception);
    522                 }
    523             }
    524         };
    525 
    526         card.getDefaultSmdpAddress(cardCb, mEuiccMainThreadHandler);
    527     }
    528 
    529     @Override
    530     public void getSmdsAddress(String callingPackage, String cardId,
    531             IGetSmdsAddressCallback callback) {
    532         checkCallingPackage(callingPackage);
    533 
    534         EuiccCard card = getEuiccCard(cardId);
    535         if (card == null) {
    536             try {
    537                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    538             } catch (RemoteException exception) {
    539                 loge("getSmdsAddress callback failure.", exception);
    540             }
    541             return;
    542         }
    543 
    544         AsyncResultCallback<String> cardCb = new AsyncResultCallback<String>() {
    545             @Override
    546             public void onResult(String result) {
    547                 try {
    548                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
    549                 } catch (RemoteException exception) {
    550                     loge("getSmdsAddress callback failure.", exception);
    551                 }
    552             }
    553 
    554             @Override
    555             public void onException(Throwable e) {
    556                 try {
    557                     loge("getSmdsAddress callback onException: ", e);
    558                     callback.onComplete(getResultCode(e), null);
    559                 } catch (RemoteException exception) {
    560                     loge("getSmdsAddress callback failure.", exception);
    561                 }
    562             }
    563         };
    564 
    565         card.getSmdsAddress(cardCb, mEuiccMainThreadHandler);
    566     }
    567 
    568     @Override
    569     public void setDefaultSmdpAddress(String callingPackage, String cardId, String address,
    570             ISetDefaultSmdpAddressCallback callback) {
    571         checkCallingPackage(callingPackage);
    572 
    573         EuiccCard card = getEuiccCard(cardId);
    574         if (card == null) {
    575             try {
    576                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND);
    577             } catch (RemoteException exception) {
    578                 loge("setDefaultSmdpAddress callback failure.", exception);
    579             }
    580             return;
    581         }
    582 
    583         AsyncResultCallback<Void> cardCb = new AsyncResultCallback<Void>() {
    584             @Override
    585             public void onResult(Void result) {
    586                 try {
    587                     callback.onComplete(EuiccCardManager.RESULT_OK);
    588                 } catch (RemoteException exception) {
    589                     loge("setDefaultSmdpAddress callback failure.", exception);
    590                 }
    591             }
    592 
    593             @Override
    594             public void onException(Throwable e) {
    595                 try {
    596                     loge("setDefaultSmdpAddress callback onException: ", e);
    597                     callback.onComplete(getResultCode(e));
    598                 } catch (RemoteException exception) {
    599                     loge("setDefaultSmdpAddress callback failure.", exception);
    600                 }
    601             }
    602         };
    603 
    604         card.setDefaultSmdpAddress(address, cardCb, mEuiccMainThreadHandler);
    605     }
    606 
    607     @Override
    608     public void getRulesAuthTable(String callingPackage, String cardId,
    609             IGetRulesAuthTableCallback callback) {
    610         checkCallingPackage(callingPackage);
    611 
    612         EuiccCard card = getEuiccCard(cardId);
    613         if (card == null) {
    614             try {
    615                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    616             } catch (RemoteException exception) {
    617                 loge("getRulesAuthTable callback failure.", exception);
    618             }
    619             return;
    620         }
    621 
    622         AsyncResultCallback<EuiccRulesAuthTable> cardCb =
    623                 new AsyncResultCallback<EuiccRulesAuthTable>() {
    624             @Override
    625             public void onResult(EuiccRulesAuthTable result) {
    626                 try {
    627                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
    628                 } catch (RemoteException exception) {
    629                     loge("getRulesAuthTable callback failure.", exception);
    630                 }
    631             }
    632 
    633             @Override
    634             public void onException(Throwable e) {
    635                 try {
    636                     loge("getRulesAuthTable callback onException: ", e);
    637                     callback.onComplete(getResultCode(e), null);
    638                 } catch (RemoteException exception) {
    639                     loge("getRulesAuthTable callback failure.", exception);
    640                 }
    641             }
    642         };
    643 
    644         card.getRulesAuthTable(cardCb, mEuiccMainThreadHandler);
    645     }
    646 
    647     @Override
    648     public void getEuiccChallenge(String callingPackage, String cardId,
    649             IGetEuiccChallengeCallback callback) {
    650         checkCallingPackage(callingPackage);
    651 
    652         EuiccCard card = getEuiccCard(cardId);
    653         if (card == null) {
    654             try {
    655                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    656             } catch (RemoteException exception) {
    657                 loge("getEuiccChallenge callback failure.", exception);
    658             }
    659             return;
    660         }
    661 
    662         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
    663             @Override
    664             public void onResult(byte[] result) {
    665                 try {
    666                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
    667                 } catch (RemoteException exception) {
    668                     loge("getEuiccChallenge callback failure.", exception);
    669                 }
    670             }
    671 
    672             @Override
    673             public void onException(Throwable e) {
    674                 try {
    675                     loge("getEuiccChallenge callback onException: ", e);
    676                     callback.onComplete(getResultCode(e), null);
    677                 } catch (RemoteException exception) {
    678                     loge("getEuiccChallenge callback failure.", exception);
    679                 }
    680             }
    681         };
    682 
    683         card.getEuiccChallenge(cardCb, mEuiccMainThreadHandler);
    684     }
    685 
    686     @Override
    687     public void getEuiccInfo1(String callingPackage, String cardId,
    688             IGetEuiccInfo1Callback callback) {
    689         checkCallingPackage(callingPackage);
    690 
    691         EuiccCard card = getEuiccCard(cardId);
    692         if (card == null) {
    693             try {
    694                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    695             } catch (RemoteException exception) {
    696                 loge("getEuiccInfo1 callback failure.", exception);
    697             }
    698             return;
    699         }
    700 
    701         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
    702             @Override
    703             public void onResult(byte[] result) {
    704                 try {
    705                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
    706                 } catch (RemoteException exception) {
    707                     loge("getEuiccInfo1 callback failure.", exception);
    708                 }
    709             }
    710 
    711             @Override
    712             public void onException(Throwable e) {
    713                 try {
    714                     loge("getEuiccInfo1 callback onException: ", e);
    715                     callback.onComplete(getResultCode(e), null);
    716                 } catch (RemoteException exception) {
    717                     loge("getEuiccInfo1 callback failure.", exception);
    718                 }
    719             }
    720         };
    721 
    722         card.getEuiccInfo1(cardCb, mEuiccMainThreadHandler);
    723     }
    724 
    725     @Override
    726     public void getEuiccInfo2(String callingPackage, String cardId,
    727             IGetEuiccInfo2Callback callback) {
    728         checkCallingPackage(callingPackage);
    729 
    730         EuiccCard card = getEuiccCard(cardId);
    731         if (card == null) {
    732             try {
    733                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    734             } catch (RemoteException exception) {
    735                 loge("getEuiccInfo2 callback failure.", exception);
    736             }
    737             return;
    738         }
    739 
    740         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
    741             @Override
    742             public void onResult(byte[] result) {
    743                 try {
    744                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
    745                 } catch (RemoteException exception) {
    746                     loge("getEuiccInfo2 callback failure.", exception);
    747                 }
    748             }
    749 
    750             @Override
    751             public void onException(Throwable e) {
    752                 try {
    753                     loge("getEuiccInfo2 callback onException: ", e);
    754                     callback.onComplete(getResultCode(e), null);
    755                 } catch (RemoteException exception) {
    756                     loge("getEuiccInfo2 callback failure.", exception);
    757                 }
    758             }
    759         };
    760 
    761         card.getEuiccInfo2(cardCb, mEuiccMainThreadHandler);
    762     }
    763 
    764     @Override
    765     public void authenticateServer(String callingPackage, String cardId, String matchingId,
    766             byte[] serverSigned1, byte[] serverSignature1, byte[] euiccCiPkIdToBeUsed,
    767             byte[] serverCertificate, IAuthenticateServerCallback callback) {
    768         checkCallingPackage(callingPackage);
    769 
    770         EuiccCard card = getEuiccCard(cardId);
    771         if (card == null) {
    772             try {
    773                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    774             } catch (RemoteException exception) {
    775                 loge("authenticateServer callback failure.", exception);
    776             }
    777             return;
    778         }
    779 
    780         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
    781             @Override
    782             public void onResult(byte[] result) {
    783                 try {
    784                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
    785                 } catch (RemoteException exception) {
    786                     loge("authenticateServer callback failure.", exception);
    787                 }
    788             }
    789 
    790             @Override
    791             public void onException(Throwable e) {
    792                 try {
    793                     loge("authenticateServer callback onException: ", e);
    794                     callback.onComplete(getResultCode(e), null);
    795                 } catch (RemoteException exception) {
    796                     loge("authenticateServer callback failure.", exception);
    797                 }
    798             }
    799         };
    800 
    801         card.authenticateServer(matchingId, serverSigned1, serverSignature1, euiccCiPkIdToBeUsed,
    802                 serverCertificate, cardCb, mEuiccMainThreadHandler);
    803     }
    804 
    805     @Override
    806     public void prepareDownload(String callingPackage, String cardId, @Nullable byte[] hashCc,
    807             byte[] smdpSigned2, byte[] smdpSignature2, byte[] smdpCertificate,
    808             IPrepareDownloadCallback callback) {
    809         checkCallingPackage(callingPackage);
    810 
    811         EuiccCard card = getEuiccCard(cardId);
    812         if (card == null) {
    813             try {
    814                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    815             } catch (RemoteException exception) {
    816                 loge("prepareDownload callback failure.", exception);
    817             }
    818             return;
    819         }
    820 
    821         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
    822             @Override
    823             public void onResult(byte[] result) {
    824                 try {
    825                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
    826                 } catch (RemoteException exception) {
    827                     loge("prepareDownload callback failure.", exception);
    828                 }
    829             }
    830 
    831             @Override
    832             public void onException(Throwable e) {
    833                 try {
    834                     loge("prepareDownload callback onException: ", e);
    835                     callback.onComplete(getResultCode(e), null);
    836                 } catch (RemoteException exception) {
    837                     loge("prepareDownload callback failure.", exception);
    838                 }
    839             }
    840         };
    841 
    842         card.prepareDownload(hashCc, smdpSigned2, smdpSignature2, smdpCertificate, cardCb,
    843                 mEuiccMainThreadHandler);
    844     }
    845 
    846     @Override
    847     public void loadBoundProfilePackage(String callingPackage, String cardId,
    848             byte[] boundProfilePackage, ILoadBoundProfilePackageCallback callback) {
    849         checkCallingPackage(callingPackage);
    850 
    851         EuiccCard card = getEuiccCard(cardId);
    852         if (card == null) {
    853             try {
    854                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    855             } catch (RemoteException exception) {
    856                 loge("loadBoundProfilePackage callback failure.", exception);
    857             }
    858             return;
    859         }
    860 
    861         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
    862             @Override
    863             public void onResult(byte[] result) {
    864                 Log.i(TAG, "Request subscription info list refresh after install.");
    865                 SubscriptionController.getInstance().requestEmbeddedSubscriptionInfoListRefresh();
    866                 try {
    867                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
    868                 } catch (RemoteException exception) {
    869                     loge("loadBoundProfilePackage callback failure.", exception);
    870                 }
    871             }
    872 
    873             @Override
    874             public void onException(Throwable e) {
    875                 try {
    876                     loge("loadBoundProfilePackage callback onException: ", e);
    877                     callback.onComplete(getResultCode(e), null);
    878                 } catch (RemoteException exception) {
    879                     loge("loadBoundProfilePackage callback failure.", exception);
    880                 }
    881             }
    882         };
    883 
    884         card.loadBoundProfilePackage(boundProfilePackage, cardCb, mEuiccMainThreadHandler);
    885     }
    886 
    887     @Override
    888     public void cancelSession(String callingPackage, String cardId, byte[] transactionId,
    889             @EuiccCardManager.CancelReason int reason, ICancelSessionCallback callback) {
    890         checkCallingPackage(callingPackage);
    891 
    892         EuiccCard card = getEuiccCard(cardId);
    893         if (card == null) {
    894             try {
    895                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    896             } catch (RemoteException exception) {
    897                 loge("cancelSession callback failure.", exception);
    898             }
    899             return;
    900         }
    901 
    902         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
    903             @Override
    904             public void onResult(byte[] result) {
    905                 try {
    906                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
    907                 } catch (RemoteException exception) {
    908                     loge("cancelSession callback failure.", exception);
    909                 }
    910             }
    911 
    912             @Override
    913             public void onException(Throwable e) {
    914                 try {
    915                     loge("cancelSession callback onException: ", e);
    916                     callback.onComplete(getResultCode(e), null);
    917                 } catch (RemoteException exception) {
    918                     loge("cancelSession callback failure.", exception);
    919                 }
    920             }
    921         };
    922 
    923         card.cancelSession(transactionId, reason, cardCb, mEuiccMainThreadHandler);
    924     }
    925 
    926     @Override
    927     public void listNotifications(String callingPackage, String cardId,
    928             @EuiccNotification.Event int events, IListNotificationsCallback callback) {
    929         checkCallingPackage(callingPackage);
    930 
    931         EuiccCard card = getEuiccCard(cardId);
    932         if (card == null) {
    933             try {
    934                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    935             } catch (RemoteException exception) {
    936                 loge("listNotifications callback failure.", exception);
    937             }
    938             return;
    939         }
    940 
    941         AsyncResultCallback<EuiccNotification[]> cardCb =
    942                 new AsyncResultCallback<EuiccNotification[]>() {
    943             @Override
    944             public void onResult(EuiccNotification[] result) {
    945                 try {
    946                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
    947                 } catch (RemoteException exception) {
    948                     loge("listNotifications callback failure.", exception);
    949                 }
    950             }
    951 
    952             @Override
    953             public void onException(Throwable e) {
    954                 try {
    955                     loge("listNotifications callback onException: ", e);
    956                     callback.onComplete(getResultCode(e), null);
    957                 } catch (RemoteException exception) {
    958                     loge("listNotifications callback failure.", exception);
    959                 }
    960             }
    961         };
    962 
    963         card.listNotifications(events, cardCb, mEuiccMainThreadHandler);
    964     }
    965 
    966     @Override
    967     public void retrieveNotificationList(String callingPackage, String cardId,
    968             @EuiccNotification.Event int events, IRetrieveNotificationListCallback callback) {
    969         checkCallingPackage(callingPackage);
    970 
    971         EuiccCard card = getEuiccCard(cardId);
    972         if (card == null) {
    973             try {
    974                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
    975             } catch (RemoteException exception) {
    976                 loge("retrieveNotificationList callback failure.", exception);
    977             }
    978             return;
    979         }
    980 
    981         AsyncResultCallback<EuiccNotification[]> cardCb =
    982                 new AsyncResultCallback<EuiccNotification[]>() {
    983                     @Override
    984                     public void onResult(EuiccNotification[] result) {
    985                         try {
    986                             callback.onComplete(EuiccCardManager.RESULT_OK, result);
    987                         } catch (RemoteException exception) {
    988                             loge("retrieveNotificationList callback failure.", exception);
    989                         }
    990                     }
    991 
    992                     @Override
    993                     public void onException(Throwable e) {
    994                         try {
    995                             loge("retrieveNotificationList callback onException: ", e);
    996                             callback.onComplete(getResultCode(e), null);
    997                         } catch (RemoteException exception) {
    998                             loge("retrieveNotificationList callback failure.", exception);
    999                         }
   1000                     }
   1001                 };
   1002 
   1003         card.retrieveNotificationList(events, cardCb, mEuiccMainThreadHandler);
   1004     }
   1005 
   1006     @Override
   1007     public void retrieveNotification(String callingPackage, String cardId, int seqNumber,
   1008             IRetrieveNotificationCallback callback) {
   1009         checkCallingPackage(callingPackage);
   1010 
   1011         EuiccCard card = getEuiccCard(cardId);
   1012         if (card == null) {
   1013             try {
   1014                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
   1015             } catch (RemoteException exception) {
   1016                 loge("retrieveNotification callback failure.", exception);
   1017             }
   1018             return;
   1019         }
   1020 
   1021         AsyncResultCallback<EuiccNotification> cardCb =
   1022                 new AsyncResultCallback<EuiccNotification>() {
   1023                     @Override
   1024                     public void onResult(EuiccNotification result) {
   1025                         try {
   1026                             callback.onComplete(EuiccCardManager.RESULT_OK, result);
   1027                         } catch (RemoteException exception) {
   1028                             loge("retrieveNotification callback failure.", exception);
   1029                         }
   1030                     }
   1031 
   1032                     @Override
   1033                     public void onException(Throwable e) {
   1034                         try {
   1035                             loge("retrieveNotification callback onException: ", e);
   1036                             callback.onComplete(getResultCode(e), null);
   1037                         } catch (RemoteException exception) {
   1038                             loge("retrieveNotification callback failure.", exception);
   1039                         }
   1040                     }
   1041                 };
   1042 
   1043         card.retrieveNotification(seqNumber, cardCb, mEuiccMainThreadHandler);
   1044     }
   1045 
   1046     @Override
   1047     public void removeNotificationFromList(String callingPackage, String cardId, int seqNumber,
   1048             IRemoveNotificationFromListCallback callback) {
   1049         checkCallingPackage(callingPackage);
   1050 
   1051         EuiccCard card = getEuiccCard(cardId);
   1052         if (card == null) {
   1053             try {
   1054                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND);
   1055             } catch (RemoteException exception) {
   1056                 loge("removeNotificationFromList callback failure.", exception);
   1057             }
   1058             return;
   1059         }
   1060 
   1061         AsyncResultCallback<Void> cardCb = new AsyncResultCallback<Void>() {
   1062                     @Override
   1063                     public void onResult(Void result) {
   1064                         try {
   1065                             callback.onComplete(EuiccCardManager.RESULT_OK);
   1066                         } catch (RemoteException exception) {
   1067                             loge("removeNotificationFromList callback failure.", exception);
   1068                         }
   1069 
   1070                     }
   1071 
   1072                     @Override
   1073                     public void onException(Throwable e) {
   1074                         try {
   1075                             loge("removeNotificationFromList callback onException: ", e);
   1076                             callback.onComplete(getResultCode(e));
   1077                         } catch (RemoteException exception) {
   1078                             loge("removeNotificationFromList callback failure.", exception);
   1079                         }
   1080                     }
   1081                 };
   1082 
   1083         card.removeNotificationFromList(seqNumber, cardCb, mEuiccMainThreadHandler);
   1084     }
   1085 
   1086     @Override
   1087     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   1088         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "Requires DUMP");
   1089         final long token = Binder.clearCallingIdentity();
   1090 
   1091         super.dump(fd, pw, args);
   1092         // TODO(b/38206971): dump more information.
   1093         pw.println("mCallingPackage=" + mCallingPackage);
   1094         pw.println("mBestComponent=" + mBestComponent);
   1095 
   1096         Binder.restoreCallingIdentity(token);
   1097     }
   1098 
   1099     private static void loge(String message) {
   1100         Log.e(TAG, message);
   1101     }
   1102 
   1103     private static void loge(String message, Throwable tr) {
   1104         Log.e(TAG, message, tr);
   1105     }
   1106 }
   1107