Android 10 cambia los permisos para los identificadores de dispositivos, de modo que todos los identificadores de dispositivos ahora están protegidos por el permiso READ_PRIVILEGED_PHONE_STATE. Antes de Android 10, los identificadores de dispositivos persistentes (IMEI/MEID, IMSI, SIM y número de serie de compilación) estaban protegidos por el permiso de tiempo de ejecución READ_PHONE_STATE.
El permiso READ_PRIVILEGED_PHONE_STATE solo se otorga a las apps firmadas con la clave de la plataforma y a las apps del sistema con privilegios.
Puedes encontrar más información sobre los nuevos requisitos de permisos en las páginas de Javadoc de TelephonyManager.java y Build.java.
Este cambio afecta a las siguientes APIs:
- TelephonyManager#getDeviceId
- TelephonyManager#getImei
- TelephonyManager#getMeid
- TelephonyManager#getSimSerialNumber
- TelephonyManager#getSubscriberId
- Build#getSerial
Acceso para apps de operadores sin el permiso READ_PRIVILEGED_PHONE_STATE
Las apps de operadores precargadas que no cumplen con los requisitos para obtener el permiso de READ_PRIVILEGED_PHONE_STATE pueden implementar una de las opciones que se indican en la siguiente tabla.
| Opción | Descripción | Limitaciones |
|---|---|---|
| Privilegios de operador de UICC | La plataforma de Android carga los certificados almacenados en la UICC y otorga permiso a las apps firmadas por estos certificados para realizar llamadas a métodos especiales. | Los operadores heredados tienen una gran cantidad de SIM establecidas, que no se pueden actualizar fácilmente. Además, los operadores que no tienen derechos de autoría para las SIMs nuevas (por ejemplo, los OMV que tienen SIMs emitidas por OMR) no pueden agregar ni actualizar certificados en las SIMs. |
| Lista de anunciantes permitidos de OEM | Los OEM pueden usar OP_READ_DEVICE_IDENTIFIER para proporcionar identificadores de dispositivos a las apps de operadores incluidas en la lista de entidades permitidas. |
Esta solución no es escalable para todos los operadores. |
| Código de asignación de tipo (TAC) | Usa el método
getTypeAllocationCode, introducido en
Android 10, para exponer el TAC que devuelve la información del fabricante y el modelo. |
La información del TAC es insuficiente para identificar un dispositivo específico. |
| MSISDN | Los operadores pueden usar el número de teléfono (MSISDN), disponible en TelephonyManager con el grupo de permisos PHONE, para buscar el IMEI en sus sistemas de backend. |
Esto requiere una inversión significativa para los operadores. Los operadores que asignan sus claves de red con el IMSI requieren recursos técnicos significativos para cambiar al MSISDN. |
Todas las apps de operador pueden acceder a los identificadores de dispositivos si actualizan el archivo CarrierConfig.xml con el hash del certificado de firma de la app de operador. Cuando la app de operador llama a un método para leer información privilegiada, la plataforma busca una coincidencia del hash del certificado de firma de la app (firma SHA-1 o SHA-256 del certificado) en el archivo CarrierConfig.xml. Si se encuentra una coincidencia, se muestra la información solicitada. Si no se encuentra ninguna coincidencia, se devuelve una excepción de seguridad.
Para implementar esta solución, las empresas de telefonía celular DEBEN seguir estos pasos:
- Actualiza
CarrierConfig.xmlcon el hash del certificado de firma de la app del operador y envía un parche. - Solicita a los OEM que actualicen su compilación con QPR1+ (recomendado) O bien con estos parches de plataforma obligatorios y el parche que contiene el archivo
CarrierConfig.xmlactualizado del paso 1 anterior.
Implementación
Actualiza tu lista de anunciantes permitidos con permisos con privilegios para otorgar el permiso de READ_PRIVILEGED_PHONE_STATE a las apps con privilegios que requieran acceso a identificadores de dispositivos.
Para obtener más información sobre las listas de entidades permitidas, consulta Inclusión de permisos con privilegios en la lista de entidades permitidas.
Para invocar las APIs afectadas, una app debe cumplir con uno de los siguientes requisitos:
- Si la app es una app privilegiada cargada previamente, necesita el permiso
READ_PRIVILEGED_PHONE_STATEdeclarado en AndroidManifest.xml. La app también debe incluir este permiso privilegiado en la lista de entidades permitidas. - Las apps que se entregan a través de Google Play necesitan privilegios de operador. Obtén más información para otorgar privilegios de operador en la página UICC Carrier Privileges.
- Una app del propietario del dispositivo o del perfil a la que se le otorgó el permiso
READ_PHONE_STATE.
Una app que no cumple con ninguno de estos requisitos tiene el siguiente comportamiento:
- Si la app está segmentada para versiones anteriores a Android Q y no tiene el permiso
READ_PHONE_STATEotorgado, se activaSecurityException. Este es el comportamiento actual de las versiones anteriores a Android Q, ya que se requiere este permiso para invocar estas APIs. - Si la app segmenta su público para versiones anteriores a Android Q y tiene otorgado el permiso
READ_PHONE_STATE, recibe un valor nulo para todas las APIs de TelephonyManager yBuild.UNKNOWNpara el métodoBuild#getSerial. - Si la app se orienta a Android 10 o versiones posteriores y no cumple con ninguno de los requisitos nuevos, recibirá una SecurityException.
Validación y pruebas
El conjunto de pruebas de compatibilidad (CTS) incluye pruebas para verificar el comportamiento esperado del acceso al identificador del dispositivo para las apps con privilegios de operador, propietarios del dispositivo y del perfil, y aquellas apps que no deberían tener acceso a los identificadores del dispositivo.
Las siguientes pruebas de CTS son específicas de esta función.
cts-tradefed run cts -m CtsCarrierApiTestCases -t android.carrierapi.cts.CarrierApiTestcts-tradefed run cts -m CtsTelephonyTestCases -t android.telephony.cts.TelephonyManagerTestcts-tradefed run cts -m CtsTelephony3TestCasescts-tradefed run cts -m CtsPermissionTestCases -t android.permission.cts.TelephonyManagerPermissionTestcts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerCanGetDeviceIdentifierscts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.ManagedProfileTest#testProfileOwnerCanGetDeviceIdentifierscts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.ManagedProfileTest#testProfileOwnerCannotGetDeviceIdentifiersWithoutPermissioncts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerCannotGetDeviceIdentifiersWithoutPermission
Preguntas frecuentes
¿Cuántas apps se pueden incluir en la lista de entidades permitidas en CarrierConfig.xml para un par (MCC, MNC) determinado?
No hay límite para la cantidad de hashes de certificados incluidos en el array.
¿Qué parámetros de CarrierConfig en CarrierConfig.xml debo usar para que una app se incluya en la lista de entidades permitidas?
Usa el siguiente elemento de configuración de nivel superior dentro del CarrierConfig.xml específico de las opciones de AOSP que estás configurando:
<string-array name="carrier_certificate_string_array" num="2">
<item value="BF02262E5EF59FDD53E57059082F1A7914F284B"/>
<item value="9F3868A3E1DD19A5311D511A60CF94D975A344B"/>
</string-array>¿Hay una plantilla base de CarrierConfig que pueda usar?
Usa la siguiente plantilla. Esto se debe agregar al recurso pertinente.
<?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>¿La SIM del operador debe estar en el dispositivo para acceder a los identificadores del dispositivo?
El CarrierConfig.xml que se usa se determina según la SIM que está insertada. Esto significa que, si la app del operador X intenta obtener privilegios de acceso mientras está insertada la SIM del operador Y, el dispositivo no encontrará una coincidencia para el hash y devolverá una excepción de seguridad.
En los dispositivos con varias SIM, el operador 1 solo tiene privilegios de acceso para la SIM 1 y viceversa.
¿Cómo convierten los operadores el certificado de firma de una app en un hash?
Para convertir los certificados de firma en un hash antes de agregarlos a CarrierConfig.xml, haz lo siguiente:
- Convierte la firma del certificado de firma en un array de bytes con
toByteArray. - Usa
MessageDigestpara convertir el array de bytes en un hash de tipo byte[]. -
Convierte el hash de byte[] a un formato de cadena hexadecimal. Para ver un ejemplo, consulta
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())); } Si
certHasheses un array de tamaño2con un valor de12345y54321, agrega lo siguiente al archivo de configuración del operador.<string-array name="carrier_certificate_string_array" num="2"> <item value="12345"/> <item value="54321"/> </string-array>