Mit der Embedded SIM-Technologie (eSIM oder eUICC) können Mobilfunknutzer ein Mobilfunkanbieterprofil herunterladen und den Dienst eines Mobilfunkanbieters aktivieren, ohne eine physische SIM-Karte zu benötigen. Es handelt sich um eine globale Spezifikation der GSMA, die die Remote-SIM-Bereitstellung (RSP) für jedes Mobilgerät ermöglicht. Ab Android 9 bietet das Android-Framework Standard-APIs für den Zugriff auf die eSIM und die Verwaltung von Abo-Profilen auf der eSIM. Mit diesen eUICC-APIs können Drittanbieter eigene Mobilfunkanbieter-Apps und lokale Profilassistenten (LPAs) auf eSIM-fähigen Android-Geräten entwickeln.
Die LPA ist eine eigenständige System-App, die im Android-Build-Image enthalten sein sollte. Die Verwaltung der Profile auf der eSIM erfolgt in der Regel durch die LPA, da sie als Brücke zwischen dem SM-DP+ (Remotedienst, der Profilpakete für Geräte vorbereitet, speichert und bereitstellt) und dem eUICC-Chip dient. Die LPA-APK kann optional eine UI-Komponente enthalten, die als LPA-UI oder LUI bezeichnet wird. Sie bietet dem Endnutzer einen zentralen Ort, an dem er alle eingebetteten Abo-Profile verwalten kann. Das Android-Framework erkennt automatisch den besten verfügbaren LPA und stellt eine Verbindung zu ihm her. Alle eUICC-Vorgänge werden über eine LPA-Instanz weitergeleitet.
Abbildung 1: Vereinfachte RSP-Architektur
Mobilfunkanbieter, die eine Carrier-App erstellen möchten, sollten sich die APIs in EuiccManager
ansehen. Diese bieten Profilverwaltungsfunktionen auf hoher Ebene wie downloadSubscription()
, switchToSubscription()
und deleteSubscription()
.
Wenn Sie ein Geräte-OEM sind und eine eigene LPA-System-App erstellen möchten, müssen Sie EuiccService
für das Android-Framework erweitern, damit eine Verbindung zu Ihren LPA-Diensten hergestellt werden kann. Außerdem sollten Sie die APIs in EuiccCardManager
verwenden, die ES10x-Funktionen basierend auf GSMA RSP v2.0 bereitstellen.
Mit diesen Funktionen werden Befehle an den eUICC-Chip gesendet, z. B. prepareDownload()
, loadBoundProfilePackage()
, retrieveNotificationList()
und resetMemory()
.
Die APIs in EuiccManager
erfordern eine korrekt implementierte LPA-App, damit sie funktionieren. Der Aufrufer von EuiccCardManager
-APIs muss eine LPA sein. Dies wird vom Android-Framework erzwungen.
Geräte mit Android 10 oder höher können Geräte mit mehreren eSIMs unterstützen. Weitere Informationen finden Sie unter Mehrere eSIMs unterstützen.
Mobilfunkanbieter-App erstellen
Die eUICC-APIs in Android 9 ermöglichen es Mobilfunkanbietern, Apps mit ihrem Markennamen zu erstellen, um ihre Profile direkt zu verwalten. Dazu gehört das Herunterladen und Löschen von Abo-Profilen, die dem Mobilfunkanbieter gehören, sowie das Wechseln zu einem Profil, das einem Mobilfunkanbieter gehört.
EuiccManager
EuiccManager
ist der Haupteinstiegspunkt für Apps, um mit der LPA zu interagieren. Dazu gehören auch Mobilfunkanbieter-Apps, die von Mobilfunkanbietern angebotene Abos herunterladen, löschen und zu diesen wechseln. Dazu gehört auch die LUI-System-App, die einen zentralen Ort/eine zentrale Benutzeroberfläche für die Verwaltung aller eingebetteten Abos bietet und eine separate App von der App sein kann, die die EuiccService
bereitstellt.
Damit eine Carrier-App die öffentlichen APIs verwenden kann, muss sie zuerst die Instanz von EuiccManager
über Context#getSystemService
abrufen:
EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
Bevor Sie eSIM-Vorgänge ausführen, sollten Sie prüfen, ob eSIM auf dem Gerät unterstützt wird. EuiccManager#isEnabled()
gibt in der Regel true
zurück, wenn das android.hardware.telephony.euicc
-Feature definiert ist und ein LPA-Paket vorhanden ist.
if (mgr == null || !mgr.isEnabled()) {
return;
}
So rufen Sie Informationen zur eUICC-Hardware und zur eSIM-Betriebssystemversion auf:
EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();
Viele APIs, z. B. downloadSubscription()
und switchToSubscription()
, verwenden PendingIntent
-Callbacks, da sie Sekunden oder sogar Minuten dauern können.
PendingIntent
wird mit einem Ergebniscode im EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_
-Bereich gesendet. Dieser enthält von Frameworks definierte Fehlercodes sowie einen beliebigen detaillierten Ergebniscode, der vom LPA als EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE
weitergegeben wird. So kann die Carrier-App ihn zu Protokollierungs- und Debuggingzwecken erfassen. Der PendingIntent
-Callback muss BroadcastReceiver
sein.
So laden Sie ein herunterladbares Abo herunter (das mit einem Aktivierungscode oder einem QR‑Code erstellt wurde):
// Register receiver.
static final String ACTION_DOWNLOAD_SUBSCRIPTION = "download_subscription";
static final String LPA_DECLARED_PERMISSION
= "com.your.company.lpa.permission.BROADCAST";
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*/);
// If the result code is a resolvable error, call startResolutionActivity
if (resultCode == EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR) {
PendingIntent callbackIntent = PendingIntent.getBroadcast(
getContext(), 0 /* requestCode */, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
mgr.startResolutionActivity(
activity,
0 /* requestCode */,
intent,
callbackIntent);
}
resultIntent = intent;
}
};
context.registerReceiver(receiver,
new IntentFilter(ACTION_DOWNLOAD_SUBSCRIPTION),
LPA_DECLARED_PERMISSION /* broadcastPermission*/,
null /* handler */);
// Download subscription asynchronously.
DownloadableSubscription sub = DownloadableSubscription
.forActivationCode(code /* encodedActivationCode*/);
Intent intent = new Intent(action).setPackage(context.getPackageName());
PendingIntent callbackIntent = PendingIntent.getBroadcast(
getContext(), 0 /* requestCode */, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
mgr.downloadSubscription(sub, true /* switchAfterDownload */,
callbackIntent);
Berechtigung in AndroidManifest.xml
definieren und verwenden:
<permission android:protectionLevel="signature" android:name="com.your.company.lpa.permission.BROADCAST" />
<uses-permission android:name="com.your.company.lpa.permission.BROADCAST"/>
So wechseln Sie zu einem Abo anhand der Abo-ID:
// Register receiver.
static final String ACTION_SWITCH_TO_SUBSCRIPTION = "switch_to_subscription";
static final String LPA_DECLARED_PERMISSION
= "com.your.company.lpa.permission.BROADCAST";
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_SWITCH_TO_SUBSCRIPTION),
LPA_DECLARED_PERMISSION /* broadcastPermission*/,
null /* handler */);
// Switch to a subscription asynchronously.
Intent intent = new Intent(action).setPackage(context.getPackageName());
PendingIntent callbackIntent = PendingIntent.getBroadcast(
getContext(), 0 /* requestCode */, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
mgr.switchToSubscription(1 /* subscriptionId */, callbackIntent);
Eine vollständige Liste der EuiccManager
APIs und Codebeispiele finden Sie unter eUICC APIs.
Behebbare Fehler
In einigen Fällen kann das System den eSIM-Vorgang nicht abschließen, der Fehler kann jedoch vom Nutzer behoben werden. downloadSubscription
kann beispielsweise fehlschlagen, wenn die Profilmetadaten angeben, dass ein Bestätigungscode des Mobilfunkanbieters erforderlich ist. Oder switchToSubscription
schlägt fehl, wenn die Mobilfunkanbieter-App Mobilfunkanbieterberechtigungen für das Zielprofil hat (d. h. der Mobilfunkanbieter ist Inhaber des Profils), aber keine Mobilfunkanbieterberechtigungen für das aktuell aktivierte Profil und daher eine Einwilligung des Nutzers erforderlich ist.
In diesen Fällen wird der Rückruf des Aufrufers mit EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR
aufgerufen. Der Callback Intent
enthält interne Extras, sodass die Auflösung über die LUI angefordert werden kann, wenn der Aufrufer ihn an EuiccManager#startResolutionActivity
übergibt. Wenn wir noch einmal den Bestätigungscode als Beispiel verwenden, löst EuiccManager#startResolutionActivity
einen LUI-Bildschirm aus, auf dem der Nutzer einen Bestätigungscode eingeben kann. Nachdem der Code eingegeben wurde, wird der Downloadvorgang fortgesetzt. Bei diesem Ansatz hat die Mobilfunkanbieter-App die volle Kontrolle darüber, wann die Benutzeroberfläche angezeigt wird. LPA/LUI erhalten jedoch eine erweiterbare Methode, um in Zukunft neue Möglichkeiten zur Behandlung von Problemen hinzuzufügen, die Nutzer selbst beheben können, ohne dass Änderungen an Client-Apps erforderlich sind.
In Android 9 werden diese behebaren Fehler in EuiccService
definiert, die von der LUI verarbeitet werden sollten:
/**
* Alert the user that this action will result in an active SIM being
* deactivated. To implement the LUI triggered by the system, you need to define
* this in AndroidManifest.xml.
*/
public static final String ACTION_RESOLVE_DEACTIVATE_SIM =
"android.service.euicc.action.RESOLVE_DEACTIVATE_SIM";
/**
* Alert the user about a download/switch being done for an app that doesn't
* currently have carrier privileges.
*/
public static final String ACTION_RESOLVE_NO_PRIVILEGES =
"android.service.euicc.action.RESOLVE_NO_PRIVILEGES";
/** Ask the user to resolve all the resolvable errors. */
public static final String ACTION_RESOLVE_RESOLVABLE_ERRORS =
"android.service.euicc.action.RESOLVE_RESOLVABLE_ERRORS";
Mobilfunkanbieterberechtigungen
Wenn Sie als Mobilfunkanbieter eine eigene Mobilfunkanbieter-App entwickeln, die EuiccManager
aufruft, um Profile auf ein Gerät herunterzuladen, sollten in Ihrem Profil in den Metadaten Mobilfunkanbieter-Berechtigungsregeln enthalten sein, die Ihrer Mobilfunkanbieter-App entsprechen. Das liegt daran, dass Abo-Profile verschiedener Mobilfunkanbieter auf der eUICC eines Geräts vorhanden sein können und jede Mobilfunkanbieter-App nur auf die Profile zugreifen darf, die dem jeweiligen Mobilfunkanbieter gehören. Beispiel: Mobilfunkanbieter A sollte kein Profil herunterladen, aktivieren oder deaktivieren können, das Mobilfunkanbieter B gehört.
Damit ein Profil nur für den Inhaber zugänglich ist, verwendet Android einen Mechanismus, um der App des Profilinhabers (d. h. der Carrier-App) spezielle Berechtigungen zu gewähren. Die Android-Plattform lädt Zertifikate, die in der Zugriffsregeldatei (Access Rule File, ARF) des Profils gespeichert sind, und erteilt Apps, die mit diesen Zertifikaten signiert sind, die Berechtigung, EuiccManager
-APIs aufzurufen. Der allgemeine Prozess wird unten beschrieben:
- Der Betreiber signiert das APK der Carrier-App. Das Tool apksigner hängt das Public-Key-Zertifikat an das APK an.
Der Mobilfunkanbieter/SM-DP+ bereitet ein Profil und seine Metadaten vor, einschließlich einer ARF, die Folgendes enthält:
- Signatur (SHA-1 oder SHA-256) des Public-Key-Zertifikats der Carrier-App (erforderlich)
- Paketname der Mobilfunkanbieter-App (dringend empfohlen)
Die Carrier-App versucht, einen eUICC-Vorgang mit der
EuiccManager
API auszuführen.Die Android-Plattform prüft, ob der SHA‑1- oder SHA‑256-Hash des Zertifikats der aufrufenden App mit der Signatur des Zertifikats übereinstimmt, das aus der ARF des Zielprofils abgerufen wurde. Wenn der Paketname der Mobilfunkanbieter-App im ARF enthalten ist, muss er auch mit dem Paketnamen der Anrufer-App übereinstimmen.
Nachdem die Signatur und der Paketname (falls enthalten) überprüft wurden, wird der Anrufer-App das Betreiberprivileg für das Zielprofil gewährt.
Da Profilmetadaten außerhalb des Profils selbst verfügbar sein können (damit LPA die Profilmetadaten vom SM-DP+ abrufen kann, bevor das Profil heruntergeladen wird, oder vom ISD-R, wenn das Profil deaktiviert ist), sollten sie dieselben Regeln für Betreibervorrechte wie im Profil enthalten.
Das eUICC-Betriebssystem und der SM-DP+ müssen das proprietäre Tag BF76
in den Profilmetadaten unterstützen. Der Tag-Inhalt sollte mit den Regeln für Betreiberberechtigungen übereinstimmen, die vom in UICC Carrier Privileges definierten Access Rule Applet (ARA) zurückgegeben werden:
RefArDo ::= [PRIVATE 2] SEQUENCE { -- Tag E2
refDo [PRIVATE 1] SEQUENCE { -- Tag E1
deviceAppIdRefDo [PRIVATE 1] OCTET STRING (SIZE(20|32)), -- Tag C1
pkgRefDo [PRIVATE 10] OCTET STRING (SIZE(0..127)) OPTIONAL -- Tag CA
},
arDo [PRIVATE 3] SEQUENCE { -- Tag E3
permArDo [PRIVATE 27] OCTET STRING (SIZE(8)) -- Tag DB
}
}
Weitere Informationen zum Signieren von Apps finden Sie unter App signieren. Weitere Informationen zu Mobilfunkanbieterberechtigungen finden Sie unter UICC Carrier Privileges.
Assistent-App für lokales Profil erstellen
Gerätehersteller können ihren eigenen lokalen Profilassistenten (Local Profile Assistant, LPA) implementieren, der mit den Android-Euicc-APIs verbunden sein muss. In den folgenden Abschnitten erhalten Sie einen kurzen Überblick über die Erstellung einer LPA-App und die Integration in das Android-System.
Hardware-/Modemanforderungen
Der LPA und das eSIM-Betriebssystem auf dem eUICC-Chip müssen mindestens GSMA RSP (Remote SIM Provisioning) v2.0 oder v2.2 unterstützen. Sie sollten auch SM-DP+ und SM-DS-Server mit einer passenden RSP-Version verwenden. Eine detaillierte RSP-Architektur finden Sie in der GSMA SGP.21 RSP Architecture Specification.
Außerdem muss das Gerätemodem zur Integration in die eUICC-APIs in Android 9 Terminalfunktionen mit Unterstützung für eUICC-Funktionen senden, die codiert sind (lokale Profilverwaltung und Profil-Download). Außerdem müssen die folgenden Methoden implementiert werden:
- IRadio HAL v1.1:
setSimPower
IRadio HAL v1.2:
getIccCardStatus
IRadioConfig HAL v1.0:
getSimSlotsStatus
IRadioConfig AIDL v1.0:
getAllowedCarriers
Das Google LPA muss den Status der Mobilfunkanbietersperre kennen, damit der eSIM-Download oder die eSIM-Übertragung nur für den zulässigen Mobilfunkanbieter möglich ist. Andernfalls laden Nutzer möglicherweise eine SIM-Karte herunter und übertragen sie, nur um später festzustellen, dass das Gerät an einen anderen Mobilfunkanbieter gebunden ist.
Anbieter oder OEMs müssen die HAL-API IRadioSim.getAllowedCarriers() implementieren.
Das RIL / Modem des Anbieters muss den Sperrstatus und die carrierId des Mobilfunkanbieters, an den das Gerät gebunden ist, als Teil der HAL-API IRadioSimResponse.getAllowedCarriersResponse() angeben.
Das Modem sollte die eSIM mit dem aktivierten Standard-Bootprofil als gültige SIM erkennen und die SIM-Stromversorgung aufrechterhalten.
Für Geräte mit Android 10 muss ein Array mit nicht entfernbarer eUICC-Slot-ID definiert werden. Beispiele finden Sie unter arrays.xml
.
<resources>
<!-- Device-specific array of SIM slot indexes which are are embedded eUICCs.
e.g. If a device has two physical slots with indexes 0, 1, and slot 1 is an
eUICC, then the value of this array should be:
<integer-array name="non_removable_euicc_slots">
<item>1</item>
</integer-array>
If a device has three physical slots and slot 1 and 2 are eUICCs, then the value of
this array should be:
<integer-array name="non_removable_euicc_slots">
<item>1</item>
<item>2</item>
</integer-array>
This is used to differentiate between removable eUICCs and built in eUICCs, and should
be set by OEMs for devices which use eUICCs. -->
<integer-array name="non_removable_euicc_slots">
<item>1</item>
</integer-array>
</resources>
Eine vollständige Liste der Modem-Anforderungen finden Sie unter Modem Requirements for eSIM Support.
EuiccService
Ein LPA besteht aus zwei separaten Komponenten (die beide in derselben APK implementiert sein können): dem LPA-Backend und der LPA-Benutzeroberfläche (LUI).
Um das LPA-Backend zu implementieren, müssen Sie EuiccService
erweitern und diesen Dienst in Ihrer Manifestdatei deklarieren. Für den Dienst muss die Systemberechtigung android.permission.BIND_EUICC_SERVICE
erforderlich sein, damit nur das System eine Bindung daran vornehmen kann. Der Dienst muss auch einen Intent-Filter mit der Aktion android.service.euicc.EuiccService
enthalten. Die Priorität des Intent-Filters sollte auf einen Wert ungleich null gesetzt werden, wenn mehrere Implementierungen auf dem Gerät vorhanden sind. Beispiel:
<service
android:name=".EuiccServiceImpl"
android:permission="android.permission.BIND_EUICC_SERVICE">
<intent-filter android:priority="100">
<action android:name="android.service.euicc.EuiccService" />
</intent-filter>
</service>
Intern bestimmt das Android-Framework den aktiven LPA und interagiert bei Bedarf damit, um die Android-eUICC-APIs zu unterstützen. PackageManager
wird für alle Apps mit der Berechtigung android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS
abgefragt, die einen Dienst für die Aktion android.service.euicc.EuiccService
angibt.
Der Dienst mit der höchsten Priorität wird ausgewählt. Wenn kein Dienst gefunden wird, ist die LPA-Unterstützung deaktiviert.
Um die LUI zu implementieren, müssen Sie eine Aktivität für die folgenden Aktionen bereitstellen:
android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS
android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION
Wie beim Dienst muss für jede Aktivität die Systemberechtigung android.permission.BIND_EUICC_SERVICE
erforderlich sein. Jede sollte einen Intent-Filter mit der entsprechenden Aktion, der Kategorie android.service.euicc.category.EUICC_UI
und einer Priorität ungleich null haben.
Eine ähnliche Logik wird verwendet, um die Implementierungen für diese Aktivitäten auszuwählen, wie bei der Auswahl der Implementierung von EuiccService
.
Beispiel:
<activity android:name=".MyLuiActivity"
android:exported="true"
android:permission="android.permission.BIND_EUICC_SERVICE">
<intent-filter android:priority="100">
<action android:name="android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS" />
<action android:name="android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.service.euicc.category.EUICC_UI" />
</intent-filter>
</activity>
Das bedeutet, dass die Benutzeroberfläche, die diese Bildschirme implementiert, aus einem anderen APK stammen kann als die Benutzeroberfläche, die EuiccService
implementiert.
Ob Sie eine einzelne APK oder mehrere APKs verwenden (z. B. eine, die EuiccService
implementiert, und eine, die LUI-Aktivitäten bereitstellt), ist eine Designentscheidung.
EuiccCardManager
EuiccCardManager
ist die Schnittstelle für die Kommunikation mit dem eSIM-Chip. Es bietet ES10-Funktionen (wie in der GSMA RSP-Spezifikation beschrieben) und verarbeitet die APDU-Anfrage-/Antwortbefehle auf niedriger Ebene sowie die ASN.1-Analyse.
EuiccCardManager
ist eine System-API und kann nur von Apps mit Systemberechtigungen aufgerufen werden.
Abbildung 2: Sowohl die Mobilfunkanbieter-App als auch LPA verwenden Euicc-APIs
Für die Profilvorgangs-APIs über EuiccCardManager
muss der Aufrufer ein LPA sein. Dies wird vom Android-Framework erzwungen. Das bedeutet, dass der Aufrufer EuiccService
erweitern und in Ihrer Manifestdatei deklariert werden muss, wie in den vorherigen Abschnitten beschrieben.
Ähnlich wie bei EuiccManager
muss Ihr LPA zuerst die Instanz von EuiccCardManager
über Context#getSystemService
abrufen, um die EuiccCardManager
-APIs zu verwenden:
EuiccCardManager cardMgr = (EuiccCardManager) context.getSystemService(Context.EUICC_CARD_SERVICE);
So rufen Sie alle Profile auf der eUICC ab:
ResultCallback<EuiccProfileInfo[]> callback =
new ResultCallback<EuiccProfileInfo[]>() {
@Override
public void onComplete(int resultCode,
EuiccProfileInfo[] result) {
if (resultCode == EuiccCardManagerReflector.RESULT_OK) {
// handle result
} else {
// handle error
}
}
};
cardMgr.requestAllProfiles(eid, AsyncTask.THREAD_POOL_EXECUTOR, callback);
Intern wird EuiccCardManager
über eine AIDL-Schnittstelle an EuiccCardController
gebunden (die im Smartphone-Prozess ausgeführt wird). Jede EuiccCardManager
-Methode empfängt ihren Callback vom Smartphone-Prozess über eine andere, dedizierte AIDL-Schnittstelle. Wenn EuiccCardManager
-APIs verwendet werden, muss der Aufrufer (LPA) ein Executor
-Objekt bereitstellen, über das der Callback aufgerufen wird. Dieses Executor
-Objekt kann in einem einzelnen Thread oder in einem Threadpool Ihrer Wahl ausgeführt werden.
Die meisten EuiccCardManager
APIs haben dasselbe Nutzungsmuster. So laden Sie beispielsweise ein gebundenes Profilpaket auf die eUICC:
...
cardMgr.loadBoundProfilePackage(eid, boundProfilePackage,
AsyncTask.THREAD_POOL_EXECUTOR, callback);
So wechseln Sie zu einem anderen Profil mit einer bestimmten ICCID:
...
cardMgr.switchToProfile(eid, iccid, true /* refresh */,
AsyncTask.THREAD_POOL_EXECUTOR, callback);
So rufen Sie die Standard-SM-DP+ Adresse vom eUICC-Chip ab:
...
cardMgr.requestDefaultSmdpAddress(eid, AsyncTask.THREAD_POOL_EXECUTOR,
callback);
So rufen Sie eine Liste von Benachrichtigungen für die angegebenen Benachrichtigungsereignisse ab:
...
cardMgr.listNotifications(eid,
EuiccNotification.Event.INSTALL
| EuiccNotification.Event.DELETE /* events */,
AsyncTask.THREAD_POOL_EXECUTOR, callback);
eSIM-Profil über eine Mobilfunkanbieter-App aktivieren
Auf Geräten mit Android 9 oder höher können Sie eine App des Mobilfunkanbieters verwenden, um die eSIM zu aktivieren und Profile herunterzuladen. Die Mobilfunkanbieter-App kann Profile herunterladen, indem sie downloadSubscription
direkt aufruft oder dem LPA einen Aktivierungscode bereitstellt.
Wenn eine Carrier-App ein Profil durch Aufrufen von downloadSubscription
herunterlädt, wird durch den Aufruf erzwungen, dass die App das Profil über ein BF76
-Metadaten-Tag verwalten kann, das Carrier-Berechtigungsregeln für das Profil codiert. Wenn ein Profil kein BF76
-Tag hat oder das BF76
-Tag nicht mit der Signatur der Anrufer-App des Mobilfunkanbieters übereinstimmt, wird der Download abgelehnt.
Im folgenden Abschnitt wird beschrieben, wie Sie eine eSIM über die App eines Mobilfunkanbieters mit einem Aktivierungscode aktivieren.
eSIM mit einem Aktivierungscode aktivieren
Wenn Sie einen Aktivierungscode zum Aktivieren eines eSIM-Profils verwenden, ruft die LPA einen Aktivierungscode aus der App des Mobilfunkanbieters ab und lädt das Profil herunter. Dieser Ablauf kann vom LPA initiiert werden. Das LPA kann den gesamten UI-Ablauf steuern, sodass keine Benutzeroberfläche der Mobilfunkanbieter-App angezeigt wird. Bei diesem Ansatz wird die Prüfung des BF76
-Tags umgangen und Netzbetreiber müssen nicht den gesamten UI-Ablauf für die eSIM-Aktivierung implementieren, einschließlich des Herunterladens eines eSIM-Profils und der Fehlerbehandlung.
eUICC-Bereitstellungsdienst des Mobilfunkanbieters definieren
Die Kommunikation zwischen der LPA und der App des Mobilfunkanbieters erfolgt über zwei AIDL-Schnittstellen: ICarrierEuiccProvisioningService
und IGetActivationCodeCallback
. Die App des Mobilfunkanbieters muss eine ICarrierEuiccProvisioningService
-Schnittstelle implementieren und in der Manifestdeklaration verfügbar machen.
Die LPA muss an ICarrierEuiccProvisioningService
gebunden sein und IGetActivationCodeCallback
implementieren. Weitere Informationen zum Implementieren und Bereitstellen einer AIDL-Schnittstelle finden Sie unter AIDL-Schnittstelle definieren.
Erstellen Sie die folgenden AIDL-Dateien für die LPA- und die Carrier-Apps, um die AIDL-Schnittstellen zu definieren.
ICarrierEuiccProvisioningService.aidl
package android.service.euicc; import android.service.euicc.IGetActivationCodeCallback; oneway interface ICarrierEuiccProvisioningService { // The method to get the activation code from the carrier app. The caller needs to pass in // the implementation of IGetActivationCodeCallback as the parameter. void getActivationCode(in IGetActivationCodeCallback callback); // The method to get the activation code from the carrier app. The caller needs to pass in // the activation code string as the first parameter and the implementation of // IGetActivationCodeCallback as the second parameter. This method provides the carrier // app the device EID which allows a carrier to pre-bind a profile to the device's EID before // the download process begins. void getActivationCodeForEid(in String eid, in IGetActivationCodeCallback callback); }
IGetActivationCodeCallback.aidl
package android.service.euicc; oneway interface IGetActivationCodeCallback { // The call back method needs to be called when the carrier app gets the activation // code successfully. The caller needs to pass in the activation code string as the // parameter. void onSuccess(String activationCode); // The call back method needs to be called when the carrier app failed to get the // activation code. void onFailure(); }
Beispiel für die Implementierung von LPA
Um die ICarrierEuiccProvisioningService
-Implementierung der Mobilfunkanbieter-App zu binden, muss der LPA sowohl ICarrierEuiccProvisioningService.aidl
als auch IGetActivationCodeCallback.aidl
in Ihr Projekt kopieren und ServiceConnection
implementieren.
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mCarrierProvisioningService = ICarrierEuiccProvisioningService.Stub.asInterface(iBinder);
}
Nachdem die LPA an die ICarrierEuiccProvisioningService
-Implementierung der Mobilfunkanbieter-App gebunden wurde, ruft sie entweder getActivationCode
oder getActivationCodeForEid
auf, um den Aktivierungscode von der Mobilfunkanbieter-App abzurufen. Dazu wird die Implementierung der IGetActivationCodeCallback
-Stub-Klasse übergeben.
Der Unterschied zwischen getActivationCode
und getActivationCodeForEid
besteht darin, dass getActivationCodeForEid
es einem Mobilfunkanbieter ermöglicht, ein Profil vor Beginn des Downloadvorgangs an die EID des Geräts zu binden.
void getActivationCodeFromCarrierApp() {
IGetActivationCodeCallback.Stub callback =
new IGetActivationCodeCallback.Stub() {
@Override
public void onSuccess(String activationCode) throws RemoteException {
// Handle the case LPA success to get activation code from a carrier app.
}
@Override
public void onFailure() throws RemoteException {
// Handle the case LPA failed to get activation code from a carrier app.
}
};
try {
mCarrierProvisioningService.getActivationCode(callback);
} catch (RemoteException e) {
// Handle Remote Exception
}
}
Beispiel für die Implementierung für eine Mobilfunkanbieter-App
Damit sich die LPA an die Carrier-App binden kann, muss die Carrier-App sowohl ICarrierEuiccProvisioningService.aidl
als auch IGetActivationCodeCallback.aidl
in Ihr Projekt kopieren und den Dienst ICarrierEuiccProvisioningService
in der Datei AndroidManifest.xml
deklarieren. Für den Dienst muss die Systemberechtigung android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS
erforderlich sein, damit nur die LPA, eine App mit Systemberechtigungen, eine Bindung daran vornehmen kann. Der Dienst muss auch einen Intent-Filter mit der Aktion android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE
enthalten.
AndroidManifest.xml
<application> ... <service android:name=".CarrierEuiccProvisioningService" android:exported="true" android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"> <intent-filter> <action android:name="android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE"/> </intent-filter> </service> ... </application>
Um den AIDL-Carrier-App-Dienst zu implementieren, erstellen Sie einen Dienst, erweitern Sie die Klasse Stub
und implementieren Sie die Methoden getActivationCode
und getActivationCodeForEid
. Die LPA kann dann eine der beiden Methoden aufrufen, um den Code für die Profilaktivierung abzurufen. Die Mobilfunkanbieter-App sollte mit dem Aufruf von IGetActivationCodeCallback#onSuccess
mit dem Aktivierungscode antworten, wenn der Code erfolgreich vom Server des Mobilfunkanbieters abgerufen wurde. Wenn die Anfrage nicht erfolgreich ist, sollte die App des Mobilfunkanbieters mit IGetActivationCodeCallback#onFailure
antworten.
CarrierEuiccProvisioningService.java
import android.service.euicc.ICarrierEuiccProvisioningService; import android.service.euicc.ICarrierEuiccProvisioningService.Stub; import android.service.euicc.IGetActivationCodeCallback; public class CarrierEuiccProvisioningService extends Service { private final ICarrierEuiccProvisioningService.Stub binder = new Stub() { @Override public void getActivationCode(IGetActivationCodeCallback callback) throws RemoteException { String activationCode = // do whatever work necessary to get an activation code (HTTP requests to carrier server, fetch from storage, etc.) callback.onSuccess(activationCode); } @Override public void getActivationCodeForEid(String eid, IGetActivationCodeCallback callback) throws RemoteException { String activationCode = // do whatever work necessary (HTTP requests, fetch from storage, etc.) callback.onSuccess(activationCode); } } }
UI der Anbieter-App im LPA-Aktivierungsablauf starten
Auf Geräten mit Android 11 und höher kann die LPA die Benutzeroberfläche einer Mobilfunkanbieter-App starten. Das ist nützlich, da für eine Carrier-App möglicherweise zusätzliche Informationen vom Nutzer erforderlich sind, bevor dem LPA ein Aktivierungscode zur Verfügung gestellt wird. Beispielsweise müssen Nutzer sich möglicherweise bei Mobilfunkanbietern anmelden, um ihre Telefonnummern zu aktivieren oder andere Portierungsdienste zu nutzen.
So starten Sie die Benutzeroberfläche einer Mobilfunkanbieter-App im LPA:
Der LPA startet den Aktivierungsablauf der Mobilfunkanbieter-App, indem er den
android.service.euicc.action.START_CARRIER_ACTIVATION
-Intent an das Paket der Mobilfunkanbieter-App sendet, das die Aktion enthält. Der Empfänger der Carrier-App muss in der Manifestdeklaration mitandroid:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
geschützt werden, damit keine Intents von Apps empfangen werden, die nicht LPA-kompatibel sind.String packageName = // The carrier app's package name Intent carrierAppIntent = new Intent(“android.service.euicc.action.START_CARRIER_ACTIVATION”) .setPackage(packageName); ResolveInfo activity = context.getPackageManager().resolveActivity(carrierAppIntent, 0); carrierAppIntent .setClassName(activity.activityInfo.packageName, activity.activityInfo.name); startActivityForResult(carrierAppIntent, requestCode);
Die Mobilfunkanbieter-App verwendet ihre eigene Benutzeroberfläche. Zum Beispiel, um den Nutzer anzumelden oder HTTP-Anfragen an das Backend des Mobilfunkanbieters zu senden.
Die Mobilfunkanbieter-App antwortet auf die LPA, indem sie
setResult(int, Intent)
undfinish()
aufruft.- Wenn die Mobilfunkanbieter-App mit
RESULT_OK
antwortet, setzt der LPA den Aktivierungsvorgang fort. Wenn die Mobilfunkanbieter-App feststellt, dass der Nutzer einen QR-Code scannen sollte, anstatt den LPA den Dienst der Mobilfunkanbieter-App binden zu lassen, antwortet die Mobilfunkanbieter-App dem LPA mitsetResult(int, Intent)
mitRESULT_OK
und einerIntent
-Instanz, die das boolesche Extraandroid.telephony.euicc.extra.USE_QR_SCANNER
enthält, das auftrue
gesetzt ist. Die LPA prüft dann das Extra und startet den QR-Scanner, anstatt dieICarrierEuiccProvisioningService
-Implementierung der Mobilfunkanbieter-App zu binden. - Wenn die Mobilfunkanbieter-App abstürzt oder mit
RESULT_CANCELED
antwortet (dies ist der Standardantwortcode), bricht der LPA den eSIM-Aktivierungsvorgang ab. - Wenn die Mobilfunkanbieter-App mit etwas anderem als
RESULT_OK
oderRESULT_CANCELED
antwortet, behandelt die LPA dies als Fehler.
Aus Sicherheitsgründen sollte die LPA einen im Ergebnis-Intent bereitgestellten Aktivierungscode nicht direkt akzeptieren, damit Anrufer, die keine LPA verwenden, keinen Aktivierungscode von der App des Mobilfunkanbieters erhalten können.
- Wenn die Mobilfunkanbieter-App mit
LPA-Aktivierungsvorgang in einer Anbieter-App starten
Ab Android 11 können Mobilfunkanbieter-Apps eUICC-APIs verwenden, um eine LUI für die eSIM-Aktivierung zu starten. Mit dieser Methode wird die Benutzeroberfläche des eSIM-Aktivierungsvorgangs des LPA angezeigt, um das eSIM-Profil zu aktivieren. Der LPA sendet dann einen Broadcast, wenn die Aktivierung des eSIM-Profils abgeschlossen ist.
Die LPA muss eine Aktivität deklarieren, die einen Intent-Filter mit der Aktion
android.service.euicc.action.START_EUICC_ACTIVATION
enthält. Die Priorität des Intent-Filters sollte auf einen Wert ungleich null gesetzt werden, wenn auf dem Gerät mehrere Implementierungen vorhanden sind. Beispiel:<application> ... <activity android:name=".CarrierAppInitActivity" android:exported="true"> <intent-filter android:priority="100"> <action android:name="android.service.euicc.action.START_EUICC_ACTIVATION" /> </intent-filter> </activity> ... </application>
Die Mobilfunkanbieter-App verwendet ihre eigene Benutzeroberfläche. Zum Beispiel, um den Nutzer anzumelden oder HTTP-Anfragen an das Backend des Mobilfunkanbieters zu senden.
An diesem Punkt muss die App des Mobilfunkanbieters bereit sein, über die
ICarrierEuiccProvisioningService
-Implementierung einen Aktivierungscode bereitzustellen. Die Mobilfunkanbieter-App startet die LPA durch Aufrufen vonstartActivityForResult(Intent, int)
mit der Aktionandroid.telephony.euicc.action.START_EUICC_ACTIVATION
. Die LPA prüft auch das boolesche Extraandroid.telephony.euicc.extra.USE_QR_SCANNER
. Wenn der Werttrue
ist, startet der LPA den QR-Scanner, damit der Nutzer den QR-Code des Profils scannen kann.Auf der LPA-Seite wird die LPA an die
ICarrierEuiccProvisioningService
-Implementierung der Mobilfunkanbieter-App gebunden, um den Aktivierungscode abzurufen und das entsprechende Profil herunterzuladen. Das LPA zeigt während des Downloads alle erforderlichen UI-Elemente an, z. B. einen Ladebildschirm.Wenn der LPA-Aktivierungsablauf abgeschlossen ist, antwortet der LPA mit einem Ergebniscode auf die Carrier-App, der in
onActivityResult(int, int, Intent)
verarbeitet wird.- Wenn das LPA das neue eSIM-Profil herunterladen kann, antwortet es mit
RESULT_OK
. - Wenn der Nutzer die Aktivierung des eSIM-Profils im LPA abbricht, wird mit
RESULT_CANCELED
geantwortet. - Wenn die LPA mit etwas anderem als
RESULT_OK
oderRESULT_CANCELED
antwortet, wird dies von der Carrier-App als Fehler behandelt.
Aus Sicherheitsgründen akzeptiert die LPA keinen Aktivierungscode direkt im bereitgestellten Intent, damit Anrufer, die nicht die LPA verwenden, den Aktivierungscode nicht über die App des Mobilfunkanbieters abrufen können.
- Wenn das LPA das neue eSIM-Profil herunterladen kann, antwortet es mit
Unterstützung mehrerer eSIMs
Auf Geräten mit Android 10 oder höher unterstützt die Klasse EuiccManager
Geräte mit mehreren eSIMs. Bei Geräten mit einer einzelnen eSIM, die auf Android 10 aktualisiert werden, ist keine Änderung der LPA-Implementierung erforderlich, da die Plattform die EuiccManager
-Instanz automatisch der Standard-eUICC zuordnet. Die Standard-eUICC wird von der Plattform für Geräte mit Radio HAL-Version 1.2 oder höher und vom LPA für Geräte mit Radio HAL-Versionen unter 1.2 bestimmt.
Voraussetzungen
Wenn ein Gerät mehrere eSIMs unterstützen soll, muss es mehr als eine eUICC haben. Das kann entweder eine integrierte eUICC oder ein physischer SIM-Slot sein, in den herausnehmbare eUICCs eingesetzt werden können.
Für die Unterstützung mehrerer eSIMs ist Radio HAL Version 1.2 oder höher erforderlich. Es wird empfohlen, die Radio HAL-Version 1.4 und die RadioConfig HAL-Version 1.2 zu verwenden.
Implementierung
Zur Unterstützung mehrerer eSIMs (einschließlich entfernbarer eUICCs oder programmierbarer SIMs) muss der LPA EuiccService
implementieren, das die Slot-ID empfängt, die der vom Anrufer angegebenen Karten-ID entspricht.
Die in arrays.xml
angegebene non_removable_euicc_slots
-Ressource ist ein Array von Ganzzahlen, die die Slot-IDs der integrierten eUICCs eines Geräts darstellen. Sie müssen diese Ressource angeben, damit die Plattform feststellen kann, ob eine eingesetzte eUICC entfernbar ist oder nicht.
Mobilfunkanbieter-App für Geräte mit mehreren eSIMs
Wenn Sie eine Carrier-App für ein Gerät mit mehreren eSIMs erstellen, verwenden Sie die Methode createForCardId
in EuiccManager
, um ein EuiccManager
-Objekt zu erstellen, das an eine bestimmte Karten-ID angepinnt ist. Die Karten-ID ist ein ganzzahliger Wert, der eine UICC oder eUICC auf dem Gerät eindeutig identifiziert.
Verwenden Sie die Methode getCardIdForDefaultEuicc
in TelephonyManager
, um die Karten-ID für die Standard-eUICC des Geräts abzurufen. Diese Methode gibt UNSUPPORTED_CARD_ID
zurück, wenn die Radio-HAL-Version niedriger als 1.2 ist, und UNINITIALIZED_CARD_ID
, wenn das Gerät die eUICC nicht gelesen hat.
Sie können Karten-IDs auch über getUiccCardsInfo
und getUiccSlotsInfo
(System-API) in TelephonyManager
sowie über getCardId
in SubscriptionInfo
abrufen.
Wenn ein EuiccManager
-Objekt mit einer bestimmten Karten-ID instanziiert wurde, werden alle Vorgänge an die eUICC mit dieser Karten-ID weitergeleitet. Wenn die eUICC nicht mehr erreichbar ist (z. B. wenn sie ausgeschaltet oder entfernt wird), funktioniert EuiccManager
nicht mehr.
Mit den folgenden Codebeispielen können Sie eine Carrier-App erstellen.
Beispiel 1: Aktives Abo abrufen und EuiccManager
instanziieren
// Get the active subscription and instantiate an EuiccManager for the eUICC which holds
// that subscription
SubscriptionManager subMan = (SubscriptionManager)
mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
int cardId = subMan.getActiveSubscriptionInfo().getCardId();
EuiccManager euiccMan = (EuiccManager) mContext.getSystemService(Context.EUICC_SERVICE)
.createForCardId(cardId);
Beispiel 2: UICCs durchlaufen und EuiccManager
für eine herausnehmbare eUICC instanziieren
// On a device with a built-in eUICC and a removable eUICC, iterate through the UICC cards
// to instantiate an EuiccManager associated with a removable eUICC
TelephonyManager telMan = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
List<UiccCardInfo> infos = telMan.getUiccCardsInfo();
int removableCardId = -1; // valid cardIds are 0 or greater
for (UiccCardInfo info : infos) {
if (info.isRemovable()) {
removableCardId = info.getCardId();
break;
}
}
if (removableCardId != -1) {
EuiccManager euiccMan = (EuiccManager) mContext.getSystemService(Context.EUICC_SERVICE)
.createForCardId(removableCardId);
}
Zertifizierungsstufe
AOSP enthält keine LPA-Implementierung und es wird nicht erwartet, dass auf allen Android-Builds eine LPA verfügbar ist (nicht jedes Smartphone unterstützt eSIM). Aus diesem Grund gibt es keine End-to-End-CTS-Testläufe. In AOSP sind jedoch grundlegende Testläufe verfügbar, um sicherzustellen, dass die bereitgestellten eUICC-APIs in Android-Builds gültig sind.
Die Builds müssen die folgenden CTS-Testläufe (für öffentliche APIs) bestehen: /platform/cts/tests/tests/telephony/current/src/android/telephony/euicc/cts.
Mobilfunkanbieter, die eine Mobilfunkanbieter-App implementieren, sollten ihre normalen internen Qualitätssicherungszyklen durchlaufen, um sicherzustellen, dass alle implementierten Funktionen wie erwartet funktionieren. Die App des Mobilfunkanbieters sollte mindestens in der Lage sein, alle Abo-Profile desselben Betreibers aufzulisten, ein Profil herunterzuladen und zu installieren, einen Dienst im Profil zu aktivieren, zwischen Profilen zu wechseln und Profile zu löschen.
Wenn Sie eine eigene LPA erstellen, sollten Sie sie viel gründlicher testen. Sie sollten mit Ihrem Modem-, eUICC-Chip- oder eSIM-Betriebssystemanbieter, SM-DP+-Anbietern und Mobilfunkanbietern zusammenarbeiten, um Probleme zu beheben und die Interoperabilität Ihres LPA in der RSP-Architektur sicherzustellen. Ein gewisses Maß an manuellen Tests ist unvermeidlich. Für eine optimale Testabdeckung sollten Sie den GSMA SGP.23 RSP Test Plan befolgen.