1 /*
2  * Copyright (C) 2017 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.Manifest;
19 import android.annotation.IntDef;
20 import android.annotation.Nullable;
21 import android.annotation.RequiresPermission;
22 import android.annotation.SdkConstant;
23 import android.annotation.SystemApi;
24 import android.app.Activity;
25 import android.app.PendingIntent;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.IntentSender;
29 import android.content.pm.PackageManager;
30 import android.os.Bundle;
31 import android.os.RemoteException;
32 import android.os.ServiceManager;
33 
34 import com.android.internal.telephony.euicc.IEuiccController;
35 
36 import java.lang.annotation.Retention;
37 import java.lang.annotation.RetentionPolicy;
38 
39 /**
40  * EuiccManager is the application interface to eUICCs, or eSIMs/embedded SIMs.
41  *
42  * <p>You do not instantiate this class directly; instead, you retrieve an instance through
43  * {@link Context#getSystemService(String)} and {@link Context#EUICC_SERVICE}.
44  *
45  * <p>See {@link #isEnabled} before attempting to use these APIs.
46  */
47 public class EuiccManager {
48 
49     /**
50      * Intent action to launch the embedded SIM (eUICC) management settings screen.
51      *
52      * <p>This screen shows a list of embedded profiles and offers the user the ability to switch
53      * between them, download new profiles, and delete unused profiles.
54      *
55      * <p>The activity will immediately finish with {@link android.app.Activity#RESULT_CANCELED} if
56      * {@link #isEnabled} is false.
57      *
58      * This is ued by non-LPA app to bring up LUI.
59      */
60     @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
61     public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS =
62             "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
63 
64 
65     /**
66      * Broadcast Action: The eUICC OTA status is changed.
67      * <p class="note">
68      * Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
69      *
70      * <p class="note">This is a protected intent that can only be sent
71      * by the system.
72      *
73      * @hide
74      */
75     @SystemApi
76     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
77     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
78     public static final String ACTION_OTA_STATUS_CHANGED =
79             "android.telephony.euicc.action.OTA_STATUS_CHANGED";
80 
81     /**
82      * Broadcast Action: The action sent to carrier app so it knows the carrier setup is not
83      * completed.
84      */
85     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
86     public static final String ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE =
87             "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE";
88 
89     /**
90      * Intent action to provision an embedded subscription.
91      *
92      * <p>May be called during device provisioning to launch a screen to perform embedded SIM
93      * provisioning, e.g. if no physical SIM is present and the user elects to configure their
94      * embedded SIM.
95      *
96      * <p>The activity will immediately finish with {@link android.app.Activity#RESULT_CANCELED} if
97      * {@link #isEnabled} is false.
98      *
99      * @hide
100      */
101     @SystemApi
102     @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
103     public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION =
104             "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
105 
106     /**
107      * Intent action to handle a resolvable error.
108      * @hide
109      */
110     public static final String ACTION_RESOLVE_ERROR =
111             "android.telephony.euicc.action.RESOLVE_ERROR";
112 
113     /**
114      * Result code for an operation indicating that the operation succeeded.
115      */
116     public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0;
117 
118     /**
119      * Result code for an operation indicating that the user must take some action before the
120      * operation can continue.
121      *
122      * @see #startResolutionActivity
123      */
124     public static final int EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR = 1;
125 
126     /**
127      * Result code for an operation indicating that an unresolvable error occurred.
128      *
129      * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} will be populated with a detailed error
130      * code for logging/debugging purposes only.
131      */
132     public static final int EMBEDDED_SUBSCRIPTION_RESULT_ERROR = 2;
133 
134     /**
135      * Key for an extra set on {@link PendingIntent} result callbacks providing a detailed result
136      * code.
137      *
138      * <p>This code is an implementation detail of the embedded subscription manager and is only
139      * intended for logging or debugging purposes.
140      */
141     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE =
142             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE";
143 
144     /**
145      * Key for an extra set on {@code #getDownloadableSubscriptionMetadata} PendingIntent result
146      * callbacks providing the downloadable subscription metadata.
147      */
148     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION =
149             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION";
150 
151     /**
152      * Key for an extra set on {@link #getDefaultDownloadableSubscriptionList} PendingIntent result
153      * callbacks providing the list of available downloadable subscriptions.
154      * @hide
155      */
156     @SystemApi
157     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS =
158             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS";
159 
160     /**
161      * Key for an extra set on {@link PendingIntent} result callbacks providing the resolution
162      * pending intent for {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}s.
163      * @hide
164      */
165     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT =
166             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT";
167 
168     /**
169      * Key for an extra set on the {@link #EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT} intent
170      * containing the EuiccService action to launch for resolution.
171      * @hide
172      */
173     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION =
174             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION";
175 
176     /**
177      * Key for an extra set on the {@link #EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT} intent
178      * providing the callback to execute after resolution is completed.
179      * @hide
180      */
181     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT =
182             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT";
183 
184     /**
185      * Key for an extra set on the {@link #ACTION_PROVISION_EMBEDDED_SUBSCRIPTION} intent for
186      * whether the user choses to use eUICC to set up network in SUW.
187      * @hide
188      */
189     public static final String EXTRA_FORCE_PROVISION =
190             "android.telephony.euicc.extra.FORCE_PROVISION";
191 
192     /**
193      * Optional meta-data attribute for a carrier app providing an icon to use to represent the
194      * carrier. If not provided, the app's launcher icon will be used as a fallback.
195      */
196     public static final String META_DATA_CARRIER_ICON = "android.telephony.euicc.carriericon";
197 
198     /**
199      * Euicc OTA update status which can be got by {@link #getOtaStatus}
200      * @hide
201      */
202     @SystemApi
203     @Retention(RetentionPolicy.SOURCE)
204     @IntDef(prefix = {"EUICC_OTA_"}, value = {
205             EUICC_OTA_IN_PROGRESS,
206             EUICC_OTA_FAILED,
207             EUICC_OTA_SUCCEEDED,
208             EUICC_OTA_NOT_NEEDED,
209             EUICC_OTA_STATUS_UNAVAILABLE
210 
211     })
212     public @interface OtaStatus{}
213 
214     /**
215      * An OTA is in progress. During this time, the eUICC is not available and the user may lose
216      * network access.
217      * @hide
218      */
219     @SystemApi
220     public static final int EUICC_OTA_IN_PROGRESS = 1;
221 
222     /**
223      * The OTA update failed.
224      * @hide
225      */
226     @SystemApi
227     public static final int EUICC_OTA_FAILED = 2;
228 
229     /**
230      * The OTA update finished successfully.
231      * @hide
232      */
233     @SystemApi
234     public static final int EUICC_OTA_SUCCEEDED = 3;
235 
236     /**
237      * The OTA update not needed since current eUICC OS is latest.
238      * @hide
239      */
240     @SystemApi
241     public static final int EUICC_OTA_NOT_NEEDED = 4;
242 
243     /**
244      * The OTA status is unavailable since eUICC service is unavailable.
245      * @hide
246      */
247     @SystemApi
248     public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5;
249 
250     private final Context mContext;
251 
252     /** @hide */
EuiccManager(Context context)253     public EuiccManager(Context context) {
254         mContext = context;
255     }
256 
257     /**
258      * Whether embedded subscriptions are currently enabled.
259      *
260      * <p>Even on devices with the {@link PackageManager#FEATURE_TELEPHONY_EUICC} feature, embedded
261      * subscriptions may be turned off, e.g. because of a carrier restriction from an inserted
262      * physical SIM. Therefore, this runtime check should be used before accessing embedded
263      * subscription APIs.
264      *
265      * @return true if embedded subscriptions are currently enabled.
266      */
isEnabled()267     public boolean isEnabled() {
268         // In the future, this may reach out to IEuiccController (if non-null) to check any dynamic
269         // restrictions.
270         return getIEuiccController() != null;
271     }
272 
273     /**
274      * Returns the EID identifying the eUICC hardware.
275      *
276      * <p>Requires that the calling app has carrier privileges on the active subscription on the
277      * eUICC.
278      *
279      * @return the EID. May be null if {@link #isEnabled()} is false or the eUICC is not ready.
280      */
281     @Nullable
getEid()282     public String getEid() {
283         if (!isEnabled()) {
284             return null;
285         }
286         try {
287             return getIEuiccController().getEid();
288         } catch (RemoteException e) {
289             throw e.rethrowFromSystemServer();
290         }
291     }
292 
293     /**
294      * Returns the current status of eUICC OTA.
295      *
296      * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
297      *
298      * @return the status of eUICC OTA. If {@link #isEnabled()} is false or the eUICC is not ready,
299      *     {@link OtaStatus#EUICC_OTA_STATUS_UNAVAILABLE} will be returned.
300      *
301      * @hide
302      */
303     @SystemApi
304     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
getOtaStatus()305     public int getOtaStatus() {
306         if (!isEnabled()) {
307             return EUICC_OTA_STATUS_UNAVAILABLE;
308         }
309         try {
310             return getIEuiccController().getOtaStatus();
311         } catch (RemoteException e) {
312             throw e.rethrowFromSystemServer();
313         }
314     }
315 
316     /**
317      * Attempt to download the given {@link DownloadableSubscription}.
318      *
319      * <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
320      * or the calling app must be authorized to manage both the currently-active subscription and
321      * the subscription to be downloaded according to the subscription metadata. Without the former,
322      * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
323      * intent to prompt the user to accept the download.
324      *
325      * @param subscription the subscription to download.
326      * @param switchAfterDownload if true, the profile will be activated upon successful download.
327      * @param callbackIntent a PendingIntent to launch when the operation completes.
328      */
329     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
downloadSubscription(DownloadableSubscription subscription, boolean switchAfterDownload, PendingIntent callbackIntent)330     public void downloadSubscription(DownloadableSubscription subscription,
331             boolean switchAfterDownload, PendingIntent callbackIntent) {
332         if (!isEnabled()) {
333             sendUnavailableError(callbackIntent);
334             return;
335         }
336         try {
337             getIEuiccController().downloadSubscription(subscription, switchAfterDownload,
338                     mContext.getOpPackageName(), callbackIntent);
339         } catch (RemoteException e) {
340             throw e.rethrowFromSystemServer();
341         }
342     }
343 
344     /**
345      * Start an activity to resolve a user-resolvable error.
346      *
347      * <p>If an operation returns {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}, this
348      * method may be called to prompt the user to resolve the issue.
349      *
350      * <p>This method may only be called once for a particular error.
351      *
352      * @param activity the calling activity (which should be in the foreground).
353      * @param requestCode an application-specific request code which will be provided to
354      *     {@link Activity#onActivityResult} upon completion. Note that the operation may still be
355      *     in progress when the resolution activity completes; it is not fully finished until the
356      *     callback intent is triggered.
357      * @param resultIntent the Intent provided to the initial callback intent which failed with
358      *     {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}.
359      * @param callbackIntent a PendingIntent to launch when the operation completes. This is
360      *     trigered upon completion of the original operation that required user resolution.
361      * @throws android.content.IntentSender.SendIntentException if called more than once.
362      */
startResolutionActivity(Activity activity, int requestCode, Intent resultIntent, PendingIntent callbackIntent)363     public void startResolutionActivity(Activity activity, int requestCode, Intent resultIntent,
364             PendingIntent callbackIntent) throws IntentSender.SendIntentException {
365         PendingIntent resolutionIntent =
366                 resultIntent.getParcelableExtra(EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT);
367         if (resolutionIntent == null) {
368             throw new IllegalArgumentException("Invalid result intent");
369         }
370         Intent fillInIntent = new Intent();
371         fillInIntent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT,
372                 callbackIntent);
373         activity.startIntentSenderForResult(resolutionIntent.getIntentSender(), requestCode,
374                 fillInIntent, 0 /* flagsMask */, 0 /* flagsValues */, 0 /* extraFlags */);
375     }
376 
377     /**
378      * Continue an operation after the user resolves an error.
379      *
380      * <p>To be called by the LUI upon completion of a resolvable error flow.
381      *
382      * <p>Requires that the calling app has the
383      * {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
384      *
385      * @param resolutionIntent The original intent used to start the LUI.
386      * @param resolutionExtras Resolution-specific extras depending on the result of the resolution.
387      *     For example, this may indicate whether the user has consented or may include the input
388      *     they provided.
389      * @hide
390      */
391     @SystemApi
392     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
continueOperation(Intent resolutionIntent, Bundle resolutionExtras)393     public void continueOperation(Intent resolutionIntent, Bundle resolutionExtras) {
394         if (!isEnabled()) {
395             PendingIntent callbackIntent =
396                     resolutionIntent.getParcelableExtra(
397                             EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT);
398             if (callbackIntent != null) {
399                 sendUnavailableError(callbackIntent);
400             }
401             return;
402         }
403         try {
404             getIEuiccController().continueOperation(resolutionIntent, resolutionExtras);
405         } catch (RemoteException e) {
406             throw e.rethrowFromSystemServer();
407         }
408     }
409 
410     /**
411      * Fills in the metadata for a DownloadableSubscription.
412      *
413      * <p>May be used in cases that a DownloadableSubscription was constructed to download a
414      * profile, but the metadata for the profile is unknown (e.g. we only know the activation code).
415      * The callback will be triggered with an Intent with
416      * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION} set to the
417      * downloadable subscription metadata upon success.
418      *
419      * <p>Requires that the calling app has the
420      * {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. This is for
421      * internal system use only.
422      *
423      * @param subscription the subscription which needs metadata filled in
424      * @param callbackIntent a PendingIntent to launch when the operation completes.
425      * @hide
426      */
427     @SystemApi
428     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
getDownloadableSubscriptionMetadata( DownloadableSubscription subscription, PendingIntent callbackIntent)429     public void getDownloadableSubscriptionMetadata(
430             DownloadableSubscription subscription, PendingIntent callbackIntent) {
431         if (!isEnabled()) {
432             sendUnavailableError(callbackIntent);
433             return;
434         }
435         try {
436             getIEuiccController().getDownloadableSubscriptionMetadata(
437                     subscription, mContext.getOpPackageName(), callbackIntent);
438         } catch (RemoteException e) {
439             throw e.rethrowFromSystemServer();
440         }
441     }
442 
443     /**
444      * Gets metadata for subscription which are available for download on this device.
445      *
446      * <p>Subscriptions returned here may be passed to {@link #downloadSubscription}. They may have
447      * been pre-assigned to this particular device, for example. The callback will be triggered with
448      * an Intent with {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS} set to the
449      * list of available subscriptions upon success.
450      *
451      * <p>Requires that the calling app has the
452      * {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. This is for
453      * internal system use only.
454      *
455      * @param callbackIntent a PendingIntent to launch when the operation completes.
456      * @hide
457      */
458     @SystemApi
459     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
getDefaultDownloadableSubscriptionList(PendingIntent callbackIntent)460     public void getDefaultDownloadableSubscriptionList(PendingIntent callbackIntent) {
461         if (!isEnabled()) {
462             sendUnavailableError(callbackIntent);
463             return;
464         }
465         try {
466             getIEuiccController().getDefaultDownloadableSubscriptionList(
467                     mContext.getOpPackageName(), callbackIntent);
468         } catch (RemoteException e) {
469             throw e.rethrowFromSystemServer();
470         }
471     }
472 
473     /**
474      * Returns information about the eUICC chip/device.
475      *
476      * @return the {@link EuiccInfo}. May be null if {@link #isEnabled()} is false or the eUICC is
477      *     not ready.
478      */
479     @Nullable
getEuiccInfo()480     public EuiccInfo getEuiccInfo() {
481         if (!isEnabled()) {
482             return null;
483         }
484         try {
485             return getIEuiccController().getEuiccInfo();
486         } catch (RemoteException e) {
487             throw e.rethrowFromSystemServer();
488         }
489     }
490 
491     /**
492      * Deletes the given subscription.
493      *
494      * <p>If this subscription is currently active, the device will first switch away from it onto
495      * an "empty" subscription.
496      *
497      * <p>Requires that the calling app has carrier privileges according to the metadata of the
498      * profile to be deleted, or the
499      * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
500      *
501      * @param subscriptionId the ID of the subscription to delete.
502      * @param callbackIntent a PendingIntent to launch when the operation completes.
503      */
504     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
deleteSubscription(int subscriptionId, PendingIntent callbackIntent)505     public void deleteSubscription(int subscriptionId, PendingIntent callbackIntent) {
506         if (!isEnabled()) {
507             sendUnavailableError(callbackIntent);
508             return;
509         }
510         try {
511             getIEuiccController().deleteSubscription(
512                     subscriptionId, mContext.getOpPackageName(), callbackIntent);
513         } catch (RemoteException e) {
514             throw e.rethrowFromSystemServer();
515         }
516     }
517 
518     /**
519      * Switch to (enable) the given subscription.
520      *
521      * <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
522      * or the calling app must be authorized to manage both the currently-active subscription and
523      * the subscription to be enabled according to the subscription metadata. Without the former,
524      * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
525      * intent to prompt the user to accept the download.
526      *
527      * @param subscriptionId the ID of the subscription to enable. May be
528      *     {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID} to deactivate the
529      *     current profile without activating another profile to replace it.
530      * @param callbackIntent a PendingIntent to launch when the operation completes.
531      */
532     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
switchToSubscription(int subscriptionId, PendingIntent callbackIntent)533     public void switchToSubscription(int subscriptionId, PendingIntent callbackIntent) {
534         if (!isEnabled()) {
535             sendUnavailableError(callbackIntent);
536             return;
537         }
538         try {
539             getIEuiccController().switchToSubscription(
540                     subscriptionId, mContext.getOpPackageName(), callbackIntent);
541         } catch (RemoteException e) {
542             throw e.rethrowFromSystemServer();
543         }
544     }
545 
546     /**
547      * Update the nickname for the given subscription.
548      *
549      * <p>Requires that the calling app has the
550      * {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. This is for
551      * internal system use only.
552      *
553      * @param subscriptionId the ID of the subscription to update.
554      * @param nickname the new nickname to apply.
555      * @param callbackIntent a PendingIntent to launch when the operation completes.
556      * @hide
557      */
558     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
updateSubscriptionNickname( int subscriptionId, String nickname, PendingIntent callbackIntent)559     public void updateSubscriptionNickname(
560             int subscriptionId, String nickname, PendingIntent callbackIntent) {
561         if (!isEnabled()) {
562             sendUnavailableError(callbackIntent);
563             return;
564         }
565         try {
566             getIEuiccController().updateSubscriptionNickname(
567                     subscriptionId, nickname, callbackIntent);
568         } catch (RemoteException e) {
569             throw e.rethrowFromSystemServer();
570         }
571     }
572 
573     /**
574      * Erase all subscriptions and reset the eUICC.
575      *
576      * <p>Requires that the calling app has the
577      * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
578      *
579      * @param callbackIntent a PendingIntent to launch when the operation completes.
580      * @hide
581      */
582     @SystemApi
583     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
eraseSubscriptions(PendingIntent callbackIntent)584     public void eraseSubscriptions(PendingIntent callbackIntent) {
585         if (!isEnabled()) {
586             sendUnavailableError(callbackIntent);
587             return;
588         }
589         try {
590             getIEuiccController().eraseSubscriptions(callbackIntent);
591         } catch (RemoteException e) {
592             throw e.rethrowFromSystemServer();
593         }
594     }
595 
596     /**
597      * Ensure that subscriptions will be retained on the next factory reset.
598      *
599      * <p>By default, all subscriptions on the eUICC are erased the first time a device boots (ever
600      * and after factory resets). This ensures that the data is wiped after a factory reset is
601      * performed via fastboot or recovery mode, as these modes do not support the necessary radio
602      * communication needed to wipe the eSIM.
603      *
604      * <p>However, this method may be called right before a factory reset issued via settings when
605      * the user elects to retain subscriptions. Doing so will mark them for retention so that they
606      * are not cleared after the ensuing reset.
607      *
608      * <p>Requires that the calling app has the {@link android.Manifest.permission#MASTER_CLEAR}
609      * permission. This is for internal system use only.
610      *
611      * @param callbackIntent a PendingIntent to launch when the operation completes.
612      * @hide
613      */
retainSubscriptionsForFactoryReset(PendingIntent callbackIntent)614     public void retainSubscriptionsForFactoryReset(PendingIntent callbackIntent) {
615         if (!isEnabled()) {
616             sendUnavailableError(callbackIntent);
617             return;
618         }
619         try {
620             getIEuiccController().retainSubscriptionsForFactoryReset(callbackIntent);
621         } catch (RemoteException e) {
622             throw e.rethrowFromSystemServer();
623         }
624     }
625 
sendUnavailableError(PendingIntent callbackIntent)626     private static void sendUnavailableError(PendingIntent callbackIntent) {
627         try {
628             callbackIntent.send(EMBEDDED_SUBSCRIPTION_RESULT_ERROR);
629         } catch (PendingIntent.CanceledException e) {
630             // Caller canceled the callback; do nothing.
631         }
632     }
633 
getIEuiccController()634     private static IEuiccController getIEuiccController() {
635         return IEuiccController.Stub.asInterface(ServiceManager.getService("econtroller"));
636     }
637 }
638