Android 10 變更了裝置 ID 的權限,現在所有裝置 ID 都受到 READ_PRIVILEGED_PHONE_STATE 權限保護。在 Android 10 推出前,永久裝置 ID (IMEI/MEID、IMSI、SIM 卡和建構序號) 是受到 READ_PHONE_STATE 執行階段權限保護。只有使用平台金鑰簽署的應用程式,以及具有特殊權限的系統應用程式,才能取得 READ_PRIVILEGED_PHONE_STATE 權限。
如要進一步瞭解新的權限規定,請參閱 TelephonyManager.java 和 Build.java 的 Javadoc 頁面。
這項異動會影響下列 API:
- TelephonyManager#getDeviceId
- TelephonyManager#getImei
- TelephonyManager#getMeid
- TelephonyManager#getSimSerialNumber
- TelephonyManager#getSubscriberId
- Build#getSerial
電信業者應用程式存取權 (無 READ_PRIVILEGED_PHONE_STATE 權限)
不符合 READ_PRIVILEGED_PHONE_STATE 權限資格的預先載入電信業者應用程式,可以實作下表中的其中一個選項。
| 選項 | 說明 | 限制 |
|---|---|---|
| UICC 電信業者權限 | Android 平台會載入儲存在 UICC 中的憑證,並授權由這些憑證簽署的應用程式呼叫特殊方法。 | 傳統電信業者擁有大量已建立的 SIM 卡族群,但這些 SIM 卡不容易更新。此外,如果電信業者沒有新 SIM 卡的授權權限 (例如,MVNO 的 SIM 卡是由 MNO 核發),就無法在 SIM 卡上新增或更新憑證。 |
| 原始設備製造商 (OEM) 許可清單 | 原始設備製造商 (OEM) 可以使用 OP_READ_DEVICE_IDENTIFIER 提供裝置 ID,供已加入許可清單的電信業者應用程式使用。 |
這個解決方案無法擴充,適用於所有電信業者。 |
| 輸入型號分配碼 (TAC) | 使用 Android 10 中導入的 getTypeAllocationCode 方法,公開傳回製造商和型號資訊的 TAC。 |
TAC 中的資訊不足以識別特定裝置。 |
| MSISDN | 電信業者可以使用手機號碼 (MSISDN,在 PHONE 權限群組下提供) 在後端系統中查詢 IMEI。TelephonyManager |
這需要電信業者投入大量資金。如果電信業者使用 IMSI 對應網路金鑰,則需要大量技術資源才能改用 MSISDN。 |
所有電信業者應用程式都可以存取裝置 ID,方法是使用電信業者應用程式的簽署憑證雜湊值更新 CarrierConfig.xml 檔案。當電信業者應用程式呼叫方法來讀取具備存取權的資訊時,平台會在 CarrierConfig.xml 檔案中尋找相符的應用程式簽署憑證雜湊值 (憑證的 SHA-1 或 SHA-256 簽章)。如果找到相符項目,系統就會傳回要求的資訊。如果找不到相符項目,系統會傳回安全性例外狀況。
如要實作此解決方案,貨運公司「必須」按照下列步驟操作:
- 更新
CarrierConfig.xml,加入電信業者應用程式的簽署憑證雜湊,然後提交修補程式。 - 請要求原始設備製造商 (OEM) 使用 QPR1 以上版本更新建構版本 (建議做法),或是使用這些必要平台修補程式,以及包含上述步驟 1 中更新版
CarrierConfig.xml檔案的修補程式。
實作
更新特許權限許可清單,將 READ_PRIVILEGED_PHONE_STATE 權限授予需要存取裝置 ID 的特許應用程式。
如要進一步瞭解許可清單,請參閱「許可清單中的特殊權限」。
如要呼叫受影響的 API,應用程式必須符合下列任一規定:
- 如果應用程式是預先載入的具備特殊權限應用程式,則需要 AndroidManifest.xml 中宣告的
READ_PRIVILEGED_PHONE_STATE權限。應用程式也必須將這項特殊權限加入許可清單。 - 透過 Google Play 提供的應用程式需要電信業者權限。 如要進一步瞭解如何授予電信業者權限,請參閱「UICC Carrier Privileges」(UICC 電信業者權限) 頁面。
- 已獲得
READ_PHONE_STATE權限的裝置或設定檔擁有者應用程式。
如果應用程式不符合上述任何規定,將會出現下列情況:
- 如果應用程式是以 Android Q 之前的版本為目標,且未獲授
READ_PHONE_STATE權限,系統就會觸發SecurityException。這是 Android Q 之前的現行行為,因為必須具備這項權限才能叫用這些 API。 - 如果應用程式是以 Android Q 之前的版本為目標,且已取得
READ_PHONE_STATE權限,則所有 TelephonyManager API 都會收到空值,Build#getSerial方法也會收到空值。Build.UNKNOWN - 如果應用程式指定 Android 10 以上版本,且不符合任何一項新規定,就會收到 SecurityException。
驗證和測試
相容性測試套件 (CTS) 包含多項測試,可驗證應用程式的預期裝置 ID 存取行為,包括具有電信業者權限、裝置和設定檔擁有者的應用程式,以及預期無法存取裝置 ID 的應用程式。
下列 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.xml 中的哪些 CarrierConfig 參數?
在您設定的 AOSP 選項中,使用下列頂層設定項目:CarrierConfig.xml
<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>如要存取裝置 ID,裝置是否必須插入電信業者 SIM 卡?
系統會根據目前插入的 SIM 卡決定使用哪一個 CarrierConfig.xml。也就是說,如果插入電信業者 Y 的 SIM 卡,電信業者 X 的應用程式嘗試取得存取權限時,裝置找不到相符的雜湊值,就會傳回安全性例外狀況。
在多 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>