La tecnologia SIM incorporata (eSIM o eUICC) consente agli utenti di dispositivi mobili di scaricare un profilo operatore e attivare il servizio di un operatore senza una scheda SIM fisica. Si tratta di una specifica globale guidata dalla GSMA che consente il provisioning remoto della SIM (RSP) di qualsiasi dispositivo mobile. A partire da Android 9, il framework Android fornisce API standard per accedere alla eSIM e gestire i profili di abbonamento sulla eSIM. Queste API eUICC consentono a terze parti di sviluppare le proprie app operatore e assistenti del profilo locale (LPA) su dispositivi Android compatibili con eSIM.
L'app LPA è un'app di sistema autonoma che deve essere inclusa nell'immagine di build di Android. La gestione dei profili sulla eSIM viene generalmente eseguita dall'LPA, che funge da ponte tra l'SM-DP+ (servizio remoto che prepara, archivia e distribuisce pacchetti di profili ai dispositivi) e il chip eUICC. L'APK LPA può includere facoltativamente un componente UI, chiamato UI LPA o LUI, per fornire un punto centrale in cui l'utente finale può gestire tutti i profili di abbonamento incorporati. Il framework Android rileva e si connette automaticamente al miglior LPA disponibile e indirizza tutte le operazioni eUICC tramite un'istanza LPA.
Figura 1. Architettura RSP semplificata
Gli operatori di rete mobile interessati a creare un'app operatore devono esaminare
le API in
EuiccManager
,
che fornisce operazioni di gestione dei profili di alto livello, come
downloadSubscription()
, switchToSubscription()
e
deleteSubscription()
.
Se sei un OEM di dispositivi interessato a creare la tua app di sistema LPA, devi
estendere
EuiccService
per consentire al framework Android di connettersi ai tuoi servizi LPA. Inoltre, devi utilizzare le API in
EuiccCardManager
,
che forniscono funzioni ES10x basate su GSMA RSP v2.0.
Queste funzioni vengono utilizzate per inviare comandi al chip eUICC, ad esempio
prepareDownload()
, loadBoundProfilePackage()
, retrieveNotificationList()
e resetMemory()
.
Le API in
EuiccManager
richiedono un'app LPA implementata correttamente per funzionare e il chiamante delle
API EuiccCardManager
deve essere un'LPA. Questo limite viene applicato dal framework Android.
I dispositivi con Android 10 o versioni successive possono supportare dispositivi con più eSIM. Per ulteriori informazioni, vedi Supporto di più eSIM.
Crea un'app operatore
Le API eUICC in Android 9 consentono agli operatori di rete mobile di creare app con il brand dell'operatore per gestire direttamente i propri profili. Ciò include il download e l'eliminazione dei profili di abbonamento di proprietà dell'operatore, nonché il passaggio a un profilo di proprietà di un operatore.
EuiccManager
EuiccManager
è l'entry point principale per le app per interagire con
LPA. Sono incluse le app dell'operatore che scaricano, eliminano e passano ad abbonamenti di proprietà dell'operatore. È inclusa anche l'app di sistema LUI, che
fornisce una posizione/interfaccia utente centrale per la gestione di tutti gli abbonamenti incorporati e
può essere un'app separata da quella che fornisce EuiccService
.
Per utilizzare le API pubbliche, un'app operatore deve prima ottenere l'istanza di
EuiccManager
tramite Context#getSystemService
:
EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
Prima di eseguire qualsiasi operazione con la eSIM, controlla se è supportata sul dispositivo. EuiccManager#isEnabled()
in genere restituisce true
se la
funzionalità android.hardware.telephony.euicc
è definita ed è presente un pacchetto LPA.
if (mgr == null || !mgr.isEnabled()) {
return;
}
Per ottenere informazioni sull'hardware eUICC e sulla versione del sistema operativo eSIM:
EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();
Molte API, come downloadSubscription()
e switchToSubscription()
, utilizzano
i callback PendingIntent
perché il completamento potrebbe richiedere secondi o addirittura minuti.
PendingIntent
viene inviato con un codice risultato nello spazio EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_
, che fornisce codici di errore definiti dal framework, nonché un codice risultato dettagliato arbitrario propagato dall'LPA come EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE
, consentendo all'app dell'operatore di eseguire il monitoraggio a scopo di logging/debug. Il callback PendingIntent
deve essere BroadcastReceiver
.
Per scaricare un determinato abbonamento scaricabile (creato da un codice di attivazione o un codice QR):
// 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);
Definisci e utilizza l'autorizzazione in AndroidManifest.xml
:
<permission android:protectionLevel="signature" android:name="com.your.company.lpa.permission.BROADCAST" />
<uses-permission android:name="com.your.company.lpa.permission.BROADCAST"/>
Per passare a un abbonamento dato l'ID abbonamento:
// 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);
Per un elenco completo di API EuiccManager
ed esempi di codice, consulta
API eUICC.
Errori risolvibili
In alcuni casi il sistema non è in grado di completare l'operazione eSIM,
ma l'errore può essere risolto dall'utente. Ad esempio, downloadSubscription
potrebbe non riuscire se i metadati del profilo indicano che è richiesto un codice di conferma dell'operatore. oppure switchToSubscription
potrebbe non riuscire se l'app dell'operatore ha privilegi
sull'operatore sul profilo di destinazione (ovvero l'operatore è proprietario del profilo), ma
non ha privilegi dell'operatore sul profilo attualmente abilitato e quindi
è necessario il consenso dell'utente.
Per questi casi, il callback del chiamante viene chiamato con
EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR
. Il callback
Intent
contiene extra interni in modo che quando il chiamante lo passa a
EuiccManager#startResolutionActivity
,
la risoluzione possa essere richiesta tramite la LUI. Utilizzando di nuovo il codice di conferma, ad esempio, EuiccManager#startResolutionActivity
viene visualizzata una schermata LUI che consente all'utente di inserire un codice di conferma; dopo aver inserito il codice, l'operazione di download viene ripresa. Questo approccio
offre all'app dell'operatore il controllo completo su quando viene visualizzata la UI, ma fornisce
all'LPA/LUI un metodo estensibile per aggiungere in futuro una nuova gestione dei problemi recuperabili dall'utente senza dover modificare le app client.
Android 9 definisce questi errori risolvibili in
EuiccService
,
che l'interfaccia utente locale deve gestire:
/**
* 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";
Privilegi del corriere
Se sei un operatore che sviluppa la propria app operatore che chiama EuiccManager
per scaricare i profili su un dispositivo, i metadati del tuo profilo devono includere
le regole dei privilegi dell'operatore corrispondenti alla tua app operatore. Questo perché
i profili di abbonamento appartenenti a operatori diversi possono coesistere
nell'eUICC di un dispositivo e ogni app operatore deve avere l'autorizzazione di accedere solo ai
profili di proprietà di quell'operatore. Ad esempio, l'operatore A non deve essere in grado di
scaricare, attivare o disattivare un profilo di proprietà dell'operatore B.
Per garantire che un profilo sia accessibile solo al suo proprietario, Android utilizza un meccanismo per
concedere privilegi speciali all'app del proprietario del profilo (ovvero l'app dell'operatore). La
piattaforma Android carica i certificati archiviati nel file delle regole di accesso (ARF) del profilo
e concede alle app firmate da questi certificati l'autorizzazione a effettuare chiamate
alle API EuiccManager
. La procedura generale è descritta di seguito:
- L'operatore firma l'APK dell'app dell'operatore; lo strumento apksigner collega il certificato della chiave pubblica all'APK.
L'operatore/SM-DP+ prepara un profilo e i relativi metadati, che includono un ARF che contiene:
- Firma (SHA-1 o SHA-256) del certificato della chiave pubblica dell'app dell'operatore (obbligatorio)
- Nome del pacchetto dell'app dell'operatore (consigliato vivamente)
L'app dell'operatore tenta di eseguire un'operazione eUICC con l'API
EuiccManager
.La piattaforma Android verifica che l'hash SHA-1 o SHA-256 del certificato dell'app chiamante corrisponda alla firma del certificato ottenuto dal file ARF del profilo di destinazione. Se il nome del pacchetto dell'app dell'operatore è incluso nel file ARF, deve corrispondere anche al nome del pacchetto dell'app chiamante.
Una volta verificata la firma e il nome del pacchetto (se incluso), il privilegio dell'operatore viene concesso all'app chiamante sul profilo di destinazione.
Poiché i metadati del profilo possono essere disponibili al di fuori del profilo stesso (in modo che LPA possa recuperare i metadati del profilo da SM-DP+ prima che il profilo venga scaricato o da ISD-R quando il profilo è disattivato), devono contenere le stesse regole di privilegio dell'operatore del profilo.
Il sistema operativo eUICC e SM-DP+ devono supportare un tag proprietario BF76
nei metadati del profilo. Il contenuto del tag deve essere uguale alle regole dei privilegi dell'operatore restituite
dall'applet della regola di accesso (ARA) definita in
Privilegi dell'operatore UICC:
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
}
}
Per ulteriori dettagli sulla firma dell'app, vedi Firma la tua app. Per dettagli sui privilegi dell'operatore, vedi Privilegi dell'operatore UICC.
Creare un'app assistente per il profilo locale
I produttori di dispositivi possono implementare il proprio assistente del profilo locale (LPA), che deve essere collegato alle API Euicc di Android. Le sezioni seguenti forniscono una breve panoramica della creazione di un'app LPA e della sua integrazione con il sistema Android.
Requisiti hardware/modem
L'LPA e il sistema operativo eSIM sul chip eUICC devono supportare almeno GSMA RSP (Remote SIM Provisioning) v2.0 o v2.2. Devi anche prevedere di utilizzare server SM-DP+ e SM-DS con una versione RSP corrispondente. Per l'architettura RSP dettagliata, vedi GSMA SGP.21 RSP Architecture Specification.
Inoltre, per l'integrazione con le API eUICC in Android 9, il modem del dispositivo deve inviare le funzionalità del terminale con il supporto delle funzionalità eUICC codificate (gestione dei profili locali e download dei profili). Deve inoltre implementare i seguenti metodi:
- IRadio HAL v1.1:
setSimPower
IRadio HAL v1.2:
getIccCardStatus
IRadioConfig HAL v1.0:
getSimSlotsStatus
IRadioConfig AIDL v1.0:
getAllowedCarriers
L'LPA di Google deve conoscere lo stato di blocco dell'operatore per consentire il download o il trasferimento dell'eSIM solo per l'operatore consentito. In caso contrario, gli utenti potrebbero scaricare e trasferire una SIM e rendersi conto in un secondo momento che il dispositivo è bloccato su un altro operatore.
I fornitori o gli OEM devono implementare l'API HAL IRadioSim.getAllowedCarriers().
Il modem / RIL del fornitore deve compilare lo stato di blocco e l'ID operatore dell'operatore a cui è bloccato il dispositivo nell'ambito dell'API HAL IRadioSimResponse.getAllowedCarriersResponse().
Il modem dovrebbe riconoscere l'eSIM con il profilo di avvio predefinito attivato come SIM valida e mantenere l'alimentazione della SIM attiva.
Per i dispositivi con Android 10, deve essere definito un array di ID slot eUICC non rimovibili. Ad esempio, vedi
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>
Per un elenco completo dei requisiti del modem, consulta Requisiti del modem per il supporto dell'eSIM.
EuiccService
Un LPA è costituito da due componenti separati (possono essere implementati entrambi nello stesso APK): il backend LPA e la UI LPA o LUI.
Per implementare il backend LPA, devi estendere
EuiccService
e dichiarare questo servizio nel file manifest. Il servizio deve richiedere l'autorizzazione di sistema android.permission.BIND_EUICC_SERVICE
per garantire che solo il sistema possa associarsi. Il servizio deve includere anche un filtro per intent con
l'azione android.service.euicc.EuiccService
. La priorità del filtro
dell'intent deve essere impostata su un valore diverso da zero nel caso in cui sul dispositivo siano presenti più implementazioni. Ad esempio:
<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>
A livello interno, il framework Android determina l'LPA attivo e interagisce con
questo in base alle necessità per supportare le API eUICC di Android. PackageManager
viene interrogato per
tutte le app con l'autorizzazione android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS
,
che specifica un servizio per l'azione android.service.euicc.EuiccService
.
Viene selezionato il servizio con la priorità più alta. Se non viene trovato alcun servizio, il supporto LPA
è disattivato.
Per implementare l'interfaccia utente vocale, devi fornire un'attività per le seguenti azioni:
android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS
android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION
Come per il servizio, ogni attività deve richiedere l'autorizzazione di sistema android.permission.BIND_EUICC_SERVICE
. Ciascuno deve avere un
filtro per intent con l'azione appropriata, la
categoria android.service.euicc.category.EUICC_UI
e una priorità diversa da zero.
Per scegliere le implementazioni per queste attività viene utilizzata una logica simile a quella utilizzata per scegliere l'implementazione di
EuiccService
.
Ad esempio:
<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>
Ciò implica che la UI che implementa queste schermate può provenire da un APK diverso da quello che implementa EuiccService
.
La scelta di avere un singolo APK o più APK (ad esempio, uno che implementa
EuiccService
e uno che fornisce attività LUI) è una decisione di progettazione.
EuiccCardManager
EuiccCardManager
è l'interfaccia per comunicare con il chip eSIM. Fornisce funzioni ES10 (come descritto nella specifica GSMA RSP) e gestisce i comandi di richiesta/risposta APDU di basso livello, nonché l'analisi ASN.1.
EuiccCardManager
è un'API di sistema e può essere chiamata solo da app con privilegi di sistema.
Figura 2. Sia l'app dell'operatore sia l'LPA utilizzano le API Euicc
Le API di operazioni sul profilo tramite EuiccCardManager
richiedono che il chiamante sia
un LPA. Questo limite viene applicato dal framework Android. Ciò significa che il chiamante deve
estendere EuiccService
ed essere dichiarato nel file manifest, come descritto nelle
sezioni precedenti.
Analogamente a EuiccManager
, per utilizzare le API EuiccCardManager
, il tuo LPA deve
prima ottenere l'istanza di EuiccCardManager
tramite
Context#getSystemService
:
EuiccCardManager cardMgr = (EuiccCardManager) context.getSystemService(Context.EUICC_CARD_SERVICE);
Poi, per ottenere tutti i profili sull'eUICC:
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);
Internamente, EuiccCardManager
si associa a EuiccCardController
(che viene eseguito nel processo del telefono) tramite un'interfaccia AIDL e ogni metodo EuiccCardManager
riceve il callback dal processo del telefono tramite un'interfaccia AIDL dedicata diversa. Quando utilizzi le API EuiccCardManager
, il chiamante (LPA) deve fornire un oggetto
Executor
tramite il quale viene richiamato il callback. Questo oggetto Executor
può essere eseguito su un singolo thread o su un pool di thread a tua scelta.
La maggior parte delle API EuiccCardManager
ha lo stesso pattern di utilizzo. Ad esempio, per caricare un pacchetto
di profili associati sull'eUICC:
...
cardMgr.loadBoundProfilePackage(eid, boundProfilePackage,
AsyncTask.THREAD_POOL_EXECUTOR, callback);
Per passare a un altro profilo con un determinato ICCID:
...
cardMgr.switchToProfile(eid, iccid, true /* refresh */,
AsyncTask.THREAD_POOL_EXECUTOR, callback);
Per ottenere l'indirizzo SM-DP+ predefinito dal chip eUICC:
...
cardMgr.requestDefaultSmdpAddress(eid, AsyncTask.THREAD_POOL_EXECUTOR,
callback);
Per recuperare un elenco di notifiche degli eventi di notifica specificati:
...
cardMgr.listNotifications(eid,
EuiccNotification.Event.INSTALL
| EuiccNotification.Event.DELETE /* events */,
AsyncTask.THREAD_POOL_EXECUTOR, callback);
Attivare un profilo eSIM tramite l'app di un operatore
Sui dispositivi con Android 9 o versioni successive, puoi utilizzare un'app dell'operatore per attivare
l'eSIM e scaricare i profili. L'app dell'operatore può scaricare i profili
chiamando
downloadSubscription
direttamente o fornendo un codice di attivazione all'LPA.
Quando un'app operatore scarica un profilo chiamando
downloadSubscription
,
la chiamata impone che l'app possa gestire il profilo tramite un BF76
tag di metadati
che codifica le regole dei privilegi dell'operatore per il
profilo. Se un profilo non ha un tag BF76
o se il suo tag BF76
non
corrisponde alla firma dell'app dell'operatore chiamante, il download viene rifiutato.
La sezione seguente descrive l'attivazione di una eSIM tramite l'app di un operatore utilizzando un codice di attivazione.
Attivare l'eSIM utilizzando un codice di attivazione
Quando si utilizza un codice di attivazione per attivare un profilo eSIM, l'LPA recupera
un codice di attivazione dall'app dell'operatore e scarica il profilo. Questo flusso può essere avviato dall'LPA
e l'LPA può controllare l'intero flusso dell'interfaccia utente, il che significa che non viene
visualizzata l'interfaccia utente dell'app dell'operatore. Questo approccio aggira il controllo del tag BF76
e gli operatori di rete non
devono implementare l'intero flusso dell'UI di attivazione dell'eSIM, incluso il download di un
profilo eSIM e la gestione degli errori.
Definisci il servizio di provisioning eUICC dell'operatore
L'app LPA e l'app operatore comunicano tramite due interfacce
AIDL:
ICarrierEuiccProvisioningService
e IGetActivationCodeCallback
. L'app dell'operatore
deve implementare un'interfaccia ICarrierEuiccProvisioningService
ed
esporla nella
dichiarazione del manifest.
L'LPA deve essere associato a ICarrierEuiccProvisioningService
e implementare
IGetActivationCodeCallback
. Per ulteriori informazioni su come implementare ed
esporre un'interfaccia AIDL, consulta Definizione di un'interfaccia AIDL.
Per definire le interfacce AIDL, crea i seguenti file AIDL sia per l'app LPA sia per l'app dell'operatore.
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(); }
Esempio di implementazione di LPA
Per eseguire il binding all'implementazione di ICarrierEuiccProvisioningService
dell'app operatore,
l'LPA deve copiare sia ICarrierEuiccProvisioningService.aidl
sia
IGetActivationCodeCallback.aidl
nel tuo progetto e implementare
ServiceConnection
.
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mCarrierProvisioningService = ICarrierEuiccProvisioningService.Stub.asInterface(iBinder);
}
Dopo il binding all'implementazione ICarrierEuiccProvisioningService
dell'app dell'operatore, l'LPA chiama getActivationCode
o
getActivationCodeForEid
per ottenere il codice di attivazione dall'app dell'operatore
passando l'implementazione della classe stub IGetActivationCodeCallback
.
La differenza tra getActivationCode
e getActivationCodeForEid
è che
getActivationCodeForEid
consente a un operatore di pre-associare un profilo all'EID
del dispositivo prima dell'inizio della procedura di download.
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
}
}
Esempio di implementazione per l'app dell'operatore
Affinché LPA si associ all'app dell'operatore, quest'ultima deve copiare sia ICarrierEuiccProvisioningService.aidl
sia IGetActivationCodeCallback.aidl
nel tuo progetto e dichiarare il servizio ICarrierEuiccProvisioningService
nel file AndroidManifest.xml
. Il servizio deve richiedere l'autorizzazione di sistema
android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS
per garantire
che solo l'LPA, un'app con privilegi di sistema, possa associarsi. Il servizio deve
includere anche un filtro per intent con l'azione
android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE
.
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>
Per implementare il servizio dell'app operatore AIDL, crea un servizio, estendi la classe Stub
e implementa i metodi getActivationCode
e getActivationCodeForEid
. L'LPA può quindi chiamare uno dei due metodi per recuperare il codice di attivazione del profilo. L'app dell'operatore deve rispondere chiamando
IGetActivationCodeCallback#onSuccess
con il codice di attivazione se il codice è stato
recuperato correttamente dal server dell'operatore. In caso di esito negativo, l'app dell'operatore
deve rispondere con IGetActivationCodeCallback#onFailure
.
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); } } }
Avvia l'interfaccia utente dell'app dell'operatore nel flusso di attivazione LPA
Sui dispositivi con Android 11 e versioni successive, l'LPA può avviare la UI di un'app operatore. Ciò è utile in quanto un'app operatore potrebbe richiedere informazioni aggiuntive all'utente prima di fornire un codice di attivazione all'LPA. Ad esempio, gli operatori potrebbero richiedere agli utenti di accedere per attivare i propri numeri di telefono o eseguire altri servizi di trasferimento.
Questa è la procedura per avviare la UI di un'app operatore in LPA:
L'LPA avvia il flusso di attivazione dell'app dell'operatore inviando l'intent
android.service.euicc.action.START_CARRIER_ACTIVATION
al pacchetto dell'app dell'operatore contenente l'azione. (Il ricevitore dell'app dell'operatore deve essere protetto nella dichiarazione del manifest conandroid:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
per evitare di ricevere intent da app non LPA.)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);
L'app dell'operatore svolge il suo lavoro utilizzando la propria UI. Ad esempio, l'accesso dell'utente o l'invio di richieste HTTP al backend dell'operatore.
L'app dell'operatore risponde all'LPA chiamando
setResult(int, Intent)
efinish()
.- Se l'app dell'operatore risponde con
RESULT_OK
, l'LPA continua il flusso di attivazione. Se l'app dell'operatore determina che l'utente deve scansionare un codice QR anziché consentire all'LPA di associare il servizio dell'app dell'operatore, l'app dell'operatore risponde all'LPA utilizzandosetResult(int, Intent)
conRESULT_OK
e un'istanzaIntent
contenente l'extra booleanoandroid.telephony.euicc.extra.USE_QR_SCANNER
impostato sutrue
. L'LPA controlla quindi l'extra e avvia lo scanner QR anziché eseguire il binding dell'implementazioneICarrierEuiccProvisioningService
dell'app operatore. - Se l'app dell'operatore va in arresto anomalo o risponde con
RESULT_CANCELED
(questo è il codice di risposta predefinito), l'LPA annulla il flusso di attivazione della eSIM. - Se l'app dell'operatore risponde con un valore diverso da
RESULT_OK
oRESULT_CANCELED
, l'LPA lo considera un errore.
Per motivi di sicurezza, l'LPA non deve accettare direttamente un codice di attivazione fornito nell'intent del risultato per garantire che i chiamanti non LPA non possano ottenere un codice di attivazione dall'app dell'operatore.
- Se l'app dell'operatore risponde con
Avviare il flusso di attivazione LPA in un'app operatore
A partire da Android 11, le app degli operatori possono utilizzare le API eUICC per avviare un'interfaccia utente di livello basso per l'attivazione dell'eSIM. Questo metodo mostra l'interfaccia utente del flusso di attivazione eSIM dell'LPA per attivare il profilo eSIM. L'LPA invia quindi una trasmissione al termine dell'attivazione del profilo eSIM.
L'LPA deve dichiarare un'attività che includa un filtro per intent con l'azione
android.service.euicc.action.START_EUICC_ACTIVATION
. La priorità del filtro per intent deve essere impostata su un valore diverso da zero nel caso in cui sul dispositivo siano presenti più implementazioni. Ad esempio:<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>
L'app dell'operatore svolge il suo lavoro utilizzando la propria UI. Ad esempio, l'accesso dell'utente o l'invio di richieste HTTP al backend dell'operatore.
A questo punto, l'app dell'operatore deve essere pronta a fornire un codice di attivazione tramite la sua implementazione
ICarrierEuiccProvisioningService
. L'app dell'operatore avvia l'LPA chiamandostartActivityForResult(Intent, int)
con l'azioneandroid.telephony.euicc.action.START_EUICC_ACTIVATION
. L'LPA controlla anche l'extra booleanoandroid.telephony.euicc.extra.USE_QR_SCANNER
. Se il valore ètrue
, l'LPA avvia lo scanner QR per consentire all'utente di scansionare il codice QR del profilo.Sul lato LPA, l'LPA si lega all'implementazione
ICarrierEuiccProvisioningService
dell'app dell'operatore per recuperare il codice di attivazione e scaricare il profilo corrispondente. L'LPA mostra tutti gli elementi dell'interfaccia utente necessari durante il download, ad esempio una schermata di caricamento.Al termine del flusso di attivazione della LPA, quest'ultima risponde all'app dell'operatore con un codice di risultato, che l'app dell'operatore gestisce in
onActivityResult(int, int, Intent)
.- Se l'LPA riesce a scaricare il nuovo profilo eSIM, risponde con
RESULT_OK
. - Se l'utente annulla l'attivazione del profilo eSIM nell'LPA, viene restituito
RESULT_CANCELED
. - Se l'LPA risponde con un valore diverso da
RESULT_OK
oRESULT_CANCELED
, l'app dell'operatore lo considera un errore.
Per motivi di sicurezza, l'LPA non accetta un codice di attivazione direttamente nell'intent fornito per garantire che i chiamanti non LPA non possano ottenere il codice di attivazione dall'app dell'operatore.
- Se l'LPA riesce a scaricare il nuovo profilo eSIM, risponde con
Supportare più eSIM
Per i dispositivi con Android 10 o versioni successive, la classe
EuiccManager
supporta i dispositivi
con più eSIM. I dispositivi con una sola eSIM che eseguono l'upgrade ad Android 10 non richiedono alcuna modifica all'implementazione LPA, in quanto la piattaforma associa automaticamente l'istanza EuiccManager
all'eUICC predefinita. L'eUICC
predefinita è determinata dalla piattaforma per i dispositivi con versione HAL radio
1.2 o successive e dall'LPA per i dispositivi con versioni HAL radio precedenti
alla 1.2.
Requisiti
Per supportare più eSIM, il dispositivo deve avere più di un'eUICC, che può essere un'eUICC integrata o uno slot SIM fisico in cui è possibile inserire eUICC rimovibili.
Per supportare più eSIM è richiesta la versione 1.2 o successive di Radio HAL. Si consiglia la versione 1.4 di Radio HAL e la versione 1.2 di RadioConfig HAL.
Implementazione
Per supportare più eSIM (incluse eUICCs rimovibili o SIM programmabili), l'LPA deve implementare
EuiccService
,
che riceve l'ID slot corrispondente all'ID scheda fornito dal chiamante.
La risorsa
non_removable_euicc_slots
specificata in
arrays.xml
è un array di numeri interi che rappresentano gli ID slot delle eUICC integrate di un dispositivo. Devi specificare questa risorsa per consentire alla piattaforma di determinare
se una eUICC inserita è rimovibile o meno.
App dell'operatore per il dispositivo con più eSIM
Quando crei un'app operatore per un dispositivo con più eSIM, utilizza il
metodo createForCardId
in EuiccManager
per creare un oggetto EuiccManager
bloccato a un
determinato ID carta. L'ID scheda è un valore intero che identifica in modo univoco una UICC
o una eUICC sul dispositivo.
Per ottenere l'ID della scheda per l'eUICC predefinita del dispositivo, utilizza il metodo
getCardIdForDefaultEuicc
in TelephonyManager
. Questo metodo restituisce
UNSUPPORTED_CARD_ID
se la versione HAL radio è precedente alla 1.2 e restituisce
UNINITIALIZED_CARD_ID
se il dispositivo non ha letto l'eUICC.
Puoi anche ottenere gli ID delle schede da
getUiccCardsInfo
e getUiccSlotsInfo
(API di sistema) in TelephonyManager
e
getCardId
in SubscriptionInfo
.
Quando un oggetto EuiccManager
è stato istanziato con un ID scheda specifico, tutte le operazioni vengono indirizzate all'eUICC con quell'ID scheda. Se l'eUICC diventa
irraggiungibile (ad esempio, quando viene spenta o rimossa), EuiccManager
non
funziona più.
Puoi utilizzare i seguenti esempi di codice per creare un'app operatore.
Esempio 1: recupera l'abbonamento attivo e crea un'istanza di EuiccManager
// 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);
Esempio 2: esegui l'iterazione tra le UICC e crea un'istanza di EuiccManager
per una
eUICC rimovibile
// 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);
}
Convalida
AOSP non include un'implementazione LPA e non è previsto che sia disponibile un LPA su tutte le build Android (non tutti gli smartphone supportano l'eSIM). Per questo motivo, non esistono scenari di test CTS end-to-end. Tuttavia, in AOSP sono disponibili casi di test di base per garantire che le API eUICC esposte siano valide nelle build di Android.
Devi assicurarti che le build superino i seguenti scenari di test CTS (per le API pubbliche): /platform/cts/tests/tests/telephony/current/src/android/telephony/euicc/cts.
Gli operatori che implementano un'app operatore devono eseguire i normali cicli interni di controllo qualità per assicurarsi che tutte le funzionalità implementate funzionino come previsto. Come minimo, l'app dell'operatore deve essere in grado di elencare tutti i profili di abbonamento di proprietà dello stesso operatore, scaricare e installare un profilo, attivare un servizio sul profilo, passare da un profilo all'altro ed eliminare i profili.
Se crei il tuo LPA, devi sottoporti a test molto più rigorosi. Devi collaborare con il fornitore del modem, del chip eUICC o del sistema operativo eSIM, con i fornitori SM-DP+ e con gli operatori per risolvere i problemi e garantire l'interoperabilità del tuo LPA nell'architettura RSP. Una buona quantità di test manuali è inevitabile. Per una copertura ottimale dei test, devi seguire il piano di test GSMA SGP.23 RSP.