La tecnologia Embedded SIM (eSIM o eUICC) consente agli utenti di dispositivi mobili di scaricare un profilo dell'operatore e attivare il servizio di un operatore senza avere una scheda SIM fisica. Si tratta di una specifica globale creata 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 all'eSIM e gestire i profili degli abbonamenti sull'eSIM. Queste API eUICC consentono a terze parti di sviluppare le proprie app dell'operatore e gli assistenti per i profili locali (LPA) sui dispositivi Android con eSIM.
L'LPA è un'app di sistema autonoma che deve essere inclusa nell'immagine di compilazione Android. La gestione dei profili sull'eSIM viene generalmente eseguita dall'LPA, in quanto funge da ponte tra SM-DP+ (servizio remoto che prepara, memorizza e carica i pacchetti di profili sui dispositivi) e il chip eUICC. L'APK LPA può includere facoltativamente un componente dell'interfaccia utente, chiamato LPA UI o LUI, per fornire all'utente finale un punto di riferimento centrale per gestire tutti i profili di abbonamento incorporati. Il framework Android rileva e si connette automaticamente al miglior LPA disponibile e inoltra tutte le operazioni eUICC tramite un'istanza LPA.
Figura 1. Architettura RSP semplificata
Gli operatori di rete mobile interessati a creare un'app dell'operatore devono esaminare le API in EuiccManager
, che forniscono 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, è consigliabile utilizzare le API in EuiccCardManager
, che forniscono funzioni ES10x basate su GSMA RSP v2.0.
Queste funzioni vengono utilizzate per emettere comandi al chip eUICC, ad esempio prepareDownload()
, loadBoundProfilePackage()
, retrieveNotificationList()
e resetMemory()
.
Le API in
EuiccManager
richiedono un'app LPA implementata correttamente per funzionare e l'autore della chiamata delle API
EuiccCardManager
deve essere un'app LPA. Questo viene applicato dal framework Android.
I dispositivi con Android 10 o versioni successive possono supportare dispositivi con più eSIM. Per maggiori informazioni, vedi Supporto di più eSIM.
Creare un'app dell'operatore
Le API eUICC in Android 9 consentono agli operatori di rete mobile di creare app con brand dell'operatore per gestire direttamente i propri profili. Ciò include il download e l'eliminazione dei profili degli abbonamenti di proprietà dell'operatore, nonché il passaggio a un profilo di proprietà di un operatore.
EuiccManager
EuiccManager
è il punto di accesso principale delle app all'LPA. Sono incluse le app dell'operatore che scaricano, eliminano e passano abbonamenti di proprietà dell'operatore. È inclusa anche l'app di sistema LUI, che
fornisce una posizione/UI 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 dell'operatore deve prima ottenere l'istanza di
EuiccManager
tramite Context#getSystemService
:
EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
Prima di eseguire qualsiasi operazione eSIM, devi verificare se l'eSIM è supportata sul dispositivo. EuiccManager#isEnabled()
in genere restituisce true
se
la funzionalità android.hardware.telephony.euicc
è definita e è presente un pacchetto LPA.
if (mgr == null || !mgr.isEnabled()) {
return;
}
Per 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 callback
PendingIntent
perché il loro completamento può richiedere secondi o addirittura minuti.
PendingIntent
viene inviato con un codice di risultato nello spazio EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_
, che fornisce codici di errore definiti dal framework, nonché un codice di risultato dettagliato arbitrario propagato dall'LPA come EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE
, consentendo all'app dell'operatore di monitorare per scopi di logging/debug. Il callback PendingIntent
debe essere BroadcastReceiver
.
Per scaricare un abbonamento scaricabile (creato da un codice di attivazione o da 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 in base all'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 delle 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 è necessario un codice di conferma dell'operatore. In alternativa, switchToSubscription
potrebbe non funzionare se l'app dell'operatore dispone dei privilegi dell'operatore sul profilo di destinazione (ovvero, l'operatore è proprietario del profilo), ma non dispone dei privilegi dell'operatore rispetto al profilo attualmente attivato, pertanto è richiesto il consenso dell'utente.
In questi casi, il callback dell'autore della chiamata 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. L'utilizzo del codice di conferma,
ad esempio,
EuiccManager#startResolutionActivity
attiva 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 sul momento in cui viene visualizzata l'interfaccia utente, ma fornisce all'LPA/LUI un metodo estendibile per aggiungere in futuro una nuova gestione dei problemi recuperabili dall'utente senza che sia necessario modificare le app client.
Android 9 definisce questi errori risolvibili in
EuiccService
,
che la LUI dovrebbe 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 che chiama EuiccManager
per scaricare i profili su un dispositivo, il tuo profilo deve includere le regole dei privilegi dell'operatore corrispondenti all'app dell'operatore nei metadati. Questo accade perché i profili degli abbonamenti appartenenti a diversi operatori possono coesistere nell'eUICC di un dispositivo e ogni app dell'operatore deve poter accedere solo ai profili di proprietà dell'operatore in questione. 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 memorizzati nel file delle regole di accesso (ARF) del profilo e concede alle app firmate da questi certificati l'autorizzazione per effettuare chiamate alle API EuiccManager
. La procedura di alto livello è descritta di seguito:
- L'operatore firma l'APK dell'app dell'operatore. Lo strumento apksigner associa il certificato della chiave pubblica all'APK.
L'operatore/l'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 (fortemente consigliato)
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 dall'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.
Dopo aver verificato la firma e il nome del pacchetto (se incluso), il privilegio dell'operatore viene concesso all'app chiamante per il profilo di destinazione.
Poiché i metadati del profilo possono essere disponibili al di fuori del profilo stesso (in modo che l'LPA possa recuperare i metadati del profilo da SM-DP+ prima che il profilo venga scaricato o da ISD-R quando il profilo è disattivato), deve contenere le stesse regole dei privilegi dell'operatore presenti nel profilo.
Il sistema operativo eUICC e SM-DP+ devono supportare un tag proprietario BF76
nei metadati del profilo. I contenuti del tag devono essere gli stessi delle regole dei privilegi dell'operatore restituite dall'applet di regole di accesso (ARA) definito 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 maggiori dettagli sulla firma dell'app, vedi Firmare l'app. Per maggiori dettagli sui privilegi dell'operatore, vedi Privilegi operatore UICC.
Crea un'app di assistente del profilo locale
I produttori di dispositivi possono implementare il proprio assistente per i profili locali (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. Inoltre, ti consigliamo di utilizzare server SM-DP+ e SM-DS con una versione RSP corrispondente. Per un'architettura RSP dettagliata, consulta la specifica dell'architettura RSP GSMA SGP.21.
Inoltre, per l'integrazione con le API eUICC in Android 9, il modem del dispositivo deve inviare le funzionalità del terminale con il supporto per le funzionalità eUICC codificate (gestione del profilo locale e download del profilo). Inoltre, deve 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 del blocco dell'operatore per poter consentire il download o il trasferimento dell'eSIM solo per l'operatore consentito. In caso contrario, gli utenti potrebbero scaricare e trasferire una SIM per poi rendersi conto che il dispositivo è bloccato su un operatore diverso.
I fornitori o gli OEM devono implementare l'API HAL IRadioSim.getAllowedCarriers().
Il fornitore RIL / Modem 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 abilitato come SIM valida e mantenere la SIM accesa.
Per i dispositivi con Android 10, è necessario definire un array di ID slot eUICC non rimovibili. Ad esempio, consulta
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, vedi Requisiti del modem per l'assistenza eSIM.
EuiccService
Un'LPA è composta da due componenti distinti (possono essere entrambi implementati nello stesso APK): il backend LPA e l'interfaccia utente 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 eseguire l'associazione al servizio. Il servizio deve includere anche un filtro per intent con
l'azione android.service.euicc.EuiccService
. 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:
<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>
Internamente, il framework Android determina l'LPA attivo e vi interagisce
se necessario per supportare le API Android eUICC. Viene richiesta una query su PackageManager
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 viene disattivato.
Per implementare la LUI, 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 di intent con l'azione appropriata, la categoria android.service.euicc.category.EUICC_UI
e una priorità diversa da zero.
Per scegliere le implementazioni di 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 l'interfaccia utente che implementa queste schermate può provenire da un APK diverso da quello che implementa EuiccService
.
È una scelta di design disporre di un singolo APK o di più APK (ad esempio, uno che implementa
EuiccService
e uno che fornisce attività LUI).
EuiccCardManager
EuiccCardManager
è l'interfaccia per la comunicazione con il chip eSIM. Fornisce funzioni ES10 (come descritto nelle specifiche RSP GSMA) e gestisce i comandi di richiesta/risposta dell'APDU di basso livello, nonché l'analisi ASN.1.
EuiccCardManager
è un'API di sistema e può essere chiamata solo da applicazioni 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 chi chiama sia un LPA. Questa operazione viene applicata dal framework Android. Ciò significa che il chiamante deve estendere EuiccService
ed essere dichiarato nel file manifest, come descritto nelle sezioni precedenti.
Come per 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);
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 lega a EuiccCardController
(che viene eseguito nel
procedura dello smartphone) tramite un'interfaccia AIDL e ogni metodo EuiccCardManager
riceve il proprio callback dal processo dello smartphone tramite un'altra interfaccia AIDL dedicata. Quando utilizzi le API EuiccCardManager
, l'utente che chiama (LPA) deve fornire un oggetto
Executor
tramite il quale viene invocato 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 nella 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 relative agli eventi di notifica specificati:
...
cardMgr.listNotifications(eid,
EuiccNotification.Event.INSTALL
| EuiccNotification.Event.DELETE /* events */,
AsyncTask.THREAD_POOL_EXECUTOR, callback);
Attivare un profilo eSIM tramite un'app dell'operatore
Sui dispositivi con Android 9 o versioni successive, puoi utilizzare un'app dell'operatore per attivare la eSIM e scaricare i profili. L'app dell'operatore può scaricare i profili chiamando direttamente downloadSubscription
o fornendo un codice di attivazione all'LPA.
Quando un'app dell'operatore scarica un profilo chiamando
downloadSubscription
,
la chiamata impone che l'app possa gestire il profilo tramite un BF76
tag metadati
che codifica le regole dei privilegi dell'operatore per il
profilo. Se un profilo non ha un tag BF76
o se il relativo tag BF76
non corrisponde alla firma dell'app dell'operatore che effettua la chiamata, il download viene rifiutato.
La sezione seguente descrive l'attivazione di un'eSIM tramite un'app dell'operatore utilizzando un codice di attivazione.
Attiva l'eSIM usando 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, che può controllare l'intero flusso dell'interfaccia utente, il che significa che non viene visualizzata alcuna 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'interfaccia utente 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 dell'operatore comunicano tramite due interfacce AIDL:ICarrierEuiccProvisioningService
e IGetActivationCodeCallback
. L'app dell'operatore deve implementare un'interfaccia ICarrierEuiccProvisioningService
e metterla in evidenza nella dichiarazione manifest.
L'LPA deve essere associata a ICarrierEuiccProvisioningService
e implementare
IGetActivationCodeCallback
. Per ulteriori informazioni su come implementare ed
esporre un'interfaccia AIDL, consulta Definizione e interfaccia AIDL.
Per definire le interfacce AIDL, crea i seguenti file AIDL sia per le app LPA sia per quelle 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 dell'operatore,
l'LPA deve copiare sia ICarrierEuiccProvisioningService.aidl
sia
IGetActivationCodeCallback.aidl
nel progetto e implementare
ServiceConnection
.
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mCarrierProvisioningService = ICarrierEuiccProvisioningService.Stub.asInterface(iBinder);
}
Dopo l'associazione 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 i criteri getActivationCode
e getActivationCodeForEid
è che
getActivationCodeForEid
consente a un operatore di associare un profilo all'EID
del dispositivo prima dell'inizio del processo 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é l'LPA possa essere associato all'app dell'operatore, l'app dell'operatore deve copiare ICarrierEuiccProvisioningService.aidl
e 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'app con privilegi di sistema possa essere associata all'LPA. 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 dell'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 dovrebbe rispondere chiamando IGetActivationCodeCallback#onSuccess
con il codice di attivazione se il codice è stato recuperato dal server dell'operatore. In caso di esito negativo, l'app dell'operatore dovrebbe 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 dell'LPA
Sui dispositivi con Android 11 e versioni successive, l'LPA può avviare l'UI dell'app di un operatore. Questo è utile perché un'app dell'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 eseguire l'accesso per attivare i propri numeri di telefono o eseguire altri servizi di portabilità.
Questa è la procedura per avviare l'interfaccia utente di un'app dell'operatore nell'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 destinatario dell'app dell'operatore deve essere protetto nella dichiarazione 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 la sua attività utilizzando la propria UI. Ad esempio, accedendo all'utente o inviando 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 prosegue il flusso di attivazione. Se l'app dell'operatore stabilisce 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é vincolare l'implementazioneICarrierEuiccProvisioningService
dell'app dell'operatore. - Se l'app dell'operatore si arresta in modo 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 tratta come un errore.
Per motivi di sicurezza, l'LPA non deve accettare direttamente un codice di attivazione fornito nell'intent del risultato per garantire che gli utenti che non sono LPA non possano ricevere un codice di attivazione dall'app dell'operatore.
- Se l'app dell'operatore risponde con
Avviare il flusso di attivazione LPA in un'app dell'operatore
A partire da Android 11, le app dell'operatore possono utilizzare le API eUICC per avviare una LUI per l'attivazione di 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 siano presenti più implementazioni sul dispositivo. 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 proprio 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 di
ICarrierEuiccProvisioningService
. L'app dell'operatore avvia l'LPA chiamandostartActivityForResult(Intent, int)
con l'azioneandroid.telephony.euicc.action.START_EUICC_ACTIVATION
. L'LPA controlla anche il valore booleano extraandroid.telephony.euicc.extra.USE_QR_SCANNER
. Se il valore ètrue
, il 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 necessari dell'interfaccia utente durante il download, ad esempio una schermata di caricamento.Al termine del flusso di attivazione dell'LPA, l'app risponde all'app dell'operatore con un codice di risultato, gestito dall'app dell'operatore 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, risponde con
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 gli utenti che chiamano da un altro LPA non possano ottenere il codice di attivazione dall'app dell'operatore.
- Se l'LPA riesce a scaricare il nuovo profilo eSIM, risponde con
Supporta più eSIM
Per i dispositivi con Android 10 o versioni successive, la classe EuiccManager
supporta dispositivi con più eSIM. I dispositivi con una singola eSIM che esegue l'upgrade ad
Android 10
non richiedono alcuna modifica all'implementazione LPA, poiché la piattaforma
associa automaticamente l'istanza EuiccManager
alla eUICC predefinita. L'eUICC predefinita è determinata dalla piattaforma per i dispositivi con versione radio HAL 1.2 o successive e dall'LPA per i dispositivi con versioni radio HAL precedenti alla 1.2.
Requisiti
Per supportare più eSIM, il dispositivo deve avere più di un eUICC, che può essere un eUICC integrato o uno slot per SIM fisico in cui possono essere inseriti eUICC rimovibili.
Per supportare più eSIM è necessaria la versione 1.2 o successive di Radio HAL. Si consigliano la versione 1.4 di Radio HAL e la versione 1.2 di RadioConfig HAL.
Implementazione
Per supportare più eSIM (incluse eUICC rimovibili o SIM programmabili), il fornitore di servizi di telefonia cellulare deve implementare EuiccService
, che riceve l'ID slot corrispondente all'ID carta fornito dall'utente che chiama.
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 un'eUICC inserita è rimovibile o meno.
App dell'operatore per un dispositivo con più eSIM
Quando crei un'app dell'operatore per un dispositivo con più eSIM, utilizza il metodo
createForCardId
in EuiccManager
per creare un oggetto EuiccManager
bloccato su un
determinato ID carta. L'ID carta è un valore intero che identifica in modo univoco una UICC o un'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 la eUICC.
Puoi anche recuperare gli ID carta da
getUiccCardsInfo
e getUiccSlotsInfo
(API di sistema) in TelephonyManager
, nonché da
getCardId
in SubscriptionInfo
.
Dopo aver creato un'istanza di un oggetto EuiccManager
con uno specifico ID carta, tutte
le operazioni vengono indirizzate all'eUICC con quell'ID carta. Se la eUICC diventa
irraggiungibile (ad esempio, quando viene disattivata o rimossa), EuiccManager
non funzionerà più.
Puoi usare i seguenti esempi di codice per creare un'app dell'operatore.
Esempio 1: attivare un abbonamento attivo e creare 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 delle UICC e crea un'istanza di EuiccManager
per un'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 di LPA e non è previsto che un LPA sia disponibile su tutte le build di Android (non tutti gli smartphone supportano eSIM). Per questo motivo, non sono disponibili 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 casi di test CTS (per le API pubbliche): /platform/cts/tests/tests/telephony/current/src/android/telephony/euicc/cts.
Gli operatori che implementano un'app per operatori devono seguire i normali cicli di controllo qualità interni 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 nel profilo, passare da un profilo all'altro ed eliminare i profili.
Se crei il tuo LPA, devi sottoporlo a test molto più rigorosi. Collabora con il tuo fornitore di modem, con il chip eUICC o con il fornitore del sistema operativo eSIM, con i fornitori SM-DP+ e con gli operatori per risolvere i problemi e garantire l'interoperabilità del tuo LPA all'interno dell'architettura RSP. È inevitabile una buona quantità di test manuali. Per una copertura ottimale dei test, devi seguire il GSMA SGP.23 RSP Test Plan.