Số nhận dạng thiết bị

Android 10 thay đổi quyền đối với số nhận dạng thiết bị để tất cả số nhận dạng thiết bị hiện được bảo vệ bằng quyền READ_PRIVILEGED_PHONE_STATE . Trước Android 10, số nhận dạng thiết bị ổn định (IMEI/MEID, IMSI, SIM và sê-ri bản dựng) được bảo vệ bằng quyền thời gian chạy READ_PHONE_STATE . Quyền READ_PRIVILEGED_PHONE_STATE chỉ được cấp cho các ứng dụng được ký bằng khóa nền tảng và các ứng dụng hệ thống đặc quyền.

Bạn có thể tìm thêm thông tin về các yêu cầu quyền mới trên các trang Javadoc dành cho TelephonyManager.javaBuild.java .

Thay đổi này ảnh hưởng đến các API sau:

  • Trình quản lý điện thoại#getDeviceId
  • Trình quản lý điện thoại#getImei
  • Trình quản lý điện thoại#getMeid
  • Trình quản lý điện thoại#getSimSerialNumber
  • Trình quản lý điện thoại#getSubscriberId
  • Bản dựng#getSerial

Truy cập các ứng dụng của nhà cung cấp dịch vụ mà không có quyền READ_PRIVILEGED_PHONE_STATE

Các ứng dụng của nhà mạng được tải sẵn không đủ điều kiện nhận quyền READ_PRIVILEGED_PHONE_STATE có thể triển khai một trong các tùy chọn trong bảng bên dưới.

Lựa chọn Sự miêu tả Hạn chế
Đặc quyền của nhà cung cấp dịch vụ UICC Nền tảng Android tải các chứng chỉ được lưu trữ trên UICC và cấp quyền cho các ứng dụng được các chứng chỉ này ký để thực hiện lệnh gọi đến các phương thức đặc biệt. Các nhà cung cấp dịch vụ truyền thống có số lượng SIM lớn và lâu đời nên không dễ cập nhật. Ngoài ra, các nhà cung cấp dịch vụ không có quyền tác giả đối với SIM mới (ví dụ: MVNO có SIM do MNO phát hành) không thể thêm hoặc cập nhật chứng chỉ trên SIM.
Danh sách cho phép OEM OEM có thể sử dụng OP_READ_DEVICE_IDENTIFIER để cung cấp mã nhận dạng thiết bị cho các ứng dụng của nhà cung cấp dịch vụ trong danh sách cho phép. Giải pháp này không thể mở rộng cho tất cả các nhà cung cấp dịch vụ.
Mã phân bổ loại (TAC) Sử dụng phương thức getTypeAllocationCode được giới thiệu trong Android 10 để hiển thị TAC trả về thông tin về nhà sản xuất và kiểu máy. Thông tin trong TAC không đủ để xác định một thiết bị cụ thể.
MSISDN Các nhà cung cấp dịch vụ có thể sử dụng số điện thoại (MSISDN), có sẵn trong TelephonyManager với nhóm quyền PHONE , để tra cứu IMEI trên hệ thống phụ trợ của họ. Điều này đòi hỏi sự đầu tư đáng kể của các nhà mạng. Các nhà cung cấp dịch vụ ánh xạ khóa mạng của họ bằng IMSI yêu cầu nguồn lực kỹ thuật đáng kể để chuyển sang MSISDN .

Tất cả các ứng dụng của nhà cung cấp dịch vụ đều có thể truy cập số nhận dạng thiết bị bằng cách cập nhật tệp CarrierConfig.xml với hàm băm chứng chỉ ký của ứng dụng nhà cung cấp dịch vụ. Khi ứng dụng của nhà cung cấp dịch vụ gọi một phương thức để đọc thông tin đặc quyền, nền tảng sẽ tìm kiếm sự trùng khớp của hàm băm chứng chỉ ký của ứng dụng (chữ ký SHA-1 hoặc SHA-256 của chứng chỉ) trong tệp CarrierConfig.xml . Nếu tìm thấy kết quả trùng khớp, thông tin được yêu cầu sẽ được trả về. Nếu không tìm thấy kết quả phù hợp, một ngoại lệ bảo mật sẽ được trả về.

Để triển khai giải pháp này, các nhà mạng PHẢI thực hiện theo các bước sau:

  1. Cập nhật CarrierConfig.xml bằng hàm băm chứng chỉ ký của ứng dụng của nhà cung cấp dịch vụ và gửi bản vá .
  2. Yêu cầu OEM cập nhật bản dựng của họ với QPR1+ (được khuyến nghị) HOẶC các bản vá nền tảng bắt buộc này và bản vá chứa tệp CarrierConfig.xml được cập nhật từ bước 1 ở trên.

Thực hiện

Cập nhật danh sách cho phép quyền đặc quyền của bạn để cấp quyền READ_PRIVILEGED_PHONE_STATE cho những ứng dụng đặc quyền yêu cầu quyền truy cập vào số nhận dạng thiết bị.

Để tìm hiểu thêm về danh sách cho phép, hãy tham khảo Danh sách cho phép có quyền đặc quyền .

Để gọi các API bị ảnh hưởng, ứng dụng phải đáp ứng một trong các yêu cầu sau:

  • Nếu ứng dụng là ứng dụng đặc quyền được tải sẵn thì ứng dụng đó cần có quyền READ_PRIVILEGED_PHONE_STATE được khai báo trong AndroidManifest.xml. Ứng dụng cũng cần đưa quyền đặc quyền này vào danh sách cho phép.
  • Ứng dụng được phân phối qua Google Play cần có đặc quyền của nhà cung cấp dịch vụ. Tìm hiểu thêm về việc cấp đặc quyền của nhà cung cấp dịch vụ trên trang Đặc quyền của nhà cung cấp UICC .
  • Ứng dụng của chủ sở hữu thiết bị hoặc hồ sơ đã được cấp quyền READ_PHONE_STATE .

Ứng dụng không đáp ứng bất kỳ yêu cầu nào trong số này sẽ có hành vi sau:

  • Nếu ứng dụng đang nhắm mục tiêu pre-Q và không được cấp quyền READ_PHONE_STATE thì SecurityException sẽ được kích hoạt. đây là hành vi trước Q hiện tại vì cần có quyền này để gọi các API này.
  • Nếu ứng dụng đang nhắm mục tiêu pre-Q và đã được cấp quyền READ_PHONE_STATE thì ứng dụng sẽ nhận được giá trị null cho tất cả các API TelephonyManager và Build.UNKNOWN cho phương thức Build#getSerial .
  • Nếu ứng dụng đang nhắm mục tiêu Android 10 trở lên và không đáp ứng bất kỳ yêu cầu mới nào thì ứng dụng sẽ nhận được SecurityException.

Xác nhận và thử nghiệm

Bộ kiểm tra khả năng tương thích (CTS) bao gồm các thử nghiệm để xác minh hành vi truy cập giá trị nhận dạng thiết bị dự kiến ​​đối với các ứng dụng có đặc quyền của nhà cung cấp dịch vụ, chủ sở hữu thiết bị và hồ sơ cũng như những ứng dụng dự kiến ​​sẽ không có quyền truy cập vào giá trị nhận dạng thiết bị.

Các thử nghiệm CTS sau đây dành riêng cho tính năng này.

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

Câu hỏi thường gặp

Có bao nhiêu ứng dụng có thể được đưa vào danh sách cho phép trong CarrierConfig.xml cho một (MCC, MNC) nhất định?

Không có giới hạn về số lượng băm chứng chỉ có trong mảng.

Tôi cần sử dụng những thông số CarrierConfig nào trong CarrierConfig.xml để đưa ứng dụng vào danh sách cho phép?

Sử dụng mục cấu hình cấp cao nhất sau đây trong CarrierConfig.xml cụ thể từ các tùy chọn AOSP mà bạn đang định cấu hình:

<string-array name="carrier_certificate_string_array" num="2">
    <item value="BF02262E5EF59FDD53E57059082F1A7914F284B"/>
    <item value="9F3868A3E1DD19A5311D511A60CF94D975A344B"/>
</string-array>

Có mẫu CarrierConfig cơ bản nào mà tôi có thể sử dụng không?

Sử dụng mẫu sau. Điều này nên được thêm vào tài sản có liên quan .

<?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 của nhà mạng có phải có trong thiết bị để truy cập số nhận dạng thiết bị không?

CarrierConfig.xml được sử dụng được xác định dựa trên SIM hiện được lắp vào. Điều này có nghĩa là nếu ứng dụng của nhà cung cấp dịch vụ X cố gắng lấy đặc quyền truy cập trong khi lắp SIM của nhà cung cấp dịch vụ Y, thiết bị sẽ không tìm thấy kết quả khớp với hàm băm và trả về một ngoại lệ bảo mật.

Trên thiết bị nhiều SIM, nhà mạng số 1 chỉ có quyền truy cập đối với SIM số 1 và ngược lại.

Làm cách nào để nhà cung cấp dịch vụ chuyển đổi chứng chỉ ký của ứng dụng thành hàm băm?

Để chuyển đổi chứng chỉ ký thành hàm băm trước khi thêm chúng vào CarrierConfig.xml , hãy làm như sau:

  1. Chuyển đổi chữ ký của chứng chỉ ký thành mảng byte bằng cách sử dụng toByteArray .
  2. Sử dụng MessageDigest để chuyển đổi mảng byte thành hàm băm theo kiểu byte[].
  3. Chuyển đổi hàm băm từ byte[] thành định dạng chuỗi hex. Để biết ví dụ, hãy xem 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. Nếu certHashes là một mảng có kích thước 2 với giá trị 1234554321 , hãy thêm phần sau vào tệp cấu hình nhà cung cấp dịch vụ.

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