Project: /_project.yaml Book: /_book.yaml
{% include “_versions.html” %}
In Android {{ androidPVersionNumber }}, profile management APIs (public and @SystemApi) are available through the class EuiccManager
. eUICC communication APIs (@SystemApi only) are available through the class EuiccCardManager
.
Carriers can make carrier apps using EuiccManager to manage profiles, as shown in Figure 1. Carrier apps don't need to be system apps but need to have carrier privileges granted by eUICC profiles. An LPA app (LUI and LPA backend) needs to be a system app (i.e., included in the system image) to call the @SystemApi.
Figure 1. Android phones with carrier app and OEM LPA
Besides the logic of calling EuiccCardManager
and talking to eUICC, LPA apps must implement the following:
Although more than one LPA app can be present in an Android phone, only one LPA can be selected to be the actual working LPA based on the priority defined in the AndroidManifest.xml
file of each app.
The LPA APIs are public through EuiccManager
(under package android.telephony.euicc
). A carrier app can get the instance of EuiccManager
, and call the methods in EuiccManager
to get the eUICC information and manage subscriptions (referred to as profiles in GSMA RSP documents) as SubscriptionInfo instances.
To call public APIs including download, switch, and delete subscription operations, the carrier app must have the required privileges. Carrier privileges are added by the mobile carrier in the profile metadata. The eUICC API enforces the carrier privilege rules accordingly.
The Android platform does not handle the profile policy rules. If a policy rule is declared in the profile metadata, the LPA can choose how to handle the profile download and installation procedure. For example, it is possible for a third-party OEM LPA to handle policy rules using a special error code (the error code is passed from the OEM LPA to the platform, then the platform passes the code to the OEM LUI).
The following APIs can be found in the EuiccManager
reference documentation{: .external} and EuiccManager.java
{: .external}.
Gets the instance of EuiccManager
through Context#getSystemService
.
EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
Checks whether the embedded subscription is enabled. This should be checked before accessing LPA APIs.
boolean isEnabled = mgr.isEnabled(); if (!isEnabled) { return; }
Gets the EID identifying the eUICC hardware. This may be null if the eUICC is not ready. The caller must have carrier privilege or the READ_PRIVILEGED_PHONE_STATE
permission.
String eid = mgr.getEid(); if (eid == null) { // Handle null case. }
Gets information about the eUICC. This contains the OS version.
EuiccInfo info = mgr.getEuiccInfo(); String osVer = info.getOsVersion();
Downloads the given subscription (referred to as “profile” in GSMA RSP documents). The subscription can be created from an activation code. For example, an activation code can be parsed from a QR code. Downloading a subscription is an asynchronous operation.
The caller must either have the WRITE_EMBEDDED_SUBSCRIPTIONS
permission or have carrier privileges for the target subscription.
// Register receiver. String action = "download_subscription"; BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (!action.equals(intent.getAction())) { return; } resultCode = getResultCode(); detailedCode = intent.getIntExtra( EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 0 /* defaultValue*/); resultIntent = intent; } }; context.registerReceiver( receiver, new IntentFilter(action), "example.broadcast.permission" /* broadcastPermission*/, null /* handler */); // Download subscription asynchronously. DownloadableSubscription sub = DownloadableSubscription.forActivationCode(code /* encodedActivationCode*/); Intent intent = new Intent(action); PendingIntent callbackIntent = PendingIntent.getBroadcast( getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT); mgr.downloadSubscription(sub, true /* switchAfterDownload */, callbackIntent);
Switches to (enables) the given subscription. The caller must either have WRITE_EMBEDDED_SUBSCRIPTIONS
or have carrier privileges for the current enabled subscription and the target subscription.
// Register receiver. String action = "switch_to_subscription"; BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (!action.equals(intent.getAction())) { return; } resultCode = getResultCode(); detailedCode = intent.getIntExtra( EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 0 /* defaultValue*/); resultIntent = intent; } }; context.registerReceiver(receiver, new IntentFilter(action), "example.broadcast.permission" /* broadcastPermission*/, null /* handler */); // Switch to a subscription asynchronously. Intent intent = new Intent(action); PendingIntent callbackIntent = PendingIntent.getBroadcast( getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT); mgr.switchToSubscription(1 /* subscriptionId */, callbackIntent);
Deletes a subscription with a subscription ID. If the subscription is currently active, it is first disabled. The caller must have either WRITE_EMBEDDED_SUBSCRIPTIONS
or carrier privileges for the target subscription.
// Register receiver. String action = "delete_subscription"; BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (!action.equals(intent.getAction())) { return; } resultCode = getResultCode(); detailedCode = intent.getIntExtra( EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 0 /* defaultValue*/); resultIntent = intent; } }; context.registerReceiver(receiver, new IntentFilter(action), "example.broadcast.permission" /* broadcastPermission*/, null /* handler */); // Delete a subscription asynchronously. Intent intent = new Intent(action); PendingIntent callbackIntent = PendingIntent.getBroadcast( getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT); mgr.deleteSubscription(1 /* subscriptionId */, callbackIntent);
Starts an activity to resolve a user-resolvable error. If an operation returns EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR
, this method can be called to prompt the user to resolve the issue. This method can only be called once for a particular error.
... mgr.startResolutionActivity(getActivity(), 0 /* requestCode */, resultIntent, callbackIntent);
To see a list of the public
constants in EuiccManager
, see Constants{: .external}.