API eUICC

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

Acerca de eUICC

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

Teléfono Android con aplicación Carrier y OEM LPA

Figura 1. Teléfonos Android con aplicación de operador y OEM LPA

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

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

Aunque más de una aplicación LPA puede estar presente 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 aplicación.

Uso de EuiccManager

Las API de LPA son públicas a través de EuiccManager (en el paquete android.telephony.euicc ). Una aplicación 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 GSMA RSP) como instancias de SubscriptionInfo.

Para llamar a las API públicas, incluidas las operaciones de descarga, cambio y eliminación de suscripción, la aplicación del operador debe tener los privilegios necesarios. Los privilegios del operador son agregados por el operador móvil en los metadatos del perfil. La API de eUICC hace cumplir las reglas de privilegio del operador en consecuencia.

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

Para obtener información sobre varias API de perfiles habilitados, consulte Varios perfiles habilitados .

API

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

Obtener instancia (pública)

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

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

Comprobar habilitado (público)

Comprueba si la suscripción integrada está habilitada. Esto debe verificarse antes de acceder a las API de LPA. Para obtener más información, consulte isEnabled .

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

Obtener EID (público)

Obtiene el EID que identifica el hardware eUICC. Esto puede ser nulo si el eUICC no está listo. La persona que llama debe tener privilegios de operador o el permiso READ_PRIVILEGED_PHONE_STATE . Para obtener más información, consulte getEid .

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

Obtener EuiccInfo (público)

Obtiene información sobre la eUICC. Contiene la versión del sistema operativo. Para obtener más información, consulte getEuiccInfo .

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

Descargar suscripción (pública)

Descarga la suscripción dada (denominada "perfil" en los documentos 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 a partir de un código QR. La descarga de una suscripción es una operación asincrónica.

La persona que llama debe tener el permiso WRITE_EMBEDDED_SUBSCRIPTIONS o tener privilegios de operador para la suscripción de destino. Para obtener más información, consulte 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 suscripción (pública)

Cambia a (habilita) la suscripción dada. La persona que llama debe tener WRITE_EMBEDDED_SUBSCRIPTIONS o tener privilegios de operador para la suscripción habilitada actual y la suscripción de destino. Para obtener más información, consulte 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 suscripción con puerto (público)

(Disponible desde Android 13) Cambia a (habilita) la suscripción dada con el índice de puerto especificado. La persona que llama debe tener WRITE_EMBEDDED_SUBSCRIPTIONS o tener privilegios de operador para la suscripción habilitada actual y la suscripción de destino. Para obtener más información, consulte 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 a partir de Android 13) Devuelve si el índice de puerto de paso está disponible. Un puerto está disponible si no tiene una suscripción habilitada o si la aplicación de llamada tiene privilegios de operador sobre la suscripción instalada en el puerto seleccionado. Para obtener más información, consulte isSimPortAvailable .

Eliminar suscripción (pública)

Elimina una suscripción con un ID de suscripción. Si la suscripción está actualmente activa, primero se deshabilita. La persona que llama debe tener WRITE_EMBEDDED_SUBSCRIPTIONS o privilegios de operador para la suscripción de destino. Para obtener más información, consulte 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, debe proporcionar un valor de enumeración EuiccCardManager#ResetOption para especificar si desea borrar todas las suscripciones de prueba, operativas o ambos tipos. La persona que llama debe tener 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úblico)

Inicia una actividad para resolver un error que puede resolver el usuario. Si una operación devuelve 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 , consulte Constantes .

,

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

Acerca de eUICC

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

Teléfono Android con aplicación Carrier y OEM LPA

Figura 1. Teléfonos Android con aplicación de operador y OEM LPA

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

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

Aunque más de una aplicación LPA puede estar presente 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 aplicación.

Uso de EuiccManager

Las API de LPA son públicas a través de EuiccManager (en el paquete android.telephony.euicc ). Una aplicación 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 GSMA RSP) como instancias de SubscriptionInfo.

Para llamar a las API públicas, incluidas las operaciones de descarga, cambio y eliminación de suscripción, la aplicación del operador debe tener los privilegios necesarios. Los privilegios del operador son agregados por el operador móvil en los metadatos del perfil. La API de eUICC hace cumplir las reglas de privilegio del operador en consecuencia.

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

Para obtener información sobre varias API de perfiles habilitados, consulte Varios perfiles habilitados .

API

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

Obtener instancia (pública)

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

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

Comprobar habilitado (público)

Comprueba si la suscripción integrada está habilitada. Esto debe verificarse antes de acceder a las API de LPA. Para obtener más información, consulte isEnabled .

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

Obtener EID (público)

Obtiene el EID que identifica el hardware eUICC. Esto puede ser nulo si el eUICC no está listo. La persona que llama debe tener privilegios de operador o el permiso READ_PRIVILEGED_PHONE_STATE . Para obtener más información, consulte getEid .

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

Obtener EuiccInfo (público)

Obtiene información sobre la eUICC. Contiene la versión del sistema operativo. Para obtener más información, consulte getEuiccInfo .

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

Descargar suscripción (pública)

Descarga la suscripción dada (denominada "perfil" en los documentos 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 a partir de un código QR. La descarga de una suscripción es una operación asincrónica.

La persona que llama debe tener el permiso WRITE_EMBEDDED_SUBSCRIPTIONS o tener privilegios de operador para la suscripción de destino. Para obtener más información, consulte 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 suscripción (pública)

Cambia a (habilita) la suscripción dada. La persona que llama debe tener WRITE_EMBEDDED_SUBSCRIPTIONS o tener privilegios de operador para la suscripción habilitada actual y la suscripción de destino. Para obtener más información, consulte 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 suscripción con puerto (público)

(Disponible desde Android 13) Cambia a (habilita) la suscripción dada con el índice de puerto especificado. La persona que llama debe tener WRITE_EMBEDDED_SUBSCRIPTIONS o tener privilegios de operador para la suscripción habilitada actual y la suscripción de destino. Para obtener más información, consulte 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 a partir de Android 13) Devuelve si el índice de puerto de paso está disponible. Un puerto está disponible si no tiene una suscripción habilitada o si la aplicación de llamada tiene privilegios de operador sobre la suscripción instalada en el puerto seleccionado. Para obtener más información, consulte isSimPortAvailable .

Eliminar suscripción (pública)

Elimina una suscripción con un ID de suscripción. Si la suscripción está actualmente activa, primero se deshabilita. La persona que llama debe tener WRITE_EMBEDDED_SUBSCRIPTIONS o privilegios de operador para la suscripción de destino. Para obtener más información, consulte 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, debe proporcionar un valor de enumeración EuiccCardManager#ResetOption para especificar si desea borrar todas las suscripciones de prueba, operativas o ambos tipos. La persona que llama debe tener 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úblico)

Inicia una actividad para resolver un error que puede resolver el usuario. Si una operación devuelve 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 , consulte Constantes .