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 la 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 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 operador precargadas que no cumplen con los requisitos para el permiso READ_PRIVILEGED_PHONE_STATE pueden implementar una de las opciones de 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 con 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 MVNO que tienen SIMs emitidas por MNO) no pueden agregar ni actualizar certificados en las SIMs. |
| Inclusión en la lista de entidades permitidas del 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, que se introdujo en Android 10, para exponer el TAC que devuelve la información del fabricante y el modelo. |
La información del TAC no es suficiente 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 IMSI requieren recursos técnicos significativos para cambiar a MSISDN. |
Todas las apps de proveedores pueden acceder a los identificadores de dispositivos actualizando el archivo CarrierConfig.xml con el hash del certificado de firma de la app del proveedor. Cuando la app del proveedor 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 devuelve 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 QPR-1 o una versión posterior (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 entidades permitidas de permisos con privilegios para otorgar el permiso READ_PRIVILEGED_PHONE_STATE a las apps con privilegios que requieran acceso a los identificadores de dispositivos.
Para obtener más información sobre las listas de entidades permitidas, consulta Lista de entidades permitidas con permisos privilegiados.
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 la declaración de permisos
READ_PRIVILEGED_PHONE_STATEdeclarada 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 de propietario de dispositivo o 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 segmenta 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 se orienta a una versión anterior a 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 nuevos requisitos, recibirá una SecurityException.
Validación y prueba
El conjunto de pruebas de compatibilidad (CTS) incluye pruebas para verificar el comportamiento esperado de acceso a los identificadores de dispositivos para las apps con privilegios de operador, los propietarios de dispositivos y perfiles, y las apps que se espera que no tengan acceso a los identificadores de dispositivos.
Las siguientes pruebas del 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 tarjeta 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 se inserta 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[] en 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>