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