Implementar eSIM

A tecnologia de chip incorporado (eSIM ou eUICC) permite que os usuários de dispositivos móveis fazer o download de um perfil e ativar o serviço de uma operadora sem precisar um chip físico. É uma especificação global promovida pela GSMA que permite provisionamento remoto de chip (RSP, na sigla em inglês) de qualquer dispositivo móvel. Começando com o Android 9, o framework do Android fornece APIs padrão para acessar o eSIM e gerenciar perfis de assinatura nele. Esses UICC As APIs permitem que terceiros desenvolvam os próprios apps de operadora e perfis locais Assistentes de rede (LPAs, na sigla em inglês) em dispositivos Android com eSIM.

O LPA é um aplicativo autônomo do sistema que deve ser incluído Imagem do build do Android. O gerenciamento dos perfis no eSIM geralmente é feito pela o LPA, atuando como uma ponte entre o SM-DP+ (serviço remoto que prepara, armazena e envia pacotes de perfil aos dispositivos) e o chip eUICC. O APK LPA pode incluir opcionalmente um componente de IU, chamado LPA UI ou LUI, para oferecem um local centralizado para o usuário final gerenciar todas as assinaturas incorporadas de perfil. O framework do Android descobre e se conecta automaticamente aos melhores o LPA disponível e encaminha todas as operações eUICC por meio de uma instância LPA.

Arquitetura simplificada de provisionamento remoto de chip (RSP, na sigla em inglês)

Figura 1. Arquitetura RSP simplificada

As operadoras de rede móvel interessadas em criar um app de operadora devem analisar as APIs no EuiccManager, que oferece operações de gerenciamento de perfil de alto nível, como downloadSubscription(), switchToSubscription() e deleteSubscription().

Se você é um OEM de dispositivo interessado em criar seu próprio app do sistema de LPA, é necessário se estendem EuiccService para que o framework do Android se conecte aos seus serviços LPA. Além disso, você devem usar as APIs EuiccCardManager, que têm funções ES10x baseadas no GSMA RSP v2.0. Essas funções são usadas para emitir comandos ao chip eUICC, como prepareDownload(), loadBoundProfilePackage() e retrieveNotificationList(). e resetMemory().

As APIs no EuiccManager exigem um aplicativo LPA implementado corretamente para funcionar e o autor da chamada de EuiccCardManager As APIs precisam ser LPA. Isso é aplicado pelo framework do Android.

Dispositivos com o Android 10 ou versões mais recentes têm suporte e dispositivos com vários eSIMs. Para mais informações, consulte Compatibilidade com vários eSIMs.

Criar um app de operadora

As APIs eUICC no Android 9 possibilitam operadores de rede móvel criem aplicativos com a marca das operadoras para gerenciar diretamente nos perfis. Isso inclui o download e a exclusão de perfis de assinatura da operadora, bem como mudar para um perfil pertencente a ela.

Gestor Euicc

O EuiccManager é o principal ponto de entrada para apps interagirem com o LPA Isso inclui apps de operadoras que fazem o download, a exclusão e a mudança para assinaturas de propriedade da operadora. Isso também inclui o app do sistema LUI, forneça um local/interface central para gerenciar todas as assinaturas incorporadas e pode ser um app separado daquele que fornece a EuiccService.

Para usar as APIs públicas, um aplicativo de operadora deve primeiro obter a instância de EuiccManager a Context#getSystemService:

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

Verifique se o eSIM é compatível com o dispositivo antes de realizar qualquer operações de eSIM. EuiccManager#isEnabled() geralmente retorna true se o O recurso android.hardware.telephony.euicc está definido e um pacote LPA é presente.

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

Para ver informações sobre o hardware eUICC e a versão do SO do eSIM:

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

Muitas APIs, como downloadSubscription() e switchToSubscription(), usam PendingIntent, já que podem levar segundos ou até minutos para serem concluídos. PendingIntent é enviado com um código de resultado no EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_, que oferece códigos de erro definidos pelo framework, bem como um código de resultado detalhado arbitrário propagadas do LPA como EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, permitindo o app da operadora para rastreamento para fins de registro/depuração. O PendingIntent o callback precisa ser BroadcastReceiver.

Para fazer download de uma determinada assinatura, criada a partir de um código de ativação ou um QR code):

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

Defina e use a permissão em 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 mudar para uma assinatura usando o ID dela, siga estas etapas:

// 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 conferir uma lista completa de APIs do EuiccManager e exemplos de código, consulte APIs eUICC.

Erros solucionáveis

Em alguns casos, o sistema não consegue concluir a operação do eSIM mas ele pode ser resolvido pelo usuário. Por exemplo, downloadSubscription. poderá falhar se os metadados do perfil indicarem que um código de confirmação da operadora é obrigatório. Ou o switchToSubscription pode falhar se o app da operadora tiver uma operadora sobre o perfil de destino (ou seja, a operadora é proprietária do perfil), mas não tem privilégios de operadora sobre o perfil ativado no momento e, portanto, o consentimento do usuário é obrigatório.

Nesses casos, o callback do autor da chamada é chamado com EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR: A chamada de retorno Intent contém extras internos, de modo que, quando o autor da chamada o transmite para EuiccManager#startResolutionActivity, e a resolução pode ser solicitada pela LUI. Usar o código de confirmação para exemplo de novo, EuiccManager#startResolutionActivity aciona uma tela de LUI que permite ao usuário inserir um código de confirmação; depois que o código for inserido, a operação de download será retomada. Essa abordagem fornece ao app da operadora controle total sobre quando a interface de usuário é mostrada, mas também o LPA/LUI é um método extensível para adicionar um novo tratamento de dados recuperáveis problemas no futuro sem precisar de alterações nos aplicativos clientes.

O Android 9 define esses erros resolvíveis EuiccService, que a LUI precisa gerenciar:

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

Privilégios da operadora

Se você é uma operadora que está desenvolvendo seu próprio app de operadora que faz chamadas para EuiccManager para fazer o download de perfis em um dispositivo, seu perfil deve incluir a operadora de privilégios correspondentes ao app da operadora nos metadados. Isso é porque perfis de assinatura de diferentes operadoras podem coexistir o eUICC de um dispositivo, e cada app de operadora só deve ter permissão para acessar o de propriedade da operadora. Por exemplo, a operadora A não poderá fazer o download, ativar ou desativar um perfil da operadora B.

Para garantir que um perfil só possa ser acessado pelo proprietário, o Android usa um mecanismo para conceder privilégios especiais ao app do proprietário do perfil (ou seja, ao app da operadora). A A plataforma Android carrega certificados armazenados no arquivo de regra de acesso do perfil (ARF, na sigla em inglês) e concede permissões para que apps assinados por esses certificados façam chamadas. às APIs EuiccManager. O processo de alto nível é descrito abaixo:

  1. O operador assina o APK do app da operadora. as apksigner (link em inglês) anexa o certificado de chave pública ao APK.
  2. O operador/SM-DP+ prepara um perfil e os metadados dele, que incluem um ARF que contenha:

    1. Assinatura (SHA-1 ou SHA-256) do certificado de chave pública do app da operadora (obrigatório)
    2. Nome do pacote do app da transportadora (altamente recomendado)
  3. O app da operadora tenta executar uma operação de eUICC com a API EuiccManager.

  4. A plataforma Android verifica o hash SHA-1 ou SHA-256 do código do app do certificado corresponde à assinatura do certificado obtido do do ARF do perfil de destino. Se o nome do pacote do app da operadora estiver incluído no do ARF, ele também precisa corresponder ao nome do pacote do app autor da chamada.

  5. Depois que a assinatura e o nome do pacote (se incluído) forem verificados, o o privilégio da operadora é concedido ao app autor da chamada no perfil de destino.

Como os metadados do perfil podem estar disponíveis fora do próprio perfil (para que O LPA pode recuperar os metadados do perfil do SM-DP+ antes que o perfil seja baixado ou a partir do ISD-R quando o perfil estiver desativado), ele deverá conter o as mesmas regras de privilégio de operadora do perfil.

O SO eUICC e o SM-DP+ precisam ser compatíveis com a tag proprietária BF76 no perfil metadados. O conteúdo da tag precisa ter as mesmas regras de privilégios da operadora retornadas pelo miniaplicativo de regra de acesso (ARA, na sigla em inglês) definido Privilégios da operadora 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 mais detalhes sobre a assinatura de apps, consulte Assinar o app. Para detalhes sobre privilégios de operadora, consulte Privilégios da operadora do UICC.

Criar um app assistente de perfil local

Os fabricantes de dispositivos podem implementar os próprios assistentes de perfil local (LPA, na sigla em inglês), que precisa ser conquistado com as APIs Android Euicc. As seções a seguir dão uma breve visão geral criar um app LPA e integrá-lo ao sistema Android.

Requisitos de hardware/modem

O LPA e o SO do eSIM no chip eUICC precisam ser compatíveis com pelo menos GSMA RSP (remoto) Provisionamento de chip) v2.0 ou v2.2. Você também deve planejar usar o SM-DP+ e o SM-DS que têm uma versão do RSP correspondente. Para conferir a arquitetura detalhada do RSP, consulte Especificação de arquitetura SGP.21 RSP do GSMA.

Além disso, para integrar com as APIs eUICC no Android 9, o modem do dispositivo deve enviar recursos do terminal com o suporte para recursos eUICC codificados (gerenciamento de perfil local e download de perfil). Ela também precisa implementar os seguintes métodos:

  • HAL do IRadio v1.1: setSimPower
  • HAL do IRadio v1.2: getIccCardStatus

  • HAL IRadioConfig v1.0: getSimSlotsStatus

  • AIDL do IRadioConfig v1.0: getAllowedCarriers

    O LPA do Google precisa saber o status do bloqueio da operadora para permitir o download ou a transferência do eSIM apenas para a operadora permitida. Caso contrário, os usuários podem acabar fazendo o download e transferindo um chip e, depois, percebem que a operadora do dispositivo está bloqueada para outra operadora.

    • Fornecedores ou OEMs precisam implementar a API IRadioSim.getAllowedCarriers()HAL.

    • A RIL / Modem do fornecedor precisa preencher o status de bloqueio e o merchantId da operadora com a qual o dispositivo está bloqueado como parte da API IRadioSimResponse.getAllowedCarriersResponse()HAL.

O modem reconhece o eSIM com o perfil de inicialização padrão ativado como chip válido e mantenha o chip ligado.

Para dispositivos com o Android 10, um eUICC não removível matriz de ID de slot deve ser definida. Por exemplo, consulte 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 uma lista completa dos requisitos de modem, consulte Requisitos de modem para suporte a eSIM.

Serviço Euicc

Um LPA consiste em dois componentes separados (ambos podem ser implementados no mesmo APK): o back-end da LPA e a interface do LPA ou LUI.

Para implementar o back-end de LPA, é preciso estender EuiccService e declare esse serviço no arquivo de manifesto. O serviço deve exigir a android.permission.BIND_EUICC_SERVICE para garantir que apenas o sistema pode se vincular a ela. O serviço também precisa incluir um filtro de intents com a ação android.service.euicc.EuiccService. A prioridade da intent filtro deve ser definido como um valor diferente de zero, caso várias implementações sejam presentes no dispositivo. Exemplo:

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

Internamente, o framework do Android determina o LPA ativo e interage com conforme necessário para oferecer suporte às APIs eUICC do Android. PackageManager recebeu uma consulta todos os apps com a permissão android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS; que especifica um serviço para a ação android.service.euicc.EuiccService. O serviço com a prioridade mais alta é selecionado. Se nenhum serviço for encontrado, o LPA suporte desativado.

Para implementar a LUI, é necessário fornecer uma atividade para as seguintes ações:

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

Assim como com o serviço, cada atividade deve exigir o Permissão do sistema android.permission.BIND_EUICC_SERVICE. Cada deve ter filtro de intent com a ação apropriada, a android.service.euicc.category.EUICC_UI e uma prioridade diferente de zero. Uma lógica semelhante é usada para escolher as implementações dessas atividades como escolher a implementação EuiccService Exemplo:

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

Isso significa que a interface que implementa essas telas pode vir de um o APK que implementa EuiccService Se é preciso ter um único APK ou vários APKs (por exemplo, um que implemente EuiccService e uma que fornece atividades de LUI) é uma escolha de design.

Gerente Cardiovascular

EuiccCardManager é a interface de comunicação com o chip de eSIM. Ela fornece funções ES10 (conforme descrito na especificação RSP do GSMA) e lida com os comandos de solicitação/resposta de APDU de baixo nível, bem como análise ASN.1. EuiccCardManager é uma API do sistema e só pode ser chamada por sistemas com privilégios apps.

Apps de operadoras, LPA e APIs Euicc

Figura 2. Tanto o app da operadora quanto a LPA usam APIs Euicc

As APIs de operação de perfil por EuiccCardManager exigem que o autor da chamada seja um LPA. Isso é aplicado pelo framework do Android. Isso significa que o autor da chamada precisa estender EuiccService e ser declarada no arquivo de manifesto, conforme descrito em nas seções anteriores.

Semelhante a EuiccManager, para usar as APIs EuiccCardManager, seu LPA precisa acesse a instância de EuiccCardManager usando Context#getSystemService:

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

Em seguida, para obter todos os perfis no eUICC:

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

Internamente, EuiccCardManager se vincula a EuiccCardController (que é executado na processo do smartphone) usando uma interface AIDL, e cada método EuiccCardManager recebe o callback do processo do smartphone por uma AIDL diferente e dedicada. interface gráfica do usuário. Ao usar APIs EuiccCardManager, o autor da chamada (LPA) precisa fornecer um Executor objeto pelo qual a chamada de retorno é invocada. Este objeto Executor pode ser executado em uma única linha de execução ou em um pool de sua escolha.

A maioria das APIs EuiccCardManager tem o mesmo padrão de uso. Por exemplo, para carregar uma o pacote de perfil vinculado ao eUICC:

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

Para alternar para um perfil diferente com um determinado ICCID:

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

Para encontrar o endereço SM-DP+ padrão no chip eUICC, faça o seguinte:

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

Para recuperar uma lista de notificações dos eventos de notificação fornecidos:

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

Ativar um perfil de eSIM no app da operadora

Em dispositivos com o Android 9 ou versões mais recentes, é possível usar o app de uma operadora para ativar o eSIM e os perfis de download. O app da operadora pode fazer o download de perfis chamar downloadSubscription diretamente ou fornecendo um código de ativação para o LPA.

Quando o app de uma operadora faz o download de um perfil por chamada downloadSubscription, a chamada determina que o app pode gerenciar o perfil usando um BF76 tag de metadados que codifica regras de privilégio da operadora para os perfil. Se um perfil não tem uma tag BF76 ou se a tag BF76 não tem corresponder à assinatura do app da operadora de chamada, o download será rejeitado.

A seção abaixo descreve a ativação de um eSIM no app de uma operadora usando uma código de ativação.

Ativar o eSIM usando um código de ativação

Ao usar um código de ativação para ativar um perfil de eSIM, o LPA busca um código de ativação app da operadora e faz o download do perfil. Esse fluxo pode ser iniciado pelo LPA e o LPA pode controlar todo o fluxo da interface, ou seja, nenhuma interface de app da operadora mostrados. Essa abordagem ignora a verificação de tags BF76, e os operadores de rede não precisa implementar todo o fluxo de interface de ativação do eSIM, incluindo o download de um perfil de eSIM e tratamento de erros.

Definir o serviço de provisionamento de eUICC da operadora

O LPA e o app da operadora se comunicam por duas AIDL (em inglês) - interface: ICarrierEuiccProvisioningService e IGetActivationCodeCallback. A transportadora app precisa implementar uma interface ICarrierEuiccProvisioningService e expô-lo na declaração de manifesto. O LPA precisa se vincular a ICarrierEuiccProvisioningService e implementar IGetActivationCodeCallback. Para mais informações sobre como implementar e expor uma interface AIDL, consulte Definição e interface AIDL.

Para definir as interfaces AIDL, crie os seguintes arquivos AIDL para apps de LPA e de operadoras.

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

Exemplo de implementação de LPA

Para vincular à implementação de ICarrierEuiccProvisioningService do app da operadora, faça o seguinte: o LPA deve copiar ICarrierEuiccProvisioningService.aidl e IGetActivationCodeCallback.aidl ao projeto e implemente ServiceConnection.

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

Depois de vincular ao ICarrierEuiccProvisioningService do app da operadora implementação, o LPA chama getActivationCode ou getActivationCodeForEid para receber o código de ativação no app da operadora até transmitindo a implementação da classe de stub IGetActivationCodeCallback.

A diferença entre getActivationCode e getActivationCodeForEid é que O getActivationCodeForEid permite que uma operadora vincule previamente um perfil ao EID antes do início do processo de download.

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

Exemplo de implementação para o app da operadora

Para que o LPA seja vinculado ao app da operadora, esse app precisa copiar ambos ICarrierEuiccProvisioningService.aidl e IGetActivationCodeCallback.aidl a seu projeto e declarar o serviço ICarrierEuiccProvisioningService na AndroidManifest.xml. O serviço deve exigir a android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS permissão do sistema para garantir que apenas o LPA, um aplicativo com privilégios de sistema, pode se vincular a ele. O serviço precisa também incluem um filtro de intent com o 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 o serviço de app de operadora AIDL, crie um serviço e estenda o Stub e implemente a getActivationCode e o getActivationCodeForEid métodos. O LPA pode chamar qualquer um dos métodos para buscar a ativação do perfil o código-fonte é alterado. O app da operadora responderá chamando IGetActivationCodeCallback#onSuccess pelo código de ativação, se ele tiver sido buscada no servidor da operadora. Se falhar, o app da operadora deve responder com 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);
              }
          }
    }
    

Iniciar a interface do app da operadora no fluxo de ativação de LPA

Em dispositivos com o Android 11 e versões mais recentes, o LPA pode iniciar a interface de um app de operadora. Isso é útil porque um app de operadora pode exigir informações adicionais do antes de fornecer um código de ativação ao LPA. Por exemplo, as operadoras podem exigir que os usuários façam login para ativar seus números de telefone ou realizar outras transferências serviços.

Este é o processo para iniciar a interface de um app de operadora no LPA:

  1. O LPA inicia o fluxo de ativação do app da operadora enviando o android.service.euicc.action.START_CARRIER_ACTIVATION para o pacote de app da operadora que contém a ação. (O receptor do app da operadora deve ser protegidas na declaração de manifesto android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" a evitar o recebimento de intents de aplicativos que não estão no 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. O app da operadora faz o trabalho usando a própria interface. Por exemplo, a geração de registros no usuário ou enviar solicitações HTTP para o back-end da operadora.

  3. O app da operadora responde ao LPA chamando setResult(int, Intent). e finish().

    1. Se o app da operadora responder com RESULT_OK, o LPA continua o fluxo de ativação. Se o app da operadora determinar que O usuário deve ler um QR code em vez de permitir que o LPA vincule a operadora do app, o app da operadora responde ao LPA usando setResult(int, Intent) com RESULT_OK e uma instância de Intent que contém o valor booleano extra O valor android.telephony.euicc.extra.USE_QR_SCANNER foi definido como true. O LPA Ele verifica o extra e inicia o leitor de QR code em vez de vincular a implementação de ICarrierEuiccProvisioningService do app da operadora.
    2. Se o app da operadora falhar ou responder com RESULT_CANCELED (esse é o código de resposta padrão), a LPA cancela o eSIM fluxo de ativação.
    3. Se o app da operadora responder com algo diferente RESULT_OK ou RESULT_CANCELED, o LPA o tratará como um erro.

    Por motivos de segurança, o LPA não deve aceitar diretamente um código de ativação fornecido na intent de resultado para garantir que os dados os autores das chamadas não recebem um código de ativação do app da operadora.

Iniciar o fluxo de ativação de LPA em um app de operadora

No Android 11 e versões mais recentes, os apps de operadoras podem usar APIs eUICC para iniciar uma LUI para eSIM ativação. Esse método mostra a interface do fluxo de ativação do eSIM da LPA para ser ativada o perfil do eSIM. O LPA envia uma transmissão quando o perfil do eSIM a ativação for concluída.

  1. O LPA precisa declarar uma atividade que inclui um filtro de intents com a android.service.euicc.action.START_EUICC_ACTIVATION. A prioridade do filtro de intenção deve ser definido como um valor diferente de zero, caso diversos e implementações estão presentes no dispositivo. Exemplo:

    <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. O app da operadora faz o trabalho usando a própria interface. Por exemplo, a geração de registros no usuário ou enviar solicitações HTTP para o back-end da operadora.

  3. O app da operadora precisa estar pronto para oferecer uma ativação o código por meio da implementação de ICarrierEuiccProvisioningService. A da operadora de celular inicia o LPA chamando startActivityForResult(Intent, int) com o android.telephony.euicc.action.START_EUICC_ACTIVATION à ação. O LPA também verifica o booleano extra android.telephony.euicc.extra.USE_QR_SCANNER: Se o valor for true, o O LPA inicia o leitor de QR code para permitir que o usuário leia o QR code do perfil.

  4. No lado do LPA, o LPA é vinculado ao código do app da operadora Implementação de ICarrierEuiccProvisioningService para buscar a ativação e faça o download do perfil correspondente. O LPA exibe todas as Elementos da interface durante o download, como uma tela de carregamento.

  5. Quando o fluxo de ativação do LPA é concluído, o LPA responde ao da operadora com um código de resultado, que é processado pelo app da operadora em onActivityResult(int, int, Intent):

    1. Se o LPA conseguir fazer o download do novo perfil de eSIM, responde com RESULT_OK.
    2. Se o usuário cancelar a ativação do perfil de eSIM no LPA, responde com RESULT_CANCELED.
    3. Se o LPA responder com algo diferente de RESULT_OK ou RESULT_CANCELED, o app da operadora trata isso como um erro.

    Por motivos de segurança, o LPA não aceita um código de ativação. diretamente na intent fornecida, para que autores da chamada que não sejam LPA não consigam o código de ativação do app da operadora.

Compatibilidade com vários eSIMs

Para dispositivos com o Android 10 ou mais recente, o A classe EuiccManager oferece suporte a dispositivos com vários eSIMs. Dispositivos com um único eSIM que estão fazendo upgrade para Android 10 não exigem nenhuma modificação na implementação do LPA, já que a plataforma associa automaticamente a instância EuiccManager ao eUICC padrão. A eUICC padrão é determinado pela plataforma para dispositivos com versão de HAL de rádio versão 1.2 ou mais recente e pelo LPA para dispositivos com versões da HAL de rádio anteriores a 1,2.

Requisitos

Para oferecer suporte a vários eSIMs, o dispositivo precisa ter mais de um eUICC, o que pode pode ser um eUICC integrado ou um slot físico para chip em que eUICCs removíveis possam ser; inserida.

A HAL de rádio versão 1.2 ou mais recente é necessária para oferecer suporte a vários eSIMs. HAL de rádio são recomendadas a versão 1.4 e a versão 1.2 da HAL RadioConfig.

Implementação

Para oferecer suporte a vários eSIMs (incluindo eUICCs removíveis ou chips programáveis), o Os LPAs precisam implementar EuiccService, que recebe o ID de slot correspondente ao ID de cartão fornecido pelo autor da chamada.

A non_removable_euicc_slots recurso especificado em arrays.xml é uma matriz de números inteiros que representa os IDs de slots do sistema integrado de eUICCs. É necessário especificar esse recurso para permitir que a plataforma determine se um eUICC inserido é removível ou não.

App da operadora para dispositivo com vários eSIMs

Ao criar um app de operadora para um dispositivo com vários eSIMs, use o createForCardId em EuiccManager para criar um objeto EuiccManager que é fixado em uma ID de cartão fornecido. O ID do cartão é um valor inteiro que identifica exclusivamente um UICC ou um eUICC no dispositivo.

Para conseguir o ID do cartão para o eUICC padrão do dispositivo, use o método getCardIdForDefaultEuicc em TelephonyManager. Esse método retorna UNSUPPORTED_CARD_ID se a versão da HAL de rádio for anterior à 1.2 e retornar UNINITIALIZED_CARD_ID se o dispositivo não tiver lido o eUICC.

Você também pode obter IDs de cartão de getUiccCardsInfo e getUiccSlotsInfo (API do sistema) em TelephonyManager, e getCardId em SubscriptionInfo.

Quando um objeto EuiccManager é instanciado com um ID de cartão específico, todos operações são direcionadas para o eUICC com esse ID de cartão. Se o eUICC se tornar inacessível (por exemplo, quando é desativado ou removido) EuiccManager não mais funciona.

Você pode usar os exemplos de código a seguir para criar um app de operadora.

Exemplo 1: receber assinatura ativa e instanciar 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);

Exemplo 2: iterar por UICCs e instanciar EuiccManager para um eUICC removível

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

Validação

O AOSP não vem com uma implementação de LPA, e não se espera que você têm um LPA disponível em todos os builds do Android (nem todos os smartphones oferecem suporte para eSIM). Para Por isso, não há casos de teste do CTS de ponta a ponta. No entanto, casos de teste básicos estão disponíveis no AOSP para garantir que as APIs eUICC expostas são válidos em builds do Android.

Verifique se os builds passam nos seguintes casos de teste do CTS (para aplicativos públicos APIs): /platform/cts/tests/tests/telephony/current/src/android/telephony/euicc/cts.

As operadoras que implementam um app de operadora precisam passar pelo processo interno normal controle de qualidade para garantir que todos os recursos implementados funcionem conforme o esperado. No No mínimo, o app da operadora deve ser capaz de listar todos os perfis de assinatura do mesmo operador, faça o download e instale um perfil, ative um serviço no perfil, alternar entre perfis e excluir perfis.

Se estiver criando seu próprio LPA, passe por etapas muito mais rigorosas testes. Entre em contato com seu fornecedor de modem, chip eUICC ou fornecedor de SO de eSIM. os fornecedores do SM-DP+ e as operadoras para resolver problemas e garantir a interoperabilidade seu LPA dentro da arquitetura do RSP. Uma boa quantidade de testes manuais inevitável. Para obter a melhor cobertura de teste, você deve seguir as Plano de teste do RSP do GSMA SGP.23.