裝置 ID

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

如要進一步瞭解新的權限需求,請參閱 TelephonyManager.java 的 Javadoc 頁面 和 Build.java

這項變更會影響下列 API:

  • TelephonyManager#getDeviceId
  • 電話管理工具#getImei
  • TelephonyManager#getMeid
  • 電話管理工具#getSimSerialNumber
  • TelephonyManager#get 訂閱者 Id
  • 版本#getSerial

沒有 READ_PRIVILEGED_PHONE_STATE 權限的電信業者應用程式存取權

預先載入不符合 READ_PRIVILEGED_PHONE_STATE 權限可實作下表中的其中一個選項。

選項 說明 限制
UICC 電信業者權限 Android 平台會載入儲存在 UICC 和授權中的憑證 授權給由這些憑證簽署的應用程式,以便呼叫特殊憑證 方法。 舊版電信業者有大量的 SIM 卡填入人數, 就能輕鬆更新此外,電信業者並未提供新授權和 SIM 卡 (例如使用 MNO 核發 SIM 卡的 MVNO) 無法新增或 更新 SIM 卡上的憑證。
原始設備製造商 (OEM) 許可清單 原始設備製造商 (OEM) 可以使用 OP_READ_DEVICE_IDENTIFIER 提供裝置 加入許可清單的電信業者應用程式。 部分電信業者無法擴充這項解決方案。
類型分配代碼 (TAC) 使用 getTypeAllocationCode敬上 方法, Android 10,以公開傳回製造商和型號的 TAC 資訊 TAC 中的資訊不足以辨識特定裝置。
MSISDN 電信業者可以撥打以下電話號碼 (MSISDN): 具備PHONE權限的TelephonyManager 群組,在後端系統上查詢 IMEI。 電信業者會為此投入大量資金。可對照比較對應的電信業者 以使用 IMSI 的網路金鑰來說 改用 MSISDN 的技術資源。

所有電信業者應用程式只要更新應用程式,即可存取裝置 ID 含有簽署憑證雜湊值的 CarrierConfig.xml 檔案 透過電信業者應用程式電信業者應用程式呼叫具有特殊權限的方法時 平台會尋找與應用程式簽署憑證相符的 雜湊 (憑證的 SHA-1 或 SHA-256 簽名) CarrierConfig.xml 檔案。如果找到相符項目,會要求 的資訊。如果系統找不到相符結果,則會發生安全性例外狀況 。

如要導入這項解決方案,電信業者「必須」按照下列步驟操作:

  1. 最新消息 CarrierConfig.xml 替換為 以及電信業者應用程式 提交修補程式
  2. 要求原始設備製造商 (OEM) 使用 QPR1+ 更新版本 (建議),「或」這些 必要平台修補程式和 已更新上述步驟 1 的 CarrierConfig.xml 檔案。

實作

更新特殊權限許可清單,以便授予 READ_PRIVILEGED_PHONE_STATE權限專屬於這些特殊權限 需要存取裝置 ID 的應用程式。

如要進一步瞭解許可清單,請參閱特殊權限 將權限加入許可清單

如要叫用受影響的 API,應用程式必須符合下列其中一項條件 規定:

  • 如果是預先載入具有特殊權限的應用程式,則必須取得 已在以下位置宣告 READ_PRIVILEGED_PHONE_STATE 項權限: AndroidManifest.xml 檔案。應用程式也必須加入許可清單 授予這項權限。
  • 透過 Google Play 提供的應用程式需要電信業者權限。 進一步瞭解如何授予 UICC 電信業者權限 權限頁面。
  • 已獲得 READ_PHONE_STATE權限。

不符合上述任一規定的應用程式具有下列特性 行為:

  • 如果應用程式指定的是 Q/Q 已授予READ_PHONE_STATE權限,SecurityException 這是目前所屬的上一個行為,因為這項權限 才能叫用這些 API
  • 如果應用程式指定的是 Pre-Q 值,且 已授予 READ_PHONE_STATE 權限,該應用程式會收到 所有 TelephonyManager API 和 Build.UNKNOWN 的空值 針對 Build#getSerial 方法。
  • 如果應用程式指定 Android 10 以上版本,且 不符合任何一個 用戶端就會收到 SecurityException。

驗證與測試

相容性 Test Suite (CTS) 包含測試,以驗證預期的裝置 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

常見問題

CarrierConfig.xml 中,特定 (MCC、MNC) 中可以有幾款應用程式加入許可清單?

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

需要使用 CarrierConfig.xml 中的哪些 CarrierConfig 參數,才能將應用程式加入許可清單?

請在 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?

使用的 CarrierConfig.xml 取決於 目前已插入的 SIM 卡。這意味著如果電信業者 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>