Implementazione dell'eSIM

La tecnologia Embedded SIM (eSIM o eUICC) consente agli utenti mobili di scaricare un profilo di operatore e attivare il servizio di un operatore senza disporre di una scheda SIM fisica. È una specifica globale guidata dal 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 l'accesso all'eSIM e la gestione dei profili di abbonamento sull'eSIM. Queste API eUICC consentono a terzi di sviluppare le proprie applicazioni carrier e assistenti profilo locali (LPAs) sui dispositivi Android Esim abilitati.

LPA è un'app di sistema autonoma che dovrebbe essere inclusa nell'immagine di build di Android. La gestione dei profili sull'eSIM è generalmente svolta dall'LPA, in quanto funge da ponte tra l'SM-DP+ (servizio remoto che prepara, archivia e consegna i pacchetti di profili ai dispositivi) e il chip eUICC. L'APK LPA può includere facoltativamente un componente dell'interfaccia utente, chiamato UI LPA o LUI, per fornire all'utente finale una posizione centrale per la gestione di tutti i profili di abbonamento incorporati. Il framework Android rileva e si connette automaticamente al miglior LPA disponibile e instrada tutte le operazioni eUICC tramite un'istanza LPA.

Architettura Remote SIM Provisioning (RSP) semplificata

Architettura Figura 1. semplificato RSP

Operatori di reti mobili interessati a creare un'applicazione di supporto dovrebbero guardare le API in EuiccManager , che fornisce le operazioni di gestione del profilo di alto livello, come downloadSubscription() , switchToSubscription() , e deleteSubscription() .

Se sei un dispositivo OEM interessato a creare la propria applicazione del sistema LPA, è necessario estendere EuiccService per il framework Android per connettersi ai servizi LPA. Inoltre, è necessario utilizzare le API di EuiccCardManager , che forniscono funzioni ES10x basate su GSMA RSP v2.0. Queste funzioni sono utilizzate per impartire comandi al chip eUICC, come prepareDownload() , loadBoundProfilePackage() , retrieveNotificationList() , e resetMemory() .

Le API in EuiccManager richiedono un'applicazione LPA corretta applicazione alla funzione e il chiamante di EuiccCardManager API deve essere un LPA. Questo è imposto dal framework Android.

I dispositivi con Android 10 o versioni successive possono supportare dispositivi con più eSIM. Per ulteriori informazioni, vedere supporto di più ESIMS .

Creare un'app per operatori

Le API eUICC in Android 9 consentono agli operatori di rete mobile di creare app a marchio carrier 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à dell'operatore.

EuiccManager

EuiccManager è il principale punto di accesso per le applicazioni di interagire con il LPA. Ciò include le app dell'operatore che scaricano, eliminano e passano agli abbonamenti di proprietà dell'operatore. Questo include anche l'applicazione del sistema LUI, che fornisce una posizione / UI centrale per la gestione tutti gli abbonamenti integrati, e può essere un app separato da quello che fornisce EuiccService .

Per utilizzare le API pubbliche, un'applicazione vettore deve prima ottenere l'istanza di EuiccManager attraverso Context#getSystemService :

EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);

È necessario verificare se l'eSIM è supportata sul dispositivo prima di eseguire qualsiasi operazione eSIM. EuiccManager#isEnabled() ritorna generalmente true se android.hardware.telephony.euicc funzione è definita e un pacchetto di LPA è presente.

boolean isEnabled = mgr.isEnabled();
if (!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() , l'uso PendingIntent callback in quanto potrebbero prendere secondi o addirittura minuti per essere completato. PendingIntent viene inviato con un codice risultato nel EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_ spazio, che fornisce codici di errore quadro definito, nonché un codice risultato dettagliato arbitrario propagato dal LPA come EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE , consentendo l'applicazione carrier per monitorare per registrazione / debugging. Il PendingIntent callback deve essere BroadcastReceiver .

Per scaricare un dato di sottoscrizione 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*/);
                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);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent,
        PendingIntent.FLAG_UPDATE_CURRENT);
mgr.downloadSubscription(sub, true /* switchAfterDownload */,
        callbackIntent);

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);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent,
        PendingIntent.FLAG_UPDATE_CURRENT);
mgr.switchToSubscription(1 /* subscriptionId */, callbackIntent);

Per un elenco completo dei EuiccManager API e esempi di codice, vedere eUICC API .

Errori risolvibili

Ci sono alcuni casi in cui il sistema non è in grado di completare l'operazione eSIM ma l'errore può essere risolto dall'utente. Ad esempio, downloadSubscription può riuscire se i metadati profilo indica che è necessario un codice di conferma portante. O switchToSubscription potrebbe non riuscire se l'applicazione vettore ha privilegi di supporto sulle profilo di destinazione (che è, vettore possiede il profilo), ma non ha i privilegi di supporto sulle profilo attualmente abilitato, e quindi è necessaria l'autorizzazione dell'utente.

Per questi casi, richiamata del chiamante viene chiamato con EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR . Il callback Intent contiene extra interni in modo tale che, quando il chiamante passa al EuiccManager#startResolutionActivity , la risoluzione può essere richiesto tramite il LUI. Utilizzando il codice di conferma, ad esempio di nuovo, EuiccManager#startResolutionActivity innesca uno schermo LUI che permette all'utente di inserire un codice di conferma; dopo l'inserimento del codice, l'operazione di download riprende. Questo approccio fornisce all'app dell'operatore il pieno controllo su quando viene mostrata l'interfaccia utente, ma offre a LPA/LUI un metodo estensibile per aggiungere una nuova gestione dei problemi recuperabili dall'utente in futuro senza dover modificare le app client.

Android 9 definisce questi errori risolvibili in EuiccService , che 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 dell'operatore

Se sei un vettore sviluppare il proprio app vettore che chiama EuiccManager ai profili di download su un dispositivo, il vostro profilo dovrebbe includere norme di privilegio carrier corrispondenti alla vostra applicazione carrier nei metadati. Questo perché i profili di abbonamento appartenenti a diversi operatori possono coesistere nell'eUICC di un dispositivo e ogni app dell'operatore dovrebbe essere autorizzata ad accedere solo ai profili di proprietà di quel vettore. Ad esempio, l'operatore A non dovrebbe essere in grado di scaricare, abilitare o disabilitare 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). L'androide carichi piattaforma certificati archiviati nel file del profilo di regola di accesso (ARF) e concede il permesso alle applicazioni firmate da questi certificati di effettuare chiamate a EuiccManager API. Il processo di alto livello è descritto di seguito:

  1. L'operatore firma l'APK dell'app dell'operatore; l'apksigner strumento attribuisce il certificato a chiave pubblica per l'APK.
  2. Operatore/SM-DP+ prepara un profilo e i suoi metadati, che includono un ARF che contiene:

    1. Firma (SHA-1 o SHA-256) del certificato di chiave pubblica dell'app dell'operatore (obbligatorio)
    2. Nome del pacchetto dell'app del corriere (facoltativo)
  3. Carrier app tenta di eseguire un'operazione eUICC via EuiccManager API.

  4. 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 nell'ARF, deve corrispondere anche al nome del pacchetto dell'app del chiamante.

  5. Dopo che la firma e il nome del pacchetto (se incluso) sono stati verificati, il privilegio dell'operatore viene concesso all'app del 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 è disabilitato), dovrebbe contenere le stesse regole di privilegio dell'operatore come nel profilo.

L'eUICC sistema operativo e SM-DP + devono supportare un tag di proprietà BF76 nei metadati profilo. Il contenuto di tag dovrebbe essere le stesse regole vettore privilegio come restituito dal applet regola di accesso (ARA) definita in privilegi UICC Carrier :

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 su App firma, vedi Segno vostra applicazione . Per informazioni dettagliate sui privilegi di vettore, vedere Privilegi UICC Carrier .

Creare un'app LPA

Puoi implementare il tuo LPA, che deve essere collegato alle API di Android Euicc. Le sezioni seguenti forniscono una breve panoramica su come creare un'app LPA e integrarla con il sistema Android.

Requisiti hardware/modem

LPA e il sistema operativo eSIM sul chip eUICC devono supportare almeno GSMA RSP (Remote SIM Provisioning) v2.0 o v2.2. Dovresti anche pianificare l'utilizzo di server SM-DP+ e SM-DS con una versione RSP corrispondente. Per l'architettura dettagliata RSP, vedere GSMA SGP.21 RSP Architecture Specification .

Inoltre, per integrarsi 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). Deve inoltre implementare i seguenti metodi:

  • IRadio HAL v1.1: setSimPower
  • IRadio HAL v1.2: getIccCardStatus

  • IRadioConfig HAL v1.0: getSimSlotsStatus

Il modem dovrebbe riconoscere l'eSIM con il profilo di avvio predefinito abilitato come SIM valida e mantenere la SIM accesa.

Per i dispositivi che eseguono Android 10, è necessario definire un array ID slot eUICC non rimovibile. Ad esempio, vedere 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, vedere Requisiti del modem per ESIM Support .

EuiccService

Un LPA è costituito da due componenti separati (entrambi possono essere implementati nello stesso APK): il backend LPA e l'interfaccia utente o LUI LPA.

Per implementare il backend LPA, è necessario estendere EuiccService e dichiarare questo servizio nel file manifest. Il servizio deve richiedere l' android.permission.BIND_EUICC_SERVICE permesso di sistema per garantire che solo il sistema può legarsi ad esso. Il servizio deve includere anche un filtro di intenti con android.service.euicc.EuiccService azione. La priorità del filtro intent deve essere impostata su un valore diverso da zero nel caso in cui siano presenti più implementazioni sul dispositivo. Per 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 interagisce con esso in base alle esigenze per supportare le API eUICC di Android. PackageManager viene interrogato per tutte le applicazioni con android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS permesso, che specifica un servizio per android.service.euicc.EuiccService azione. Viene selezionato il servizio con la priorità più alta. Se non viene trovato alcun servizio, il supporto LPA è disabilitato.

Per implementare la LUI, è necessario 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' android.permission.BIND_EUICC_SERVICE permesso di sistema. Ciascuno dovrebbe avere un filtro intenti con l'azione appropriata, android.service.euicc.category.EUICC_UI categoria, e una priorità diverso da zero. Logica simile viene utilizzato per raccogliere le implementazioni per queste attività con la raccolta l'attuazione di EuiccService . Per 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>

Questo implica che l'IU attuazione questi schermi possono provenire da un'APK diversa da quella che implementa EuiccService . Se avere un unico APK o più APK (per esempio, uno che implementa EuiccService e uno che prevede attività LUI) è una scelta di design.

EuiccCardManager

EuiccCardManager è l'interfaccia per comunicare con il chip ESIM. Fornisce funzioni ES10 (come descritto nelle specifiche GSMA RSP) e gestisce i comandi di richiesta/risposta APDU di basso livello e l'analisi ASN.1. EuiccCardManager è un'API di sistema e può essere chiamato solo da applicazioni di sistema privilegiato.

App per operatori, LPA e API Euicc

Figura 2. Sia app portante ed uso LPA Euicc API

Le API di funzionamento profilo attraverso EuiccCardManager richiedono al chiamante di essere un LPA. Questo è imposto dal framework Android. Questo significa che il chiamante deve estendersi EuiccService ed essere dichiarato nel file manifest, come descritto nei paragrafi precedenti.

Simile a EuiccManager , di utilizzare EuiccCardManager API, il tuo LPA deve prima ottenere l'istanza di EuiccCardManager attraverso Context#getSystemService :

EuiccCardManager cardMgr = (EuiccCardManager) context.getSystemService(Context.EUICC_CARD_SERVICE);

Quindi, 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 lega al EuiccCardController (che viene eseguito nel processo telefono) tramite un'interfaccia AIDL, ed ogni EuiccCardManager metodo riceve la sua richiamata dal processo cellulare tramite un diverso, un'interfaccia AIDL dedicata. Quando si utilizza EuiccCardManager API, il chiamante (LPA) deve fornire un Executor oggetto attraverso cui viene richiamato il callback. Questo Executor oggetto può funzionare su un singolo thread o su un pool di thread di vostra scelta.

La maggior parte dei EuiccCardManager API hanno lo stesso modello di utilizzo. Ad esempio, per caricare un pacchetto di profili associati su eUICC:

...
cardMgr.loadBoundProfilePackage(eid, boundProfilePackage,
        AsyncTask.THREAD_POOL_EXECUTOR, callback);

Per passare a un profilo diverso 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);

Attivazione di un profilo eSIM tramite un'app dell'operatore

Sui dispositivi con Android 9 o versioni successive, puoi utilizzare un'app dell'operatore per attivare l'eSIM e scaricare i profili. L'applicazione vettore può scaricare i profili chiamando downloadSubscription direttamente o fornendo un codice di attivazione per la LPA.

Quando un'applicazione portante scarica un profilo chiamando downloadSubscription , le fa rispettare chiamata che l'applicazione in grado di gestire il profilo attraverso un BF76 tag di metadati che codifica le regole vettore di privilegio per il profilo. Se un profilo non dispone di un BF76 tag o se la sua BF76 tag non corrispondente alla firma del chiamante supporto dell'applicazione, il download è respinto.

La sezione seguente descrive l'attivazione di una eSIM tramite un'app del gestore utilizzando un codice di attivazione.

Attivazione dell'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 del gestore 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 mostrata l'interfaccia utente dell'app dell'operatore. Questo approccio ignora il BF76 controllo tag, e gli operatori di rete non hanno bisogno di implementare l'intera ESIM di attivazione UI fluire tra cui il download di un profilo Esim e la gestione degli errori.

Definizione del servizio di fornitura eUICC dell'operatore

LPA e portante app comunicano attraverso due AIDL interfacce: ICarrierEuiccProvisioningService e IGetActivationCodeCallback . L'applicazione vettore deve attuare ICarrierEuiccProvisioningService un'interfaccia ed esporlo nella sua dichiarazione di manifesta . La LPA deve legarsi a ICarrierEuiccProvisioningService e implementare IGetActivationCodeCallback . Per ulteriori informazioni su come implementare ed esporre un'interfaccia AIDL, vedere l'interfaccia Definizione e AIDL .

Per definire le interfacce AIDL, crea i seguenti file AIDL sia per l'LPA che per le 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 LPA

Per associare alla dell'applicazione portante ICarrierEuiccProvisioningService attuazione, la LPA deve copiare sia ICarrierEuiccProvisioningService.aidl e IGetActivationCodeCallback.aidl al progetto e implementare ServiceConnection .

@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    mCarrierProvisioningService = ICarrierEuiccProvisioningService.Stub.asInterface(iBinder);
}

Dopo legame dell'app portante ICarrierEuiccProvisioningService attuazione, le chiamate LPA sia getActivationCode o getActivationCodeForEid per ottenere il codice di attivazione dall'applicazione portante passando per l'esecuzione del IGetActivationCodeCallback classe stub.

La differenza tra getActivationCode e getActivationCodeForEid è che getActivationCodeForEid permette un vettore di pre-bind un profilo per EID del dispositivo prima che il processo di download ha inizio.

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

Per la LPA di legarsi alla applicazione di supporto, l'applicazione vettore deve copiare sia ICarrierEuiccProvisioningService.aidl e IGetActivationCodeCallback.aidl al progetto e dichiarare ICarrierEuiccProvisioningService servizio nel AndroidManifest.xml file. Il servizio deve richiedere l' android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS permesso di sistema per garantire che solo il LPA, un'applicazione del sistema-privilegiata, può legarsi ad essa. Il servizio deve includere anche un filtro di intenti con android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE azione.

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 di applicazione carrier AIDL, creare un servizio, estendere la Stub di classe e attuare le getActivationCode e getActivationCodeForEid metodi. L'LPA può quindi chiamare uno dei due metodi per recuperare il codice di attivazione del profilo. L'applicazione vettore dovrebbe rispondere chiamando IGetActivationCodeCallback#onSuccess con il codice di attivazione, se il codice è stato recuperato dal server del carrier con successo. In caso di insuccesso, l'applicazione vettore 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);
            }
      }
}

Avvio dell'interfaccia utente dell'app dell'operatore nel flusso di attivazione LPA

Sui dispositivi con Android 11 e versioni successive, l'LPA può avviare l'interfaccia utente di un'app dell'operatore. Ciò è utile in quanto un'app dell'operatore potrebbe richiedere ulteriori informazioni all'utente prima di fornire un codice di attivazione all'LPA. Ad esempio, i gestori potrebbero richiedere agli utenti di accedere 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:

  1. I lanci LPA flusso di attivazione dell'app carrier inviando android.service.euicc.action.START_CARRIER_ACTIVATION intento di pacchetto app supporto contenente l'azione. (Il ricevitore portante applicazione deve essere protetto nella dichiarazione manifesta con android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" per evitare di ricevere intenti da applicazioni 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);
    
  2. L'app dell'operatore svolge il proprio lavoro utilizzando la propria interfaccia utente. Ad esempio, l'accesso dell'utente o l'invio di richieste HTTP al backend del gestore.

  3. Gli risponde carrier App per l'LPA chiamando setResult(int, Intent) e finish() .

    1. Se l'applicazione portante risponde con RESULT_OK , la LPA continua il flusso di attivazione. Se l'applicazione di supporto determina che l'utente deve eseguire la scansione di un codice QR, invece di lasciare che la LPA legano servizio dell'applicazione carrier, le risponde vettore app al LPA utilizzando setResult(int, Intent) con RESULT_OK ed un Intent un'istanza contenente il booleano aggiuntivo android.telephony.euicc.extra.USE_QR_SCANNER impostata su true . La LPA controlla l'aggiuntivi e avviare lo scanner QR, invece di legare dell'app portante ICarrierEuiccProvisioningService implementazione.
    2. Se si blocca vettore app o risponda con RESULT_CANCELED (questo è il codice di risposta predefinito), il LPA annulla il flusso attivazione ESIM.
    3. Se l'applicazione vettore risponde con qualcosa di diverso da RESULT_OK o RESULT_CANCELED , le LPA tratta come un errore.

    Per motivi di sicurezza, la LPA non dovrebbe accettare direttamente un codice di attivazione fornito nel risultato intento di garantire che i chiamanti non-LPA non è possibile ottenere un codice di attivazione dall'applicazione vettore.

Avvio del 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 dell'eSIM. Questo metodo fa emergere l'interfaccia utente del flusso di attivazione eSIM della LPA per attivare il profilo eSIM. L'LPA invia quindi una trasmissione al termine dell'attivazione del profilo eSIM.

  1. La LPA deve dichiarare un'attività tra cui un filtro di intenti con android.service.euicc.action.START_EUICC_ACTIVATION azione. La priorità del filtro intent deve essere impostata su un valore diverso da zero nel caso in cui siano presenti più implementazioni sul dispositivo. Per 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>
    
  2. L'app dell'operatore svolge il proprio lavoro utilizzando la propria interfaccia utente. Ad esempio, l'accesso dell'utente o l'invio di richieste HTTP al backend del gestore.

  3. A questo punto, l'applicazione trasportatore deve essere pronto a fornire un codice di attivazione attraverso la sua ICarrierEuiccProvisioningService attuazione. Il carrier app lanci la LPA chiamando startActivityForResult(Intent, int) con android.telephony.euicc.action.START_EUICC_ACTIVATION azione. La LPA anche controlli il booleano aggiuntivo android.telephony.euicc.extra.USE_QR_SCANNER . Se il valore è true , i lanci LPA lo scanner QR per consentire all'utente di scansione del codice QR profilo.

  4. Sul lato LPA, si lega LPA dell'app portante ICarrierEuiccProvisioningService attuazione minuti per recuperare il codice di attivazione e scaricare il profilo corrispondente. L'LPA visualizza tutti gli elementi dell'interfaccia utente necessari durante il download, ad esempio una schermata di caricamento.

  5. Quando il flusso di attivazione LPA è completa, il LPA risponde al app portante con un codice risultato che le maniglie vettore app nella onActivityResult(int, int, Intent) .

    1. Se la LPA riesce a scaricare il nuovo profilo Esim, risponde con RESULT_OK .
    2. Se l'utente annulla il profilo di attivazione ESIM nel LPA, risponde con RESULT_CANCELED .
    3. Se l'LPA risponde con qualcosa di diverso da RESULT_OK o RESULT_CANCELED , il vettore app considera questo come un errore.

    Per motivi di sicurezza, la LPA non accetta un codice di attivazione direttamente in dotazione intento di garantire che i chiamanti non-LPA non è possibile ottenere il codice di attivazione dal app vettore.

Supporto di più eSIM

Per i dispositivi con Android 10 o superiore, i EuiccManager supporta la classe dispositivi con più ESIMS. Dispositivi con un solo ESim che stanno aggiornando ad Android 10 non richiedono alcuna modifica alla realizzazione LPA come piattaforma associa automaticamente l' EuiccManager istanza con l'eUICC predefinito. L'eUICC di default è determinato dalla piattaforma per i dispositivi con radio HAL versione 1.2 o superiore e dall'LPA per i dispositivi con radio HAL versione inferiore 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 SIM fisico in cui è possibile inserire eUICC rimovibili.

Per supportare più eSIM è necessaria la versione 1.2 o successiva di Radio HAL. Si consigliano Radio HAL versione 1.4 e RadioConfig HAL versione 1.2.

Implementazione

Per supportare più ESIMS (compresi eUICCs rimovibili o SIM programmabili), il LPA deve attuare EuiccService , che riceve l'ID di slot corrispondente all'ID carta chiamante fornito.

Il non_removable_euicc_slots risorsa specificata in arrays.xml è un array di numeri interi che rappresentano gli ID di slot di eUICCs incorporati in un dispositivo. È necessario specificare questa risorsa per consentire alla piattaforma di determinare se un eUICC inserito è rimovibile o meno.

App dell'operatore per dispositivi con più eSIM

Quando si effettua un'applicazione portante per un dispositivo con più ESIMS, utilizzare il createForCardId metodo EuiccManager per creare un EuiccManager oggetto che è bloccato a un determinato ID carta. L'ID della carta è un valore intero che identifica in modo univoco un UICC o un eUICC sul dispositivo.

Per ottenere la carta d'identità per eUICC di default del dispositivo, utilizzare il getCardIdForDefaultEuicc metodo TelephonyManager . Questo metodo restituisce UNSUPPORTED_CARD_ID se la versione radiofonica HAL è inferiore a 1,2 e ritorna UNINITIALIZED_CARD_ID se il dispositivo non ha letto l'eUICC.

È inoltre possibile ottenere gli ID di carte da getUiccCardsInfo e getUiccSlotsInfo (sistema di API) in TelephonyManager , e getCardId in SubscriptionInfo .

Quando un EuiccManager oggetto è creato un'istanza con un ID scheda specifica, tutte le operazioni sono dirette al eUICC con quel ID carta. Se l'eUICC diventa irraggiungibile (ad esempio, quando è spento o rimosso) EuiccManager non funziona più.

Puoi utilizzare i seguenti esempi di codice per creare un'app per operatori.

Esempio 1: Ottenere abbonamento attivo e creare un'istanza 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: Scorrere UICCs e instantiate EuiccManager per un eUICC amovibile

// 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 viene fornito con un'implementazione LPA e non dovresti avere un LPA disponibile su tutte le build Android (non tutti i telefoni supportano eSIM). Per questo motivo, non esistono test case 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 Android.

È necessario assicurarsi le generazioni passano i seguenti casi di test CTS (per le API pubbliche): la piattaforma / / CTS / test / test / telefonia / corrente / src / android / telefonia / euicc / CTS .

I vettori che implementano un'app per operatori dovrebbero seguire i loro normali cicli di garanzia della qualità interni per garantire che tutte le funzionalità implementate funzionino come previsto. Come minimo, l'app dell'operatore dovrebbe 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 stai creando il tuo LPA, dovresti passare attraverso test molto più rigorosi. Dovresti collaborare con il tuo fornitore di modem, chip eUICC o fornitore del sistema operativo eSIM, fornitori di SM-DP+ e vettori per risolvere i problemi e garantire l'interoperabilità del tuo LPA all'interno dell'architettura RSP. Una buona quantità di test manuali è inevitabile. Per una migliore copertura di test, è necessario seguire il piano di test GSMA SGP.23 RSP .