Mã nhận dạng thiết bị

Android 10 thay đổi quyền đối với giá trị nhận dạng thiết bị để tất cả giá trị 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, các giá trị nhận dạng thiết bị cố định (IMEI/MEID, IMSI, SIM và số sê-ri bản dựng) được bảo vệ bằng quyền trong 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 khoá nền tảng và các ứng dụng hệ thống đặc quyền.

Bạn có thể xem thêm thông tin về các yêu cầu mới về quyền trong các trang Javadoc cho TelephonyManager.javaBuild.java.

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

  • TelephonyManager#getDeviceId
  • TelephonyManager#getImei
  • TelephonyManager#getMeid
  • TelephonyManager#getSimSerialNumber
  • TelephonyManager#getSubscriberId
  • Build#getSerial

Quyền truy cập cho ứng dụng của nhà mạng không có quyền READ_PRIVILEGED_PHONE_STATE

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

Tuỳ chọn Nội dung mô tả Giới hạn
Đặc quyền của nhà mạng đối với 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 do 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à mạng cũ có một lượng lớn thẻ SIM đã được thiết lập và khó cập nhật. Ngoài ra, những nhà mạng không có quyền tác giả đối với thẻ SIM mới (ví dụ: MVNO có thẻ SIM do MNO phát hành) không thể thêm hoặc cập nhật chứng chỉ trên thẻ SIM.
Thêm vào danh sách cho phép của OEM OEM có thể sử dụng OP_READ_DEVICE_IDENTIFIER để cung cấp giá trị nhận dạng thiết bị cho các ứng dụng của nhà mạng có 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à mạng.
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 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 Nhà mạng có thể sử dụng số điện thoại (MSISDN) có 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 các nhà mạng phải đầu tư đáng kể. Những nhà mạng liên kết khoá mạng bằng IMSI cần có nhiều tài nguyên kỹ thuật để chuyển sang MSISDN.

Tất cả ứng dụng của nhà mạng đều có thể truy cập vào giá trị nhận dạng thiết bị bằng cách cập nhật tệp CarrierConfig.xml bằng hàm băm chứng chỉ ký của ứng dụng của nhà mạng. Khi ứng dụng của nhà mạng gọi một phương thức để đọc thông tin đặc quyền, nền tảng sẽ tìm kiếm 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ả trùng khớp, hệ thống sẽ trả về một trường hợp ngoại lệ về bảo mật.

Để triển khai giải pháp này, nhà mạng PHẢI làm 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à mạng và gửi bản vá.
  2. Yêu cầu nhà sản xuất thiết bị gốc (OEM) cập nhật bản dựng bằng QPR1 trở lên (nên dùng) 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ập nhật từ bước 1 ở trên.

Triển khai

Cập nhật danh sách cho phép quyền đặc quyền để cấp quyền READ_PRIVILEGED_PHONE_STATE cho những ứng dụng đặc quyền cần quyền truy cập vào giá trị 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 bài viết Danh sách cho phép 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 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.
  • Các ứng dụng được phân phối thông 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ề cách cấp đặc quyền cho nhà mạng trên trang Đặc quyền của nhà mạng trên 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 đến phiên bản trước 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 hiện tại trước Q vì quyền này là bắt buộc để gọi các API này.
  • Nếu ứng dụng đang nhắm đến phiên bản trước Q và được cấp quyền READ_PHONE_STATE, thì ứng dụng đó sẽ nhận được giá trị rỗng cho tất cả API TelephonyManager và Build.UNKNOWN cho phương thức Build#getSerial.
  • Nếu ứng dụng nhắm đến 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 một SecurityException.

Xác thực và kiểm thử

Bộ kiểm thử tính tương thích (CTS) bao gồm các kiểm thử để xác minh hành vi truy cập giá trị nhận dạng thiết bị dự kiến cho các ứng dụng có đặc quyền của nhà mạng, 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 kiểm thử 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

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

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

Tôi cần sử dụng thông số CarrierConfig nào trong CarrierConfig.xml để ứng dụng được đưa 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 tuỳ 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>

Tôi có thể sử dụng mẫu CarrierConfig cơ sở nào không?

Sử dụng mẫu sau. Bạn nên thêm thông tin này vào thành phần 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>

Có phải phải lắp thẻ SIM của nhà mạng vào thiết bị thì mới có thể truy cập vào giá trị nhận dạng thiết bị không?

CarrierConfig.xml được sử dụng được xác định dựa trên thẻ SIM đang được lắp. Điều này có nghĩa là nếu ứng dụng của nhà mạng X cố gắng nhận đặc quyền truy cập trong khi thẻ SIM của nhà mạng Y được lắp vào, thì thiết bị sẽ không tìm thấy kết quả trùng khớp cho 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 #1 chỉ có đặc quyền truy cập vào SIM #1 và ngược lại.

Nhà mạng chuyển đổi chứng chỉ ký của ứng dụng thành hàm băm như thế nào?

Để chuyển đổi chứng chỉ ký thành hàm băm trước khi thêm các chứng chỉ đó 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ột 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 trong loại byte[].
  3. Chuyển đổi hàm băm từ byte[] sang định dạng chuỗi thập lục phân. Để 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ị là 1234554321, hãy thêm nội dung sau vào tệp cấu hình của nhà mạng.

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