裝置 ID

Android 10 會變更裝置 ID 的權限,讓所有裝置 ID 都受到 READ_PRIVILEGED_PHONE_STATE 權限的保護。在 Android 10 之前,永久裝置 ID (IMEI/MEID、IMSI、SIM 卡和版本序號) 受到 READ_PHONE_STATE 執行階段權限的保護。READ_PRIVILEGED_PHONE_STATE 權限僅授予使用平台金鑰簽署的應用程式,以及具有特殊權限的系統應用程式。

如要進一步瞭解新權限規定,請參閱 TelephonyManager.javaBuild.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 卡的著作權 (例如,MVNO 有由 MNO 核發的 SIM 卡),就無法在 SIM 卡上新增或更新憑證。
原始設備製造商 (OEM) 許可清單 原始設備製造商 (OEM) 可以使用 OP_READ_DEVICE_IDENTIFIER,為已核准的電信業者應用程式提供裝置 ID。 這項解決方案無法適用於所有電信業者。
類型分配碼 (TAC) 使用 Android 10 中推出的 getTypeAllocationCode 方法,公開可傳回製造商和型號資訊的 TAC。 TAC 中的資訊不足以識別特定裝置。
MSISDN 電信業者可以使用 TelephonyManager 下方具有 PHONE 權限群組的電話號碼 (MSISDN),在後端系統中查詢 IMEI。 這需要電信業者投入大量資金。使用 IMSI 對應網路金鑰的電信業者,需要大量技術資源才能改用 MSISDN

所有電信業者應用程式都可以透過更新 CarrierConfig.xml 檔案,並使用電信業者應用程式的簽署憑證雜湊值,存取裝置 ID。當電信業者應用程式呼叫方法來讀取特權資訊時,平台會在 CarrierConfig.xml 檔案中尋找應用程式的簽署憑證雜湊值 (憑證的 SHA-1 或 SHA-256 簽名) 是否相符。如果找到相符項目,系統會傳回要求的資訊。如果找不到相符項目,系統會傳回安全性例外狀況。

如要實作此解決方案,運營商必須按照下列步驟操作:

  1. 使用電信業者應用程式的簽署憑證雜湊更新 CarrierConfig.xml,並提交修補程式
  2. 請 OEM 廠商使用 QPR1+ (建議) 或以下必要的平台修補程式更新其版本,以及包含上述步驟 1 中更新 CarrierConfig.xml 檔案的修補程式。

實作

更新特權權限許可清單,將 READ_PRIVILEGED_PHONE_STATE 權限授予需要存取裝置 ID 的特權應用程式。

如要進一步瞭解許可清單,請參閱「特權權限許可清單」。

如要叫用受影響的 API,應用程式必須符合下列任一規定:

  • 如果應用程式是預先載入的特權應用程式,就需要在 AndroidManifest.xml 中宣告 READ_PRIVILEGED_PHONE_STATE 權限。應用程式也需要將這項特權權限加入許可清單。
  • 透過 Google Play 提供的應用程式需要電信業者特殊權限。 如要進一步瞭解如何授予電信業者權限,請參閱「UICC 電信業者權限」頁面。
  • 已授予 READ_PHONE_STATE 權限的裝置或設定檔擁有者應用程式。

不符合任何規定的應用程式會出現以下行為:

  • 如果應用程式指定的目標版本為 Q 以下版本,且未獲得 READ_PHONE_STATE 權限,系統就會觸發 SecurityException。這是目前 Q 以下版本的行為,因為需要這項權限才能叫用這些 API。
  • 如果應用程式指定的目標為 Android Q 以下版本,且已授予 READ_PHONE_STATE 權限,則會針對所有 TelephonyManager API 收到空值,並針對 Build#getSerial 方法收到 Build.UNKNOWN
  • 如果應用程式指定 Android 10 以上版本,但不符合任何一項新規定,就會收到 SecurityException。

驗證和測試

Compatibility Test Suite (CTS) 包含測試,可驗證具有電信業者權限的應用程式、裝置和設定檔擁有者,以及預期不會存取裝置 ID 的應用程式,預期的裝置 ID 存取行為。

下列 CTS 測試專門針對這項功能進行測試。

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

常見問題

在特定 (MCC、MNC) 中,CarrierConfig.xml 可加入許可清單的應用程式數量為何?

陣列中包含的憑證雜湊數量沒有限制。

如要將應用程式加入許可清單,我需要使用 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>

是否必須將電信業者 SIM 卡插入裝置才能存取裝置 ID?

系統會根據目前插入的 SIM 卡來決定要使用的 CarrierConfig.xml。也就是說,如果電信業者 X 的應用程式在插入電信業者 Y 的 SIM 卡時嘗試取得存取權限,裝置就不會找到相符的雜湊值,並傳回安全性例外狀況。

在多 SIM 卡裝置上,電信業者 #1 僅有 SIM 卡 #1 的存取權限,反之亦然。

電信業者如何將應用程式的簽署憑證轉換為雜湊?

如要將簽署憑證轉換為雜湊值,再將其新增至 CarrierConfig.xml,請執行下列操作:

  1. 使用 toByteArray,將簽署憑證的簽章轉換為位元組陣列。
  2. 使用 MessageDigest 將位元組陣列轉換為 byte[] 類型的雜湊。
  3. 將雜湊值從 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()));
    }
  4. 如果 certHashes 是大小為 2 的陣列,且值為 1234554321,請將下列內容新增至電信業者設定檔。

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