• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static android.content.pm.PackageManager.FEATURE_TELEPHONY_EUICC;
20 import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING;
21 
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.app.AppOpsManager;
25 import android.app.compat.CompatChanges;
26 import android.content.BroadcastReceiver;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.content.SharedPreferences;
31 import android.content.pm.ComponentInfo;
32 import android.content.pm.PackageManager;
33 import android.os.Binder;
34 import android.os.Build;
35 import android.os.Handler;
36 import android.os.RemoteException;
37 import android.os.SystemProperties;
38 import android.preference.PreferenceManager;
39 import android.provider.Settings;
40 import android.service.euicc.EuiccProfileInfo;
41 import android.telephony.TelephonyFrameworkInitializer;
42 import android.telephony.TelephonyManager;
43 import android.telephony.euicc.EuiccCardManager;
44 import android.telephony.euicc.EuiccNotification;
45 import android.telephony.euicc.EuiccRulesAuthTable;
46 import android.text.TextUtils;
47 import android.util.Log;
48 
49 import com.android.internal.annotations.VisibleForTesting;
50 import com.android.internal.telephony.flags.FeatureFlags;
51 import com.android.internal.telephony.subscription.SubscriptionManagerService;
52 import com.android.internal.telephony.uicc.UiccCard;
53 import com.android.internal.telephony.uicc.UiccController;
54 import com.android.internal.telephony.uicc.UiccPort;
55 import com.android.internal.telephony.uicc.UiccSlot;
56 import com.android.internal.telephony.uicc.euicc.EuiccCard;
57 import com.android.internal.telephony.uicc.euicc.EuiccCardErrorException;
58 import com.android.internal.telephony.uicc.euicc.EuiccPort;
59 import com.android.internal.telephony.uicc.euicc.async.AsyncResultCallback;
60 
61 import java.io.FileDescriptor;
62 import java.io.PrintWriter;
63 import java.util.List;
64 
65 /** Backing implementation of {@link EuiccCardManager}. */
66 public class EuiccCardController extends IEuiccCardController.Stub {
67     private static final String TAG = "EuiccCardController";
68     private static final String KEY_LAST_BOOT_COUNT = "last_boot_count";
69 
70     private final Context mContext;
71     private AppOpsManager mAppOps;
72     private String mCallingPackage;
73     private ComponentInfo mBestComponent;
74     private Handler mEuiccMainThreadHandler;
75     private SimSlotStatusChangedBroadcastReceiver mSimSlotStatusChangeReceiver;
76     private EuiccController mEuiccController;
77     private UiccController mUiccController;
78     private FeatureFlags mFeatureFlags;
79     private PackageManager mPackageManager;
80     private final int mVendorApiLevel;
81 
82     private static EuiccCardController sInstance;
83 
84     private class SimSlotStatusChangedBroadcastReceiver extends BroadcastReceiver {
85         @Override
onReceive(Context context, Intent intent)86         public void onReceive(Context context, Intent intent) {
87             if (TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED.equals(intent.getAction())) {
88                 // We want to keep listening if card is not present yet since the first state might
89                 // be an error state
90                 if (!isEmbeddedCardPresent()) {
91                     return;
92                 }
93                 if (isEmbeddedSlotActivated()) {
94                     mEuiccController.startOtaUpdatingIfNecessary();
95                 }
96                 mContext.unregisterReceiver(mSimSlotStatusChangeReceiver);
97             }
98         }
99     }
100 
101     /** Initialize the instance. Should only be called once. */
init(Context context, FeatureFlags featureFlags)102     public static EuiccCardController init(Context context, FeatureFlags featureFlags) {
103         synchronized (EuiccCardController.class) {
104             if (sInstance == null) {
105                 sInstance = new EuiccCardController(context, featureFlags);
106             } else {
107                 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
108             }
109         }
110         return sInstance;
111     }
112 
113     /** Get an instance. Assumes one has already been initialized with {@link #init}. */
get()114     public static EuiccCardController get() {
115         if (sInstance == null) {
116             synchronized (EuiccCardController.class) {
117                 if (sInstance == null) {
118                     throw new IllegalStateException("get() called before init()");
119                 }
120             }
121         }
122         return sInstance;
123     }
124 
EuiccCardController(Context context, FeatureFlags featureFlags)125     private EuiccCardController(Context context, FeatureFlags featureFlags) {
126         this(context, new Handler(), EuiccController.get(), UiccController.getInstance(),
127                 featureFlags);
128         TelephonyFrameworkInitializer
129                 .getTelephonyServiceManager()
130                 .getEuiccCardControllerServiceRegisterer()
131                 .register(this);
132     }
133 
134     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
EuiccCardController( Context context, Handler handler, EuiccController euiccController, UiccController uiccController, FeatureFlags featureFlags)135     public EuiccCardController(
136             Context context,
137             Handler handler,
138             EuiccController euiccController,
139             UiccController uiccController,
140             FeatureFlags featureFlags) {
141         mContext = context;
142         mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
143 
144         mEuiccMainThreadHandler = handler;
145         mUiccController = uiccController;
146         mEuiccController = euiccController;
147         mFeatureFlags = featureFlags;
148         mPackageManager = context.getPackageManager();
149         mVendorApiLevel = SystemProperties.getInt(
150                 "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT);
151 
152         if (isBootUp(mContext)) {
153             mSimSlotStatusChangeReceiver = new SimSlotStatusChangedBroadcastReceiver();
154             mContext.registerReceiver(
155                     mSimSlotStatusChangeReceiver,
156                     new IntentFilter(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
157         }
158     }
159 
160     /**
161      * Check whether the restored boot count is the same as current one. If not, update the restored
162      * one.
163      */
164     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
isBootUp(Context context)165     public static boolean isBootUp(Context context) {
166         int bootCount = Settings.Global.getInt(
167                 context.getContentResolver(), Settings.Global.BOOT_COUNT, -1);
168         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
169         int lastBootCount = sp.getInt(KEY_LAST_BOOT_COUNT, -1);
170         if (bootCount == -1 || lastBootCount == -1 || bootCount != lastBootCount) {
171             sp.edit().putInt(KEY_LAST_BOOT_COUNT, bootCount).apply();
172             return true;
173         }
174         return false;
175     }
176 
177     /** Whether embedded slot is activated or not. */
178     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
isEmbeddedSlotActivated()179     public boolean isEmbeddedSlotActivated() {
180         UiccSlot[] slots = mUiccController.getUiccSlots();
181         if (slots == null) {
182             return false;
183         }
184         for (int i = 0; i < slots.length; ++i) {
185             UiccSlot slotInfo = slots[i];
186             if (slotInfo != null && !slotInfo.isRemovable() && slotInfo.isActive()) {
187                 return true;
188             }
189         }
190         return false;
191     }
192 
193     /** Whether embedded card is present or not */
194     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
isEmbeddedCardPresent()195     public boolean isEmbeddedCardPresent() {
196         UiccSlot[] slots = mUiccController.getUiccSlots();
197         if (slots == null) {
198             return false;
199         }
200         for (UiccSlot slotInfo : slots) {
201             if (slotInfo != null
202                     && !slotInfo.isRemovable()
203                     && slotInfo.getCardState() != null
204                     && slotInfo.getCardState().isCardPresent()) {
205                 return true;
206             }
207         }
208         return false;
209     }
210 
checkCallingPackage(String callingPackage)211     private void checkCallingPackage(String callingPackage) {
212         // Check the caller is LPA.
213         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
214         mCallingPackage = callingPackage;
215         mBestComponent = EuiccConnector.findBestComponent(mContext.getPackageManager());
216         if (mBestComponent == null
217                 || !TextUtils.equals(mCallingPackage, mBestComponent.packageName)) {
218             throw new SecurityException("The calling package can only be LPA.");
219         }
220     }
221 
getUiccSlotForEmbeddedCard(String cardId)222     private UiccSlot getUiccSlotForEmbeddedCard(String cardId) {
223         int slotId = mUiccController.getUiccSlotForCardId(cardId);
224         UiccSlot slot = mUiccController.getUiccSlot(slotId);
225         if (slot == null) {
226             loge("UiccSlot is null. slotId : " + slotId + " cardId : " + cardId);
227             return null;
228         }
229         if (!slot.isEuicc()) {
230             loge("UiccSlot is not embedded slot : " + slotId + " cardId : " + cardId);
231             return null;
232         }
233         return slot;
234     }
235 
getEuiccCard(String cardId)236     private EuiccCard getEuiccCard(String cardId) {
237         UiccSlot slot = getUiccSlotForEmbeddedCard(cardId);
238         if (slot == null) {
239             return null;
240         }
241         UiccCard card = slot.getUiccCard();
242         if (card == null) {
243             loge("UiccCard is null. cardId : " + cardId);
244             return null;
245         }
246         return (EuiccCard) card;
247     }
248 
getEuiccPortFromIccId(String cardId, String iccid)249     private EuiccPort getEuiccPortFromIccId(String cardId, String iccid) {
250         UiccSlot slot = getUiccSlotForEmbeddedCard(cardId);
251         if (slot == null) {
252             return null;
253         }
254         UiccCard card = slot.getUiccCard();
255         if (card == null) {
256             loge("UiccCard is null. cardId : " + cardId);
257             return null;
258         }
259         int portIndex = slot.getPortIndexFromIccId(iccid);
260         UiccPort port = card.getUiccPort(portIndex);
261         if (port == null) {
262             loge("UiccPort is null. cardId : " + cardId + " portIndex : " + portIndex);
263             return null;
264         }
265         return (EuiccPort) port;
266     }
267 
getFirstActiveEuiccPort(String cardId)268     private EuiccPort getFirstActiveEuiccPort(String cardId) {
269         EuiccCard card = getEuiccCard(cardId);
270         if (card == null) {
271             return null;
272         }
273         if (card.getUiccPortList().length > 0 ) {
274             return (EuiccPort) card.getUiccPortList()[0]; // return first active port.
275         }
276         loge("No active ports exists. cardId : " + cardId);
277         return null;
278     }
279 
getEuiccPort(String cardId, int portIndex)280     private EuiccPort getEuiccPort(String cardId, int portIndex) {
281         EuiccCard card = getEuiccCard(cardId);
282         if (card == null) {
283             return null;
284         }
285         UiccPort port = card.getUiccPort(portIndex);
286         if (port == null) {
287             loge("UiccPort is null. cardId : " + cardId + " portIndex : " + portIndex);
288             return null;
289         }
290         return (EuiccPort) port;
291     }
292 
getResultCode(Throwable e)293     private int getResultCode(Throwable e) {
294         if (e instanceof EuiccCardErrorException) {
295             return ((EuiccCardErrorException) e).getErrorCode();
296         }
297         return EuiccCardManager.RESULT_UNKNOWN_ERROR;
298     }
299 
300     @Override
getAllProfiles(String callingPackage, String cardId, IGetAllProfilesCallback callback)301     public void getAllProfiles(String callingPackage, String cardId,
302             IGetAllProfilesCallback callback) {
303         try {
304             checkCallingPackage(callingPackage);
305         } catch (SecurityException se) {
306             try {
307                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
308             } catch (RemoteException re) {
309                 loge("callback onComplete failure after checkCallingPackage.", re);
310             }
311             return;
312         }
313 
314         enforceTelephonyFeatureWithException(callingPackage, "getAllProfiles");
315 
316         EuiccPort port = getFirstActiveEuiccPort(cardId);
317         if (port == null) {
318             try {
319                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
320             } catch (RemoteException exception) {
321                 loge("getAllProfiles callback failure.", exception);
322             }
323             return;
324         }
325 
326         AsyncResultCallback<EuiccProfileInfo[]> cardCb =
327                 new AsyncResultCallback<EuiccProfileInfo[]>() {
328             @Override
329             public void onResult(EuiccProfileInfo[] result) {
330                 try {
331                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
332                 } catch (RemoteException exception) {
333                     loge("getAllProfiles callback failure.", exception);
334                 }
335             }
336 
337             @Override
338             public void onException(Throwable e) {
339                 try {
340                     loge("getAllProfiles callback onException: ", e);
341                     callback.onComplete(getResultCode(e), null);
342                 } catch (RemoteException exception) {
343                     loge("getAllProfiles callback failure.", exception);
344                 }
345             }
346         };
347 
348         port.getAllProfiles(cardCb, mEuiccMainThreadHandler);
349     }
350 
351     @Override
getProfile(String callingPackage, String cardId, String iccid, IGetProfileCallback callback)352     public void getProfile(String callingPackage, String cardId, String iccid,
353             IGetProfileCallback callback) {
354         try {
355             checkCallingPackage(callingPackage);
356         } catch (SecurityException se) {
357             try {
358                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
359             } catch (RemoteException re) {
360                 loge("callback onComplete failure after checkCallingPackage.", re);
361             }
362             return;
363         }
364 
365         enforceTelephonyFeatureWithException(callingPackage, "getProfile");
366 
367         EuiccPort port = getFirstActiveEuiccPort(cardId);
368         if (port == null) {
369             try {
370                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
371             } catch (RemoteException exception) {
372                 loge("getProfile callback failure.", exception);
373             }
374             return;
375         }
376 
377         AsyncResultCallback<EuiccProfileInfo> cardCb = new AsyncResultCallback<EuiccProfileInfo>() {
378                     @Override
379                     public void onResult(EuiccProfileInfo result) {
380                         try {
381                             callback.onComplete(EuiccCardManager.RESULT_OK, result);
382                         } catch (RemoteException exception) {
383                             loge("getProfile callback failure.", exception);
384                         }
385                     }
386 
387                     @Override
388                     public void onException(Throwable e) {
389                         try {
390                             loge("getProfile callback onException: ", e);
391                             callback.onComplete(getResultCode(e), null);
392                         } catch (RemoteException exception) {
393                             loge("getProfile callback failure.", exception);
394                         }
395                     }
396                 };
397 
398         port.getProfile(iccid, cardCb, mEuiccMainThreadHandler);
399     }
400 
401     @Override
getEnabledProfile(String callingPackage, String cardId, int portIndex, IGetProfileCallback callback)402     public void getEnabledProfile(String callingPackage, String cardId, int portIndex,
403             IGetProfileCallback callback) {
404         try {
405             checkCallingPackage(callingPackage);
406         } catch (SecurityException se) {
407             try {
408                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
409             } catch (RemoteException re) {
410                 loge("callback onComplete failure after checkCallingPackage.", re);
411             }
412             return;
413         }
414 
415         enforceTelephonyFeatureWithException(callingPackage, "getEnabledProfile");
416 
417         String iccId = null;
418         boolean isValidSlotPort = false;
419         // get the iccid whether or not the port is active
420         for (UiccSlot slot : mUiccController.getUiccSlots()) {
421             if (slot.getEid().equals(cardId)) {
422                 // find the matching slot. first validate if the passing port index is valid.
423                 if (slot.isValidPortIndex(portIndex)) {
424                     isValidSlotPort = true;
425                     iccId = slot.getIccId(portIndex);
426                 }
427             }
428         }
429         if(!isValidSlotPort) {
430             try {
431                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
432             } catch (RemoteException exception) {
433                 loge("getEnabledProfile callback failure due to invalid port slot.",
434                         exception);
435             }
436             return;
437         }
438         // if there is no iccid enabled on this port, return null.
439         if (TextUtils.isEmpty(iccId)) {
440             try {
441                 callback.onComplete(EuiccCardManager.RESULT_PROFILE_DOES_NOT_EXIST, null);
442             } catch (RemoteException exception) {
443                 loge("getEnabledProfile callback failure.", exception);
444             }
445             return;
446         }
447 
448         EuiccPort port = getEuiccPort(cardId, portIndex);
449         if (port == null) {
450             // If the port is inactive, send the APDU on the first active port
451             port = getFirstActiveEuiccPort(cardId);
452             if (port == null) {
453                 try {
454                     callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
455                 } catch (RemoteException exception) {
456                     loge("getEnabledProfile callback failure.", exception);
457                 }
458                 return;
459             }
460         }
461 
462         AsyncResultCallback<EuiccProfileInfo> cardCb = new AsyncResultCallback<EuiccProfileInfo>() {
463             @Override
464             public void onResult(EuiccProfileInfo result) {
465                 try {
466                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
467                 } catch (RemoteException exception) {
468                     loge("getEnabledProfile callback failure.", exception);
469                 }
470             }
471 
472             @Override
473             public void onException(Throwable e) {
474                 try {
475                     loge("getEnabledProfile callback onException: ", e);
476                     callback.onComplete(getResultCode(e), null);
477                 } catch (RemoteException exception) {
478                     loge("getEnabledProfile callback failure.", exception);
479                 }
480             }
481         };
482 
483         port.getProfile(iccId, cardCb, mEuiccMainThreadHandler);
484 
485     }
486 
487     @Override
disableProfile(String callingPackage, String cardId, String iccid, boolean refresh, IDisableProfileCallback callback)488     public void disableProfile(String callingPackage, String cardId, String iccid, boolean refresh,
489             IDisableProfileCallback callback) {
490         try {
491             checkCallingPackage(callingPackage);
492         } catch (SecurityException se) {
493             try {
494                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED);
495             } catch (RemoteException re) {
496                 loge("callback onComplete failure after checkCallingPackage.", re);
497             }
498             return;
499         }
500 
501         enforceTelephonyFeatureWithException(callingPackage, "disableProfile");
502 
503         EuiccPort port = getEuiccPortFromIccId(cardId, iccid);
504         if (port == null) {
505             try {
506                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND);
507             } catch (RemoteException exception) {
508                 loge("disableProfile callback failure.", exception);
509             }
510             return;
511         }
512 
513         AsyncResultCallback<Void> cardCb = new AsyncResultCallback<Void>() {
514             @Override
515             public void onResult(Void result) {
516                 try {
517                     callback.onComplete(EuiccCardManager.RESULT_OK);
518                 } catch (RemoteException exception) {
519                     loge("disableProfile callback failure.", exception);
520                 }
521             }
522 
523             @Override
524             public void onException(Throwable e) {
525                 try {
526                     loge("disableProfile callback onException: ", e);
527                     callback.onComplete(getResultCode(e));
528                 } catch (RemoteException exception) {
529                     loge("disableProfile callback failure.", exception);
530                 }
531             }
532         };
533 
534         port.disableProfile(iccid, refresh, cardCb, mEuiccMainThreadHandler);
535     }
536 
537     @Override
switchToProfile(String callingPackage, String cardId, String iccid, int portIndex, boolean refresh, ISwitchToProfileCallback callback)538     public void switchToProfile(String callingPackage, String cardId, String iccid, int portIndex,
539             boolean refresh, ISwitchToProfileCallback callback) {
540         try {
541             checkCallingPackage(callingPackage);
542         } catch (SecurityException se) {
543             try {
544                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
545             } catch (RemoteException re) {
546                 loge("callback onComplete failure after checkCallingPackage.", re);
547             }
548             return;
549         }
550 
551         enforceTelephonyFeatureWithException(callingPackage, "switchToProfile");
552 
553         EuiccPort port = getEuiccPort(cardId, portIndex);
554         if (port == null) {
555             try {
556                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
557             } catch (RemoteException exception) {
558                 loge("switchToProfile callback failure for portIndex :" + portIndex, exception);
559             }
560             return;
561         }
562 
563         AsyncResultCallback<EuiccProfileInfo> profileCb =
564                 new AsyncResultCallback<EuiccProfileInfo>() {
565             @Override
566             public void onResult(EuiccProfileInfo profile) {
567                 AsyncResultCallback<Void> switchCb = new AsyncResultCallback<Void>() {
568                     @Override
569                     public void onResult(Void result) {
570                         try {
571                             callback.onComplete(EuiccCardManager.RESULT_OK, profile);
572                         } catch (RemoteException exception) {
573                             loge("switchToProfile callback failure.", exception);
574                         }
575                     }
576 
577                     @Override
578                     public void onException(Throwable e) {
579                         try {
580                             loge("switchToProfile callback onException: ", e);
581                             callback.onComplete(getResultCode(e), profile);
582                         } catch (RemoteException exception) {
583                             loge("switchToProfile callback failure.", exception);
584                         }
585                     }
586                 };
587 
588                 port.switchToProfile(iccid, refresh, switchCb, mEuiccMainThreadHandler);
589             }
590 
591             @Override
592             public void onException(Throwable e) {
593                 try {
594                     loge("getProfile in switchToProfile callback onException: ", e);
595                     callback.onComplete(getResultCode(e), null);
596                 } catch (RemoteException exception) {
597                     loge("switchToProfile callback failure.", exception);
598                 }
599             }
600         };
601 
602         port.getProfile(iccid, profileCb, mEuiccMainThreadHandler);
603     }
604 
605     @Override
setNickname(String callingPackage, String cardId, String iccid, String nickname, ISetNicknameCallback callback)606     public void setNickname(String callingPackage, String cardId, String iccid, String nickname,
607             ISetNicknameCallback callback) {
608         try {
609             checkCallingPackage(callingPackage);
610         } catch (SecurityException se) {
611             try {
612                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED);
613             } catch (RemoteException re) {
614                 loge("callback onComplete failure after checkCallingPackage.", re);
615             }
616             return;
617         }
618 
619         enforceTelephonyFeatureWithException(callingPackage, "setNickname");
620 
621         EuiccPort port = getFirstActiveEuiccPort(cardId);
622         if (port == null) {
623             try {
624                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND);
625             } catch (RemoteException exception) {
626                 loge("setNickname callback failure.", exception);
627             }
628             return;
629         }
630 
631         AsyncResultCallback<Void> cardCb = new AsyncResultCallback<Void>() {
632             @Override
633             public void onResult(Void result) {
634                 try {
635                     callback.onComplete(EuiccCardManager.RESULT_OK);
636                 } catch (RemoteException exception) {
637                     loge("setNickname callback failure.", exception);
638                 }
639             }
640 
641             @Override
642             public void onException(Throwable e) {
643                 try {
644                     loge("setNickname callback onException: ", e);
645                     callback.onComplete(getResultCode(e));
646                 } catch (RemoteException exception) {
647                     loge("setNickname callback failure.", exception);
648                 }
649             }
650         };
651 
652         port.setNickname(iccid, nickname, cardCb, mEuiccMainThreadHandler);
653     }
654 
655     @Override
deleteProfile(String callingPackage, String cardId, String iccid, IDeleteProfileCallback callback)656     public void deleteProfile(String callingPackage, String cardId, String iccid,
657             IDeleteProfileCallback callback) {
658         try {
659             checkCallingPackage(callingPackage);
660         } catch (SecurityException se) {
661             try {
662                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED);
663             } catch (RemoteException re) {
664                 loge("callback onComplete failure after checkCallingPackage.", re);
665             }
666             return;
667         }
668 
669         enforceTelephonyFeatureWithException(callingPackage, "deleteProfile");
670 
671         EuiccPort port = getFirstActiveEuiccPort(cardId);
672         if (port == null) {
673             try {
674                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND);
675             } catch (RemoteException exception) {
676                 loge("deleteProfile callback failure.", exception);
677             }
678             return;
679         }
680 
681         AsyncResultCallback<Void> cardCb = new AsyncResultCallback<Void>() {
682             @Override
683             public void onResult(Void result) {
684                 Log.i(TAG, "Request subscription info list refresh after delete.");
685                 SubscriptionManagerService.getInstance().updateEmbeddedSubscriptions(
686                         List.of(mUiccController.convertToPublicCardId(cardId)), null);
687                 try {
688                     callback.onComplete(EuiccCardManager.RESULT_OK);
689                 } catch (RemoteException exception) {
690                     loge("deleteProfile callback failure.", exception);
691                 }
692             };
693 
694             @Override
695             public void onException(Throwable e) {
696                 try {
697                     loge("deleteProfile callback onException: ", e);
698                     callback.onComplete(getResultCode(e));
699                 } catch (RemoteException exception) {
700                     loge("deleteProfile callback failure.", exception);
701                 }
702             }
703         };
704 
705         port.deleteProfile(iccid, cardCb, mEuiccMainThreadHandler);
706     }
707 
708     @Override
resetMemory(String callingPackage, String cardId, @EuiccCardManager.ResetOption int options, IResetMemoryCallback callback)709     public void resetMemory(String callingPackage, String cardId,
710             @EuiccCardManager.ResetOption int options, IResetMemoryCallback callback) {
711         try {
712             checkCallingPackage(callingPackage);
713         } catch (SecurityException se) {
714             try {
715                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED);
716             } catch (RemoteException re) {
717                 loge("callback onComplete failure after checkCallingPackage.", re);
718             }
719             return;
720         }
721 
722         enforceTelephonyFeatureWithException(callingPackage, "resetMemory");
723 
724         EuiccPort port = getFirstActiveEuiccPort(cardId);
725         if (port == null) {
726             try {
727                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND);
728             } catch (RemoteException exception) {
729                 loge("resetMemory callback failure.", exception);
730             }
731             return;
732         }
733 
734         AsyncResultCallback<Void> cardCb = new AsyncResultCallback<Void>() {
735             @Override
736             public void onResult(Void result) {
737                 Log.i(TAG, "Request subscription info list refresh after reset memory.");
738                 SubscriptionManagerService.getInstance().updateEmbeddedSubscriptions(
739                         List.of(mUiccController.convertToPublicCardId(cardId)), null);
740                 try {
741                     callback.onComplete(EuiccCardManager.RESULT_OK);
742                 } catch (RemoteException exception) {
743                     loge("resetMemory callback failure.", exception);
744                 }
745             }
746 
747             @Override
748             public void onException(Throwable e) {
749                 try {
750                     loge("resetMemory callback onException: ", e);
751                     callback.onComplete(getResultCode(e));
752                 } catch (RemoteException exception) {
753                     loge("resetMemory callback failure.", exception);
754                 }
755             }
756         };
757 
758         port.resetMemory(options, cardCb, mEuiccMainThreadHandler);
759     }
760 
761     @Override
getDefaultSmdpAddress(String callingPackage, String cardId, IGetDefaultSmdpAddressCallback callback)762     public void getDefaultSmdpAddress(String callingPackage, String cardId,
763             IGetDefaultSmdpAddressCallback callback) {
764         try {
765             checkCallingPackage(callingPackage);
766         } catch (SecurityException se) {
767             try {
768                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
769             } catch (RemoteException re) {
770                 loge("callback onComplete failure after checkCallingPackage.", re);
771             }
772             return;
773         }
774 
775         enforceTelephonyFeatureWithException(callingPackage, "getDefaultSmdpAddress");
776 
777         EuiccPort port = getFirstActiveEuiccPort(cardId);
778         if (port == null) {
779             try {
780                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
781             } catch (RemoteException exception) {
782                 loge("getDefaultSmdpAddress callback failure.", exception);
783             }
784             return;
785         }
786 
787         AsyncResultCallback<String> cardCb = new AsyncResultCallback<String>() {
788             @Override
789             public void onResult(String result) {
790                 try {
791                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
792                 } catch (RemoteException exception) {
793                     loge("getDefaultSmdpAddress callback failure.", exception);
794                 }
795             }
796 
797             @Override
798             public void onException(Throwable e) {
799                 try {
800                     loge("getDefaultSmdpAddress callback onException: ", e);
801                     callback.onComplete(getResultCode(e), null);
802                 } catch (RemoteException exception) {
803                     loge("getDefaultSmdpAddress callback failure.", exception);
804                 }
805             }
806         };
807 
808         port.getDefaultSmdpAddress(cardCb, mEuiccMainThreadHandler);
809     }
810 
811     @Override
getSmdsAddress(String callingPackage, String cardId, IGetSmdsAddressCallback callback)812     public void getSmdsAddress(String callingPackage, String cardId,
813             IGetSmdsAddressCallback callback) {
814         try {
815             checkCallingPackage(callingPackage);
816         } catch (SecurityException se) {
817             try {
818                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
819             } catch (RemoteException re) {
820                 loge("callback onComplete failure after checkCallingPackage.", re);
821             }
822             return;
823         }
824 
825         enforceTelephonyFeatureWithException(callingPackage, "getSmdsAddress");
826 
827         EuiccPort port = getFirstActiveEuiccPort(cardId);
828         if (port == null) {
829             try {
830                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
831             } catch (RemoteException exception) {
832                 loge("getSmdsAddress callback failure.", exception);
833             }
834             return;
835         }
836 
837         AsyncResultCallback<String> cardCb = new AsyncResultCallback<String>() {
838             @Override
839             public void onResult(String result) {
840                 try {
841                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
842                 } catch (RemoteException exception) {
843                     loge("getSmdsAddress callback failure.", exception);
844                 }
845             }
846 
847             @Override
848             public void onException(Throwable e) {
849                 try {
850                     loge("getSmdsAddress callback onException: ", e);
851                     callback.onComplete(getResultCode(e), null);
852                 } catch (RemoteException exception) {
853                     loge("getSmdsAddress callback failure.", exception);
854                 }
855             }
856         };
857 
858         port.getSmdsAddress(cardCb, mEuiccMainThreadHandler);
859     }
860 
861     @Override
setDefaultSmdpAddress(String callingPackage, String cardId, String address, ISetDefaultSmdpAddressCallback callback)862     public void setDefaultSmdpAddress(String callingPackage, String cardId, String address,
863             ISetDefaultSmdpAddressCallback callback) {
864         try {
865             checkCallingPackage(callingPackage);
866         } catch (SecurityException se) {
867             try {
868                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED);
869             } catch (RemoteException re) {
870                 loge("callback onComplete failure after checkCallingPackage.", re);
871             }
872             return;
873         }
874 
875         enforceTelephonyFeatureWithException(callingPackage, "setDefaultSmdpAddress");
876 
877         EuiccPort port = getFirstActiveEuiccPort(cardId);
878         if (port == null) {
879             try {
880                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND);
881             } catch (RemoteException exception) {
882                 loge("setDefaultSmdpAddress callback failure.", exception);
883             }
884             return;
885         }
886 
887         AsyncResultCallback<Void> cardCb = new AsyncResultCallback<Void>() {
888             @Override
889             public void onResult(Void result) {
890                 try {
891                     callback.onComplete(EuiccCardManager.RESULT_OK);
892                 } catch (RemoteException exception) {
893                     loge("setDefaultSmdpAddress callback failure.", exception);
894                 }
895             }
896 
897             @Override
898             public void onException(Throwable e) {
899                 try {
900                     loge("setDefaultSmdpAddress callback onException: ", e);
901                     callback.onComplete(getResultCode(e));
902                 } catch (RemoteException exception) {
903                     loge("setDefaultSmdpAddress callback failure.", exception);
904                 }
905             }
906         };
907 
908         port.setDefaultSmdpAddress(address, cardCb, mEuiccMainThreadHandler);
909     }
910 
911     @Override
getRulesAuthTable(String callingPackage, String cardId, IGetRulesAuthTableCallback callback)912     public void getRulesAuthTable(String callingPackage, String cardId,
913             IGetRulesAuthTableCallback callback) {
914         try {
915             checkCallingPackage(callingPackage);
916         } catch (SecurityException se) {
917             try {
918                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
919             } catch (RemoteException re) {
920                 loge("callback onComplete failure after checkCallingPackage.", re);
921             }
922             return;
923         }
924 
925         enforceTelephonyFeatureWithException(callingPackage, "getRulesAuthTable");
926 
927         EuiccPort port = getFirstActiveEuiccPort(cardId);
928         if (port == null) {
929             try {
930                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
931             } catch (RemoteException exception) {
932                 loge("getRulesAuthTable callback failure.", exception);
933             }
934             return;
935         }
936 
937         AsyncResultCallback<EuiccRulesAuthTable> cardCb =
938                 new AsyncResultCallback<EuiccRulesAuthTable>() {
939             @Override
940             public void onResult(EuiccRulesAuthTable result) {
941                 try {
942                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
943                 } catch (RemoteException exception) {
944                     loge("getRulesAuthTable callback failure.", exception);
945                 }
946             }
947 
948             @Override
949             public void onException(Throwable e) {
950                 try {
951                     loge("getRulesAuthTable callback onException: ", e);
952                     callback.onComplete(getResultCode(e), null);
953                 } catch (RemoteException exception) {
954                     loge("getRulesAuthTable callback failure.", exception);
955                 }
956             }
957         };
958 
959         port.getRulesAuthTable(cardCb, mEuiccMainThreadHandler);
960     }
961 
962     @Override
getEuiccChallenge(String callingPackage, String cardId, IGetEuiccChallengeCallback callback)963     public void getEuiccChallenge(String callingPackage, String cardId,
964             IGetEuiccChallengeCallback callback) {
965         try {
966             checkCallingPackage(callingPackage);
967         } catch (SecurityException se) {
968             try {
969                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
970             } catch (RemoteException re) {
971                 loge("callback onComplete failure after checkCallingPackage.", re);
972             }
973             return;
974         }
975 
976         enforceTelephonyFeatureWithException(callingPackage, "getEuiccChallenge");
977 
978         EuiccPort port = getFirstActiveEuiccPort(cardId);
979         if (port == null) {
980             try {
981                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
982             } catch (RemoteException exception) {
983                 loge("getEuiccChallenge callback failure.", exception);
984             }
985             return;
986         }
987 
988         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
989             @Override
990             public void onResult(byte[] result) {
991                 try {
992                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
993                 } catch (RemoteException exception) {
994                     loge("getEuiccChallenge callback failure.", exception);
995                 }
996             }
997 
998             @Override
999             public void onException(Throwable e) {
1000                 try {
1001                     loge("getEuiccChallenge callback onException: ", e);
1002                     callback.onComplete(getResultCode(e), null);
1003                 } catch (RemoteException exception) {
1004                     loge("getEuiccChallenge callback failure.", exception);
1005                 }
1006             }
1007         };
1008 
1009         port.getEuiccChallenge(cardCb, mEuiccMainThreadHandler);
1010     }
1011 
1012     @Override
getEuiccInfo1(String callingPackage, String cardId, IGetEuiccInfo1Callback callback)1013     public void getEuiccInfo1(String callingPackage, String cardId,
1014             IGetEuiccInfo1Callback callback) {
1015         try {
1016             checkCallingPackage(callingPackage);
1017         } catch (SecurityException se) {
1018             try {
1019                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
1020             } catch (RemoteException re) {
1021                 loge("callback onComplete failure after checkCallingPackage.", re);
1022             }
1023             return;
1024         }
1025 
1026         enforceTelephonyFeatureWithException(callingPackage, "getEuiccInfo1");
1027 
1028         EuiccPort port = getFirstActiveEuiccPort(cardId);
1029         if (port == null) {
1030             try {
1031                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
1032             } catch (RemoteException exception) {
1033                 loge("getEuiccInfo1 callback failure.", exception);
1034             }
1035             return;
1036         }
1037 
1038         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
1039             @Override
1040             public void onResult(byte[] result) {
1041                 try {
1042                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
1043                 } catch (RemoteException exception) {
1044                     loge("getEuiccInfo1 callback failure.", exception);
1045                 }
1046             }
1047 
1048             @Override
1049             public void onException(Throwable e) {
1050                 try {
1051                     loge("getEuiccInfo1 callback onException: ", e);
1052                     callback.onComplete(getResultCode(e), null);
1053                 } catch (RemoteException exception) {
1054                     loge("getEuiccInfo1 callback failure.", exception);
1055                 }
1056             }
1057         };
1058 
1059         port.getEuiccInfo1(cardCb, mEuiccMainThreadHandler);
1060     }
1061 
1062     @Override
getEuiccInfo2(String callingPackage, String cardId, IGetEuiccInfo2Callback callback)1063     public void getEuiccInfo2(String callingPackage, String cardId,
1064             IGetEuiccInfo2Callback callback) {
1065         try {
1066             checkCallingPackage(callingPackage);
1067         } catch (SecurityException se) {
1068             try {
1069                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
1070             } catch (RemoteException re) {
1071                 loge("callback onComplete failure after checkCallingPackage.", re);
1072             }
1073             return;
1074         }
1075 
1076         enforceTelephonyFeatureWithException(callingPackage, "getEuiccInfo2");
1077 
1078         EuiccPort port = getFirstActiveEuiccPort(cardId);
1079         if (port == null) {
1080             try {
1081                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
1082             } catch (RemoteException exception) {
1083                 loge("getEuiccInfo2 callback failure.", exception);
1084             }
1085             return;
1086         }
1087 
1088         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
1089             @Override
1090             public void onResult(byte[] result) {
1091                 try {
1092                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
1093                 } catch (RemoteException exception) {
1094                     loge("getEuiccInfo2 callback failure.", exception);
1095                 }
1096             }
1097 
1098             @Override
1099             public void onException(Throwable e) {
1100                 try {
1101                     loge("getEuiccInfo2 callback onException: ", e);
1102                     callback.onComplete(getResultCode(e), null);
1103                 } catch (RemoteException exception) {
1104                     loge("getEuiccInfo2 callback failure.", exception);
1105                 }
1106             }
1107         };
1108 
1109         port.getEuiccInfo2(cardCb, mEuiccMainThreadHandler);
1110     }
1111 
1112     @Override
authenticateServer(String callingPackage, String cardId, String matchingId, byte[] serverSigned1, byte[] serverSignature1, byte[] euiccCiPkIdToBeUsed, byte[] serverCertificate, IAuthenticateServerCallback callback)1113     public void authenticateServer(String callingPackage, String cardId, String matchingId,
1114             byte[] serverSigned1, byte[] serverSignature1, byte[] euiccCiPkIdToBeUsed,
1115             byte[] serverCertificate, IAuthenticateServerCallback callback) {
1116         try {
1117             checkCallingPackage(callingPackage);
1118         } catch (SecurityException se) {
1119             try {
1120                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
1121             } catch (RemoteException re) {
1122                 loge("callback onComplete failure after checkCallingPackage.", re);
1123             }
1124             return;
1125         }
1126 
1127         enforceTelephonyFeatureWithException(callingPackage, "authenticateServer");
1128 
1129         EuiccPort port = getFirstActiveEuiccPort(cardId);
1130         if (port == null) {
1131             try {
1132                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
1133             } catch (RemoteException exception) {
1134                 loge("authenticateServer callback failure.", exception);
1135             }
1136             return;
1137         }
1138 
1139         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
1140             @Override
1141             public void onResult(byte[] result) {
1142                 try {
1143                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
1144                 } catch (RemoteException exception) {
1145                     loge("authenticateServer callback failure.", exception);
1146                 }
1147             }
1148 
1149             @Override
1150             public void onException(Throwable e) {
1151                 try {
1152                     loge("authenticateServer callback onException: ", e);
1153                     callback.onComplete(getResultCode(e), null);
1154                 } catch (RemoteException exception) {
1155                     loge("authenticateServer callback failure.", exception);
1156                 }
1157             }
1158         };
1159 
1160         port.authenticateServer(matchingId, serverSigned1, serverSignature1, euiccCiPkIdToBeUsed,
1161                 serverCertificate, cardCb, mEuiccMainThreadHandler);
1162     }
1163 
1164     @Override
prepareDownload(String callingPackage, String cardId, @Nullable byte[] hashCc, byte[] smdpSigned2, byte[] smdpSignature2, byte[] smdpCertificate, IPrepareDownloadCallback callback)1165     public void prepareDownload(String callingPackage, String cardId, @Nullable byte[] hashCc,
1166             byte[] smdpSigned2, byte[] smdpSignature2, byte[] smdpCertificate,
1167             IPrepareDownloadCallback callback) {
1168         try {
1169             checkCallingPackage(callingPackage);
1170         } catch (SecurityException se) {
1171             try {
1172                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
1173             } catch (RemoteException re) {
1174                 loge("callback onComplete failure after checkCallingPackage.", re);
1175             }
1176             return;
1177         }
1178 
1179         enforceTelephonyFeatureWithException(callingPackage, "prepareDownload");
1180 
1181         EuiccPort port = getFirstActiveEuiccPort(cardId);
1182         if (port == null) {
1183             try {
1184                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
1185             } catch (RemoteException exception) {
1186                 loge("prepareDownload callback failure.", exception);
1187             }
1188             return;
1189         }
1190 
1191         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
1192             @Override
1193             public void onResult(byte[] result) {
1194                 try {
1195                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
1196                 } catch (RemoteException exception) {
1197                     loge("prepareDownload callback failure.", exception);
1198                 }
1199             }
1200 
1201             @Override
1202             public void onException(Throwable e) {
1203                 try {
1204                     loge("prepareDownload callback onException: ", e);
1205                     callback.onComplete(getResultCode(e), null);
1206                 } catch (RemoteException exception) {
1207                     loge("prepareDownload callback failure.", exception);
1208                 }
1209             }
1210         };
1211 
1212         port.prepareDownload(hashCc, smdpSigned2, smdpSignature2, smdpCertificate, cardCb,
1213                 mEuiccMainThreadHandler);
1214     }
1215 
1216     @Override
loadBoundProfilePackage(String callingPackage, String cardId, byte[] boundProfilePackage, ILoadBoundProfilePackageCallback callback)1217     public void loadBoundProfilePackage(String callingPackage, String cardId,
1218             byte[] boundProfilePackage, ILoadBoundProfilePackageCallback callback) {
1219         try {
1220             checkCallingPackage(callingPackage);
1221         } catch (SecurityException se) {
1222             try {
1223                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
1224             } catch (RemoteException re) {
1225                 loge("callback onComplete failure after checkCallingPackage.", re);
1226             }
1227             return;
1228         }
1229 
1230         enforceTelephonyFeatureWithException(callingPackage, "loadBoundProfilePackage");
1231 
1232         EuiccPort port = getFirstActiveEuiccPort(cardId);
1233         if (port == null) {
1234             try {
1235                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
1236             } catch (RemoteException exception) {
1237                 loge("loadBoundProfilePackage callback failure.", exception);
1238             }
1239             return;
1240         }
1241 
1242         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
1243             @Override
1244             public void onResult(byte[] result) {
1245                 Log.i(TAG, "Request subscription info list refresh after install.");
1246                 SubscriptionManagerService.getInstance().updateEmbeddedSubscriptions(
1247                         List.of(mUiccController.convertToPublicCardId(cardId)), null);
1248                 try {
1249                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
1250                 } catch (RemoteException exception) {
1251                     loge("loadBoundProfilePackage callback failure.", exception);
1252                 }
1253             }
1254 
1255             @Override
1256             public void onException(Throwable e) {
1257                 try {
1258                     loge("loadBoundProfilePackage callback onException: ", e);
1259                     callback.onComplete(getResultCode(e), null);
1260                 } catch (RemoteException exception) {
1261                     loge("loadBoundProfilePackage callback failure.", exception);
1262                 }
1263             }
1264         };
1265 
1266         port.loadBoundProfilePackage(boundProfilePackage, cardCb, mEuiccMainThreadHandler);
1267     }
1268 
1269     @Override
cancelSession(String callingPackage, String cardId, byte[] transactionId, @EuiccCardManager.CancelReason int reason, ICancelSessionCallback callback)1270     public void cancelSession(String callingPackage, String cardId, byte[] transactionId,
1271             @EuiccCardManager.CancelReason int reason, ICancelSessionCallback callback) {
1272         try {
1273             checkCallingPackage(callingPackage);
1274         } catch (SecurityException se) {
1275             try {
1276                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
1277             } catch (RemoteException re) {
1278                 loge("callback onComplete failure after checkCallingPackage.", re);
1279             }
1280             return;
1281         }
1282 
1283         enforceTelephonyFeatureWithException(callingPackage, "cancelSession");
1284 
1285         EuiccPort port = getFirstActiveEuiccPort(cardId);
1286         if (port == null) {
1287             try {
1288                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
1289             } catch (RemoteException exception) {
1290                 loge("cancelSession callback failure.", exception);
1291             }
1292             return;
1293         }
1294 
1295         AsyncResultCallback<byte[]> cardCb = new AsyncResultCallback<byte[]>() {
1296             @Override
1297             public void onResult(byte[] result) {
1298                 try {
1299                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
1300                 } catch (RemoteException exception) {
1301                     loge("cancelSession callback failure.", exception);
1302                 }
1303             }
1304 
1305             @Override
1306             public void onException(Throwable e) {
1307                 try {
1308                     loge("cancelSession callback onException: ", e);
1309                     callback.onComplete(getResultCode(e), null);
1310                 } catch (RemoteException exception) {
1311                     loge("cancelSession callback failure.", exception);
1312                 }
1313             }
1314         };
1315 
1316         port.cancelSession(transactionId, reason, cardCb, mEuiccMainThreadHandler);
1317     }
1318 
1319     @Override
listNotifications(String callingPackage, String cardId, @EuiccNotification.Event int events, IListNotificationsCallback callback)1320     public void listNotifications(String callingPackage, String cardId,
1321             @EuiccNotification.Event int events, IListNotificationsCallback callback) {
1322         try {
1323             checkCallingPackage(callingPackage);
1324         } catch (SecurityException se) {
1325             try {
1326                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
1327             } catch (RemoteException re) {
1328                 loge("callback onComplete failure after checkCallingPackage.", re);
1329             }
1330             return;
1331         }
1332 
1333         enforceTelephonyFeatureWithException(callingPackage, "listNotifications");
1334 
1335         EuiccPort port = getFirstActiveEuiccPort(cardId);
1336         if (port == null) {
1337             try {
1338                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
1339             } catch (RemoteException exception) {
1340                 loge("listNotifications callback failure.", exception);
1341             }
1342             return;
1343         }
1344 
1345         AsyncResultCallback<EuiccNotification[]> cardCb =
1346                 new AsyncResultCallback<EuiccNotification[]>() {
1347             @Override
1348             public void onResult(EuiccNotification[] result) {
1349                 try {
1350                     callback.onComplete(EuiccCardManager.RESULT_OK, result);
1351                 } catch (RemoteException exception) {
1352                     loge("listNotifications callback failure.", exception);
1353                 }
1354             }
1355 
1356             @Override
1357             public void onException(Throwable e) {
1358                 try {
1359                     loge("listNotifications callback onException: ", e);
1360                     callback.onComplete(getResultCode(e), null);
1361                 } catch (RemoteException exception) {
1362                     loge("listNotifications callback failure.", exception);
1363                 }
1364             }
1365         };
1366 
1367         port.listNotifications(events, cardCb, mEuiccMainThreadHandler);
1368     }
1369 
1370     @Override
retrieveNotificationList(String callingPackage, String cardId, @EuiccNotification.Event int events, IRetrieveNotificationListCallback callback)1371     public void retrieveNotificationList(String callingPackage, String cardId,
1372             @EuiccNotification.Event int events, IRetrieveNotificationListCallback callback) {
1373         try {
1374             checkCallingPackage(callingPackage);
1375         } catch (SecurityException se) {
1376             try {
1377                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
1378             } catch (RemoteException re) {
1379                 loge("callback onComplete failure after checkCallingPackage.", re);
1380             }
1381             return;
1382         }
1383 
1384         enforceTelephonyFeatureWithException(callingPackage, "retrieveNotificationList");
1385 
1386         EuiccPort port = getFirstActiveEuiccPort(cardId);
1387         if (port == null) {
1388             try {
1389                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
1390             } catch (RemoteException exception) {
1391                 loge("retrieveNotificationList callback failure.", exception);
1392             }
1393             return;
1394         }
1395 
1396         AsyncResultCallback<EuiccNotification[]> cardCb =
1397                 new AsyncResultCallback<EuiccNotification[]>() {
1398                     @Override
1399                     public void onResult(EuiccNotification[] result) {
1400                         try {
1401                             callback.onComplete(EuiccCardManager.RESULT_OK, result);
1402                         } catch (RemoteException exception) {
1403                             loge("retrieveNotificationList callback failure.", exception);
1404                         }
1405                     }
1406 
1407                     @Override
1408                     public void onException(Throwable e) {
1409                         try {
1410                             loge("retrieveNotificationList callback onException: ", e);
1411                             callback.onComplete(getResultCode(e), null);
1412                         } catch (RemoteException exception) {
1413                             loge("retrieveNotificationList callback failure.", exception);
1414                         }
1415                     }
1416                 };
1417 
1418         port.retrieveNotificationList(events, cardCb, mEuiccMainThreadHandler);
1419     }
1420 
1421     @Override
retrieveNotification(String callingPackage, String cardId, int seqNumber, IRetrieveNotificationCallback callback)1422     public void retrieveNotification(String callingPackage, String cardId, int seqNumber,
1423             IRetrieveNotificationCallback callback) {
1424         try {
1425             checkCallingPackage(callingPackage);
1426         } catch (SecurityException se) {
1427             try {
1428                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
1429             } catch (RemoteException re) {
1430                 loge("callback onComplete failure after checkCallingPackage.", re);
1431             }
1432             return;
1433         }
1434 
1435         enforceTelephonyFeatureWithException(callingPackage, "retrieveNotification");
1436 
1437         EuiccPort port = getFirstActiveEuiccPort(cardId);
1438         if (port == null) {
1439             try {
1440                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
1441             } catch (RemoteException exception) {
1442                 loge("retrieveNotification callback failure.", exception);
1443             }
1444             return;
1445         }
1446 
1447         AsyncResultCallback<EuiccNotification> cardCb =
1448                 new AsyncResultCallback<EuiccNotification>() {
1449                     @Override
1450                     public void onResult(EuiccNotification result) {
1451                         try {
1452                             callback.onComplete(EuiccCardManager.RESULT_OK, result);
1453                         } catch (RemoteException exception) {
1454                             loge("retrieveNotification callback failure.", exception);
1455                         }
1456                     }
1457 
1458                     @Override
1459                     public void onException(Throwable e) {
1460                         try {
1461                             loge("retrieveNotification callback onException: ", e);
1462                             callback.onComplete(getResultCode(e), null);
1463                         } catch (RemoteException exception) {
1464                             loge("retrieveNotification callback failure.", exception);
1465                         }
1466                     }
1467                 };
1468 
1469         port.retrieveNotification(seqNumber, cardCb, mEuiccMainThreadHandler);
1470     }
1471 
1472     @Override
removeNotificationFromList(String callingPackage, String cardId, int seqNumber, IRemoveNotificationFromListCallback callback)1473     public void removeNotificationFromList(String callingPackage, String cardId, int seqNumber,
1474             IRemoveNotificationFromListCallback callback) {
1475         try {
1476             checkCallingPackage(callingPackage);
1477         } catch (SecurityException se) {
1478             try {
1479                 callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED);
1480             } catch (RemoteException re) {
1481                 loge("callback onComplete failure after checkCallingPackage.", re);
1482             }
1483             return;
1484         }
1485 
1486         enforceTelephonyFeatureWithException(callingPackage, "removeNotificationFromList");
1487 
1488         EuiccPort port = getFirstActiveEuiccPort(cardId);
1489         if (port == null) {
1490             try {
1491                 callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND);
1492             } catch (RemoteException exception) {
1493                 loge("removeNotificationFromList callback failure.", exception);
1494             }
1495             return;
1496         }
1497 
1498         AsyncResultCallback<Void> cardCb = new AsyncResultCallback<Void>() {
1499                     @Override
1500                     public void onResult(Void result) {
1501                         try {
1502                             callback.onComplete(EuiccCardManager.RESULT_OK);
1503                         } catch (RemoteException exception) {
1504                             loge("removeNotificationFromList callback failure.", exception);
1505                         }
1506 
1507                     }
1508 
1509                     @Override
1510                     public void onException(Throwable e) {
1511                         try {
1512                             loge("removeNotificationFromList callback onException: ", e);
1513                             callback.onComplete(getResultCode(e));
1514                         } catch (RemoteException exception) {
1515                             loge("removeNotificationFromList callback failure.", exception);
1516                         }
1517                     }
1518                 };
1519 
1520         port.removeNotificationFromList(seqNumber, cardCb, mEuiccMainThreadHandler);
1521     }
1522 
1523     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)1524     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1525         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "Requires DUMP");
1526         final long token = Binder.clearCallingIdentity();
1527 
1528         super.dump(fd, pw, args);
1529         // TODO(b/38206971): dump more information.
1530         pw.println("mCallingPackage=" + mCallingPackage);
1531         pw.println("mBestComponent=" + mBestComponent);
1532 
1533         Binder.restoreCallingIdentity(token);
1534     }
1535 
1536     /**
1537      * Make sure the device has required telephony feature
1538      *
1539      * @throws UnsupportedOperationException if the device does not have required telephony feature
1540      */
enforceTelephonyFeatureWithException(@ullable String callingPackage, @NonNull String methodName)1541     private void enforceTelephonyFeatureWithException(@Nullable String callingPackage,
1542             @NonNull String methodName) {
1543         if (callingPackage == null || mPackageManager == null) {
1544             return;
1545         }
1546 
1547         if (!CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
1548                 Binder.getCallingUserHandle())
1549                 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
1550             // Skip to check associated telephony feature,
1551             // if compatibility change is not enabled for the current process or
1552             // the SDK version of vendor partition is less than Android V.
1553             return;
1554         }
1555 
1556         if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY_EUICC)) {
1557             throw new UnsupportedOperationException(
1558                     methodName + " is unsupported without " + FEATURE_TELEPHONY_EUICC);
1559         }
1560     }
1561 
loge(String message)1562     private static void loge(String message) {
1563         Log.e(TAG, message);
1564     }
1565 
loge(String message, Throwable tr)1566     private static void loge(String message, Throwable tr) {
1567         Log.e(TAG, message, tr);
1568     }
1569 }
1570