Implementa eSIM

La tecnologia SIM integrata (eSIM o eUICC) consente agli utenti di dispositivi mobili scaricare il profilo di un operatore e attivare il servizio di un operatore senza una scheda SIM fisica. Si tratta di una specifica globale gestita da GSMA che consente il provisioning remoto di SIM (RSP) di qualsiasi dispositivo mobile. A partire da Android 9, il framework Android fornisce API standard per accesso all'eSIM e gestione dei profili degli abbonamenti sull'eSIM. Queste eUICC Le API consentono a terze parti di sviluppare le proprie app dell'operatore e il proprio profilo locale assistenti (LPA) su dispositivi Android con eSIM.

L'LPA è un'app di sistema autonoma che deve essere inclusa nel Immagine build Android. La gestione dei profili sull'eSIM viene generalmente eseguita l'LPA, in quanto funge da collegamento tra SM-DP+ (servizio remoto che prepara, memorizza e invia pacchetti di profili ai dispositivi) e il chip eUICC. L'APK LPA può facoltativamente includere un componente dell'interfaccia utente, chiamato UI o LUI, per fornire all'utente finale una posizione centralizzata per la gestione di tutti gli abbonamenti incorporati profili. Il framework Android rileva e si connette automaticamente ai LPA disponibile e instrada tutte le operazioni eUICC attraverso un'istanza LPA.

Architettura RSP (Remote SIM Provisioning) semplificata

Figura 1. Architettura RSP semplificata

Gli operatori di rete mobile interessati a creare un'app dell'operatore dovrebbero consultare le API EuiccManager, che offre operazioni di gestione del profilo di alto livello come downloadSubscription(), switchToSubscription() e deleteSubscription().

Se sei un OEM di dispositivi e ti interessa creare la tua app di sistema LPA, devi: estendere EuiccService affinché il framework Android si connetta ai tuoi servizi LPA. Inoltre, devono utilizzare le API EuiccCardManager, che forniscono funzioni ES10x basate su GSMA RSP v2.0. Queste funzioni vengono utilizzate per inviare comandi al chip eUICC, come prepareDownload(), loadBoundProfilePackage(), retrieveNotificationList() e resetMemory().

Le API in EuiccManager richiedono un'app LPA correttamente implementata per funzionare e il chiamante EuiccCardManager Le API devono essere un LPA. Questa operazione viene applicata dal framework Android.

I dispositivi con Android 10 o versioni successive supportano con più eSIM. Per ulteriori informazioni, vedi Supporto di più eSIM.

Crea un'app dell'operatore

Le API eUICC in Android 9 rendono possibile operatori di rete mobile di creare app con il brand dell'operatore per gestire i propri profili. Sono inclusi il download e l'eliminazione dei profili degli abbonamenti. di proprietà dell'operatore, nonché il passaggio a un profilo di proprietà di un operatore.

Gestore Euicc

EuiccManager è il punto di accesso principale per l'interazione delle app con LPA. Sono incluse le app dell'operatore che scaricano, eliminano e passano a abbonamenti di proprietà dell'operatore. È compresa anche l'app di sistema LUI, 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 usare le API pubbliche, un'app dell'operatore deve prima ottenere l'istanza Da EuiccManager a Context#getSystemService:

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

Devi controllare se l'eSIM è supportata sul dispositivo prima di eseguire qualsiasi Operazioni dell'eSIM. EuiccManager#isEnabled() generalmente restituisce true se La funzionalità android.hardware.telephony.euicc è definita e un pacchetto LPA è presenti.

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, ad esempio downloadSubscription() e switchToSubscription(), utilizzano PendingIntent perché potrebbero richiedere secondi o persino minuti. PendingIntent viene inviato con un codice risultato in 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 l'app dell'operatore per monitorare i fini di logging/debug. PendingIntent il callback 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 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 di API EuiccManager ed esempi di codice, consulta API eUICC.

Errori risolvibili

In alcuni casi il sistema non è in grado di completare l'operazione dell'eSIM ma l'errore può essere risolto dall'utente. Ad esempio, downloadSubscription potrebbe non riuscire se i metadati del profilo indicano che un codice di conferma dell'operatore è obbligatorio. Oppure switchToSubscription potrebbe non funzionare se l'app dell'operatore ha un operatore privilegiati sul profilo di destinazione (ossia, l'operatore è proprietario del profilo), ma non dispone dei privilegi di operatore rispetto al profilo attualmente abilitato, pertanto il consenso dell'utente è obbligatorio.

In questi casi, la richiamata del chiamante viene chiamata con EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR. Il callback Intent contiene extra interni che, quando il chiamante la passa a EuiccManager#startResolutionActivity, può essere richiesta tramite la LUI. L'utilizzo del codice di conferma per di nuovo un esempio, EuiccManager#startResolutionActivity attiva una schermata LUI che consente all'utente di inserire un codice di conferma; dopo l'inserimento del codice, l'operazione di download viene ripresa. Questo approccio offre all'app dell'operatore il pieno controllo su quando viene mostrata l'UI, ma fornisce LPA/LUI, un metodo estensibile per aggiungere una nuova gestione dei contenuti recuperabili dall'utente in futuro senza dover modificare le app client.

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

Se sei un operatore che sviluppa un'app del tuo operatore che chiama EuiccManager per scaricare i profili su un dispositivo, il tuo profilo deve includere l'operatore le regole sui privilegi corrispondenti all'app dell'operatore nei metadati. Questo è dato che i profili di abbonamento che appartengono a operatori diversi possono coesistere in alla eUICC di un dispositivo e a ogni app dell'operatore deve essere consentito accedere soltanto profili di proprietà dell'operatore in questione. Ad esempio, l'operatore A non deve essere in grado 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 (ossia l'app dell'operatore). La La piattaforma Android carica i certificati archiviati nel file delle regole di accesso del profilo (ARF) e concede alle app firmate da questi certificati l'autorizzazione per effettuare chiamate alle API di EuiccManager. La procedura generale è descritta di seguito:

  1. L'operatore firma l'APK dell'app dell'operatore; il apksigner collega il certificato di chiave pubblica all'APK.
  2. Operator/SM-DP+ prepara un profilo e i relativi 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 dell'operatore (vivamente consigliato)
  3. L'app dell'operatore tenta di eseguire un'operazione eUICC con l'API EuiccManager.

  4. La piattaforma Android verifica l'hash SHA-1 o SHA-256 dell'app chiamante corrisponda alla firma del certificato ottenuto ARF del profilo di destinazione. Se il nome del pacchetto dell'app dell'operatore è incluso nella l'ARF, deve corrispondere anche al nome del pacchetto dell'app del chiamante.

  5. Dopo aver verificato la firma e il nome del pacchetto (se incluso), i campi All'app chiamante viene concesso il privilegio dell'operatore al profilo di destinazione.

Poiché i metadati del profilo possono essere disponibili all'esterno del profilo stesso (in modo che LPA può recuperare i metadati del profilo da SM-DP+ prima che il profilo scaricato o da ISD-R quando il profilo è disattivato), questo dovrebbe contenere le stesse regole sui privilegi dell'operatore del profilo.

Il sistema operativo eUICC e SM-DP+ devono supportare un tag proprietario BF76 nel profilo metadati. I contenuti del tag devono corrispondere alle regole relative ai privilegi dell'operatore restituiti dall'applet delle 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 Firma l'app. Per maggiori dettagli sui privilegi dell'operatore, vedi Privilegi dell'operatore UICC.

Crea un'app di assistente del profilo locale

I produttori di dispositivi possono implementare il proprio assistente di profilo locale (LPA), che devono essere agganciati con le API Android Euicc. Le seguenti sezioni forniscono una breve panoramica creare un'app LPA e integrarla nel sistema Android.

Requisiti hardware/modem

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

Inoltre, per l'integrazione con le API eUICC in Android 9, il modem del dispositivo deve inviare funzionalità del terminale con il supporto delle funzionalità eUICC codificate (gestione dei profili locali e download 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 di eSIM solo per l'operatore autorizzato. In caso contrario, gli utenti potrebbero scaricare e trasferire una SIM e in un secondo momento scoprire che il dispositivo è bloccato dall'operatore di un altro operatore.

    • I fornitori o gli OEM devono implementare l'API IRadioSim.getAllowedCarriers()HAL.

    • Il Fornitore RIL / Modem completerà lo stato del blocco e il carrierId dell'operatore in cui il dispositivo è bloccato nell'ambito dell'API IRadioSimResponse.getAllowedCarriersResponse()HAL.

Il modem deve riconoscere l'eSIM con il profilo di avvio predefinito abilitato come una SIM valida e tienila accesa.

Per i dispositivi con Android 10, è prevista una eUICC non rimovibile è necessario definire l'array di ID slot. 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, vedi Requisiti del modem per l'assistenza eSIM.

Servizio Euicc

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

Per implementare il backend LPA, devi estendere EuiccService e dichiarare questo servizio nel tuo file manifest. Il servizio deve richiedere android.permission.BIND_EUICC_SERVICE di autorizzazione di sistema per garantire che il sistema possa associarsi. Il servizio deve includere anche un filtro per intent con l'azione android.service.euicc.EuiccService. La priorità dell'intent deve essere impostato su un valore diverso da zero nel caso in cui vengano eseguite più implementazioni presente sul dispositivo. 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 interagisce con se necessario per supportare le API Android eUICC. È stata eseguita una query su PackageManager tutte le app con 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, l'LPA il supporto è disabilitato.

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 la android.permission.BIND_EUICC_SERVICE autorizzazione di sistema. Ognuno di questi deve avere un filtro per intent con l'azione appropriata, android.service.euicc.category.EUICC_UI e una priorità diversa da zero. Viene utilizzata una logica simile per scegliere le implementazioni per queste attività scegliere l'implementazione 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'origine APK di quello che implementa EuiccService Indica se avere un singolo APK o più APK (ad esempio, uno che implementa EuiccService e uno che offre attività LUI) è una scelta di progettazione.

EuiccCardManager

EuiccCardManager è l'interfaccia per comunicare con il chip eSIM. it fornisce funzioni ES10 (come descritto nelle specifiche RSP GSMA) e gestisce comandi di richiesta/risposta APDU di basso livello nonché analisi ASN.1. EuiccCardManager è un'API di sistema e può essere chiamato solo con privilegi di sistema app.

App operatore, API LPA ed Euicc

Figura 2. Sia l'app dell'operatore sia l'LPA utilizzano le API Euicc

Le API per le operazioni del profilo tramite EuiccCardManager richiedono che il chiamante un LPA. Questa operazione viene applicata dal framework Android. Ciò significa che il chiamante deve estendere EuiccService e essere dichiarati nel file manifest, come descritto in le sezioni precedenti.

Analogamente a EuiccManager, per usare le API EuiccCardManager, il tuo LPA deve per prima cosa ottieni l'istanza di EuiccCardManager Context#getSystemService:

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

Quindi, per recuperare tutti i profili sulla 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 in smartphone) mediante un'interfaccia AIDL e ciascun metodo EuiccCardManager riceve la richiamata dalla procedura telefonica attraverso un AIDL dedicato diverso a riga di comando. Quando si utilizzano le API EuiccCardManager, il chiamante (LPA) deve fornire un Executor attraverso il quale viene richiamato il callback. Questo oggetto Executor può essere eseguito in un singolo thread o in un pool di thread di tua scelta.

La maggior parte delle EuiccCardManager API ha lo stesso pattern di utilizzo. Ad esempio, per caricare un file pacchetto del profilo associato alla 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);

Attiva un profilo eSIM tramite l'app di un operatore

Su dispositivi con Android 9 o versioni successive, puoi usare un'app dell'operatore per attivare l'eSIM e scaricare profili. L'app dell'operatore può scaricare profili chiamata downloadSubscription direttamente 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 ha un tag corrisponda 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 di attivazione/disattivazione.

Attiva l'eSIM usando un codice di attivazione

Se usi un codice di attivazione per attivare un profilo eSIM, l'LPA recupera un codice di attivazione l'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, perciò nessuna UI dell'app dell'operatore viene come mostrato nell'immagine. Questo approccio ignora il controllo dei tag BF76 e gli operatori di rete non implementare l'intero flusso dell'interfaccia utente di attivazione dell'eSIM, incluso il download di un Profilo eSIM e gestione degli errori.

Definire il servizio di provisioning eUICC dell'operatore

L'LPA e l'app dell'operatore comunicano tramite due AIDL interfacce: ICarrierEuiccProvisioningService e IGetActivationCodeCallback. Il vettore l'app deve implementare un'interfaccia ICarrierEuiccProvisioningService e espongo nella sua dichiarazione manifest. L'LPA deve collegarsi a ICarrierEuiccProvisioningService e implementare IGetActivationCodeCallback. Per ulteriori informazioni su come implementare esporre un'interfaccia AIDL, consulta Definizione e interfaccia AIDL.

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

Per eseguire l'associazione all'implementazione ICarrierEuiccProvisioningService dell'app dell'operatore, l'LPA deve copiare sia ICarrierEuiccProvisioningService.aidl che IGetActivationCodeCallback.aidl al progetto e implementa ServiceConnection.

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

Dopo l'associazione con ICarrierEuiccProvisioningService dell'app dell'operatore implementazione, l'LPA chiama getActivationCode o getActivationCodeForEid per ricevere il codice di attivazione dall'app dell'operatore entro il giorno superare l'implementazione della classe stub IGetActivationCodeCallback.

La differenza tra getActivationCode e getActivationCodeForEid è che getActivationCodeForEid consente a un operatore di pre-associare un profilo all'account del dispositivo EID 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 si colleghi all'app dell'operatore, l'app dell'operatore deve copiare entrambi ICarrierEuiccProvisioningService.aidl e IGetActivationCodeCallback.aidl per del progetto e dichiarare il servizio ICarrierEuiccProvisioningService AndroidManifest.xml file. Il servizio deve richiedere android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS autorizzazione di sistema per garantire che solo l'LPA, un'app con privilegi di sistema, può associarla. Il servizio deve includi anche un filtro per intent con 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 ed estendi il Stub e implementare getActivationCode e getActivationCodeForEid di machine learning. L'LPA può quindi chiamare uno dei due metodi per recuperare l'attivazione del profilo le API nel tuo codice. L'app dell'operatore dovrebbe rispondere chiamando IGetActivationCodeCallback#onSuccess con il codice di attivazione, se il codice era recuperato correttamente dal server dell'operatore. Se non funziona, 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 LPA

Sui dispositivi con Android 11 e versioni successive, l'LPA può avviare l'UI dell'app di un operatore. È utile perché l'app dell'operatore potrebbe richiedere ulteriori informazioni dall' l'utente prima di fornire un codice di attivazione all'LPA. Ad esempio, gli operatori richiedere agli utenti di eseguire l'accesso per attivare i propri numeri di telefono o eseguire altre portazioni i servizi di machine learning.

Questa è la procedura per avviare nell'LPA l'interfaccia utente dell'app dell'operatore:

  1. L'LPA avvia il flusso di attivazione dell'app dell'operatore inviando il metodo intent di android.service.euicc.action.START_CARRIER_ACTIVATION alla pacchetto dell'app dell'operatore contenente l'azione. Il destinatario dell'app dell'operatore deve essere protetti nella dichiarazione del file manifest con Da android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" a 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);
    
  2. L'app dell'operatore svolge il proprio lavoro utilizzando la propria UI. Ad esempio, logging presenti nell'utente o inviare richieste HTTP al backend dell'operatore.

  3. L'app dell'operatore risponde all'LPA chiamando il numero setResult(int, Intent) e finish().

    1. Se l'app dell'operatore risponde con RESULT_OK, l'LPA continua il flusso di attivazione. Se l'app dell'operatore stabilisce che l'utente deve scansionare un codice QR anziché permettere all'LPA di vincolare l'operatore al servizio dell'app, l'app dell'operatore risponde all'LPA usando setResult(int, Intent) con RESULT_OK e un'istanza Intent contenente il valore extra booleano android.telephony.euicc.extra.USE_QR_SCANNER impostato su true. LPA poi controlla l'extra e avvia lo scanner QR invece di eseguire il binding l'implementazione di ICarrierEuiccProvisioningService dell'app dell'operatore.
    2. Se l'app dell'operatore si arresta in modo anomalo o risponde con RESULT_CANCELED (questo è il codice di risposta predefinito), l'LPA annulla l'eSIM flusso di attivazione.
    3. Se l'app dell'operatore risponde con qualcosa di diverso da RESULT_OK o RESULT_CANCELED, l'LPA lo considera un errore.

    Per motivi di sicurezza, l'LPA non deve accettare direttamente un fornito nell'intent di risultato per garantire che le i chiamanti non possono ricevere un codice di attivazione dall'app dell'operatore.

Avvia il flusso di attivazione LPA in un'app dell'operatore

A partire da Android 11, le app dell'operatore possono usare le API eUICC per avviare una LUI per eSIM dell'attivazione. Questo metodo mostra l'UI del flusso di attivazione eSIM dell'LPA per l'attivazione il profilo eSIM. L'LPA invia quindi un annuncio quando il profilo eSIM e l'attivazione termina l'attivazione.

  1. L'LPA deve dichiarare un'attività che includa un filtro per intent con Azione android.service.euicc.action.START_EUICC_ACTIVATION. La priorità del filtro per intent deve essere impostato su un valore diverso da zero nel caso in cui le implementazioni siano presenti 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>
    
  2. L'app dell'operatore svolge il proprio lavoro utilizzando la propria UI. Ad esempio, logging presenti nell'utente o inviare richieste HTTP al backend dell'operatore.

  3. A questo punto, l'app dell'operatore deve essere pronta per fornire un tramite la sua implementazione ICarrierEuiccProvisioningService. La l'app dell'operatore avvia l'LPA chiamando startActivityForResult(Intent, int) con android.telephony.euicc.action.START_EUICC_ACTIVATION un'azione. L'LPA controlla anche l'extra booleano android.telephony.euicc.extra.USE_QR_SCANNER. Se il valore è true, il valore LPA avvia lo scanner QR per consentire all'utente di scansionare il codice QR del profilo.

  4. Sul lato LPA, l'LPA si collega alla rete ICarrierEuiccProvisioningService implementazione per recuperare l'attivazione codice e scarica il profilo corrispondente. L'LPA visualizza tutti i dati necessari Elementi UI durante il download, ad esempio una schermata di caricamento.

  5. Quando il flusso di attivazione LPA è completo, l'LPA risponde app dell'operatore con un codice risultato, che l'app dell'operatore gestisce onActivityResult(int, int, Intent).

    1. Se l'LPA riesce a scaricare il nuovo profilo eSIM, risponde con RESULT_OK.
    2. Se l'utente annulla l'attivazione del profilo eSIM nell'LPA, risponde con RESULT_CANCELED.
    3. Se l'LPA risponde con qualcosa di diverso da RESULT_OK o RESULT_CANCELED, l'app dell'operatore considera questo messaggio come un errore.

    Per motivi di sicurezza, l'LPA non accetta un codice di attivazione direttamente nell'intent specificato per garantire che i chiamanti non LPA non possano il codice di attivazione dall'app dell'operatore.

Supporta più eSIM

Per i dispositivi con Android 10 o versioni successive, La classe EuiccManager supporta i dispositivi con più eSIM. Dispositivi con una sola eSIM in fase di upgrade Android 10 non richiedono modifiche all'implementazione LPA come piattaforma associa automaticamente l'istanza EuiccManager alla eUICC predefinita. La 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 inferiori a 1.2.

Requisiti

Per supportare più eSIM, il dispositivo deve avere più di una eUICC, che può essere essere una eUICC integrata o uno slot per SIM fisica in cui è possibile inserire le eUICC rimovibili inserito.

Per supportare più eSIM, è necessaria la versione 1.2 o versioni successive dell'HAL per la radio. Radio HAL si consiglia la versione 1.4 e la versione 1.2 di RadioConfig HAL.

Implementazione

Per supportare più eSIM (incluse eUICC rimovibili o SIM programmabili), L'LPA deve implementare EuiccService, che riceve l'ID slot corrispondente all'ID carta fornito dal chiamante.

La non_removable_euicc_slots risorsa specificata in arrays.xml è un array di numeri interi che rappresentano gli ID slot dell'infrastruttura integrata di un dispositivo eUICC. Devi specificare questa risorsa per consentire alla piattaforma di determinare se una eUICC inserita è rimovibile.

App operatore per dispositivo con più eSIM

Quando crei un'app dell'operatore per un dispositivo con più eSIM, utilizza createForCardId in EuiccManager per creare un oggetto EuiccManager bloccato a un ID carta specificato. L'ID carta è un valore intero che identifica in modo univoco un UICC o una eUICC sul dispositivo.

Per ottenere l'ID carta per l'eUICC predefinita del dispositivo, utilizza la getCardIdForDefaultEuicc in TelephonyManager. Questo metodo restituisce UNSUPPORTED_CARD_ID se la versione HAL della radio è precedente alla 1.2 e restituisce UNINITIALIZED_CARD_ID se il dispositivo non ha letto l'eUICC.

Puoi anche ottenere gli ID carta da getUiccCardsInfo e getUiccSlotsInfo (API di sistema) in TelephonyManager e getCardId a SubscriptionInfo.

Quando viene creata un'istanza di un oggetto EuiccManager con un ID carta specifico, vengono indirizzate alla eUICC con quell'ID carta. Se l'eUICC diventa non raggiungibile (ad esempio, quando viene disattivato o rimosso) EuiccManager no funziona più a lungo.

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: eseguire l'iterazione nelle UICC e creare 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 viene fornito con un'implementazione LPA e non è previsto avere un LPA disponibile su tutte le build Android (non tutti gli smartphone supportano l'eSIM). Per Per questo motivo, non esistono scenari di test CTS end-to-end. Tuttavia, scenari di test di base sono disponibili in AOSP per garantire che le API eUICC esposte sono valide nelle build Android.

Devi assicurarti che le build superino i seguenti scenari di test CTS (per API): /platform/cts/tests/tests/telephony/current/src/android/telephony/euicc/cts.

Gli operatori che implementano un'app dell'operatore devono eseguire le normali operazioni interne garanzia di qualità per garantire che tutte le funzionalità implementate funzionino come previsto. Al come minimo, l'app dell'operatore deve essere in grado di elencare tutti i profili degli abbonamenti di proprietà dello stesso operatore, scarica e installa un profilo, attiva un servizio sul profilo, passare da un profilo all'altro ed eliminare i profili.

Per realizzare il tuo LPA, devi superare una fase molto più test. Rivolgiti al tuo fornitore di modem, al chip eUICC o al fornitore del sistema operativo eSIM. fornitori e operatori SM-DP+ per risolvere i problemi e garantire l'interoperabilità l'LPA nell'architettura RSP. Una buona quantità di test manuali è inevitabile. Per una migliore copertura dei test, devi seguire le Piano di test RSP SGP.23 GSMA.