Android 10 изменяет разрешения для идентификаторов устройств, так что все идентификаторы устройств теперь защищены разрешением READ_PRIVILEGED_PHONE_STATE . До Android 10 постоянные идентификаторы устройств (IMEI/MEID, IMSI, SIM и серийный номер сборки) были защищены разрешением времени выполнения READ_PHONE_STATE . Разрешение READ_PRIVILEGED_PHONE_STATE предоставляется только приложениям, подписанным с помощью ключа платформы, и привилегированным системным приложениям.
Более подробную информацию о новых требованиях к разрешениям можно найти на страницах Javadoc для TelephonyManager.java и Build.java .
Это изменение затрагивает следующие API:
- TelephonyManager#getDeviceId
 - Менеджер телефонии#getImei
 - Менеджер телефонии#getMeid
 - TelephonyManager#getSimSerialNumber
 - TelephonyManager#getSubscriberId
 - Сборка#getSerial
 
Доступ к приложениям оператора без разрешения READ_PRIVILEGED_PHONE_STATE
 Предустановленные приложения оператора, не имеющие разрешения READ_PRIVILEGED_PHONE_STATE могут реализовать один из вариантов, приведенных в таблице ниже.
| Вариант | Описание | Ограничения | 
|---|---|---|
| Привилегии оператора UICC | Платформа Android загружает сертификаты, хранящиеся на UICC, и предоставляет приложениям, подписанным этими сертификатами, разрешение на вызовы специальных методов. | Устаревшие операторы имеют большую, устоявшуюся популяцию SIM-карт, которую нелегко обновить. Кроме того, операторы, у которых нет прав на создание новых SIM-карт (например, MVNO, у которых есть SIM-карты, выпущенные MNO), не могут добавлять или обновлять сертификаты на SIM-картах. | 
| Разрешение OEM-производителей |  OEM-производители могут использовать OP_READ_DEVICE_IDENTIFIER для предоставления идентификаторов устройств приложениям-операторам, включенным в разрешенный список. | Это решение не масштабируется для всех операторов. | 
| Код распределения типа (TAC) |  Используйте метод getTypeAllocationCode , представленный в Android 10, чтобы предоставить TAC, который возвращает информацию о производителе и модели. | Информация в TAC недостаточна для идентификации конкретного устройства. | 
| MSISDN |  Операторы могут использовать номер телефона (MSISDN), доступный в TelephonyManager с группой разрешений PHONE , для поиска IMEI в своих внутренних системах. | Это требует значительных инвестиций от операторов. Операторам, которые сопоставляют свои сетевые ключи с использованием IMSI , требуются значительные технические ресурсы для перехода на MSISDN . | 
 Все приложения оператора могут получить доступ к идентификаторам устройств, обновив файл CarrierConfig.xml хэшем сертификата подписи приложения оператора. Когда приложение оператора вызывает метод для чтения привилегированной информации, платформа ищет совпадение хеша сертификата подписи приложения (подпись SHA-1 или SHA-256 сертификата) в файле CarrierConfig.xml . Если совпадение найдено, возвращается запрошенная информация. Если совпадений не найдено, возвращается исключение безопасности.
Для внедрения этого решения операторы ДОЛЖНЫ выполнить следующие шаги:
-  Обновите 
CarrierConfig.xml, указав хэш сертификата подписи приложения оператора, и отправьте исправление . -  Попросите OEM-производителей обновить свои сборки до QPR1+ (рекомендуется) ИЛИ установить эти требуемые исправления платформы и исправление, содержащее обновленный файл 
CarrierConfig.xmlиз шага 1 выше. 
Выполнение
 Обновите список разрешенных привилегированных разрешений, чтобы предоставить разрешение READ_PRIVILEGED_PHONE_STATE тем привилегированным приложениям, которым требуется доступ к идентификаторам устройств.
Дополнительную информацию о разрешении доступа см. в разделе Разрешение доступа с привилегированным доступом .
Для вызова уязвимых API приложение должно соответствовать одному из следующих требований:
-  Если приложение является предустановленным привилегированным приложением, ему необходимо разрешение 
READ_PRIVILEGED_PHONE_STATE, объявленное в AndroidManifest.xml. Приложению также необходимо добавить это привилегированное разрешение в список разрешенных. - Приложения, доставляемые через Google Play, требуют привилегий оператора. Узнайте больше о предоставлении привилегий оператора на странице привилегий оператора UICC .
 -  Приложение владельца устройства или профиля, которому предоставлено разрешение 
READ_PHONE_STATE. 
Приложение, не отвечающее ни одному из этих требований, ведет себя следующим образом:
-  Если приложение ориентировано на версию pre-Q и ему не предоставлено разрешение 
READ_PHONE_STATE, срабатываетSecurityException. Это текущее поведение pre-Q, поскольку это разрешение требуется для вызова этих API. -  Если приложение ориентировано на версию до Q и ему предоставлено разрешение 
READ_PHONE_STATE, оно получает нулевое значение для всех API TelephonyManager иBuild.UNKNOWNдля методаBuild#getSerial. - Если приложение предназначено для Android 10 или выше и не соответствует ни одному из новых требований, оно получает исключение SecurityException.
 
Проверка и тестирование
Набор тестов на совместимость (CTS) включает в себя тесты для проверки ожидаемого поведения доступа к идентификаторам устройств для приложений с привилегиями оператора, владельцев устройств и профилей, а также тех приложений, которые, как ожидается, не будут иметь доступа к идентификаторам устройств.
Следующие тесты CTS специфичны для этой функции.
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
Часто задаваемые вопросы
 Сколько приложений можно добавить в разрешенный список в CarrierConfig.xml для заданного оператора (MCC, MNC)?
Количество хэшей сертификатов, включаемых в массив, не ограничено.
 Какие параметры CarrierConfig в CarrierConfig.xml необходимо использовать, чтобы приложение было внесено в белый список?
 Используйте следующий элемент конфигурации верхнего уровня в определенном файле CarrierConfig.xml из настраиваемых вами параметров AOSP:
<string-array name="carrier_certificate_string_array" num="2">
    <item value="BF02262E5EF59FDD53E57059082F1A7914F284B"/>
    <item value="9F3868A3E1DD19A5311D511A60CF94D975A344B"/>
</string-array>Есть ли базовый шаблон CarrierConfig, который я могу использовать?
Используйте следующий шаблон. Его следует добавить к соответствующему активу .
<?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>Обязательно ли наличие SIM-карты оператора в устройстве для доступа к идентификаторам устройства?
 Используемый CarrierConfig.xml определяется на основе SIM-карты, которая в данный момент вставлена. Это означает, что если приложение оператора X попытается получить привилегии доступа, пока вставлена SIM-карта оператора Y, устройство не найдет совпадения для хэша и вернет исключение безопасности.
На устройствах с несколькими SIM-картами оператор №1 имеет права доступа только к SIM-карте №1 и наоборот.
Как операторы преобразуют сертификат подписи приложения в хэш?
 Чтобы преобразовать сертификаты подписи в хэш перед добавлением их в CarrierConfig.xml , выполните следующие действия:
-  Преобразуйте подпись сертификата подписи в массив байтов с помощью 
toByteArray. -  Используйте 
MessageDigestдля преобразования массива байтов в хэш типа byte[]. Конвертировать хэш из byte[] в формат шестнадцатеричной строки. Пример см. в
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())); }Если
certHashes— это массив размером2со значениями12345и54321, добавьте следующее в файл конфигурации оператора.<string-array name="carrier_certificate_string_array" num="2"> <item value="12345"/> <item value="54321"/> </string-array>