Implementa una eSIM

La tecnología de SIM incorporada (eSIM o eUICC) permite que los usuarios de dispositivos móviles descarga un perfil de operador y activa un servicio de operador sin tener que tarjeta SIM física. Es una especificación global impulsada por la GSMA que permite aprovisionamiento remoto de SIM (RSP) de cualquier dispositivo móvil. Primeros pasos con Android 9, el framework de Android ofrece APIs estándar para acceder a la eSIM y administrar los perfiles de suscripción en ella Estos eUICC Las APIs permiten que terceros desarrollen sus propios perfiles y apps de operador (LPA) en dispositivos Android compatibles con eSIM.

La LPA es una aplicación de sistema independiente que debería incluirse en el Imagen de compilación de Android. Por lo general, la administración de los perfiles en la eSIM la realiza al LPA, ya que funciona como puente entre el SM-DP+ (servicio remoto que prepara, almacena y entrega paquetes de perfiles a los dispositivos) y el chip eUICC. De manera opcional, el APK de LPA puede incluir un componente de IU, llamado IU de LPA o LUI, para Proporcionan un lugar central para que el usuario final administre todas las suscripciones incorporadas. perfiles. El framework de Android detecta y se conecta automáticamente a los mejores recursos y enruta todas las operaciones de eUICC a través de una instancia de LPA.

Arquitectura simplificada de aprovisionamiento remoto de SIM (RSP)

Figura 1: Arquitectura de RSP simplificada

Los operadores de redes móviles interesados en crear una app de operador deben tener en cuenta lo siguiente: las APIs en EuiccManager: que ofrece operaciones de administración de perfiles de alto nivel, como downloadSubscription(), switchToSubscription() y deleteSubscription()

Si eres un OEM de dispositivos y te interesa crear tu propia app de sistema de LPA, debes extender EuiccService para que el framework de Android se conecte a tus servicios de LPA. Además, deberías usar las APIs en EuiccCardManager: que proporcionan funciones ES10x basadas en GSMA RSP v2.0. Estas funciones se usan para emitir comandos al chip eUICC, como prepareDownload(), loadBoundProfilePackage() y retrieveNotificationList() y resetMemory().

Las APIs de EuiccManager requieren una app de LPA implementada correctamente para funcionar, y el llamador de EuiccCardManager Las APIs deben ser un LPA. El framework de Android aplica esto.

Los dispositivos que ejecutan Android 10 o versiones posteriores son compatibles con varias eSIM. Para obtener más información, consulta Compatibilidad con varias eSIM.

Crea una app de operador

Las APIs de eUICC en Android 9 posibilitan que operadores de redes móviles para crear apps de la marca del operador para administrar sus perfiles directamente. Esto incluye descargar y borrar perfiles de suscripción propiedad del operador, así como cambiarse a un perfil que sea propiedad de este.

EuiccManager

EuiccManager es el punto de entrada principal para que las apps interactúen con el el LPA Esto incluye las apps del operador que descargan, borran y cambian del proveedor. Esto también incluye la app del sistema LUI, Proporciona una ubicación/IU central para administrar todas las suscripciones incorporadas. Puede ser una app independiente de la que proporciona el EuiccService.

Para usar las APIs públicas, una app de operador primero debe obtener la instancia de De EuiccManager a Context#getSystemService:

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

Debes comprobar si el dispositivo admite la eSIM antes de realizar cualquier operaciones de eSIM. EuiccManager#isEnabled() generalmente muestra true si el elemento Se define la función android.hardware.telephony.euicc y se crea un paquete de LPA presente.

if (mgr == null || !mgr.isEnabled()) {
    return;
}

Para obtener información sobre el hardware de eUICC y la versión del SO de la eSIM, haz lo siguiente:

EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();

Muchas APIs, como downloadSubscription() y switchToSubscription(), usan PendingIntent de devoluciones de llamada, ya que pueden tardar segundos o incluso minutos en completarse. Se envía PendingIntent con un código de resultado en el EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_, que proporciona los códigos de error definidos por el framework, así como un código de resultado detallado y arbitrario propagado desde el LPA como EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, lo que permite la app del operador para hacer un seguimiento con fines de registro/depuración. El PendingIntent La devolución de llamada debe ser BroadcastReceiver.

Para descargar una suscripción descargable determinada (creada a partir de un código de activación o código 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);

Define y usa el permiso en AndroidManifest.xml:

    <permission android:protectionLevel="signature" android:name="com.your.company.lpa.permission.BROADCAST" />
    <uses-permission android:name="com.your.company.lpa.permission.BROADCAST"/>

Para cambiar a una suscripción con el ID correspondiente, haz lo siguiente:

// 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);

Para ver una lista completa de las APIs y ejemplos de código de EuiccManager, consulta APIs de eUICC:

Errores que se pueden resolver

En algunos casos, el sistema no puede completar la operación de eSIM. pero el usuario puede resolver el error. Por ejemplo, downloadSubscription. puede fallar si los metadatos del perfil indican que un código de confirmación de proveedor es obligatorio. O bien, es posible que switchToSubscription falle si la app del operador tiene un operador privilegios sobre el perfil de destino (es decir, el operador es propietario del perfil), pero no tiene privilegios de operador sobre el perfil actualmente habilitado y, por lo tanto, el consentimiento del usuario es obligatorio.

En estos casos, se llama a la devolución de llamada del emisor con EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR La devolución de llamada Intent contiene extras internos de modo que, cuando el llamador se lo pasa al EuiccManager#startResolutionActivity, la resolución del problema se puede solicitar a través de la LUI. Se usará el código de confirmación para ejemplo de nuevo, EuiccManager#startResolutionActivity activa una pantalla LUI que permite al usuario ingresar un código de confirmación. Después de ingresar el código, se reanuda la operación de descarga. Este enfoque le proporciona a la app del operador el control total sobre cuándo se muestra la IU, pero le da El LPA/LUI es un método extensible para agregar un nuevo manejo de datos problemas en el futuro sin la necesidad de que las apps cliente cambien.

Android 9 define estos errores que se pueden resolver EuiccService: que la LUI debe controlar:

/**
 * 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";

Privilegios del proveedor

Si representas a un operador que desarrolla su propia app del operador que llama a EuiccManager Para descargar perfiles en un dispositivo, tu perfil debe incluir el proveedor reglas de privilegios correspondientes a tu app de operador en los metadatos. Este es debido a que los perfiles de suscripción que pertenecen a distintos operadores pueden coexistir el eUICC de un dispositivo, y cada app del operador solo debe poder acceder al perfiles que pertenezcan a ese operador. Por ejemplo, el operador A no debería poder descargar, habilitar o inhabilitar un perfil propiedad del operador B.

Para garantizar que solo el propietario pueda acceder a un perfil, Android usa un mecanismo otorgar privilegios especiales a la app del propietario del perfil (es decir, la app del operador) El La plataforma de Android carga los certificados almacenados en el archivo de reglas de acceso del perfil (ARF) y otorga permiso a las apps firmadas por estos certificados para realizar llamadas a las APIs de EuiccManager. El proceso de alto nivel se describe a continuación:

  1. El operador firma el APK de la app del operador. el apksigner: adjunta el certificado de clave pública al APK.
  2. El operador/SM-DP+ prepara un perfil y sus metadatos, que incluyen un ARF que contiene:

    1. Firma (SHA-1 o SHA-256) del certificado de clave pública de la app del operador (obligatorio)
    2. Nombre del paquete de la app del operador (muy recomendado)
  3. La app del operador intenta realizar una operación eUICC con la API de EuiccManager.

  4. La plataforma de Android verifica el hash SHA-1 o SHA-256 del código de la app que realiza la llamada certificado coincida con la firma del certificado obtenido del el ARF del perfil de destino. Si el nombre del paquete de la app del operador se incluye en el ARF, también debe coincidir con el nombre del paquete de la app que realiza la llamada.

  5. Una vez que se verifiquen la firma y el nombre del paquete (si se incluye), el se le otorga a la aplicación que realiza la llamada el privilegio de operador sobre el perfil objetivo.

Como los metadatos del perfil pueden estar disponibles fuera del perfil (para que El LPA puede recuperar los metadatos del perfil de SM-DP+ antes de que se cree el perfil descargado, o desde ISD-R cuando el perfil esté inhabilitado), debería contener el a las mismas reglas de privilegios de operador que en el perfil.

El SO eUICC y SM-DP+ deben admitir una etiqueta propia BF76 en el perfil metadatos. El contenido de la etiqueta debe tener las mismas reglas de privilegios de operador que se muestran por la applet de regla de acceso (ARA) definida en Privilegios de proveedor de 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
    }
}

Para obtener más detalles sobre la firma de apps, consulta Firma la app. Para obtener detalles sobre los privilegios de proveedor, consulta Privilegios de Proveedor de UICC.

Crea una app de asistente de perfil local

Los fabricantes de dispositivos pueden implementar su propio asistente de perfil local (LPA), que debe engancharse con las APIs de Android Euicc. En las siguientes secciones, se brinda una breve descripción crear una app de LPA y, luego, integrarla con el sistema Android.

Requisitos de hardware o módem

El LPA y el SO de eSIM en el chip eUICC deben admitir, al menos, el RSP (remoto) de GSMA aprovisionamiento de SIM) v2.0 o v2.2. También debes planificar el uso de SM-DP+ y SM-DS servidores que tengan una versión de RSP que coincida. Para ver detalles sobre la arquitectura de RSP, consulta Especificación de la arquitectura de RSP GSMA SGP.21.

Además, integrar las APIs de eUICC en Android 9, el módem del dispositivo debe enviar capacidades de terminal con la compatibilidad con capacidades eUICC codificadas (administración de perfiles locales y la descarga del perfil). También debe implementar los siguientes métodos:

  • HAL de IRadio versión 1.1: setSimPower
  • HAL de IRadio versión 1.2: getIccCardStatus

  • HAL de IRadioConfig versión 1.0: getSimSlotsStatus

  • AIDL de IRadioConfig v1.0: getAllowedCarriers

    La LPA de Google debe conocer el estado de bloqueo del operador para poder permitir la descarga o transferencia de eSIM solo para el operador permitido. De lo contrario, los usuarios podrían descargar y transferir una SIM y, luego, darse cuenta de que el dispositivo está bloqueado por el operador para otro operador.

    • Los proveedores o los OEM deben implementar la API de IRadioSim.getAllowedCarriers()HAL.

    • Como parte de la API de IRadioSimResponse.getAllowedCarriersResponse()HAL, el RIL / mód del proveedor completará el estado de la cerradura y el ID de proveedor del operador en el que esté bloqueado el dispositivo.

El módem debería reconocer la eSIM con el perfil de inicio predeterminado habilitado como SIM válida y manténla encendida.

Para los dispositivos que ejecutan Android 10, se crea un eUICC no extraíble Se debe definir la matriz de ID de ranura. Por ejemplo, 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>

Para obtener una lista completa de los requisitos de módem, consulta Requisitos del módem para la compatibilidad con eSIM

EuiccService

Un LPA consta de dos componentes separados (ambos pueden implementarse en la misma APK): el backend de LPA y la IU de LPA o LUI.

Para implementar el backend de LPA, debes extender EuiccService y declara este servicio en tu archivo de manifiesto. El servicio debe requerir la android.permission.BIND_EUICC_SERVICE para garantizar que solo el sistema puede vincularse a él. El servicio también debe incluir un filtro de intents con la acción android.service.euicc.EuiccService. La prioridad del intent el filtro se debe establecer en un valor distinto de cero en caso de que se necesiten varias implementaciones presente en el dispositivo. Por ejemplo:

<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>

De forma interna, el framework de Android determina el LPA activo e interactúa con según sea necesario para admitir las APIs de eUICC de Android. Se consulta PackageManager por todas las apps con el permiso android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS que especifica un servicio para la acción android.service.euicc.EuiccService. Se seleccionará el servicio con la prioridad más alta. Si no se encuentra ningún servicio, la LPA la compatibilidad está inhabilitada.

A fin de implementar el LUI, debes proporcionar una actividad para las siguientes acciones:

  • android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS
  • android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION

Al igual que con el servicio, cada actividad debe requerir la Permiso del sistema android.permission.BIND_EUICC_SERVICE. Cada uno debe tener un filtro de intents con la acción adecuada, android.service.euicc.category.EUICC_UI y una prioridad distinta de cero. Se usa una lógica similar para elegir las implementaciones para estas actividades: con la selección de la implementación EuiccService Por ejemplo:

<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>

Esto implica que la IU que implementa estas pantallas puede provenir de un diferente APK desde el que implementa EuiccService Tener un solo APK o varios APK (por ejemplo, uno que implemente EuiccService y uno que proporciona actividades de LUI) es una elección de diseño.

EuiccCardManager

EuiccCardManager es la interfaz para comunicarse con el chip eSIM. Integra proporciona funciones ES10 (como se describe en las especificaciones del RSP de GSMA) y maneja las comandos de solicitud/respuesta de APDU de bajo nivel y análisis de ASN.1. EuiccCardManager es una API del sistema y solo lo pueden llamar con privilegios del sistema de Google Chat.

Apps del operador, LPA y APIs de Euicc

Figura 2: Tanto la app del operador como el LPA usan APIs de Euicc

Las APIs de operaciones de perfil a través de EuiccCardManager requieren que el llamador esté un LPA. El framework de Android aplica esto. Esto significa que el llamador extender EuiccService y declararse en tu archivo de manifiesto, como se describe en secciones anteriores.

Al igual que con EuiccManager, para usar las APIs de EuiccCardManager, tu LPA debe primero obtén la instancia de EuiccCardManager mediante Context#getSystemService:

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

Luego, para obtener todos los perfiles en el eUICC, haz lo siguiente:

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);

De forma interna, EuiccCardManager se vincula a EuiccCardController (que se ejecuta en proceso telefónico) a través de una interfaz de AIDL, y cada método EuiccCardManager recibe su devolución de llamada del proceso telefónico a través de un AIDL dedicado diferente interfaz de usuario. Cuando se usan las APIs de EuiccCardManager, el llamador (LPA) debe proporcionar un Executor a través del cual se invoca la devolución de llamada. Este objeto Executor se puede ejecutar en en un solo subproceso o en el conjunto de subprocesos que elijas.

La mayoría de las APIs de EuiccCardManager tienen el mismo patrón de uso. Por ejemplo, para cargar un de perfil vinculado al eUICC:

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

Para cambiar a un perfil diferente con un ICCID determinado, haz lo siguiente:

...
cardMgr.switchToProfile(eid, iccid, true /* refresh */,
        AsyncTask.THREAD_POOL_EXECUTOR, callback);

Para obtener la dirección SM-DP+ predeterminada del chip eUICC, haz lo siguiente:

...
cardMgr.requestDefaultSmdpAddress(eid, AsyncTask.THREAD_POOL_EXECUTOR,
        callback);

Para recuperar una lista de notificaciones de los eventos de notificación determinados, haz lo siguiente:

...
cardMgr.listNotifications(eid,
        EuiccNotification.Event.INSTALL
              | EuiccNotification.Event.DELETE /* events */,
        AsyncTask.THREAD_POOL_EXECUTOR, callback);

Cómo activar un perfil de eSIM a través de la app de un operador

En dispositivos que ejecutan Android 9 o versiones posteriores, puedes usar una app del operador para activar la eSIM y descarga los perfiles. La app del operador puede descargar perfiles llamando downloadSubscription directamente o proporcionando un código de activación a la LPA.

Cuando una app del operador llama para descargar un perfil downloadSubscription: la llamada exige que la app administre el perfil mediante un elemento BF76 etiqueta de metadatos que codifica reglas de privilegios de proveedor para la perfil. Si un perfil no tiene una etiqueta BF76 o si su etiqueta BF76 no tiene una coincida con la firma de la app del operador que realiza la llamada, se rechazará la descarga.

En la siguiente sección, se describe cómo activar una eSIM a través de una app de operador con una código de activación.

Activa la eSIM con un código de activación

Cuando se usa un código de activación para activar un perfil de eSIM, el LPA recupera un código de activación de la app del operador y descarga el perfil. El LPA puede iniciar este flujo y el LPA puede controlar todo el flujo de la IU, lo que significa que no se que se muestra. Este enfoque omite la verificación de etiqueta BF76 y los operadores de red no implementar todo el flujo de la IU de activación de eSIM, lo que incluye descargar una Perfil de eSIM y manejo de errores.

Define el servicio de aprovisionamiento de eUICC del proveedor

El LPA y la app del operador se comunican a través de dos AIDL interfaces: ICarrierEuiccProvisioningService y IGetActivationCodeCallback. La empresa de transporte La app debe implementar una interfaz ICarrierEuiccProvisioningService y la exponían en su declaración del manifiesto. El LPA debe vincularse a ICarrierEuiccProvisioningService e implementar IGetActivationCodeCallback Para obtener más información sobre cómo implementar expón una interfaz de AIDL, consulta Definición y interfaz de AIDL.

Para definir las interfaces del AIDL, crea los siguientes archivos del AIDL tanto para la LPA como para las apps del operador.

  • 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();
    }
    

Ejemplo de implementación de LPA

Para realizar la vinculación con la implementación de ICarrierEuiccProvisioningService de la app del operador, haz lo siguiente: el LPA debe copiar tanto ICarrierEuiccProvisioningService.aidl como IGetActivationCodeCallback.aidl a tu proyecto y, luego, implementa ServiceConnection

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

Después de la vinculación con la ICarrierEuiccProvisioningService de la app del operador implementación, el LPA llama a getActivationCode o getActivationCodeForEid para obtener el código de activación de la app del operador antes del pasando la implementación de la clase de stub IGetActivationCodeCallback.

La diferencia entre getActivationCode y getActivationCodeForEid es que getActivationCodeForEid permite que un operador vincule previamente un perfil al del dispositivo. el EID antes de que comience el proceso de descarga.

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
    }
}

Ejemplo de implementación para una app del operador

Para que el LPA se vincule con la app del operador, esta última debe copiar ICarrierEuiccProvisioningService.aidl y IGetActivationCodeCallback.aidl para tu proyecto y declara el servicio ICarrierEuiccProvisioningService en el AndroidManifest.xml. El servicio debe requerir la android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS permiso del sistema para garantizar que solo la LPA, una app con privilegios del sistema, puede vincularse a ella. El servicio debe también puedes incluir un filtro de intents con la 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>
    

Para implementar el servicio de la app de proveedor del AIDL, crea un servicio y extiende el Stub e implementaremos getActivationCode y getActivationCodeForEid. . Luego, el LPA puede llamar a cualquiera de los dos métodos para recuperar la activación del perfil. código. La app del operador debería responder llamando IGetActivationCodeCallback#onSuccess por el código de activación si se proporcionó del servidor del operador. Si no funciona, la app del operador debería responder 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);
              }
          }
    }
    

Inicia la IU de una app de operador en el flujo de activación de LPA

En dispositivos con Android 11 y versiones posteriores, el LPA puede iniciar la IU de una app del operador. Esto es útil cuando una app de operador puede requerir información adicional de la usuario antes de proporcionarle un código de activación a la LPA. Por ejemplo, las empresas de transporte podrían Exigir que los usuarios accedan para activar sus números de teléfono o realizar otra portabilidad de Google Cloud.

Este es el proceso para iniciar la IU de una app del operador en el LPA:

  1. La LPA inicia el flujo de activación de la app del operador enviando el el intent android.service.euicc.action.START_CARRIER_ACTIVATION al paquete de app del operador que contiene la acción. (El receptor de la app del operador debe en la declaración del manifiesto con android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" a evita recibir intents de aplicaciones que no sean 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. La app del operador realiza su trabajo usando su propia IU. Por ejemplo, el registro en el usuario o enviar solicitudes HTTP al backend del proveedor.

  3. La app del operador responde al LPA llamando a setResult(int, Intent). y finish().

    1. Si la app del operador responde con RESULT_OK, el LPA y continúa el flujo de activación. Si la app del operador determina que el el usuario debe escanear el código QR en lugar de permitir que el LPA vincule al operador servicio de la app, la app del operador responde al LPA con setResult(int, Intent) con RESULT_OK y una instancia Intent con el valor booleano adicional android.telephony.euicc.extra.USE_QR_SCANNER se estableció en true. La LPA verifica el extra y, luego, inicia el escáner de códigos QR en lugar de vincularlo la implementación de ICarrierEuiccProvisioningService de la app del operador
    2. Si la app del operador falla o responde con RESULT_CANCELED (este es el código de respuesta predeterminado), el LPA cancela de activación.
    3. Si la app del operador responde RESULT_OK o RESULT_CANCELED, el LPA lo trata como un error.

    Por motivos de seguridad, la LPA no debe aceptar directamente un código de activación proporcionado en el intent del resultado para garantizar que los los emisores no pueden obtener un código de activación de la app del operador.

Cómo iniciar el flujo de activación de LPA en una app de operador

A partir de Android 11, las apps de operadores pueden usar las APIs de eUICC para iniciar una LUI para eSIM activación. Este método muestra la IU del flujo de activación de eSIM del LPA para activar el perfil de eSIM. El LPA envía una transmisión cuando el perfil de eSIM finaliza la activación.

  1. El LPA debe declarar una actividad que incluya un filtro de intents con el elemento android.service.euicc.action.START_EUICC_ACTIVATION. La prioridad del filtro de intents debe fijarse en un valor distinto de cero en caso de que implementaciones están presentes en el dispositivo. Por ejemplo:

    <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. La app del operador realiza su trabajo usando su propia IU. Por ejemplo, el registro en el usuario o enviar solicitudes HTTP al backend del proveedor.

  3. En este punto, la app del operador debe estar lista para proporcionar una activación código a través de su implementación de ICarrierEuiccProvisioningService. El una app de operador de telefonía celular inicia la LPA llamando startActivityForResult(Intent, int) con el android.telephony.euicc.action.START_EUICC_ACTIVATION acción. El LPA también verifica el valor booleano adicional android.telephony.euicc.extra.USE_QR_SCANNER Si el valor es true, la El LPA inicia el escáner de códigos QR para permitir que el usuario escanee el código QR del perfil.

  4. En el lado del LPA, el LPA se vincula al Implementación de ICarrierEuiccProvisioningService para recuperar la activación código y descarga el perfil correspondiente. El LPA muestra toda la información elementos de la IU durante la descarga, como una pantalla de carga.

  5. Cuando se completa el flujo de activación del LPA, el LPA responde al app del operador con un código de resultado, que la app del operador procesa en onActivityResult(int, int, Intent)

    1. Si la LPA logra descargar el nuevo perfil de eSIM, responde con RESULT_OK.
    2. Si el usuario cancela la activación del perfil de eSIM en el LPA, responde con RESULT_CANCELED.
    3. Si el LPA responde con algo distinto a RESULT_OK o RESULT_CANCELED, la app del operador considera que se produjo un error.

    Por motivos de seguridad, la LPA no acepta un código de activación. directamente en el intent proporcionado para garantizar que el código de activación de la app del operador.

Compatibilidad con varias eSIM

Para dispositivos con Android 10 o versiones posteriores, la La clase EuiccManager admite dispositivos con varias eSIM. Dispositivos con una sola eSIM que se actualizarán a Android 10 no requieren ninguna modificación en la implementación de LPA como la plataforma asocia de forma automática la instancia de EuiccManager con el eUICC predeterminado. El La plataforma determina el eUICC predeterminado para los dispositivos con versión de HAL de radio 1.2 o superior, y por el LPA para dispositivos con versiones de HAL de radio inferiores a 1.2

Requisitos

Para admitir varias eSIM, el dispositivo debe tener más de un eUICC, que puede un eUICC integrado o una ranura SIM física en la que se puedan o insertarse.

Se requiere la versión 1.2 de la HAL de radio o una posterior para admitir varias eSIM. HAL de radio se recomiendan la versión 1.4 y la versión 1.2 de la HAL de RadioConfig.

Implementación

Para admitir varias eSIM (incluidos los eUICC extraíbles o las SIM programables), la El LPA debe implementar EuiccService: que recibe el ID de ranura correspondiente al ID de tarjeta proporcionado por el emisor.

El non_removable_euicc_slots recurso especificado en arrays.xml es un array de números enteros que representan los IDs de ranuras de la interfaz eUICC. Debes especificar este recurso para permitir que la plataforma determine si se puede quitar o no un eUICC insertado.

App del operador para dispositivos con varias eSIM

Si creas una app de operador para un dispositivo con varias eSIM, usa la createForCardId en EuiccManager para crear un objeto EuiccManager que se fije a un el ID de la tarjeta proporcionada. El ID de la tarjeta es un número entero que identifica de forma exclusiva un UICC. o un eUICC en el dispositivo.

Para obtener el ID de la tarjeta del eUICC predeterminado del dispositivo, usa el getCardIdForDefaultEuicc en TelephonyManager. Este método devuelve UNSUPPORTED_CARD_ID si la versión de la HAL de la radio es anterior a la 1.2 y devuelve UNINITIALIZED_CARD_ID si el dispositivo no leyó el eUICC.

También puedes obtener los IDs de la tarjeta en getUiccCardsInfo y getUiccSlotsInfo (API del sistema) en TelephonyManager, y getCardId en SubscriptionInfo.

Cuando se crea una instancia de un objeto EuiccManager con un ID de tarjeta específico, las operaciones se dirigen al eUICC con ese ID de tarjeta. Si el eUICC se convierte en inaccesible (por ejemplo, cuando se desactiva o se quita) EuiccManager no más largo.

Puedes usar las siguientes muestras de código para crear una app de operador.

Ejemplo 1: Obtén una suscripción activa y crea una instancia de 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);

Ejemplo 2: Itera a través de las UICC y crea una instancia de EuiccManager para un eUICC extraíble

// 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);
}

Validación

AOSP no incluye una implementación de LPA y no se espera que tú Tener un LPA disponible en todas las versiones de Android (no todos los teléfonos admiten eSIM). Para por lo que no hay casos de prueba de CTS de extremo a extremo. Sin embargo, los casos de prueba básicos están disponibles en AOSP para garantizar que se expongan las APIs de eUICC son válidos en compilaciones de Android.

Debes asegurarte de que las compilaciones pasen los siguientes casos de prueba de CTS (para uso APIs): /platform/cts/tests/tests/telephony/current/src/android/telephony/euicc/cts.

Los operadores que implementan una app de operador deben someterse a su procedimiento interno habitual. control de calidad para garantizar que todas las funciones implementadas funcionen según lo previsto. En el como mínimo, la app del operador debería poder enumerar todos los perfiles de suscripción propiedad del mismo operador, descargar e instalar un perfil, activar un servicio en el perfil, cambiar entre perfiles y borrarlos.

Si creas tu propio LPA, deberías pasar por y pruebas. Debes trabajar con tu proveedor de módem, chip eUICC o proveedor de SO eSIM, proveedores y operadores de SM-DP+ para resolver problemas y garantizar la interoperabilidad de tu LPA dentro de la arquitectura de RSP. Una buena cantidad de pruebas manuales inevitable. Para lograr una mejor cobertura de prueba, sigue las Plan de prueba de RSP de GSMA SGP.23.