No Android 9, as APIs de gerenciamento de perfis (públicas e
@SystemApi) estão disponíveis na classe EuiccManager
. As APIs de comunicação eUICC
(somente @SystemApi) estão disponíveis na classe EuiccCardManager
.
Sobre o eUICC
As operadoras podem criar apps usando o EuiccManager para gerenciar perfis, conforme mostrado na Figura 1. Os apps das operadoras não precisam ser apps do sistema, mas precisam ter privilégios de operadora concedidos por perfis de eUICC. Um app LPA (LUI e LPA backend) precisa ser um app do sistema (ou seja, incluído na imagem do sistema) para chamar a @SystemApi.
Figura 1. Smartphones Android com app da operadora e LPA do OEM
Além da lógica de chamar EuiccCardManager
e se comunicar com o eUICC, os apps LPA
precisam implementar o seguinte:
- Cliente SM-DP+ conversando com o servidor SM-DP+ para autenticar e fazer o download de perfis
- [Opcional] SM-DS para receber mais perfis para download
- Processamento de notificações para enviar notificações ao servidor e atualizar o estado do perfil
- [Opcional] Gerenciamento de slots, incluindo a troca entre a lógica de eSIM e pSIM. Isso é opcional se o smartphone tiver apenas um chip eSIM.
- OTA do eSIM
Embora mais de um app de LPA possa estar presente em um smartphone Android, apenas um pode ser selecionado como o LPA em funcionamento com base na prioridade definida no arquivo AndroidManifest.xml
de cada app.
Usar o EuiccManager
As APIs LPA são públicas por meio de EuiccManager
(no pacote
android.telephony.euicc
). Um app da operadora pode receber a instância de EuiccManager
e chamar os métodos em EuiccManager
para receber as informações do eUICC e gerenciar
assinaturas (chamadas de perfis nos documentos RSP da GSMA) como
instâncias SubscriptionInfo.
Para chamar APIs públicas, incluindo operações de download, troca e exclusão de assinatura, o app da operadora precisa 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 com a situação.
A plataforma Android não processa as regras de política de perfil. Se uma regra de política for declarada nos metadados do perfil, a LPA poderá escolher como lidar com o procedimento de download e instalação do perfil. Por exemplo, é possível que uma LPA OEM de terceiros processe regras de política usando um código de erro especial (o código é transmitido da LPA OEM para a plataforma, que o transmite para a LUI OEM).
Para informações sobre várias APIs de perfis ativados, consulte Vários perfis ativados.
APIs
As seguintes APIs podem ser encontradas na
documentação de referência do EuiccManager
e
EuiccManager.java
.
Acessar instância (pública)
Recebe a instância de EuiccManager
por Context#getSystemService
.
Para mais detalhes, consulte
getSystemService
.
EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
Verificação ativada (pública)
Verifica se a assinatura incorporada está ativada. Isso precisa ser verificado
antes de acessar as APIs do LPA. Para mais detalhes, consulte
isEnabled
.
boolean isEnabled = mgr.isEnabled();
if (!isEnabled) {
return;
}
Receber EID (público)
Recebe o EID que identifica o hardware eUICC. Pode ser nulo se o eUICC não estiver pronto. O autor da chamada precisa ter privilégio de operadora ou a permissão
READ_PRIVILEGED_PHONE_STATE
. Para mais detalhes, consulte
getEid
.
String eid = mgr.getEid();
if (eid == null) {
// Handle null case.
}
Receber EuiccInfo (público)
Recebe informações sobre o eUICC. Ele contém a versão do SO. Para detalhes, consulte
getEuiccInfo
.
EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();
Baixar assinatura (pública)
Faz o download da assinatura especificada (chamada de "perfil" nos documentos RSP da GSMA). A assinatura pode ser criada com um código de ativação. Por exemplo, um código de ativação pode ser analisado de um QR code. O download de uma assinatura é uma operação assíncrona.
O autor da chamada precisa ter a permissão WRITE_EMBEDDED_SUBSCRIPTIONS
ou
privilégios de operadora para a assinatura de destino. Para mais 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ública)
Muda para (ativa) a assinatura especificada. O autor da chamada precisa ter WRITE_EMBEDDED_SUBSCRIPTIONS
ou privilégios de operadora para a assinatura ativada atual e a assinatura de destino. Para mais 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);
Mudar a assinatura com porta (pública)
(Disponível no Android 13) Muda para (ativa)
a assinatura especificada com o índice de porta especificado.
O autor da chamada precisa ter WRITE_EMBEDDED_SUBSCRIPTIONS
ou privilégios de operadora para a assinatura ativada atual e a assinatura de destino.
Para mais 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 do chip está disponível (pública)?
public boolean isSimPortAvailable(int portIndex)
(Disponível no Android 13) Retorna se o
índice da porta de transmissão está disponível. Uma porta está disponível se ela
não tiver uma assinatura ativada ou se o app de chamada tiver privilégio da operadora sobre a
assinatura instalada na porta selecionada. Para mais detalhes, consulte
isSimPortAvailable
.
Excluir assinatura (pública)
Exclui uma assinatura com um ID de assinatura. Se a assinatura estiver ativa, ela será desativada primeiro. O autor da chamada precisa ter WRITE_EMBEDDED_SUBSCRIPTIONS
ou privilégios de operadora para a assinatura de destino. Para mais 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);
Apagar todas as assinaturas (API do sistema)
Apaga todas as assinaturas em um dispositivo. A partir do Android
11, é necessário fornecer um valor de enumeração EuiccCardManager#ResetOption
para especificar se é preciso apagar todos os tipos de assinaturas de teste, operacional ou ambos. O autor da chamada precisa ter a 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ública)
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 pedir que o usuário resolva o problema. Esse método só pode ser chamado
uma vez para um erro específico.
...
mgr.startResolutionActivity(getActivity(), 0 /* requestCode */, resultIntent, callbackIntent);
Constantes
Para conferir uma lista das constantes public
em EuiccManager
, consulte
Constantes.