يغيّر نظام التشغيل Android 10 أذونات
معرّفات الأجهزة لكي تصبح جميع معرّفات الأجهزة محمية الآن باستخدام
إذن READ_PRIVILEGED_PHONE_STATE
. قبل الإصدار
Android 10، كانت معرّفات الجهاز الدائمة
(IMEI/MEID وIMSI وشريحة SIM والرقم التسلسلي للإصدار) محمية من خلال إذن التشغيل
READ_PHONE_STATE
.
لا يُمنح الإذن READ_PRIVILEGED_PHONE_STATE
إلا
للتطبيقات الموقَّعة باستخدام مفتاح النظام الأساسي وتطبيقات النظام المميّزة.
يمكنك الاطّلاع على مزيد من المعلومات حول متطلبات الأذونات الجديدة في صفحات Javadoc لكلّ من TelephonyManager.java وBuild.java.
يؤثر هذا التغيير في واجهات برمجة التطبيقات التالية:
- TelephonyManager#getDeviceId
- TelephonyManager#getImei
- TelephonyManager#getMeid
- TelephonyManager#getSimSerialNumber
- TelephonyManager#getSubscriberId
- Build#getSerial
الوصول إلى تطبيقات مشغّل شبكة الجوّال بدون إذن READ_PRIVILEGED_PHONE_STATE
يمكن لتطبيقات مشغّلي الشبكات المُحمَّلة مُسبَقًا التي لا تستوفي متطلبات إذن
READ_PRIVILEGED_PHONE_STATE
تنفيذ أحد الخيارات الواردة في الجدول أدناه.
الخيار | الوصف | القيود |
---|---|---|
امتيازات مشغّل شبكة الجوّال في شريحة UICC | يحمِّل نظام Android الشهادات المخزّنة على شريحة UICC ويمنح الإذن للتطبيقات الموقَّعة بهذه الشهادات لإجراء مكالمات إلى methods الخاصة. | تمتلك شركات الجوّال القديمة عددًا كبيرًا من شرائح SIM الراسخة التي لا يمكن تعديلها بسهولة. بالإضافة إلى ذلك، لا يمكن لمشغّلي شبكات الجوّال الذين لا يملكون حقوق التأليف لشرائح SIM الجديدة (مثل مزوّدي خدمات الجوّال الافتراضية الذين لديهم شرائح SIM صادرة عن مزوّدي خدمات الجوّال التقليديين) إضافة الشهادات أو تعديلها على شرائح SIM. |
قائمة السماح للمصنع الأصلي للجهاز | يمكن لمصنّعي المعدّات الأصلية استخدام OP_READ_DEVICE_IDENTIFIER لتوفير معرّفات
للأجهزة لتطبيقات مشغّلي الشبكات المدرَجة في القائمة المسموح بها. |
لا يمكن توسيع نطاق هذا الحلّ ليشمل جميع مشغّلي شبكات الجوّال. |
رمز تخصيص النوع (TAC) | استخدِم الإجراء
getTypeAllocationCode
الذي تم طرحه في
الإصدار 10 من Android لعرض TAC الذي يعرض معلومات المصنّع والطراز. |
المعلومات الواردة في طلب الحصول على إذن الوصول إلى الحساب غير كافية لتحديد جهاز معيّن. |
رقم MSISDN | يمكن لمشغّلي شبكات الجوّال استخدام رقم الهاتف (MSISDN) المتوفّر ضمن مجموعة
TelephonyManager التي تملك إذن PHONE
، للبحث عن رقم IMEI في أنظمة الخلفية. |
ويتطلّب ذلك من شركات النقل استثمارًا كبيرًا. إنّ مشغّلي شبكات الجوّال الذين يربطون مفاتيح الشبكة باستخدام IMSI يحتاجون إلى موارد فنية كبيرة للتبديل إلى MSISDN. |
يمكن لجميع تطبيقات مشغّلي شبكات الجوّال الوصول إلى معرّفات الجهاز من خلال تعديلملف CarrierConfig.xml
باستخدام تجزئة شهادة التوقيع الخاصة
بتطبيق مشغّل شبكة الجوّال. عندما يستدعي تطبيق مشغّل شبكة الجوّال طريقة لقراءة
المعلومات المحظورة، يبحث النظام الأساسي عن تطابق مع تجزئة شهادة توقيع التطبيق (توقيع SHA-1 أو SHA-256 للشهادة) فيملف
CarrierConfig.xml
. في حال العثور على مطابقة، يتم عرض
المعلومات المطلوبة. في حال عدم العثور على أي مطابقة، يتم عرض استثناء أمان.
لتنفيذ هذا الحل، على مشغّلي الشبكات اتّباع الخطوات التالية:
- عدِّل
CarrierConfig.xml
باستخدام تجزئة شهادة التوقيع الخاصة بتطبيق مشغّل شبكة الجوال وأرسِل تصحيحًا. - يُرجى طلب من المصنّعين الأصليّين للأجهزة تحديث الإصدار باستخدام QPR1 أو إصدار أحدث (إجراء يُنصح به) أو
تصحيحات المنصة المطلوبة والتصحيح الذي يحتوي على
ملف
CarrierConfig.xml
المعدَّل من الخطوة 1 أعلاه.
التنفيذ
عدِّل قائمة التطبيقات المسموح لها بالحصول على الأذونات المميّزة لمنح إذن
READ_PRIVILEGED_PHONE_STATE
للتطبيقات المميّزة
التي تتطلّب الوصول إلى معرّفات الأجهزة.
لمعرفة المزيد من المعلومات عن القائمة المسموح بها، يُرجى الاطّلاع على مقالة إضافة التطبيقات إلى القائمة المسموح بها للحصول على أذونات بامتيازات.
لاستدعاء واجهات برمجة التطبيقات المتأثرة، يجب أن يستوفي التطبيق أحد ال requirements التالية:
- إذا كان التطبيق من التطبيقات المُحمَّلة مُسبَقًا المزوّدة بامتيازات، يجب أن يحصل على إذن
READ_PRIVILEGED_PHONE_STATE
الذي تم تعريفه فيملف AndroidManifest.xml. يجب أيضًا أن يضيف التطبيق هذا الإذن المميّز إلى القائمة المسموح بها. - تحتاج التطبيقات التي يتم تسليمها من خلال Google Play إلى امتيازات مشغّل شبكة الجوَّال. اطّلِع على مزيد من المعلومات عن منح امتيازات مشغّل شبكة الجوَّال في صفحة امتيازات مشغّل شبكة الجوَّال (UICC).
- تطبيق مالك الجهاز أو الملف الشخصي الذي تم منحه الإذن
READ_PHONE_STATE
إذا لم يستوفِ التطبيق أيًا من هذه المتطلبات، سيظهر عليه السلوك التالي:
- إذا كان التطبيق يستهدف الإصدارات التجريبية من نظام التشغيل، ولم يتم منح الإذن
READ_PHONE_STATE
، يتم تشغيلSecurityException
. وهذا هو السلوك الحالي للإصدارات التجريبية من نظام التشغيل، لأنّ هذا الإذن مطلوب لاستدعاء واجهات برمجة التطبيقات هذه. - إذا كان التطبيق يستهدف الإصدارات الأقدم من Android Q وكان قد تم منحه إذن
READ_PHONE_STATE
، سيتلقّى قيمة فارغة لجميع واجهات برمجة التطبيقات TelephonyManager وBuild.UNKNOWN
لطريقةBuild#getSerial
. - إذا كان التطبيق يستهدف الإصدار 10 من نظام التشغيل Android أو الإصدارات الأحدث ولم يكن يستوفي أيًا من المتطلبات الجديدة، سيتلقّى SecurityException.
التحقّق والاختبار
تتضمّن مجموعة اختبار التوافق (CTS) اختبارات للتحقّق من سلوك الوصول المتوقّع إلى معرّف الجهاز للتطبيقات التي تمتلك امتيازات مشغّل شبكة الجوّال وأصحاب الأجهزة والملف الشخصي والتطبيقات التي من المتوقّع ألا تتمكن من الوصول إلى معرّفات الجهاز.
اختبارات 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
لحساب معيّن (مركز عملائي أو شركة اتصالات وطنية)؟
ما مِن حدّ أقصى لعدد تجزئات الشهادات المضمّنة في الصفيف.
ما هي مَعلمات CarrierConfig في CarrierConfig.xml
التي يجب استخدامها لكي يتم إدراج التطبيق في القائمة المسموح بها؟
استخدِم عنصر الضبط الأعلى مستوى التالي ضمن
CarrierConfig.xml
المحدّد من خيارات AOSP التي يتم ضبطها:
<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 الخاصة بمشغّل شبكة الجوّال مثبّتة في الجهاز للوصول إلى معرّفات الجهاز؟
يتم تحديد CarrierConfig.xml
المستخدَم استنادًا إلى
شريحة SIM المُدرَجة حاليًا. وهذا يعني أنّه إذا حاول تطبيق مشغّل شبكة الجوّال "س"
الحصول على امتيازات الوصول أثناء إدخال شريحة SIM الخاصة بمشغّل شبكة الجوّال "ص"، لن يعثر الجهاز على
مطابقة للقيمة المحوَّلة إلى سلسلة من الأحرف ويعرض استثناءً للأمان.
على الأجهزة التي تتضمّن عدة شرائح SIM، لا يحصل مشغّل شبكة الجوّال رقم 1 إلا على امتيازات الوصول إلى شريحة SIM رقم 1، والعكس صحيح.
كيف تحوّل شركات الجوّال شهادة توقيع التطبيق إلى تجزئة؟
لتحويل شهادات التوقيع إلى تجزئة قبل إضافتها إلى
CarrierConfig.xml
، اتّبِع الخطوات التالية:
- حوِّل توقيع شهادة التوقيع إلى صفيف بايت باستخدام
toByteArray
. - استخدِم
MessageDigest
لتحويل صفيف البايت إلى تجزئة في نوع byte[]. -
حوِّل التجزئة من 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())); }
إذا كانت
certHashes
صفيفًا بحجم2
وقيمة12345
و54321
، أضِف ما يلي إلىملف إعدادات carrier.<string-array name="carrier_certificate_string_array" num="2"> <item value="12345"/> <item value="54321"/> </string-array>