• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.RequiresPermission;
23 import android.annotation.SdkConstant;
24 import android.annotation.SystemApi;
25 import android.app.Activity;
26 import android.app.PendingIntent;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.IntentSender;
30 import android.content.pm.PackageManager;
31 import android.os.Bundle;
32 import android.os.RemoteException;
33 import android.os.ServiceManager;
34 import android.telephony.TelephonyManager;
35 
36 import com.android.internal.telephony.euicc.IEuiccController;
37 
38 import java.lang.annotation.Retention;
39 import java.lang.annotation.RetentionPolicy;
40 
41 /**
42  * EuiccManager is the application interface to eUICCs, or eSIMs/embedded SIMs.
43  *
44  * <p>You do not instantiate this class directly; instead, you retrieve an instance through
45  * {@link Context#getSystemService(String)} and {@link Context#EUICC_SERVICE}. This instance will be
46  * created using the default eUICC.
47  *
48  * <p>On a device with multiple eUICCs, you may want to create multiple EuiccManagers. To do this
49  * you can call {@link #createForCardId}.
50  *
51  * <p>See {@link #isEnabled} before attempting to use these APIs.
52  */
53 public class EuiccManager {
54 
55     /**
56      * Intent action to launch the embedded SIM (eUICC) management settings screen.
57      *
58      * <p>This screen shows a list of embedded profiles and offers the user the ability to switch
59      * between them, download new profiles, and delete unused profiles.
60      *
61      * <p>The activity will immediately finish with {@link android.app.Activity#RESULT_CANCELED} if
62      * {@link #isEnabled} is false.
63      *
64      * This is ued by non-LPA app to bring up LUI.
65      */
66     @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
67     public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS =
68             "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
69 
70     /**
71      * Broadcast Action: The eUICC OTA status is changed.
72      * <p class="note">
73      * Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
74      *
75      * <p class="note">This is a protected intent that can only be sent
76      * by the system.
77      *
78      * @hide
79      */
80     @SystemApi
81     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
82     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
83     public static final String ACTION_OTA_STATUS_CHANGED =
84             "android.telephony.euicc.action.OTA_STATUS_CHANGED";
85 
86     /**
87      * Broadcast Action: The action sent to carrier app so it knows the carrier setup is not
88      * completed.
89      */
90     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
91     public static final String ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE =
92             "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE";
93 
94     /**
95      * Intent action to provision an embedded subscription.
96      *
97      * <p>May be called during device provisioning to launch a screen to perform embedded SIM
98      * provisioning, e.g. if no physical SIM is present and the user elects to configure their
99      * embedded SIM.
100      *
101      * <p>The activity will immediately finish with {@link android.app.Activity#RESULT_CANCELED} if
102      * {@link #isEnabled} is false.
103      *
104      * @hide
105      */
106     @SystemApi
107     @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
108     public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION =
109             "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
110 
111     /**
112      * Intent action to handle a resolvable error.
113      * @hide
114      */
115     public static final String ACTION_RESOLVE_ERROR =
116             "android.telephony.euicc.action.RESOLVE_ERROR";
117 
118     /**
119      * Intent action sent by system apps (such as the Settings app) to the Telephony framework to
120      * enable or disable a subscription. Must be accompanied with {@link #EXTRA_SUBSCRIPTION_ID} and
121      * {@link #EXTRA_ENABLE_SUBSCRIPTION}, and optionally {@link #EXTRA_FROM_SUBSCRIPTION_ID}.
122      *
123      * <p>Requires the caller to be a privileged process with the
124      * {@link android.permission#CALL_PRIVILEGED} permission for the intent to reach the Telephony
125      * stack.
126      *
127      * <p>Unlike {@link #switchToSubscription(int, PendingIntent)}, using this action allows the
128      * underlying eUICC service (i.e. the LPA app) to control the UI experience during this
129      * operation. The action is received by the Telephony framework, which in turn selects and
130      * launches an appropriate LPA activity to present UI to the user. For example, the activity may
131      * show a confirmation dialog, a progress dialog, or an error dialog when necessary.
132      *
133      * <p>The launched activity will immediately finish with
134      * {@link android.app.Activity#RESULT_CANCELED} if {@link #isEnabled} is false.
135      *
136      * @hide
137      */
138     @SystemApi
139     public static final String ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED =
140             "android.telephony.euicc.action.TOGGLE_SUBSCRIPTION_PRIVILEGED";
141 
142     /**
143      * Intent action sent by system apps (such as the Settings app) to the Telephony framework to
144      * delete a subscription. Must be accompanied with {@link #EXTRA_SUBSCRIPTION_ID}.
145      *
146      * <p>Requires the caller to be a privileged process with the
147      * {@link android.permission#CALL_PRIVILEGED} permission for the intent to reach the Telephony
148      * stack.
149      *
150      * <p>Unlike {@link #deleteSubscription(int, PendingIntent)}, using this action allows the
151      * underlying eUICC service (i.e. the LPA app) to control the UI experience during this
152      * operation. The action is received by the Telephony framework, which in turn selects and
153      * launches an appropriate LPA activity to present UI to the user. For example, the activity may
154      * show a confirmation dialog, a progress dialog, or an error dialog when necessary.
155      *
156      * <p>The launched activity will immediately finish with
157      * {@link android.app.Activity#RESULT_CANCELED} if {@link #isEnabled} is false.
158      *
159      * @hide
160      */
161     @SystemApi
162     public static final String ACTION_DELETE_SUBSCRIPTION_PRIVILEGED =
163             "android.telephony.euicc.action.DELETE_SUBSCRIPTION_PRIVILEGED";
164 
165     /**
166      * Intent action sent by system apps (such as the Settings app) to the Telephony framework to
167      * rename a subscription. Must be accompanied with {@link #EXTRA_SUBSCRIPTION_ID} and
168      * {@link #EXTRA_SUBSCRIPTION_NICKNAME}.
169      *
170      * <p>Requires the caller to be a privileged process with the
171      * {@link android.permission#CALL_PRIVILEGED} permission for the intent to reach the Telephony
172      * stack.
173      *
174      * <p>Unlike {@link #updateSubscriptionNickname(int, String, PendingIntent)}, using this action
175      * allows the the underlying eUICC service (i.e. the LPA app) to control the UI experience
176      * during this operation. The action is received by the Telephony framework, which in turn
177      * selects and launches an appropriate LPA activity to present UI to the user. For example, the
178      * activity may show a confirmation dialog, a progress dialog, or an error dialog when
179      * necessary.
180      *
181      * <p>The launched activity will immediately finish with
182      * {@link android.app.Activity#RESULT_CANCELED} if {@link #isEnabled} is false.
183      *
184      * @hide
185      */
186     @SystemApi
187     public static final String ACTION_RENAME_SUBSCRIPTION_PRIVILEGED =
188             "android.telephony.euicc.action.RENAME_SUBSCRIPTION_PRIVILEGED";
189 
190     /**
191      * Result code for an operation indicating that the operation succeeded.
192      */
193     public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0;
194 
195     /**
196      * Result code for an operation indicating that the user must take some action before the
197      * operation can continue.
198      *
199      * @see #startResolutionActivity
200      */
201     public static final int EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR = 1;
202 
203     /**
204      * Result code for an operation indicating that an unresolvable error occurred.
205      *
206      * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} will be populated with a detailed error
207      * code for logging/debugging purposes only.
208      */
209     public static final int EMBEDDED_SUBSCRIPTION_RESULT_ERROR = 2;
210 
211     /**
212      * Key for an extra set on the {@link #ACTION_PROVISION_EMBEDDED_SUBSCRIPTION} intent for which
213      * kind of activation flow will be evolved. (see {@code EUICC_ACTIVATION_})
214      *
215      * @hide
216      */
217     @SystemApi
218     public static final String EXTRA_ACTIVATION_TYPE =
219             "android.telephony.euicc.extra.ACTIVATION_TYPE";
220 
221     /**
222      * Key for an extra set on {@link PendingIntent} result callbacks providing a detailed result
223      * code.
224      *
225      * <p>This code is an implementation detail of the embedded subscription manager and is only
226      * intended for logging or debugging purposes.
227      */
228     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE =
229             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE";
230 
231     /**
232      * Key for an extra set on {@code #getDownloadableSubscriptionMetadata} PendingIntent result
233      * callbacks providing the downloadable subscription metadata.
234      */
235     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION =
236             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION";
237 
238     /**
239      * Key for an extra set on {@link #getDefaultDownloadableSubscriptionList} PendingIntent result
240      * callbacks providing the list of available downloadable subscriptions.
241      * @hide
242      */
243     @SystemApi
244     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS =
245             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS";
246 
247     /**
248      * Key for an extra set on {@link PendingIntent} result callbacks providing the resolution
249      * pending intent for {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}s.
250      * @hide
251      */
252     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT =
253             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT";
254 
255     /**
256      * Key for an extra set on the {@link #EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT} intent
257      * containing the EuiccService action to launch for resolution.
258      * @hide
259      */
260     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION =
261             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION";
262 
263     /**
264      * Key for an extra set on the {@link #EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT} intent
265      * providing the callback to execute after resolution is completed.
266      * @hide
267      */
268     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT =
269             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT";
270 
271     /**
272      * Key for an extra set on the {@link #ACTION_PROVISION_EMBEDDED_SUBSCRIPTION} intent for
273      * whether eSIM provisioning flow is forced to be started or not. If this extra hasn't been
274      * set, eSIM provisioning flow may be skipped and the corresponding carrier's app will be
275      * notified. Otherwise, eSIM provisioning flow will be started when
276      * {@link #ACTION_PROVISION_EMBEDDED_SUBSCRIPTION} has been received.
277      * @hide
278      */
279     @SystemApi
280     public static final String EXTRA_FORCE_PROVISION =
281             "android.telephony.euicc.extra.FORCE_PROVISION";
282 
283     /**
284      * Key for an extra set on privileged actions {@link #ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED},
285      * {@link #ACTION_DELETE_SUBSCRIPTION_PRIVILEGED}, and
286      * {@link #ACTION_RENAME_SUBSCRIPTION_PRIVILEGED} providing the ID of the targeted subscription.
287      *
288      * <p>Expected type of the extra data: int
289      *
290      * @hide
291      */
292     @SystemApi
293     public static final String EXTRA_SUBSCRIPTION_ID =
294             "android.telephony.euicc.extra.SUBSCRIPTION_ID";
295 
296     /**
297      * Key for an extra set on {@link #ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED} providing a boolean
298      * value of whether to enable or disable the targeted subscription.
299      *
300      * <p>Expected type of the extra data: boolean
301      *
302      * @hide
303      */
304     @SystemApi
305     public static final String EXTRA_ENABLE_SUBSCRIPTION =
306             "android.telephony.euicc.extra.ENABLE_SUBSCRIPTION";
307 
308     /**
309      * Key for an extra set on {@link #ACTION_RENAME_SUBSCRIPTION_PRIVILEGED} providing a new
310      * nickname for the targeted subscription.
311      *
312      * <p>Expected type of the extra data: String
313      *
314      * @hide
315      */
316     @SystemApi
317     public static final String EXTRA_SUBSCRIPTION_NICKNAME =
318             "android.telephony.euicc.extra.SUBSCRIPTION_NICKNAME";
319 
320     /**
321      * Key for an extra set on {@link #ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED} providing the ID of
322      * the subscription we're toggling from. This extra is optional and is only used for UI
323      * purposes by the underlying eUICC service (i.e. the LPA app), such as displaying a dialog
324      * titled "Switch X with Y". If set, the provided subscription will be used as the "from"
325      * subscription in UI (the "X" in the dialog example). Otherwise, the currently active
326      * subscription that will be disabled is the "from" subscription.
327      *
328      * <p>Expected type of the extra data: int
329      *
330      * @hide
331      */
332     @SystemApi
333     public static final String EXTRA_FROM_SUBSCRIPTION_ID =
334             "android.telephony.euicc.extra.FROM_SUBSCRIPTION_ID";
335 
336     /**
337      * Key for an extra set on privileged actions {@link #ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED}
338      * providing the physical slot ID of the target slot.
339      *
340      * <p>Expected type of the extra data: int
341      *
342      * @hide
343      */
344     // TODO: Make this a @SystemApi.
345     public static final String EXTRA_PHYSICAL_SLOT_ID =
346             "android.telephony.euicc.extra.PHYSICAL_SLOT_ID";
347 
348     /**
349      * Optional meta-data attribute for a carrier app providing an icon to use to represent the
350      * carrier. If not provided, the app's launcher icon will be used as a fallback.
351      */
352     public static final String META_DATA_CARRIER_ICON = "android.telephony.euicc.carriericon";
353 
354     /**
355      * Euicc activation type which will be included in {@link #EXTRA_ACTIVATION_TYPE} and used to
356      * decide which kind of activation flow should be lauched.
357      *
358      * @hide
359      */
360     @Retention(RetentionPolicy.SOURCE)
361     @IntDef(prefix = {"EUICC_ACTIVATION_"}, value = {
362             EUICC_ACTIVATION_TYPE_DEFAULT,
363             EUICC_ACTIVATION_TYPE_BACKUP,
364             EUICC_ACTIVATION_TYPE_TRANSFER,
365             EUICC_ACTIVATION_TYPE_ACCOUNT_REQUIRED,
366     })
367     public @interface EuiccActivationType{}
368 
369 
370     /**
371      * The default euicc activation type which includes checking server side and downloading the
372      * profile based on carrier's download configuration.
373      *
374      * @hide
375      */
376     @SystemApi
377     public static final int EUICC_ACTIVATION_TYPE_DEFAULT = 1;
378 
379     /**
380      * The euicc activation type used when the default download process failed. LPA will start the
381      * backup flow and try to download the profile for the carrier.
382      *
383      * @hide
384      */
385     @SystemApi
386     public static final int EUICC_ACTIVATION_TYPE_BACKUP = 2;
387 
388     /**
389      * The activation flow of eSIM seamless transfer will be used. LPA will start normal eSIM
390      * activation flow and if it's failed, the name of the carrier selected will be recorded. After
391      * the future device pairing, LPA will contact this carrier to transfer it from the other device
392      * to this device.
393      *
394      * @hide
395      */
396     @SystemApi
397     public static final int EUICC_ACTIVATION_TYPE_TRANSFER = 3;
398 
399     /**
400      * The activation flow of eSIM requiring user account will be started. This can only be used
401      * when there is user account signed in. Otherwise, the flow will be failed.
402      *
403      * @hide
404      */
405     @SystemApi
406     public static final int EUICC_ACTIVATION_TYPE_ACCOUNT_REQUIRED = 4;
407 
408     /**
409      * Euicc OTA update status which can be got by {@link #getOtaStatus}
410      * @hide
411      */
412     @SystemApi
413     @Retention(RetentionPolicy.SOURCE)
414     @IntDef(prefix = {"EUICC_OTA_"}, value = {
415             EUICC_OTA_IN_PROGRESS,
416             EUICC_OTA_FAILED,
417             EUICC_OTA_SUCCEEDED,
418             EUICC_OTA_NOT_NEEDED,
419             EUICC_OTA_STATUS_UNAVAILABLE
420 
421     })
422     public @interface OtaStatus{}
423 
424     /**
425      * An OTA is in progress. During this time, the eUICC is not available and the user may lose
426      * network access.
427      * @hide
428      */
429     @SystemApi
430     public static final int EUICC_OTA_IN_PROGRESS = 1;
431 
432     /**
433      * The OTA update failed.
434      * @hide
435      */
436     @SystemApi
437     public static final int EUICC_OTA_FAILED = 2;
438 
439     /**
440      * The OTA update finished successfully.
441      * @hide
442      */
443     @SystemApi
444     public static final int EUICC_OTA_SUCCEEDED = 3;
445 
446     /**
447      * The OTA update not needed since current eUICC OS is latest.
448      * @hide
449      */
450     @SystemApi
451     public static final int EUICC_OTA_NOT_NEEDED = 4;
452 
453     /**
454      * The OTA status is unavailable since eUICC service is unavailable.
455      * @hide
456      */
457     @SystemApi
458     public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5;
459 
460     private final Context mContext;
461     private int mCardId;
462 
463     /** @hide */
EuiccManager(Context context)464     public EuiccManager(Context context) {
465         mContext = context;
466         TelephonyManager tm = (TelephonyManager)
467                 context.getSystemService(Context.TELEPHONY_SERVICE);
468         mCardId = tm.getCardIdForDefaultEuicc();
469     }
470 
471     /** @hide */
EuiccManager(Context context, int cardId)472     private EuiccManager(Context context, int cardId) {
473         mContext = context;
474         mCardId = cardId;
475     }
476 
477     /**
478      * Create a new EuiccManager object pinned to the given card ID.
479      *
480      * @return an EuiccManager that uses the given card ID for all calls.
481      */
482     @NonNull
createForCardId(int cardId)483     public EuiccManager createForCardId(int cardId) {
484         return new EuiccManager(mContext, cardId);
485     }
486 
487     /**
488      * Whether embedded subscriptions are currently enabled.
489      *
490      * <p>Even on devices with the {@link PackageManager#FEATURE_TELEPHONY_EUICC} feature, embedded
491      * subscriptions may be turned off, e.g. because of a carrier restriction from an inserted
492      * physical SIM. Therefore, this runtime check should be used before accessing embedded
493      * subscription APIs.
494      *
495      * @return true if embedded subscriptions are currently enabled.
496      */
isEnabled()497     public boolean isEnabled() {
498         // In the future, this may reach out to IEuiccController (if non-null) to check any dynamic
499         // restrictions.
500         return getIEuiccController() != null && refreshCardIdIfUninitialized();
501     }
502 
503     /**
504      * Returns the EID identifying the eUICC hardware.
505      *
506      * <p>Requires that the calling app has carrier privileges on the active subscription on the
507      * current eUICC. A calling app with carrier privileges for one eUICC may not necessarily have
508      * access to the EID of another eUICC.
509      *
510      * @return the EID. May be null if the eUICC is not ready.
511      */
512     @Nullable
getEid()513     public String getEid() {
514         if (!isEnabled()) {
515             return null;
516         }
517         try {
518             return getIEuiccController().getEid(mCardId, mContext.getOpPackageName());
519         } catch (RemoteException e) {
520             throw e.rethrowFromSystemServer();
521         }
522     }
523 
524     /**
525      * Returns the current status of eUICC OTA.
526      *
527      * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
528      *
529      * @return the status of eUICC OTA. If the eUICC is not ready,
530      *         {@link OtaStatus#EUICC_OTA_STATUS_UNAVAILABLE} will be returned.
531      *
532      * @hide
533      */
534     @SystemApi
535     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
getOtaStatus()536     public int getOtaStatus() {
537         if (!isEnabled()) {
538             return EUICC_OTA_STATUS_UNAVAILABLE;
539         }
540         try {
541             return getIEuiccController().getOtaStatus(mCardId);
542         } catch (RemoteException e) {
543             throw e.rethrowFromSystemServer();
544         }
545     }
546 
547     /**
548      * Attempt to download the given {@link DownloadableSubscription}.
549      *
550      * <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
551      * or the calling app must be authorized to manage both the currently-active subscription on the
552      * current eUICC and the subscription to be downloaded according to the subscription metadata.
553      * Without the former, an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be
554      * returned in the callback intent to prompt the user to accept the download.
555      *
556      * <p>On a multi-active SIM device, requires the
557      * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, or a calling app
558      * only if the targeted eUICC does not currently have an active subscription or the calling app
559      * is authorized to manage the active subscription on the target eUICC, and the calling app is
560      * authorized to manage any active subscription on any SIM. Without it, an
561      * {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
562      * intent to prompt the user to accept the download. The caller should also be authorized to
563      * manage the subscription to be downloaded.
564      *
565      * @param subscription the subscription to download.
566      * @param switchAfterDownload if true, the profile will be activated upon successful download.
567      * @param callbackIntent a PendingIntent to launch when the operation completes.
568      */
569     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
downloadSubscription(DownloadableSubscription subscription, boolean switchAfterDownload, PendingIntent callbackIntent)570     public void downloadSubscription(DownloadableSubscription subscription,
571             boolean switchAfterDownload, PendingIntent callbackIntent) {
572         if (!isEnabled()) {
573             sendUnavailableError(callbackIntent);
574             return;
575         }
576         try {
577             getIEuiccController().downloadSubscription(mCardId, subscription, switchAfterDownload,
578                     mContext.getOpPackageName(), null /* resolvedBundle */, callbackIntent);
579         } catch (RemoteException e) {
580             throw e.rethrowFromSystemServer();
581         }
582     }
583 
584     /**
585      * Start an activity to resolve a user-resolvable error.
586      *
587      * <p>If an operation returns {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}, this
588      * method may be called to prompt the user to resolve the issue.
589      *
590      * <p>This method may only be called once for a particular error.
591      *
592      * @param activity the calling activity (which should be in the foreground).
593      * @param requestCode an application-specific request code which will be provided to
594      *     {@link Activity#onActivityResult} upon completion. Note that the operation may still be
595      *     in progress when the resolution activity completes; it is not fully finished until the
596      *     callback intent is triggered.
597      * @param resultIntent the Intent provided to the initial callback intent which failed with
598      *     {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}.
599      * @param callbackIntent a PendingIntent to launch when the operation completes. This is
600      *     trigered upon completion of the original operation that required user resolution.
601      * @throws android.content.IntentSender.SendIntentException if called more than once.
602      */
startResolutionActivity(Activity activity, int requestCode, Intent resultIntent, PendingIntent callbackIntent)603     public void startResolutionActivity(Activity activity, int requestCode, Intent resultIntent,
604             PendingIntent callbackIntent) throws IntentSender.SendIntentException {
605         PendingIntent resolutionIntent =
606                 resultIntent.getParcelableExtra(EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT);
607         if (resolutionIntent == null) {
608             throw new IllegalArgumentException("Invalid result intent");
609         }
610         Intent fillInIntent = new Intent();
611         fillInIntent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT,
612                 callbackIntent);
613         activity.startIntentSenderForResult(resolutionIntent.getIntentSender(), requestCode,
614                 fillInIntent, 0 /* flagsMask */, 0 /* flagsValues */, 0 /* extraFlags */);
615     }
616 
617     /**
618      * Continue an operation after the user resolves an error.
619      *
620      * <p>To be called by the LUI upon completion of a resolvable error flow.
621      *
622      * <p>Requires that the calling app has the
623      * {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
624      *
625      * @param resolutionIntent The original intent used to start the LUI.
626      * @param resolutionExtras Resolution-specific extras depending on the result of the resolution.
627      *     For example, this may indicate whether the user has consented or may include the input
628      *     they provided.
629      * @hide
630      */
631     @SystemApi
632     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
continueOperation(Intent resolutionIntent, Bundle resolutionExtras)633     public void continueOperation(Intent resolutionIntent, Bundle resolutionExtras) {
634         if (!isEnabled()) {
635             PendingIntent callbackIntent =
636                     resolutionIntent.getParcelableExtra(
637                             EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT);
638             if (callbackIntent != null) {
639                 sendUnavailableError(callbackIntent);
640             }
641             return;
642         }
643         try {
644             getIEuiccController().continueOperation(mCardId, resolutionIntent, resolutionExtras);
645         } catch (RemoteException e) {
646             throw e.rethrowFromSystemServer();
647         }
648     }
649 
650     /**
651      * Fills in the metadata for a DownloadableSubscription.
652      *
653      * <p>May be used in cases that a DownloadableSubscription was constructed to download a
654      * profile, but the metadata for the profile is unknown (e.g. we only know the activation code).
655      * The callback will be triggered with an Intent with
656      * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION} set to the
657      * downloadable subscription metadata upon success.
658      *
659      * <p>Requires that the calling app has the
660      * {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. This is for
661      * internal system use only.
662      *
663      * @param subscription the subscription which needs metadata filled in
664      * @param callbackIntent a PendingIntent to launch when the operation completes.
665      * @hide
666      */
667     @SystemApi
668     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
getDownloadableSubscriptionMetadata( DownloadableSubscription subscription, PendingIntent callbackIntent)669     public void getDownloadableSubscriptionMetadata(
670             DownloadableSubscription subscription, PendingIntent callbackIntent) {
671         if (!isEnabled()) {
672             sendUnavailableError(callbackIntent);
673             return;
674         }
675         try {
676             getIEuiccController().getDownloadableSubscriptionMetadata(mCardId, subscription,
677                     mContext.getOpPackageName(), callbackIntent);
678         } catch (RemoteException e) {
679             throw e.rethrowFromSystemServer();
680         }
681     }
682 
683     /**
684      * Gets metadata for subscription which are available for download on this device.
685      *
686      * <p>Subscriptions returned here may be passed to {@link #downloadSubscription}. They may have
687      * been pre-assigned to this particular device, for example. The callback will be triggered with
688      * an Intent with {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS} set to the
689      * list of available subscriptions upon success.
690      *
691      * <p>Requires that the calling app has the
692      * {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. This is for
693      * internal system use only.
694      *
695      * @param callbackIntent a PendingIntent to launch when the operation completes.
696      * @hide
697      */
698     @SystemApi
699     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
getDefaultDownloadableSubscriptionList(PendingIntent callbackIntent)700     public void getDefaultDownloadableSubscriptionList(PendingIntent callbackIntent) {
701         if (!isEnabled()) {
702             sendUnavailableError(callbackIntent);
703             return;
704         }
705         try {
706             getIEuiccController().getDefaultDownloadableSubscriptionList(mCardId,
707                     mContext.getOpPackageName(), callbackIntent);
708         } catch (RemoteException e) {
709             throw e.rethrowFromSystemServer();
710         }
711     }
712 
713     /**
714      * Returns information about the eUICC chip/device.
715      *
716      * @return the {@link EuiccInfo}. May be null if the eUICC is not ready.
717      */
718     @Nullable
getEuiccInfo()719     public EuiccInfo getEuiccInfo() {
720         if (!isEnabled()) {
721             return null;
722         }
723         try {
724             return getIEuiccController().getEuiccInfo(mCardId);
725         } catch (RemoteException e) {
726             throw e.rethrowFromSystemServer();
727         }
728     }
729 
730     /**
731      * Deletes the given subscription.
732      *
733      * <p>If this subscription is currently active, the device will first switch away from it onto
734      * an "empty" subscription.
735      *
736      * <p>Requires that the calling app has carrier privileges according to the metadata of the
737      * profile to be deleted, or the
738      * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
739      *
740      * @param subscriptionId the ID of the subscription to delete.
741      * @param callbackIntent a PendingIntent to launch when the operation completes.
742      */
743     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
deleteSubscription(int subscriptionId, PendingIntent callbackIntent)744     public void deleteSubscription(int subscriptionId, PendingIntent callbackIntent) {
745         if (!isEnabled()) {
746             sendUnavailableError(callbackIntent);
747             return;
748         }
749         try {
750             getIEuiccController().deleteSubscription(mCardId,
751                     subscriptionId, mContext.getOpPackageName(), callbackIntent);
752         } catch (RemoteException e) {
753             throw e.rethrowFromSystemServer();
754         }
755     }
756 
757     /**
758      * Switch to (enable) the given subscription.
759      *
760      * <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
761      * or the calling app must be authorized to manage both the currently-active subscription and
762      * the subscription to be enabled according to the subscription metadata. Without the former,
763      * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
764      * intent to prompt the user to accept the download.
765      *
766      * <p>On a multi-active SIM device, requires the
767      * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, or a calling app
768      *  only if the targeted eUICC does not currently have an active subscription or the calling app
769      * is authorized to manage the active subscription on the target eUICC, and the calling app is
770      * authorized to manage any active subscription on any SIM. Without it, an
771      * {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
772      * intent to prompt the user to accept the download. The caller should also be authorized to
773      * manage the subscription to be enabled.
774      *
775      * @param subscriptionId the ID of the subscription to enable. May be
776      *     {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID} to deactivate the
777      *     current profile without activating another profile to replace it. If it's a disable
778      *     operation, requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS}
779      *     permission, or the calling app must be authorized to manage the active subscription on
780      *     the target eUICC.
781      * @param callbackIntent a PendingIntent to launch when the operation completes.
782      */
783     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
switchToSubscription(int subscriptionId, PendingIntent callbackIntent)784     public void switchToSubscription(int subscriptionId, PendingIntent callbackIntent) {
785         if (!isEnabled()) {
786             sendUnavailableError(callbackIntent);
787             return;
788         }
789         try {
790             getIEuiccController().switchToSubscription(mCardId,
791                     subscriptionId, mContext.getOpPackageName(), callbackIntent);
792         } catch (RemoteException e) {
793             throw e.rethrowFromSystemServer();
794         }
795     }
796 
797     /**
798      * Update the nickname for the given subscription.
799      *
800      * <p>Requires that the calling app has carrier privileges according to the metadata of the
801      * profile to be updated, or the
802      * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
803      *
804      * @param subscriptionId the ID of the subscription to update.
805      * @param nickname the new nickname to apply.
806      * @param callbackIntent a PendingIntent to launch when the operation completes.
807      */
808     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
updateSubscriptionNickname( int subscriptionId, @Nullable String nickname, @NonNull PendingIntent callbackIntent)809     public void updateSubscriptionNickname(
810             int subscriptionId, @Nullable String nickname, @NonNull PendingIntent callbackIntent) {
811         if (!isEnabled()) {
812             sendUnavailableError(callbackIntent);
813             return;
814         }
815         try {
816             getIEuiccController().updateSubscriptionNickname(mCardId,
817                     subscriptionId, nickname, mContext.getOpPackageName(), callbackIntent);
818         } catch (RemoteException e) {
819             throw e.rethrowFromSystemServer();
820         }
821     }
822 
823     /**
824      * Erase all subscriptions and reset the eUICC.
825      *
826      * <p>Requires that the calling app has the
827      * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
828      *
829      * @param callbackIntent a PendingIntent to launch when the operation completes.
830      * @hide
831      */
832     @SystemApi
833     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
eraseSubscriptions(PendingIntent callbackIntent)834     public void eraseSubscriptions(PendingIntent callbackIntent) {
835         if (!isEnabled()) {
836             sendUnavailableError(callbackIntent);
837             return;
838         }
839         try {
840             getIEuiccController().eraseSubscriptions(mCardId, callbackIntent);
841         } catch (RemoteException e) {
842             throw e.rethrowFromSystemServer();
843         }
844     }
845 
846     /**
847      * Ensure that subscriptions will be retained on the next factory reset.
848      *
849      * <p>By default, all subscriptions on the eUICC are erased the first time a device boots (ever
850      * and after factory resets). This ensures that the data is wiped after a factory reset is
851      * performed via fastboot or recovery mode, as these modes do not support the necessary radio
852      * communication needed to wipe the eSIM.
853      *
854      * <p>However, this method may be called right before a factory reset issued via settings when
855      * the user elects to retain subscriptions. Doing so will mark them for retention so that they
856      * are not cleared after the ensuing reset.
857      *
858      * <p>Requires that the calling app has the {@link android.Manifest.permission#MASTER_CLEAR}
859      * permission. This is for internal system use only.
860      *
861      * @param callbackIntent a PendingIntent to launch when the operation completes.
862      * @hide
863      */
retainSubscriptionsForFactoryReset(PendingIntent callbackIntent)864     public void retainSubscriptionsForFactoryReset(PendingIntent callbackIntent) {
865         if (!isEnabled()) {
866             sendUnavailableError(callbackIntent);
867             return;
868         }
869         try {
870             getIEuiccController().retainSubscriptionsForFactoryReset(mCardId, callbackIntent);
871         } catch (RemoteException e) {
872             throw e.rethrowFromSystemServer();
873         }
874     }
875 
876     /**
877      * Refreshes the cardId if its uninitialized, and returns whether we should continue the
878      * operation.
879      * <p>
880      * Note that after a successful refresh, the mCardId may be TelephonyManager.UNSUPPORTED_CARD_ID
881      * on older HALs. For backwards compatability, we continue to the LPA and let it decide which
882      * card to use.
883      */
refreshCardIdIfUninitialized()884     private boolean refreshCardIdIfUninitialized() {
885         // Refresh mCardId if its UNINITIALIZED_CARD_ID
886         if (mCardId == TelephonyManager.UNINITIALIZED_CARD_ID) {
887             TelephonyManager tm = (TelephonyManager)
888                     mContext.getSystemService(Context.TELEPHONY_SERVICE);
889             mCardId = tm.getCardIdForDefaultEuicc();
890         }
891         if (mCardId == TelephonyManager.UNINITIALIZED_CARD_ID) {
892             return false;
893         }
894         return true;
895     }
896 
sendUnavailableError(PendingIntent callbackIntent)897     private static void sendUnavailableError(PendingIntent callbackIntent) {
898         try {
899             callbackIntent.send(EMBEDDED_SUBSCRIPTION_RESULT_ERROR);
900         } catch (PendingIntent.CanceledException e) {
901             // Caller canceled the callback; do nothing.
902         }
903     }
904 
getIEuiccController()905     private static IEuiccController getIEuiccController() {
906         return IEuiccController.Stub.asInterface(ServiceManager.getService("econtroller"));
907     }
908 }
909