APIs eUICC

No Android 9, as APIs de gerenciamento de perfis (public e @SystemApi) estão disponíveis por meio da classe EuiccManager . As APIs de comunicação eUICC (somente @SystemApi) estão disponíveis por meio da classe EuiccCardManager .

Sobre eUICC

As operadoras podem criar aplicativos de operadora usando o EuiccManager para gerenciar perfis, conforme mostrado na Figura 1. Os aplicativos de operadora não precisam ser aplicativos do sistema, mas precisam ter privilégios de operadora concedidos pelos perfis eUICC. Um aplicativo LPA (LUI e back-end LPA) precisa ser um aplicativo do sistema (ou seja, incluído na imagem do sistema) para chamar o método @SystemApi.

Telefone Android com Carrier App e OEM LPA

Figura 1. Telefones Android com aplicativo de operadora e OEM LPA

Além da lógica de chamar EuiccCardManager e falar com o eUICC, os aplicativos LPA devem implementar o seguinte:

  • Cliente SM-DP+ conversando com servidor SM-DP+ para autenticação e download de perfis
  • [Opcional] SM-DS para obter mais perfis para download em potencial
  • Tratamento de notificação para enviar notificações ao servidor para atualizar o estado do perfil
  • [Opcional] Gerenciamento de slots, incluindo alternância entre lógica eSIM e pSIM. Isso é opcional se o telefone tiver apenas um chip eSIM.
  • eSIM OTA

Embora mais de um aplicativo LPA possa estar presente em um telefone Android, apenas um LPA pode ser selecionado para ser o LPA de trabalho real com base na prioridade definida no arquivo AndroidManifest.xml de cada aplicativo.

Usando o EuiccManager

As APIs LPA são públicas por meio EuiccManager (no pacote android.telephony.euicc ). Um aplicativo de operadora pode obter a instância de EuiccManager e chamar os métodos em EuiccManager para obter as informações de eUICC e gerenciar assinaturas (referidas como perfis em documentos GSMA RSP) como instâncias de SubscriptionInfo.

Para chamar APIs públicas, incluindo operações de download, troca e exclusão de assinatura, o aplicativo da operadora deve ter os privilégios necessários. Os privilégios da operadora são adicionados pela operadora de celular nos metadados do perfil. A API eUICC impõe as regras de privilégio da operadora de acordo.

A plataforma Android não lida com as regras de política de perfil. Se uma regra de política for declarada nos metadados do perfil, o LPA poderá escolher como lidar com o procedimento de download e instalação do perfil. Por exemplo, é possível que um OEM LPA de terceiros manipule regras de política usando um código de erro especial (o código de erro é passado do OEM LPA para a plataforma e, em seguida, a plataforma passa o código para o OEM LUI).

Para obter informações sobre APIs de vários perfis ativados, consulte Vários perfis ativados .

APIs

As APIs a seguir podem ser encontradas na documentação de referência EuiccManager e EuiccManager.java .

Obter instância (pública)

Obtém a instância do EuiccManager por meio de Context#getSystemService . Para obter detalhes, consulte getSystemService .

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

Cheque ativado (público)

Verifica se a assinatura incorporada está habilitada. Isso deve ser verificado antes de acessar APIs LPA. Para obter detalhes, consulte isEnabled .

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

Obter EID (público)

Obtém o EID que identifica o hardware eUICC. Isso pode ser nulo se o eUICC não estiver pronto. O chamador deve ter privilégio de operadora ou a permissão READ_PRIVILEGED_PHONE_STATE . Para obter detalhes, consulte getEid .

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

Obter EuiccInfo (público)

Obtém informações sobre o eUICC. Este contém a versão do sistema operacional. Para obter detalhes, consulte getEuiccInfo .

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

Baixar assinatura (público)

Baixa a assinatura fornecida (referida como "perfil" nos documentos GSMA RSP). A assinatura pode ser criada a partir de um código de ativação. Por exemplo, um código de ativação pode ser analisado a partir de um código QR. O download de uma assinatura é uma operação assíncrona.

O chamador deve ter a permissão WRITE_EMBEDDED_SUBSCRIPTIONS ou ter privilégios de operadora para a assinatura de destino. Para obter detalhes, 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);

Trocar assinatura (público)

Muda para (habilita) a assinatura fornecida. O chamador deve ter WRITE_EMBEDDED_SUBSCRIPTIONS ou ter privilégios de operadora para a assinatura habilitada atual e a assinatura de destino. Para obter detalhes, 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);

Trocar assinatura com porta (pública)

(Disponível a partir do Android 13) Muda para (habilita) a assinatura fornecida com o índice de porta especificado. O chamador deve ter WRITE_EMBEDDED_SUBSCRIPTIONS ou ter privilégios de operadora para a assinatura habilitada atual e a assinatura de destino. Para obter detalhes, 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);

A porta SIM está disponível (pública)

public boolean isSimPortAvailable(int portIndex)

(Disponível a partir do Android 13) Retorna se o índice da porta de passagem está disponível. Uma porta está disponível se não tiver assinatura habilitada ou se o aplicativo de chamada tiver privilégio de operadora sobre a assinatura instalada na porta selecionada. Para obter detalhes, consulte isSimPortAvailable .

Excluir assinatura (público)

Exclui uma assinatura com um ID de assinatura. Se a assinatura estiver ativa no momento, ela será desativada primeiro. O chamador deve ter WRITE_EMBEDDED_SUBSCRIPTIONS ou privilégios de operadora para a assinatura de destino. Para obter detalhes, 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);

Apague todas as assinaturas (API do sistema)

Apaga todas as assinaturas em um dispositivo. A partir do Android 11, você deve fornecer um valor de enumeração EuiccCardManager#ResetOption para especificar se deseja apagar todos os tipos de assinaturas de teste, operacionais ou ambos. O chamador deve ter permissão 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 atividade de resolução (público)

Inicia uma atividade para resolver um erro que pode ser resolvido pelo usuário. Se uma operação retornar EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR , esse método poderá ser chamado para solicitar que o usuário resolva o problema. Este método só pode ser chamado uma vez para um erro específico.

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

Constantes

Para ver uma lista das constantes public no EuiccManager , consulte Constants .

,

No Android 9, as APIs de gerenciamento de perfis (public e @SystemApi) estão disponíveis por meio da classe EuiccManager . As APIs de comunicação eUICC (somente @SystemApi) estão disponíveis por meio da classe EuiccCardManager .

Sobre eUICC

As operadoras podem criar aplicativos de operadora usando o EuiccManager para gerenciar perfis, conforme mostrado na Figura 1. Os aplicativos de operadora não precisam ser aplicativos do sistema, mas precisam ter privilégios de operadora concedidos pelos perfis eUICC. Um aplicativo LPA (LUI e back-end LPA) precisa ser um aplicativo do sistema (ou seja, incluído na imagem do sistema) para chamar o método @SystemApi.

Telefone Android com Carrier App e OEM LPA

Figura 1. Telefones Android com aplicativo de operadora e OEM LPA

Além da lógica de chamar EuiccCardManager e falar com o eUICC, os aplicativos LPA devem implementar o seguinte:

  • Cliente SM-DP+ conversando com servidor SM-DP+ para autenticação e download de perfis
  • [Opcional] SM-DS para obter mais perfis para download em potencial
  • Tratamento de notificação para enviar notificações ao servidor para atualizar o estado do perfil
  • [Opcional] Gerenciamento de slots, incluindo alternância entre lógica eSIM e pSIM. Isso é opcional se o telefone tiver apenas um chip eSIM.
  • eSIM OTA

Embora mais de um aplicativo LPA possa estar presente em um telefone Android, apenas um LPA pode ser selecionado para ser o LPA de trabalho real com base na prioridade definida no arquivo AndroidManifest.xml de cada aplicativo.

Usando o EuiccManager

As APIs LPA são públicas por meio EuiccManager (no pacote android.telephony.euicc ). Um aplicativo de operadora pode obter a instância de EuiccManager e chamar os métodos em EuiccManager para obter as informações de eUICC e gerenciar assinaturas (referidas como perfis em documentos GSMA RSP) como instâncias de SubscriptionInfo.

Para chamar APIs públicas, incluindo operações de download, troca e exclusão de assinatura, o aplicativo da operadora deve ter os privilégios necessários. Os privilégios da operadora são adicionados pela operadora de celular nos metadados do perfil. A API eUICC aplica as regras de privilégio da operadora de acordo.

A plataforma Android não lida com as regras de política de perfil. Se uma regra de política for declarada nos metadados do perfil, o LPA poderá escolher como lidar com o procedimento de download e instalação do perfil. Por exemplo, é possível que um OEM LPA de terceiros manipule regras de política usando um código de erro especial (o código de erro é passado do OEM LPA para a plataforma e, em seguida, a plataforma passa o código para o OEM LUI).

Para obter informações sobre APIs de vários perfis ativados, consulte Vários perfis ativados .

APIs

As APIs a seguir podem ser encontradas na documentação de referência EuiccManager e EuiccManager.java .

Obter instância (pública)

Obtém a instância do EuiccManager por meio de Context#getSystemService . Para obter detalhes, consulte getSystemService .

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

Cheque ativado (público)

Verifica se a assinatura incorporada está habilitada. Isso deve ser verificado antes de acessar APIs LPA. Para obter detalhes, consulte isEnabled .

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

Obter EID (público)

Obtém o EID que identifica o hardware eUICC. Isso pode ser nulo se o eUICC não estiver pronto. O chamador deve ter privilégio de operadora ou a permissão READ_PRIVILEGED_PHONE_STATE . Para obter detalhes, consulte getEid .

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

Obter EuiccInfo (público)

Obtém informações sobre o eUICC. Este contém a versão do sistema operacional. Para obter detalhes, consulte getEuiccInfo .

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

Baixar assinatura (público)

Baixa a assinatura fornecida (referida como "perfil" nos documentos GSMA RSP). A assinatura pode ser criada a partir de um código de ativação. Por exemplo, um código de ativação pode ser analisado a partir de um código QR. O download de uma assinatura é uma operação assíncrona.

O chamador deve ter a permissão WRITE_EMBEDDED_SUBSCRIPTIONS ou ter privilégios de operadora para a assinatura de destino. Para obter detalhes, 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);

Trocar assinatura (público)

Muda para (habilita) a assinatura fornecida. O chamador deve ter WRITE_EMBEDDED_SUBSCRIPTIONS ou ter privilégios de operadora para a assinatura habilitada atual e a assinatura de destino. Para obter detalhes, 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);

Trocar assinatura com porta (pública)

(Disponível a partir do Android 13) Muda para (habilita) a assinatura fornecida com o índice de porta especificado. O chamador deve ter WRITE_EMBEDDED_SUBSCRIPTIONS ou ter privilégios de operadora para a assinatura habilitada atual e a assinatura de destino. Para obter detalhes, 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);

A porta SIM está disponível (pública)

public boolean isSimPortAvailable(int portIndex)

(Disponível a partir do Android 13) Retorna se o índice da porta de passagem está disponível. Uma porta está disponível se não tiver assinatura habilitada ou se o aplicativo de chamada tiver privilégio de operadora sobre a assinatura instalada na porta selecionada. Para obter detalhes, consulte isSimPortAvailable .

Excluir assinatura (público)

Exclui uma assinatura com um ID de assinatura. Se a assinatura estiver ativa no momento, ela será desativada primeiro. O chamador deve ter WRITE_EMBEDDED_SUBSCRIPTIONS ou privilégios de operadora para a assinatura de destino. Para obter detalhes, 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);

Apague todas as assinaturas (API do sistema)

Apaga todas as assinaturas em um dispositivo. A partir do Android 11, você deve fornecer um valor de enumeração EuiccCardManager#ResetOption para especificar se deseja apagar todos os tipos de assinaturas de teste, operacionais ou ambos. O chamador deve ter permissão 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 atividade de resolução (público)

Inicia uma atividade para resolver um erro que pode ser resolvido pelo usuário. Se uma operação retornar EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR , esse método poderá ser chamado para solicitar que o usuário resolva o problema. Este método só pode ser chamado uma vez para um erro específico.

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

Constantes

Para ver uma lista das constantes public no EuiccManager , consulte Constants .