Identificadores de dispositivo

O Android 10 muda as permissões para identificadores de dispositivos, de modo que todos os identificadores de dispositivos agora são protegidos pela permissão READ_PRIVILEGED_PHONE_STATE. Antes do Android 10, os identificadores de dispositivo persistentes (IMEI/MEID, IMSI, chip e número de série da versão) eram protegidos pela permissão de execução READ_PHONE_STATE. A permissão READ_PRIVILEGED_PHONE_STATE só é concedida a apps assinados com a chave da plataforma e apps privilegiados do sistema.

Mais informações sobre os novos requisitos de permissão podem ser encontradas nas páginas do Javadoc para TelephonyManager.java e Build.java.

Essa mudança afeta as seguintes APIs:

  • TelephonyManager#getDeviceId
  • TelephonyManager#getImei
  • TelephonyManager#getMeid
  • TelephonyManager#getSimSerialNumber
  • TelephonyManager#getSubscriberId
  • Build#getSerial

Acesso a apps de operadoras sem a permissão READ_PRIVILEGED_PHONE_STATE

Os apps de operadora pré-carregados que não se qualificam para a permissão READ_PRIVILEGED_PHONE_STATE podem implementar uma das opções na tabela abaixo.

Opção Descrição Limitações
Privilégios da operadora UICC A Plataforma Android carrega certificados armazenados no UICC e concede permissão a apps assinados por esses certificados para fazer chamadas para métodos especiais. As operadoras legadas têm uma grande população de chips SIM estabelecida, que não é facilmente atualizável. Além disso, as operadoras que não têm direitos de criação de novos chips (por exemplo, MVNOs que têm chips emitidos por MNOs) não podem adicionar ou atualizar certificados nos chips.
Lista de permissões de OEM Os OEMs podem usar OP_READ_DEVICE_IDENTIFIER para fornecer identificadores de dispositivos a apps de operadoras na lista de permissões. Essa solução não é escalonável para todas as operadoras.
Código de alocação de tipo (TAC) Use o método getTypeAllocationCode, introduzido no Android 10, para expor o TAC que retorna as informações do fabricante e do modelo. As informações do TAC são inadequadas para identificar um dispositivo específico.
MSISDN As operadoras podem usar o número de telefone (MSISDN), disponível em TelephonyManager com o grupo de permissão PHONE, para procurar o IMEI nos sistemas de back-end. Isso exige um investimento significativo das operadoras. As operadoras que mapeiam as chaves de rede usando IMSI precisam de recursos técnicos significativos para mudar para MSISDN.

Todos os apps de operadora podem acessar os identificadores de dispositivo atualizando o arquivo CarrierConfig.xml com o hash do certificado de assinatura do app. Quando o app de operadora chama um método para ler informações privilegiadas, a plataforma procura uma correspondência do hash do certificado de assinatura do app (assinatura SHA-1 ou SHA-256 do certificado) no arquivo CarrierConfig.xml. Se uma correspondência for encontrada, as informações solicitadas serão retornadas. Se nenhuma correspondência for encontrada, uma exceção de segurança será retornada.

Para implementar essa solução, as operadoras precisam seguir estas etapas:

  1. Atualize CarrierConfig.xml com o hash do certificado de assinatura do app da operadora e envie um patch.
  2. Peça aos OEMs para atualizar o build com o QPR1+ (recomendado) OU estes patches de plataforma necessários e o patch que contém o arquivo CarrierConfig.xml atualizado da etapa 1 acima.

Implementação

Atualize a lista de permissões privilegiadas para conceder a permissão READ_PRIVILEGED_PHONE_STATE aos apps privilegiados que exigem acesso aos identificadores do dispositivo.

Para saber mais sobre a lista de permissões, consulte Lista de permissões privilegiadas.

Para invocar as APIs afetadas, um app precisa atender a um dos seguintes requisitos:

  • Se o app for pré-carregado e privilegiado, ele precisará da permissão READ_PRIVILEGED_PHONE_STATE declarada no AndroidManifest.xml. O app também precisa permitir essa permissão privilegiada.
  • Os apps entregues pelo Google Play precisam de privilégios da operadora. Saiba mais sobre a concessão de privilégios da operadora na página Privilégios da operadora UICC.
  • Um app de proprietário do dispositivo ou do perfil que recebeu a permissão READ_PHONE_STATE.

Um app que não atende a nenhum desses requisitos tem o seguinte comportamento:

  • Se o app for destinado ao pré-Q e não tiver a permissão READ_PHONE_STATE concedida, o SecurityException será acionado. Esse é o comportamento atual do pré-Q, já que essa permissão é necessária para invocar essas APIs.
  • Se o app for direcionado a versões anteriores ao Android Q e tiver a permissão READ_PHONE_STATE concedida, ele vai receber um valor nulo para todas as APIs do TelephonyManager e Build.UNKNOWN para o método Build#getSerial.
  • Se o app for destinado ao Android 10 ou mais recente e não atender a nenhum dos novos requisitos, ele vai receber uma SecurityException.

Validação e teste

O conjunto de testes de compatibilidade (CTS) inclui testes para verificar o comportamento esperado de acesso ao identificador de dispositivo para apps com privilégios de operadora, proprietários de dispositivo e perfil e apps que não têm acesso a identificadores de dispositivo.

Os testes do CTS a seguir são específicos para esse recurso.

cts-tradefed run cts -m CtsCarrierApiTestCases -t
    android.carrierapi.cts.CarrierApiTest

cts-tradefed run cts -m CtsTelephonyTestCases -t
    android.telephony.cts.TelephonyManagerTest

cts-tradefed run cts -m CtsTelephony3TestCases

cts-tradefed run cts -m CtsPermissionTestCases -t
    android.permission.cts.TelephonyManagerPermissionTest

cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t
    com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerCanGetDeviceIdentifiers

cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t
    com.android.cts.devicepolicy.ManagedProfileTest#testProfileOwnerCanGetDeviceIdentifiers

cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t
    com.android.cts.devicepolicy.ManagedProfileTest#testProfileOwnerCannotGetDeviceIdentifiersWithoutPermission

cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t
    com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerCannotGetDeviceIdentifiersWithoutPermission

Perguntas frequentes

Quantos apps podem ser incluídos na lista de permissões em CarrierConfig.xml para uma determinada (MCC, MNC)?

Não há limite para o número de hashes de certificado incluídos no array.

Quais parâmetros da CarrierConfig em CarrierConfig.xml preciso usar para que um app seja incluído na lista de permissões?

Use o seguinte item de configuração de nível superior no CarrierConfig.xml específico das opções do AOSP que você está configurando:

<string-array name="carrier_certificate_string_array" num="2">
    <item value="BF02262E5EF59FDD53E57059082F1A7914F284B"/>
    <item value="9F3868A3E1DD19A5311D511A60CF94D975A344B"/>
</string-array>

Há um modelo de CarrierConfig básico que posso usar?

Use o modelo a seguir. Isso precisa ser adicionado ao recurso relevante.

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<carrier_config>
    <string-array name="carrier_certificate_string_array"
num="1">
        <item value="CERTIFICATE_HASH_HERE"/>
    </string-array>
</carrier_config>

O chip da operadora precisa estar no dispositivo para acessar os identificadores?

O CarrierConfig.xml usado é determinado com base no chip inserido. Isso significa que, se o app da operadora X tentar acessar privilégios de acesso enquanto o SIM da operadora Y estiver inserido, o dispositivo não vai encontrar uma correspondência para o hash e retornará uma exceção de segurança.

Em dispositivos com vários chips, a operadora 1 só tem privilégios de acesso para o chip 1 e vice-versa.

Como as operadoras convertem o certificado de assinatura de um app em um hash?

Para converter certificados de assinatura em um hash antes de adicioná-los a CarrierConfig.xml, faça o seguinte:

  1. Converta a assinatura do certificado de assinatura em uma matriz de bytes usando toByteArray.
  2. Use MessageDigest para converter a matriz de bytes em um hash no tipo byte[].
  3. Converte o hash de byte[] em um formato de string hexadecimal. Confira um exemplo em IccUtils.java.

    List<String> certHashes = new ArrayList<>();
    PackageInfo pInfo; // Carrier app PackageInfo
    MessageDigest md =
    MessageDigest.getInstance("SHA-256");
    for (Signature signature : pInfo.signatures) {
        certHashes.add(bytesToHexString(md.digest(signature.toByteArray()));
    }
  4. Se certHashes for uma matriz de tamanho 2 com um valor de 12345 e 54321, adicione o seguinte ao arquivo de configuração da operadora.

    <string-array name="carrier_certificate_string_array" num="2">
        <item value="12345"/>
        <item value="54321"/>
    </string-array>