APIs de eUICC

En Android 9, las APIs de administración de perfiles (públicas y @SystemApi) están disponibles a través de la clase EuiccManager. Las APIs de comunicación de eUICC (solo @SystemApi) están disponibles a través de la clase EuiccCardManager.

Acerca de eUICC

Los operadores pueden crear apps de operador con EuiccManager para administrar perfiles, como se muestra en la Figura 1. Las apps de operador no necesitan ser apps del sistema, pero deben tener privilegios de operador otorgados por perfiles de eUICC. Una app de LPA (LUI y backend de LPA ) debe ser una app del sistema (es decir, incluida en la imagen del sistema) para llamar a la @SystemApi.

Teléfono Android con la app de la operadora y la LPA del OEM

Figura 1: Teléfonos Android con app de operador y LPA de OEM

Además de la lógica de llamar a EuiccCardManager y comunicarse con eUICC, las apps de LPA deben implementar lo siguiente:

  • Cliente de SM-DP+ que se comunica con el servidor de SM-DP+ para autenticar y descargar perfiles
  • [Opcional] SM-DS para obtener más perfiles descargables potenciales
  • Control de notificaciones para enviar notificaciones al servidor para actualizar el estado del perfil
  • [Opcional] Administración de ranuras, incluido el cambio entre la lógica de eSIM y pSIM. Esto es opcional si el teléfono solo tiene un chip eSIM.
  • OTA de eSIM

Aunque puede haber más de una app de LPA en un teléfono Android, solo se puede seleccionar una LPA para que sea la LPA de trabajo real según la prioridad definida en el archivo AndroidManifest.xml de cada app.

Usa EuiccManager

Las APIs de LPA son públicas a través de EuiccManager (en el paquete android.telephony.euicc). Una app de operador puede obtener la instancia de EuiccManager y llamar a los métodos en EuiccManager para obtener la información de eUICC y administrar las suscripciones (denominadas perfiles en los documentos de GSMA RSP) como instancias de SubscriptionInfo.

Para llamar a las APIs públicas, incluidas las operaciones de descarga, cambio y eliminación de suscripciones, la app de operador debe tener los privilegios necesarios. El operador de telefonía celular agrega los privilegios de operador en los metadatos del perfil. La API de eUICC aplica las reglas de privilegios de operador en consecuencia.

La plataforma de Android no controla las reglas de política de perfiles. Si se declara una regla de política en los metadatos del perfil, la LPA puede elegir cómo controlar el procedimiento de descarga e instalación del perfil. Por ejemplo, es posible que una LPA de OEM de terceros controle las reglas de política con un código de error especial (el código de error se pasa de la LPA de OEM a la plataforma y, luego, la plataforma pasa el código a la LUI de OEM).

Para obtener información sobre las APIs de varios perfiles habilitados, consulta Varios perfiles habilitados.

API

Las siguientes APIs se pueden encontrar en la EuiccManager documentación de referencia y EuiccManager.java.

Obtener instancia (pública)

Obtiene la instancia de EuiccManager a través de Context#getSystemService. Para obtener más información, consulta getSystemService.

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

Verificación habilitada (pública)

Verifica si la suscripción incorporada está habilitada. Esto se debe verificar antes de acceder a las APIs de LPA. Para obtener más información, consulta isEnabled.

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

Obtener EID (público)

Obtiene el EID que identifica el hardware de eUICC. Puede ser nulo si la eUICC no está lista. El llamador debe tener privilegios de operador o el permiso READ_PRIVILEGED_PHONE_STATE. Para obtener más información, consulta getEid.

String eid = mgr.getEid();
if (eid == null) {
  // Handle null case.
}

Obtener EuiccInfo (público)

Obtiene información sobre la eUICC. Esto contiene la versión del SO. Para obtener más información, consulta getEuiccInfo.

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

Descargar suscripción (pública)

Descarga la suscripción determinada (denominada "perfil" en los documentos de GSMA RSP). La suscripción se puede crear a partir de un código de activación. Por ejemplo, un código de activación se puede analizar desde un código QR. La descarga de una suscripción es una operación asíncrona.

El llamador debe tener el permiso WRITE_EMBEDDED_SUBSCRIPTIONS o privilegios de operador para la suscripción de destino. Para obtener más información, consulta downloadSubscription.

// Register receiver.
String action = "download_subscription";
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),
        "example.broadcast.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);

Cambiar de suscripción (pública)

Cambia a la suscripción determinada (la habilita). El llamador debe tener WRITE_EMBEDDED_SUBSCRIPTIONS o privilegios de operador para la suscripción habilitada actual y la suscripción de destino. Para obtener más información, consulta switchToSubscription.

// Register receiver.
String action = "switch_to_subscription";
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),
        "example.broadcast.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);

Cambiar de suscripción con puerto (pública)

(Disponible desde Android 13) Cambia a la suscripción determinada (la habilita) con el índice de puerto especificado. El llamador debe tener WRITE_EMBEDDED_SUBSCRIPTIONS o privilegios de operador para la suscripción habilitada actual y la suscripción de destino. Para obtener más información, consulta switchToSubscription.

// Register receiver.
String action = "switch_to_subscription";
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),
        "example.broadcast.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 */, 0 /*portIndex*/, callbackIntent);

¿Está disponible el puerto SIM? (público)

public boolean isSimPortAvailable(int portIndex)

(Disponible desde Android 13) Muestra si el índice de puerto de paso está disponible. Un puerto está disponible si no tiene ninguna suscripción habilitada o si la app que llama tiene privilegios de operador sobre la suscripción instalada en el puerto seleccionado. Para obtener más información, consulta isSimPortAvailable.

Borrar suscripción (pública)

Borra una suscripción con un ID de suscripción. Si la suscripción está activa, primero se inhabilita. El llamador debe tener WRITE_EMBEDDED_SUBSCRIPTIONS o privilegios de operador para la suscripción de destino. Para obtener más información, consulta deleteSubscription.

// Register receiver.
String action = "delete_subscription";
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),
        "example.broadcast.permission" /* broadcastPermission*/,
        null /* handler */);

// Delete a subscription asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.deleteSubscription(1 /* subscriptionId */, callbackIntent);

Borrar todas las suscripciones (API del sistema)

Borra todas las suscripciones en un dispositivo. A partir de Android 11, debes proporcionar un valor de enum EuiccCardManager#ResetOption para especificar si se deben borrar todas las suscripciones de prueba, operativas o ambos tipos. El llamador debe tener el permiso WRITE_EMBEDDED_SUBSCRIPTIONS.

// Register receiver.
String action = "delete_subscription";
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),
        "example.broadcast.permission" /* broadcastPermission*/,
        null /* handler */);

// Erase all operational subscriptions asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.eraseSubscriptions(
        EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, callbackIntent);

Iniciar actividad de resolución (pública)

Inicia una actividad para resolver un error que el usuario puede resolver. Si una operación muestra EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR, se puede llamar a este método para solicitar al usuario que resuelva el problema. Este método solo se puede llamar una vez para un error en particular.

...
mgr.startResolutionActivity(getActivity(), 0 /* requestCode */, resultIntent, callbackIntent);

Constantes

Para ver una lista de las constantes public en EuiccManager, consulta Constantes.