Android 10 thay đổi các quyền đối với giá trị nhận dạng thiết bị để giờ đây, tất cả giá trị nhận dạng thiết bị đều đượ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 đối với quyền trong các trang Javadoc cho TelephonyManager.java và Build.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 các ứng dụng của nhà mạng mà không có quyền READ_PRIVILEGED_PHONE_STATE
Được tải sẵn Các ứng dụng của nhà mạng không đủ điều kiện để có quyền READ_PRIVILEGED_PHONE_STATE có thể triển khai một trong các lựa chọn trong bảng bên dưới.
| Lựa chọn | Nội dung mô tả | Giới hạn |
|---|---|---|
| Đặc quyền của nhà mạng trên 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 ký bằng những chứng chỉ này để gọi các phương thức đặc biệt. | Các nhà mạng truyền thống có số lượng SIM lớn và ổn định, nhưng không dễ dàng cập nhật. Ngoài ra, những nhà mạng không có quyền tạo 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. |
| Thêm OEM vào danh sách cho phép | Các 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 nằm 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 hãng vận chuyển. |
| Mã phân bổ loại (TAC) | Sử dụng phương thức getTypeAllocationCode (ra mắt 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 | 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 hãng vận chuyển phải đầu tư đáng kể. Những nhà mạng ánh xạ 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 mã 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 nhà mạng. Khi ứng dụng 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 một 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, một trường hợp ngoại lệ bảo mật sẽ được trả về.
Để triển khai giải pháp này, hãng vận chuyển PHẢI làm theo các bước sau:
- Cập nhật
CarrierConfig.xmlbằng hàm băm chứng chỉ ký của ứng dụng nhà mạng và gửi bản vá. - Yêu cầu các OEM cập nhật bản dựng của họ 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á có 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ó đặc quyền để cấp quyền READ_PRIVILEGED_PHONE_STATE cho những ứng dụng có đặc quyền cần truy cập vào mã nhận dạng thiết bị.
Để tìm hiểu thêm về việc đưa vào danh sách cho phép, hãy tham khảo bài viết Đưa quyền đặc biệt vào danh sách cho phép.
Để 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à một ứ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 biệt 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 UICC.
- Một ứng dụng chủ sở hữu thiết bị hoặc hồ sơ đã được cấp quyền
READ_PHONE_STATE.
Một ứ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 nhắm đến phiên bản trước Q và chưa được cấp quyền
READ_PHONE_STATE, thìSecurityExceptionsẽ được kích hoạt. Đây là hành vi trước Q hiện tại vì quyền này là bắt buộc để gọi các API này. - Nếu ứng dụng 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ả các API TelephonyManager vàBuild.UNKNOWNcho phương thứcBuild#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 mã 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 không có quyền truy cập vào mã 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.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
Câu hỏi thường gặp
Có thể đưa bao nhiêu ứng dụng 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 hàm 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 để một ứ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 sau đây trong CarrierConfig.xml cụ thể từ các lựa 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ơ bản không?
Hãy sử dụng mẫu sau. Bạn nên thêm thông tin này vào thành phầ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>Có phải thẻ SIM của nhà mạng phải nằm trong thiết bị thì mới truy cập được vào giá trị nhận dạng thiết bị không?
CarrierConfig.xml được dùng sẽ được xác định dựa trên SIM hiện đ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 lấy đặc quyền truy cập trong khi 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 các thiết bị có nhiều SIM, nhà mạng số 1 chỉ có quyền truy cập vào SIM số 1 và ngược lại.
Làm cách nào để nhà mạng chuyển đổi chứng chỉ ký của ứng dụng thành một hàm băm?
Để chuyển đổi chứng chỉ ký thành một hàm băm trước khi thêm chúng vào CarrierConfig.xml, hãy làm như sau:
- 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. - Sử dụng
MessageDigestđể chuyển đổi mảng byte thành một hàm băm thuộc loại byte[]. -
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())); } Nếu
certHasheslà một mảng có kích thước2với giá trị12345và54321, hãy thêm nội dung sau vào tệp cấu hình nhà mạng.<string-array name="carrier_certificate_string_array" num="2"> <item value="12345"/> <item value="54321"/> </string-array>