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 package android.telephony.euicc;
17 
18 import android.annotation.CallbackExecutor;
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.RequiresFeature;
23 import android.annotation.SystemApi;
24 import android.content.Context;
25 import android.content.pm.PackageManager;
26 import android.os.Binder;
27 import android.os.RemoteException;
28 import android.service.euicc.EuiccProfileInfo;
29 import android.telephony.TelephonyFrameworkInitializer;
30 import android.telephony.TelephonyManager;
31 import android.util.Log;
32 
33 import com.android.internal.telephony.euicc.IAuthenticateServerCallback;
34 import com.android.internal.telephony.euicc.ICancelSessionCallback;
35 import com.android.internal.telephony.euicc.IDeleteProfileCallback;
36 import com.android.internal.telephony.euicc.IDisableProfileCallback;
37 import com.android.internal.telephony.euicc.IEuiccCardController;
38 import com.android.internal.telephony.euicc.IGetAllProfilesCallback;
39 import com.android.internal.telephony.euicc.IGetDefaultSmdpAddressCallback;
40 import com.android.internal.telephony.euicc.IGetEuiccChallengeCallback;
41 import com.android.internal.telephony.euicc.IGetEuiccInfo1Callback;
42 import com.android.internal.telephony.euicc.IGetEuiccInfo2Callback;
43 import com.android.internal.telephony.euicc.IGetProfileCallback;
44 import com.android.internal.telephony.euicc.IGetRulesAuthTableCallback;
45 import com.android.internal.telephony.euicc.IGetSmdsAddressCallback;
46 import com.android.internal.telephony.euicc.IListNotificationsCallback;
47 import com.android.internal.telephony.euicc.ILoadBoundProfilePackageCallback;
48 import com.android.internal.telephony.euicc.IPrepareDownloadCallback;
49 import com.android.internal.telephony.euicc.IRemoveNotificationFromListCallback;
50 import com.android.internal.telephony.euicc.IResetMemoryCallback;
51 import com.android.internal.telephony.euicc.IRetrieveNotificationCallback;
52 import com.android.internal.telephony.euicc.IRetrieveNotificationListCallback;
53 import com.android.internal.telephony.euicc.ISetDefaultSmdpAddressCallback;
54 import com.android.internal.telephony.euicc.ISetNicknameCallback;
55 import com.android.internal.telephony.euicc.ISwitchToProfileCallback;
56 
57 import java.lang.annotation.Retention;
58 import java.lang.annotation.RetentionPolicy;
59 import java.util.concurrent.Executor;
60 
61 /**
62  * EuiccCardManager is the application interface to an eSIM card.
63  * @hide
64  */
65 @SystemApi
66 @RequiresFeature(PackageManager.FEATURE_TELEPHONY_EUICC)
67 public class EuiccCardManager {
68     private static final String TAG = "EuiccCardManager";
69 
70     /**
71      * Reason for canceling a profile download session
72      *
73      * @removed mistakenly exposed previously
74      */
75     @Retention(RetentionPolicy.SOURCE)
76     @IntDef(prefix = {"CANCEL_REASON_"}, value = {
77             CANCEL_REASON_END_USER_REJECTED,
78             CANCEL_REASON_POSTPONED,
79             CANCEL_REASON_TIMEOUT,
80             CANCEL_REASON_PPR_NOT_ALLOWED
81     })
82     public @interface CancelReason {
83     }
84 
85     /**
86      * The end user has rejected the download. The profile will be put into the error state and
87      * cannot be downloaded again without the operator's change.
88      */
89     public static final int CANCEL_REASON_END_USER_REJECTED = 0;
90 
91     /** The download has been postponed and can be restarted later. */
92     public static final int CANCEL_REASON_POSTPONED = 1;
93 
94     /** The download has been timed out and can be restarted later. */
95     public static final int CANCEL_REASON_TIMEOUT = 2;
96 
97     /**
98      * The profile to be downloaded cannot be installed due to its policy rule is not allowed by
99      * the RAT (Rules Authorisation Table) on the eUICC or by other installed profiles. The
100      * download can be restarted later.
101      */
102     public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3;
103 
104     /**
105      * Options for resetting eUICC memory
106      *
107      * @removed mistakenly exposed previously
108      */
109     @Retention(RetentionPolicy.SOURCE)
110     @IntDef(flag = true, prefix = {"RESET_OPTION_"}, value = {
111             RESET_OPTION_DELETE_OPERATIONAL_PROFILES,
112             RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES,
113             RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS
114     })
115     public @interface ResetOption {
116     }
117 
118     /** Deletes all operational profiles. */
119     public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1;
120 
121     /** Deletes all field-loaded testing profiles. */
122     public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 1 << 1;
123 
124     /** Resets the default SM-DP+ address. */
125     public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 1 << 2;
126 
127     /** Result code when the requested profile is not found.
128      * {@link #RESULT_PROFILE_NOT_FOUND} is not used in Android U+,
129      * use {@link #RESULT_PROFILE_DOES_NOT_EXIST} instead.
130      **/
131     public static final int RESULT_PROFILE_NOT_FOUND = 1;
132 
133     /** Result code of execution with no error. */
134     public static final int RESULT_OK = 0;
135 
136     /** Result code of an unknown error. */
137     public static final int RESULT_UNKNOWN_ERROR = -1;
138 
139     /** Result code when the eUICC card with the given card Id is not found. */
140     public static final int RESULT_EUICC_NOT_FOUND = -2;
141 
142     /** Result code indicating the caller is not the active LPA. */
143     public static final int RESULT_CALLER_NOT_ALLOWED = -3;
144 
145     /** Result code when the requested profile does not exist */
146     public static final int RESULT_PROFILE_DOES_NOT_EXIST = -4;
147 
148     /**
149      * Callback to receive the result of an eUICC card API.
150      *
151      * @param <T> Type of the result.
152      */
153     public interface ResultCallback<T> {
154         /**
155          * This method will be called when an eUICC card API call is completed.
156          *
157          * @param resultCode This can be {@link #RESULT_OK} or other positive values returned by the
158          *                   eUICC.
159          * @param result     The result object. It can be null if the {@code resultCode} is not
160          *                   {@link #RESULT_OK}.
161          */
onComplete(int resultCode, T result)162         void onComplete(int resultCode, T result);
163     }
164 
165     private final Context mContext;
166 
167     /** @hide */
EuiccCardManager(Context context)168     public EuiccCardManager(Context context) {
169         mContext = context;
170     }
171 
getIEuiccCardController()172     private IEuiccCardController getIEuiccCardController() {
173         return IEuiccCardController.Stub.asInterface(
174                 TelephonyFrameworkInitializer
175                         .getTelephonyServiceManager()
176                         .getEuiccCardControllerServiceRegisterer()
177                         .get());
178     }
179 
180     /**
181      * Requests all the profiles on eUicc.
182      *
183      * @param cardId   The Id of the eUICC.
184      * @param executor The executor through which the callback should be invoked.
185      * @param callback The callback to get the result code and all the profiles.
186      *
187      * @throws UnsupportedOperationException If the device does not have
188      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
189      */
requestAllProfiles(String cardId, @CallbackExecutor Executor executor, ResultCallback<EuiccProfileInfo[]> callback)190     public void requestAllProfiles(String cardId, @CallbackExecutor Executor executor,
191             ResultCallback<EuiccProfileInfo[]> callback) {
192         try {
193             getIEuiccCardController().getAllProfiles(mContext.getOpPackageName(), cardId,
194                     new IGetAllProfilesCallback.Stub() {
195                         @Override
196                         public void onComplete(int resultCode, EuiccProfileInfo[] profiles) {
197                             final long token = Binder.clearCallingIdentity();
198                             try {
199                                 executor.execute(() -> callback.onComplete(resultCode, profiles));
200                             } finally {
201                                 Binder.restoreCallingIdentity(token);
202                             }
203                         }
204                     });
205         } catch (RemoteException e) {
206             Log.e(TAG, "Error calling getAllProfiles", e);
207             throw e.rethrowFromSystemServer();
208         }
209     }
210 
211     /**
212      * Requests the profile of the given iccid.
213      *
214      * @param cardId   The Id of the eUICC.
215      * @param iccid    The iccid of the profile.
216      * @param executor The executor through which the callback should be invoked.
217      * @param callback The callback to get the result code and profile.
218      *
219      * @throws UnsupportedOperationException If the device does not have
220      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
221      */
requestProfile(String cardId, String iccid, @CallbackExecutor Executor executor, ResultCallback<EuiccProfileInfo> callback)222     public void requestProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
223             ResultCallback<EuiccProfileInfo> callback) {
224         try {
225             getIEuiccCardController().getProfile(mContext.getOpPackageName(), cardId, iccid,
226                     new IGetProfileCallback.Stub() {
227                         @Override
228                         public void onComplete(int resultCode, EuiccProfileInfo profile) {
229                             final long token = Binder.clearCallingIdentity();
230                             try {
231                                 executor.execute(() -> callback.onComplete(resultCode, profile));
232                             } finally {
233                                 Binder.restoreCallingIdentity(token);
234                             }
235                         }
236                     });
237         } catch (RemoteException e) {
238             Log.e(TAG, "Error calling getProfile", e);
239             throw e.rethrowFromSystemServer();
240         }
241     }
242 
243     /**
244      * Requests the enabled profile for a given port on an eUicc. Callback with result code
245      * {@link RESULT_PROFILE_DOES_NOT_EXIST} and {@code NULL} EuiccProfile if there is no enabled
246      * profile on the target port.
247      *
248      * @param cardId    The Id of the eUICC.
249      * @param portIndex The portIndex to use. The port may be active or inactive. As long as the
250      *                  ICCID is known, an APDU will be sent through to read the enabled profile.
251      * @param executor  The executor through which the callback should be invoked.
252      * @param callback  The callback to get the result code and the profile.
253      *
254      * @throws UnsupportedOperationException If the device does not have
255      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
256      */
requestEnabledProfileForPort(@onNull String cardId, int portIndex, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<EuiccProfileInfo> callback)257     public void requestEnabledProfileForPort(@NonNull String cardId, int portIndex,
258             @NonNull @CallbackExecutor Executor executor,
259             @NonNull ResultCallback<EuiccProfileInfo> callback) {
260         try {
261             getIEuiccCardController().getEnabledProfile(mContext.getOpPackageName(), cardId,
262                     portIndex,
263                     new IGetProfileCallback.Stub() {
264                         @Override
265                         public void onComplete(int resultCode, EuiccProfileInfo profile) {
266                             final long token = Binder.clearCallingIdentity();
267                             try {
268                                 executor.execute(() -> callback.onComplete(resultCode, profile));
269                             } finally {
270                                 Binder.restoreCallingIdentity(token);
271                             }
272                         }
273                     });
274         } catch (RemoteException e) {
275             Log.e(TAG, "Error calling requestEnabledProfileForPort", e);
276             throw e.rethrowFromSystemServer();
277         }
278     }
279 
280     /**
281      * Disables the profile of the given iccid.
282      *
283      * @param cardId   The Id of the eUICC.
284      * @param iccid    The iccid of the profile.
285      * @param refresh  Whether sending the REFRESH command to modem.
286      * @param executor The executor through which the callback should be invoked.
287      * @param callback The callback to get the result code.
288      *
289      * @throws UnsupportedOperationException If the device does not have
290      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
291      */
disableProfile(String cardId, String iccid, boolean refresh, @CallbackExecutor Executor executor, ResultCallback<Void> callback)292     public void disableProfile(String cardId, String iccid, boolean refresh,
293             @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
294         try {
295             getIEuiccCardController().disableProfile(mContext.getOpPackageName(), cardId, iccid,
296                     refresh, new IDisableProfileCallback.Stub() {
297                         @Override
298                         public void onComplete(int resultCode) {
299                             final long token = Binder.clearCallingIdentity();
300                             try {
301                                 executor.execute(() -> callback.onComplete(resultCode, null));
302                             } finally {
303                                 Binder.restoreCallingIdentity(token);
304                             }
305                         }
306                     });
307         } catch (RemoteException e) {
308             Log.e(TAG, "Error calling disableProfile", e);
309             throw e.rethrowFromSystemServer();
310         }
311     }
312 
313     /**
314      * Switches from the current profile to another profile. The current profile will be disabled
315      * and the specified profile will be enabled.
316      *
317      * @param cardId   The Id of the eUICC.
318      * @param iccid    The iccid of the profile to switch to.
319      * @param refresh  Whether sending the REFRESH command to modem.
320      * @param executor The executor through which the callback should be invoked.
321      * @param callback The callback to get the result code and the EuiccProfileInfo enabled.
322      *
323      * @throws UnsupportedOperationException If the device does not have
324      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
325      * @deprecated instead use {@link #switchToProfile(String, String, int, boolean, Executor,
326      * ResultCallback)}
327      */
328     @Deprecated
switchToProfile(String cardId, String iccid, boolean refresh, @CallbackExecutor Executor executor, ResultCallback<EuiccProfileInfo> callback)329     public void switchToProfile(String cardId, String iccid, boolean refresh,
330             @CallbackExecutor Executor executor, ResultCallback<EuiccProfileInfo> callback) {
331         try {
332             getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), cardId, iccid,
333                     TelephonyManager.DEFAULT_PORT_INDEX, refresh,
334                     new ISwitchToProfileCallback.Stub() {
335                         @Override
336                         public void onComplete(int resultCode, EuiccProfileInfo profile) {
337                             final long token = Binder.clearCallingIdentity();
338                             try {
339                                 executor.execute(() -> callback.onComplete(resultCode, profile));
340                             } finally {
341                                 Binder.restoreCallingIdentity(token);
342                             }
343                         }
344                     });
345         } catch (RemoteException e) {
346             Log.e(TAG, "Error calling switchToProfile", e);
347             throw e.rethrowFromSystemServer();
348         }
349     }
350 
351     /**
352      * Switches from the current profile to another profile. The current profile will be disabled
353      * and the specified profile will be enabled. Here portIndex specifies on which port the
354      * profile is to be enabled.
355      *
356      * @param cardId    The Id of the eUICC.
357      * @param iccid     The iccid of the profile to switch to.
358      * @param portIndex The Port index is the unique index referring to a port.
359      * @param refresh   Whether sending the REFRESH command to modem.
360      * @param executor  The executor through which the callback should be invoked.
361      * @param callback  The callback to get the result code and the EuiccProfileInfo enabled.
362      *
363      * @throws UnsupportedOperationException If the device does not have
364      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
365      */
switchToProfile(@ullable String cardId, @Nullable String iccid, int portIndex, boolean refresh, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<EuiccProfileInfo> callback)366     public void switchToProfile(@Nullable String cardId, @Nullable String iccid, int portIndex,
367             boolean refresh, @NonNull @CallbackExecutor Executor executor,
368             @NonNull ResultCallback<EuiccProfileInfo> callback) {
369         try {
370             getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), cardId, iccid,
371                     portIndex, refresh, new ISwitchToProfileCallback.Stub() {
372                         @Override
373                         public void onComplete(int resultCode, EuiccProfileInfo profile) {
374                             final long token = Binder.clearCallingIdentity();
375                             try {
376                                 executor.execute(() -> callback.onComplete(resultCode, profile));
377                             } finally {
378                                 Binder.restoreCallingIdentity(token);
379                             }
380                         }
381                     });
382         } catch (RemoteException e) {
383             Log.e(TAG, "Error calling switchToProfile", e);
384             throw e.rethrowFromSystemServer();
385         }
386     }
387 
388     /**
389      * Sets the nickname of the profile of the given iccid.
390      *
391      * @param cardId The Id of the eUICC.
392      * @param iccid The iccid of the profile.
393      * @param nickname The nickname of the profile.
394      * @param executor The executor through which the callback should be invoked.
395      * @param callback The callback to get the result code.
396      *
397      * @throws UnsupportedOperationException If the device does not have
398      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
399      */
setNickname(String cardId, String iccid, String nickname, @CallbackExecutor Executor executor, ResultCallback<Void> callback)400     public void setNickname(String cardId, String iccid, String nickname,
401             @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
402         try {
403             getIEuiccCardController().setNickname(mContext.getOpPackageName(), cardId, iccid,
404                     nickname, new ISetNicknameCallback.Stub() {
405                         @Override
406                         public void onComplete(int resultCode) {
407                             final long token = Binder.clearCallingIdentity();
408                             try {
409                                 executor.execute(() -> callback.onComplete(resultCode, null));
410                             } finally {
411                                 Binder.restoreCallingIdentity(token);
412                             }
413                         }
414                     });
415         } catch (RemoteException e) {
416             Log.e(TAG, "Error calling setNickname", e);
417             throw e.rethrowFromSystemServer();
418         }
419     }
420 
421     /**
422      * Deletes the profile of the given iccid from eUICC.
423      *
424      * @param cardId The Id of the eUICC.
425      * @param iccid The iccid of the profile.
426      * @param executor The executor through which the callback should be invoked.
427      * @param callback The callback to get the result code.
428      *
429      * @throws UnsupportedOperationException If the device does not have
430      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
431      */
deleteProfile(String cardId, String iccid, @CallbackExecutor Executor executor, ResultCallback<Void> callback)432     public void deleteProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
433             ResultCallback<Void> callback) {
434         try {
435             getIEuiccCardController().deleteProfile(mContext.getOpPackageName(), cardId, iccid,
436                     new IDeleteProfileCallback.Stub() {
437                         @Override
438                         public void onComplete(int resultCode) {
439                             final long token = Binder.clearCallingIdentity();
440                             try {
441                                 executor.execute(() -> callback.onComplete(resultCode, null));
442                             } finally {
443                                 Binder.restoreCallingIdentity(token);
444                             }
445                         }
446                     });
447         } catch (RemoteException e) {
448             Log.e(TAG, "Error calling deleteProfile", e);
449             throw e.rethrowFromSystemServer();
450         }
451     }
452 
453     /**
454      * Resets the eUICC memory.
455      *
456      * @param cardId The Id of the eUICC.
457      * @param options Bits of the options of resetting which parts of the eUICC memory. See
458      *     EuiccCard for details.
459      * @param executor The executor through which the callback should be invoked.
460      * @param callback The callback to get the result code.
461      *
462      * @throws UnsupportedOperationException If the device does not have
463      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
464      */
resetMemory(String cardId, @ResetOption int options, @CallbackExecutor Executor executor, ResultCallback<Void> callback)465     public void resetMemory(String cardId, @ResetOption int options,
466             @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
467         try {
468             getIEuiccCardController().resetMemory(mContext.getOpPackageName(), cardId, options,
469                     new IResetMemoryCallback.Stub() {
470                         @Override
471                         public void onComplete(int resultCode) {
472                             final long token = Binder.clearCallingIdentity();
473                             try {
474                                 executor.execute(() -> callback.onComplete(resultCode, null));
475                             } finally {
476                                 Binder.restoreCallingIdentity(token);
477                             }
478                         }
479                     });
480         } catch (RemoteException e) {
481             Log.e(TAG, "Error calling resetMemory", e);
482             throw e.rethrowFromSystemServer();
483         }
484     }
485 
486     /**
487      * Requests the default SM-DP+ address from eUICC.
488      *
489      * @param cardId The Id of the eUICC.
490      * @param executor The executor through which the callback should be invoked.
491      * @param callback The callback to get the result code and the default SM-DP+ address.
492      *
493      * @throws UnsupportedOperationException If the device does not have
494      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
495      */
requestDefaultSmdpAddress(String cardId, @CallbackExecutor Executor executor, ResultCallback<String> callback)496     public void requestDefaultSmdpAddress(String cardId, @CallbackExecutor Executor executor,
497             ResultCallback<String> callback) {
498         try {
499             getIEuiccCardController().getDefaultSmdpAddress(mContext.getOpPackageName(), cardId,
500                     new IGetDefaultSmdpAddressCallback.Stub() {
501                         @Override
502                         public void onComplete(int resultCode, String address) {
503                             final long token = Binder.clearCallingIdentity();
504                             try {
505                                 executor.execute(() -> callback.onComplete(resultCode, address));
506                             } finally {
507                                 Binder.restoreCallingIdentity(token);
508                             }
509                         }
510                     });
511         } catch (RemoteException e) {
512             Log.e(TAG, "Error calling getDefaultSmdpAddress", e);
513             throw e.rethrowFromSystemServer();
514         }
515     }
516 
517     /**
518      * Requests the SM-DS address from eUICC.
519      *
520      * @param cardId The Id of the eUICC.
521      * @param executor The executor through which the callback should be invoked.
522      * @param callback The callback to get the result code and the SM-DS address.
523      *
524      * @throws UnsupportedOperationException If the device does not have
525      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
526      */
requestSmdsAddress(String cardId, @CallbackExecutor Executor executor, ResultCallback<String> callback)527     public void requestSmdsAddress(String cardId, @CallbackExecutor Executor executor,
528             ResultCallback<String> callback) {
529         try {
530             getIEuiccCardController().getSmdsAddress(mContext.getOpPackageName(), cardId,
531                     new IGetSmdsAddressCallback.Stub() {
532                         @Override
533                         public void onComplete(int resultCode, String address) {
534                             final long token = Binder.clearCallingIdentity();
535                             try {
536                                 executor.execute(() -> callback.onComplete(resultCode, address));
537                             } finally {
538                                 Binder.restoreCallingIdentity(token);
539                             }
540                         }
541                     });
542         } catch (RemoteException e) {
543             Log.e(TAG, "Error calling getSmdsAddress", e);
544             throw e.rethrowFromSystemServer();
545         }
546     }
547 
548     /**
549      * Sets the default SM-DP+ address of eUICC.
550      *
551      * @param cardId The Id of the eUICC.
552      * @param defaultSmdpAddress The default SM-DP+ address to set.
553      * @param executor The executor through which the callback should be invoked.
554      * @param callback The callback to get the result code.
555      *
556      * @throws UnsupportedOperationException If the device does not have
557      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
558      */
setDefaultSmdpAddress(String cardId, String defaultSmdpAddress, @CallbackExecutor Executor executor, ResultCallback<Void> callback)559     public void setDefaultSmdpAddress(String cardId, String defaultSmdpAddress,
560             @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
561         try {
562             getIEuiccCardController().setDefaultSmdpAddress(mContext.getOpPackageName(), cardId,
563                     defaultSmdpAddress,
564                     new ISetDefaultSmdpAddressCallback.Stub() {
565                         @Override
566                         public void onComplete(int resultCode) {
567                             final long token = Binder.clearCallingIdentity();
568                             try {
569                                 executor.execute(() -> callback.onComplete(resultCode, null));
570                             } finally {
571                                 Binder.restoreCallingIdentity(token);
572                             }
573                         }
574                     });
575         } catch (RemoteException e) {
576             Log.e(TAG, "Error calling setDefaultSmdpAddress", e);
577             throw e.rethrowFromSystemServer();
578         }
579     }
580 
581     /**
582      * Requests Rules Authorisation Table.
583      *
584      * @param cardId The Id of the eUICC.
585      * @param executor The executor through which the callback should be invoked.
586      * @param callback the callback to get the result code and the rule authorisation table.
587      *
588      * @throws UnsupportedOperationException If the device does not have
589      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
590      */
requestRulesAuthTable(String cardId, @CallbackExecutor Executor executor, ResultCallback<EuiccRulesAuthTable> callback)591     public void requestRulesAuthTable(String cardId, @CallbackExecutor Executor executor,
592             ResultCallback<EuiccRulesAuthTable> callback) {
593         try {
594             getIEuiccCardController().getRulesAuthTable(mContext.getOpPackageName(), cardId,
595                     new IGetRulesAuthTableCallback.Stub() {
596                         @Override
597                         public void onComplete(int resultCode, EuiccRulesAuthTable rat) {
598                             final long token = Binder.clearCallingIdentity();
599                             try {
600                                 executor.execute(() -> callback.onComplete(resultCode, rat));
601                             } finally {
602                                 Binder.restoreCallingIdentity(token);
603                             }
604                         }
605                     });
606         } catch (RemoteException e) {
607             Log.e(TAG, "Error calling getRulesAuthTable", e);
608             throw e.rethrowFromSystemServer();
609         }
610     }
611 
612     /**
613      * Requests the eUICC challenge for new profile downloading.
614      *
615      * @param cardId The Id of the eUICC.
616      * @param executor The executor through which the callback should be invoked.
617      * @param callback the callback to get the result code and the challenge.
618      *
619      * @throws UnsupportedOperationException If the device does not have
620      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
621      */
requestEuiccChallenge(String cardId, @CallbackExecutor Executor executor, ResultCallback<byte[]> callback)622     public void requestEuiccChallenge(String cardId, @CallbackExecutor Executor executor,
623             ResultCallback<byte[]> callback) {
624         try {
625             getIEuiccCardController().getEuiccChallenge(mContext.getOpPackageName(), cardId,
626                     new IGetEuiccChallengeCallback.Stub() {
627                         @Override
628                         public void onComplete(int resultCode, byte[] challenge) {
629                             final long token = Binder.clearCallingIdentity();
630                             try {
631                                 executor.execute(() -> callback.onComplete(resultCode, challenge));
632                             } finally {
633                                 Binder.restoreCallingIdentity(token);
634                             }
635                         }
636                     });
637         } catch (RemoteException e) {
638             Log.e(TAG, "Error calling getEuiccChallenge", e);
639             throw e.rethrowFromSystemServer();
640         }
641     }
642 
643     /**
644      * Requests the eUICC info1 defined in GSMA RSP v2.0+ for new profile downloading.
645      *
646      * @param cardId The Id of the eUICC.
647      * @param executor The executor through which the callback should be invoked.
648      * @param callback the callback to get the result code and the info1.
649      *
650      * @throws UnsupportedOperationException If the device does not have
651      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
652      */
requestEuiccInfo1(String cardId, @CallbackExecutor Executor executor, ResultCallback<byte[]> callback)653     public void requestEuiccInfo1(String cardId, @CallbackExecutor Executor executor,
654             ResultCallback<byte[]> callback) {
655         try {
656             getIEuiccCardController().getEuiccInfo1(mContext.getOpPackageName(), cardId,
657                     new IGetEuiccInfo1Callback.Stub() {
658                         @Override
659                         public void onComplete(int resultCode, byte[] info) {
660                             final long token = Binder.clearCallingIdentity();
661                             try {
662                                 executor.execute(() -> callback.onComplete(resultCode, info));
663                             } finally {
664                                 Binder.restoreCallingIdentity(token);
665                             }
666                         }
667                     });
668         } catch (RemoteException e) {
669             Log.e(TAG, "Error calling getEuiccInfo1", e);
670             throw e.rethrowFromSystemServer();
671         }
672     }
673 
674     /**
675      * Gets the eUICC info2 defined in GSMA RSP v2.0+ for new profile downloading.
676      *
677      * @param cardId The Id of the eUICC.
678      * @param executor The executor through which the callback should be invoked.
679      * @param callback the callback to get the result code and the info2.
680      *
681      * @throws UnsupportedOperationException If the device does not have
682      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
683      */
requestEuiccInfo2(String cardId, @CallbackExecutor Executor executor, ResultCallback<byte[]> callback)684     public void requestEuiccInfo2(String cardId, @CallbackExecutor Executor executor,
685             ResultCallback<byte[]> callback) {
686         try {
687             getIEuiccCardController().getEuiccInfo2(mContext.getOpPackageName(), cardId,
688                     new IGetEuiccInfo2Callback.Stub() {
689                         @Override
690                         public void onComplete(int resultCode, byte[] info) {
691                             final long token = Binder.clearCallingIdentity();
692                             try {
693                                 executor.execute(() -> callback.onComplete(resultCode, info));
694                             } finally {
695                                 Binder.restoreCallingIdentity(token);
696                             }
697                         }
698                     });
699         } catch (RemoteException e) {
700             Log.e(TAG, "Error calling getEuiccInfo2", e);
701             throw e.rethrowFromSystemServer();
702         }
703     }
704 
705     /**
706      * Authenticates the SM-DP+ server by the eUICC.
707      *
708      * @param cardId The Id of the eUICC.
709      * @param matchingId the activation code token defined in GSMA RSP v2.0+ or empty when it is not
710      *     required.
711      * @param serverSigned1 ASN.1 data in byte array signed and returned by the SM-DP+ server.
712      * @param serverSignature1 ASN.1 data in byte array indicating a SM-DP+ signature which is
713      *     returned by SM-DP+ server.
714      * @param euiccCiPkIdToBeUsed ASN.1 data in byte array indicating CI Public Key Identifier to be
715      *     used by the eUICC for signature which is returned by SM-DP+ server. This is defined in
716      *     GSMA RSP v2.0+.
717      * @param serverCertificate ASN.1 data in byte array indicating SM-DP+ Certificate returned by
718      *     SM-DP+ server.
719      * @param executor The executor through which the callback should be invoked.
720      * @param callback the callback to get the result code and a byte array which represents a
721      *     {@code AuthenticateServerResponse} defined in GSMA RSP v2.0+.
722      *
723      * @throws UnsupportedOperationException If the device does not have
724      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
725      */
authenticateServer(String cardId, String matchingId, byte[] serverSigned1, byte[] serverSignature1, byte[] euiccCiPkIdToBeUsed, byte[] serverCertificate, @CallbackExecutor Executor executor, ResultCallback<byte[]> callback)726     public void authenticateServer(String cardId, String matchingId, byte[] serverSigned1,
727             byte[] serverSignature1, byte[] euiccCiPkIdToBeUsed, byte[] serverCertificate,
728             @CallbackExecutor Executor executor, ResultCallback<byte[]> callback) {
729         try {
730             getIEuiccCardController().authenticateServer(
731                     mContext.getOpPackageName(),
732                     cardId,
733                     matchingId,
734                     serverSigned1,
735                     serverSignature1,
736                     euiccCiPkIdToBeUsed,
737                     serverCertificate,
738                     new IAuthenticateServerCallback.Stub() {
739                         @Override
740                         public void onComplete(int resultCode, byte[] response) {
741                             final long token = Binder.clearCallingIdentity();
742                             try {
743                                 executor.execute(() -> callback.onComplete(resultCode, response));
744                             } finally {
745                                 Binder.restoreCallingIdentity(token);
746                             }
747                         }
748                     });
749         } catch (RemoteException e) {
750             Log.e(TAG, "Error calling authenticateServer", e);
751             throw e.rethrowFromSystemServer();
752         }
753     }
754 
755     /**
756      * Prepares the profile download request sent to SM-DP+.
757      *
758      * @param cardId The Id of the eUICC.
759      * @param hashCc the hash of confirmation code. It can be null if there is no confirmation code
760      *     required.
761      * @param smdpSigned2 ASN.1 data in byte array indicating the data to be signed by the SM-DP+
762      *     returned by SM-DP+ server.
763      * @param smdpSignature2 ASN.1 data in byte array indicating the SM-DP+ signature returned by
764      *     SM-DP+ server.
765      * @param smdpCertificate ASN.1 data in byte array indicating the SM-DP+ Certificate returned
766      *     by SM-DP+ server.
767      * @param executor The executor through which the callback should be invoked.
768      * @param callback the callback to get the result code and a byte array which represents a
769      *     {@code PrepareDownloadResponse} defined in GSMA RSP v2.0+
770      *
771      * @throws UnsupportedOperationException If the device does not have
772      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
773      */
prepareDownload(String cardId, @Nullable byte[] hashCc, byte[] smdpSigned2, byte[] smdpSignature2, byte[] smdpCertificate, @CallbackExecutor Executor executor, ResultCallback<byte[]> callback)774     public void prepareDownload(String cardId, @Nullable byte[] hashCc, byte[] smdpSigned2,
775             byte[] smdpSignature2, byte[] smdpCertificate, @CallbackExecutor Executor executor,
776             ResultCallback<byte[]> callback) {
777         try {
778             getIEuiccCardController().prepareDownload(
779                     mContext.getOpPackageName(),
780                     cardId,
781                     hashCc,
782                     smdpSigned2,
783                     smdpSignature2,
784                     smdpCertificate,
785                     new IPrepareDownloadCallback.Stub() {
786                         @Override
787                         public void onComplete(int resultCode, byte[] response) {
788                             final long token = Binder.clearCallingIdentity();
789                             try {
790                                 executor.execute(() -> callback.onComplete(resultCode, response));
791                             } finally {
792                                 Binder.restoreCallingIdentity(token);
793                             }
794                         }
795                     });
796         } catch (RemoteException e) {
797             Log.e(TAG, "Error calling prepareDownload", e);
798             throw e.rethrowFromSystemServer();
799         }
800     }
801 
802     /**
803      * Loads a downloaded bound profile package onto the eUICC.
804      *
805      * @param cardId The Id of the eUICC.
806      * @param boundProfilePackage the Bound Profile Package data returned by SM-DP+ server.
807      * @param executor The executor through which the callback should be invoked.
808      * @param callback the callback to get the result code and a byte array which represents a
809      *     {@code LoadBoundProfilePackageResponse} defined in GSMA RSP v2.0+.
810      *
811      * @throws UnsupportedOperationException If the device does not have
812      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
813      */
loadBoundProfilePackage(String cardId, byte[] boundProfilePackage, @CallbackExecutor Executor executor, ResultCallback<byte[]> callback)814     public void loadBoundProfilePackage(String cardId, byte[] boundProfilePackage,
815             @CallbackExecutor Executor executor, ResultCallback<byte[]> callback) {
816         try {
817             getIEuiccCardController().loadBoundProfilePackage(
818                     mContext.getOpPackageName(),
819                     cardId,
820                     boundProfilePackage,
821                     new ILoadBoundProfilePackageCallback.Stub() {
822                         @Override
823                         public void onComplete(int resultCode, byte[] response) {
824                             final long token = Binder.clearCallingIdentity();
825                             try {
826                                 executor.execute(() -> callback.onComplete(resultCode, response));
827                             } finally {
828                                 Binder.restoreCallingIdentity(token);
829                             }
830                         }
831                     });
832         } catch (RemoteException e) {
833             Log.e(TAG, "Error calling loadBoundProfilePackage", e);
834             throw e.rethrowFromSystemServer();
835         }
836     }
837 
838     /**
839      * Cancels the current profile download session.
840      *
841      * @param cardId The Id of the eUICC.
842      * @param transactionId the transaction ID returned by SM-DP+ server.
843      * @param reason the cancel reason.
844      * @param executor The executor through which the callback should be invoked.
845      * @param callback the callback to get the result code and an byte[] which represents a
846      *     {@code CancelSessionResponse} defined in GSMA RSP v2.0+.
847      *
848      * @throws UnsupportedOperationException If the device does not have
849      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
850      */
cancelSession(String cardId, byte[] transactionId, @CancelReason int reason, @CallbackExecutor Executor executor, ResultCallback<byte[]> callback)851     public void cancelSession(String cardId, byte[] transactionId, @CancelReason int reason,
852             @CallbackExecutor Executor executor, ResultCallback<byte[]> callback) {
853         try {
854             getIEuiccCardController().cancelSession(
855                     mContext.getOpPackageName(),
856                     cardId,
857                     transactionId,
858                     reason,
859                     new ICancelSessionCallback.Stub() {
860                         @Override
861                         public void onComplete(int resultCode, byte[] response) {
862                             final long token = Binder.clearCallingIdentity();
863                             try {
864                                 executor.execute(() -> callback.onComplete(resultCode, response));
865                             } finally {
866                                 Binder.restoreCallingIdentity(token);
867                             }
868                         }
869                     });
870         } catch (RemoteException e) {
871             Log.e(TAG, "Error calling cancelSession", e);
872             throw e.rethrowFromSystemServer();
873         }
874     }
875 
876     /**
877      * Lists all notifications of the given {@code events}.
878      *
879      * @param cardId The Id of the eUICC.
880      * @param events bits of the event types ({@link EuiccNotification.Event}) to list.
881      * @param executor The executor through which the callback should be invoked.
882      * @param callback the callback to get the result code and the list of notifications.
883      *
884      * @throws UnsupportedOperationException If the device does not have
885      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
886      */
listNotifications(String cardId, @EuiccNotification.Event int events, @CallbackExecutor Executor executor, ResultCallback<EuiccNotification[]> callback)887     public void listNotifications(String cardId, @EuiccNotification.Event int events,
888             @CallbackExecutor Executor executor, ResultCallback<EuiccNotification[]> callback) {
889         try {
890             getIEuiccCardController().listNotifications(mContext.getOpPackageName(), cardId, events,
891                     new IListNotificationsCallback.Stub() {
892                         @Override
893                         public void onComplete(int resultCode, EuiccNotification[] notifications) {
894                             final long token = Binder.clearCallingIdentity();
895                             try {
896                                 executor.execute(() -> callback.onComplete(
897                                         resultCode, notifications));
898                             } finally {
899                                 Binder.restoreCallingIdentity(token);
900                             }
901                         }
902                     });
903         } catch (RemoteException e) {
904             Log.e(TAG, "Error calling listNotifications", e);
905             throw e.rethrowFromSystemServer();
906         }
907     }
908 
909     /**
910      * Retrieves contents of all notification of the given {@code events}.
911      *
912      * @param cardId The Id of the eUICC.
913      * @param events bits of the event types ({@link EuiccNotification.Event}) to list.
914      * @param executor The executor through which the callback should be invoked.
915      * @param callback the callback to get the result code and the list of notifications.
916      *
917      * @throws UnsupportedOperationException If the device does not have
918      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
919      */
retrieveNotificationList(String cardId, @EuiccNotification.Event int events, @CallbackExecutor Executor executor, ResultCallback<EuiccNotification[]> callback)920     public void retrieveNotificationList(String cardId, @EuiccNotification.Event int events,
921             @CallbackExecutor Executor executor, ResultCallback<EuiccNotification[]> callback) {
922         try {
923             getIEuiccCardController().retrieveNotificationList(mContext.getOpPackageName(), cardId,
924                     events, new IRetrieveNotificationListCallback.Stub() {
925                         @Override
926                         public void onComplete(int resultCode, EuiccNotification[] notifications) {
927                             final long token = Binder.clearCallingIdentity();
928                             try {
929                                 executor.execute(() -> callback.onComplete(
930                                         resultCode, notifications));
931                             } finally {
932                                 Binder.restoreCallingIdentity(token);
933                             }
934                         }
935                     });
936         } catch (RemoteException e) {
937             Log.e(TAG, "Error calling retrieveNotificationList", e);
938             throw e.rethrowFromSystemServer();
939         }
940     }
941 
942     /**
943      * Retrieves the content of a notification of the given {@code seqNumber}.
944      *
945      * @param cardId The Id of the eUICC.
946      * @param seqNumber the sequence number of the notification.
947      * @param executor The executor through which the callback should be invoked.
948      * @param callback the callback to get the result code and the notification.
949      *
950      * @throws UnsupportedOperationException If the device does not have
951      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
952      */
retrieveNotification(String cardId, int seqNumber, @CallbackExecutor Executor executor, ResultCallback<EuiccNotification> callback)953     public void retrieveNotification(String cardId, int seqNumber,
954             @CallbackExecutor Executor executor, ResultCallback<EuiccNotification> callback) {
955         try {
956             getIEuiccCardController().retrieveNotification(mContext.getOpPackageName(), cardId,
957                     seqNumber, new IRetrieveNotificationCallback.Stub() {
958                         @Override
959                         public void onComplete(int resultCode, EuiccNotification notification) {
960                             final long token = Binder.clearCallingIdentity();
961                             try {
962                                 executor.execute(() -> callback.onComplete(
963                                         resultCode, notification));
964                             } finally {
965                                 Binder.restoreCallingIdentity(token);
966                             }
967                         }
968                     });
969         } catch (RemoteException e) {
970             Log.e(TAG, "Error calling retrieveNotification", e);
971             throw e.rethrowFromSystemServer();
972         }
973     }
974 
975     /**
976      * Removes a notification from eUICC.
977      *
978      * @param cardId The Id of the eUICC.
979      * @param seqNumber the sequence number of the notification.
980      * @param executor The executor through which the callback should be invoked.
981      * @param callback the callback to get the result code.
982      *
983      * @throws UnsupportedOperationException If the device does not have
984      *          {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
985      */
removeNotificationFromList(String cardId, int seqNumber, @CallbackExecutor Executor executor, ResultCallback<Void> callback)986     public void removeNotificationFromList(String cardId, int seqNumber,
987             @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
988         try {
989             getIEuiccCardController().removeNotificationFromList(
990                     mContext.getOpPackageName(),
991                     cardId,
992                     seqNumber,
993                     new IRemoveNotificationFromListCallback.Stub() {
994                         @Override
995                         public void onComplete(int resultCode) {
996                             final long token = Binder.clearCallingIdentity();
997                             try {
998                                 executor.execute(() -> callback.onComplete(resultCode, null));
999                             } finally {
1000                                 Binder.restoreCallingIdentity(token);
1001                             }
1002                         }
1003                     });
1004         } catch (RemoteException e) {
1005             Log.e(TAG, "Error calling removeNotificationFromList", e);
1006             throw e.rethrowFromSystemServer();
1007         }
1008     }
1009 }
1010