يقوم Android 11 بتفكيك قسم product
، مما يجعله مستقلاً عن أقسام system
vendor
. وكجزء من هذه التغييرات، يمكنك الآن التحكم في وصول قسم product
إلى الواجهات الأصلية وواجهات Java (والتي تشبه كيفية عمل فرض الواجهة لأقسام vendor
).
فرض الواجهات الأصلية
لتمكين فرض الواجهة الأصلية، قم بتعيين PRODUCT_PRODUCT_VNDK_VERSION
على current
. (يتم تعيين الإصدار تلقائيًا على current
عندما يكون مستوى واجهة برمجة التطبيقات للشحن للهدف أكبر من 29.) يسمح التنفيذ بما يلي:
- الوحدات الأصلية في قسم
product
للربط:- بشكل ثابت أو ديناميكي إلى الوحدات النمطية الأخرى في قسم
product
والتي تتضمن مكتبات ثابتة أو مشتركة أو مكتبات رأسية. - ديناميكيًا إلى مكتبات VNDK في قسم
system
.
- بشكل ثابت أو ديناميكي إلى الوحدات النمطية الأخرى في قسم
- مكتبات JNI في ملفات APK غير مجمعة في قسم
product
للارتباط بالمكتبات في/product/lib
أو/product/lib64
(هذا بالإضافة إلى مكتبات NDK).
لا يسمح التنفيذ بارتباطات أخرى إلى أقسام أخرى غير قسم product
.
تنفيذ وقت البناء (Android.bp)
في Android 11، يمكن لوحدات النظام إنشاء متغير صورة المنتج بالإضافة إلى متغيرات الصور الأساسية وصور البائعين. عند تمكين فرض الواجهة الأصلية (يتم تعيين PRODUCT_PRODUCT_VNDK_VERSION
على current
):
الوحدات النمطية الأصلية في قسم
product
موجودة في متغير المنتج بدلاً من المتغير الأساسي.الوحدات التي تحتوي على
product_available: true
في ملفاتAndroid.bp
الخاصة بها متاحة لمتغير المنتج.يمكن للمكتبات أو الثنائيات التي تحدد
product_specific: true
أن ترتبط بالمكتبات الأخرى التي تحددproduct_specific: true
أوproduct_available: true
في ملفاتAndroid.bp
الخاصة بها.يجب أن تحتوي مكتبات VNDK على
product_available: true
في ملفاتAndroid.bp
الخاصة بها حتى تتمكن ثنائياتproduct
من الارتباط بمكتبات VNDK.
يلخص الجدول التالي خصائص Android.bp
المستخدمة لإنشاء متغيرات الصور.
الخصائص في Android.bp | تم إنشاء المتغيرات | |
---|---|---|
قبل التنفيذ | بعد التنفيذ | |
الافتراضي (لا شيء) | جوهر (يتضمن | جوهر (يتضمن |
system_ext_specific: true | جوهر | جوهر |
product_specific: true | جوهر | منتج |
vendor: true | بائع | بائع |
vendor_available: true | جوهر، بائع | جوهر، بائع |
product_available: true | لا يوجد | الأساسية، المنتج |
vendor_available: true product_available: true | لا يوجد | الأساسية، المنتج، البائع |
system_ext_specific: true والبائع vendor_available: true | جوهر، بائع | جوهر، بائع |
product_specific: true vendor_available: true | جوهر، بائع | المنتج، البائع |
تنفيذ وقت البناء (Android.mk)
عند تمكين فرض الواجهة الأصلية، يكون للوحدات النمطية الأصلية المثبتة على قسم product
نوع رابط native:product
يمكنه الارتباط فقط بوحدات native:product
أو native:vndk
. تؤدي محاولة الارتباط بأي وحدات نمطية غير هذه إلى قيام نظام الإنشاء بإنشاء خطأ في التحقق من نوع الارتباط.
إنفاذ وقت التشغيل
عند تمكين فرض الواجهة الأصلية، فإن تكوين الرابط للرابط الإلكتروني لا يسمح لعمليات النظام باستخدام مكتبات product
، مما يؤدي إلى إنشاء قسم product
لعمليات product
التي لا يمكنها الارتباط بالمكتبات خارج قسم product
(ومع ذلك، يمكن لمثل هذه العمليات رابط إلى مكتبات VNDK). تؤدي محاولات انتهاك تكوين ارتباط وقت التشغيل إلى فشل العملية وإنشاء رسالة خطأ CANNOT LINK EXECUTABLE
.
فرض واجهات جافا
لتمكين فرض واجهة Java، قم بتعيين PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
على true
. (يتم تعيين القيمة تلقائيًا على true
عندما يكون مستوى واجهة برمجة التطبيقات للشحن للهدف أكبر من 29.) عند التمكين، يسمح/يمنع التنفيذ الوصول التالي.
واجهة برمجة التطبيقات | /نظام | /system_ext | /منتج | /بائع | /بيانات |
---|---|---|---|---|---|
واجهة برمجة التطبيقات العامة | |||||
@SystemApi | |||||
@إخفاء واجهة برمجة التطبيقات |
كما هو الحال في قسم vendor
، يُسمح لتطبيق أو مكتبة Java في قسم product
باستخدام واجهات برمجة التطبيقات العامة وواجهات برمجة التطبيقات الخاصة بالنظام فقط؛ لا يُسمح بالارتباط بمكتبة تستخدم واجهات برمجة التطبيقات المخفية. يتضمن هذا التقييد الارتباط في وقت الإنشاء والانعكاس في وقت التشغيل.
بناء إنفاذ الوقت
في وقت الإنشاء، يتحقق Make وSoong من أن وحدات Java في قسم product
لا تستخدم واجهات برمجة التطبيقات المخفية عن طريق التحقق من حقلي platform_apis
و sdk_version
. يجب ملء إصدار sdk_version
للتطبيقات الموجودة في قسم product
بالإصدار current
أو system_current
أو الرقمي لواجهة برمجة التطبيقات (API)، ويجب أن يكون حقل platform_apis
فارغًا.
إنفاذ وقت التشغيل
يتحقق وقت تشغيل Android من أن التطبيقات الموجودة في قسم product
لا تستخدم واجهات برمجة التطبيقات المخفية، بما في ذلك الانعكاس. للحصول على التفاصيل، راجع القيود المفروضة على الواجهات غير التابعة لـ SDK .
تمكين إنفاذ واجهة المنتج
استخدم الخطوات الواردة في هذا القسم لتمكين فرض واجهة المنتج.
خطوة | مهمة | مطلوب |
---|---|---|
1 | حدد ملف تعريف النظام الخاص بك الذي يحدد الحزم الخاصة بقسم system ، ثم قم بتعيين التحقق من متطلبات مسار العناصر في device.mk (لمنع الوحدات غير النظامية من التثبيت على قسم system ). | ن |
2 | تنظيف القائمة المسموح بها. | ن |
3 | فرض الواجهات الأصلية وتحديد حالات فشل الارتباط في وقت التشغيل (يمكن تشغيلها بالتوازي مع فرض Java). | ي |
4 | فرض واجهات Java والتحقق من سلوك وقت التشغيل (يمكن تشغيله بالتوازي مع التنفيذ الأصلي). | ي |
5 | التحقق من سلوكيات وقت التشغيل. | ي |
6 | قم بتحديث device.mk من خلال فرض واجهة المنتج. | ي |
الخطوة 1: إنشاء ملف تعريفي وتمكين التحقق من مسار القطعة الأثرية
في هذه الخطوة، يمكنك تحديد ملف تعريف system
.
قم بإنشاء ملف تعريفي يحدد الحزم الخاصة بقسم
system
. على سبيل المثال، قم بإنشاء ملفoem_system.mk
بما يلي:$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk) # Applications PRODUCT_PACKAGES += \ CommonSystemApp1 \ CommonSystemApp2 \ CommonSystemApp3 \ # Binaries PRODUCT_PACKAGES += \ CommonSystemBin1 \ CommonSystemBin2 \ CommonSystemBin3 \ # Libraries PRODUCT_PACKAGES += \ CommonSystemLib1 \ CommonSystemLib2 \ CommonSystemLib3 \ PRODUCT_SYSTEM_NAME := oem_system PRODUCT_SYSTEM_BRAND := Android PRODUCT_SYSTEM_MANUFACTURER := Android PRODUCT_SYSTEM_MODEL := oem_system PRODUCT_SYSTEM_DEVICE := generic # For system-as-root devices, system.img should be mounted at /, so we # include ROOT here. _my_paths := \ $(TARGET_COPY_OUT_ROOT)/ \ $(TARGET_COPY_OUT_SYSTEM)/ \ $(call require-artifacts-in-path, $(_my_paths),)
في ملف
device.mk
، يمكنك الحصول على ملف makefile الشائع لقسمsystem
وتمكين التحقق من متطلبات مسار القطعة الأثرية. على سبيل المثال:$(call inherit-product, $(SRC_TARGET_DIR)/product/oem_system.mk) # Enable artifact path requirements checking PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := strict
حول متطلبات مسار القطعة الأثرية
عند تعيين PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
على true
أو strict
، يمنع نظام البناء الحزم المحددة في ملفات تكوين أخرى من التثبيت على المسارات المحددة في require-artifacts-in-path
ويمنع الحزم المحددة في ملف makefile الحالي من تثبيت العناصر خارج المسارات المحددة في require-artifacts-in-path
.
في المثال أعلاه، مع تعيين PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
على strict
، لا يمكن أن تتضمن ملفات الإنشاء الموجودة خارج oem_system.mk
الوحدات النمطية المثبتة على root
أو قسم system
. لتضمين هذه الوحدات، يجب عليك إما تعريفها في الملف oem_system.mk
نفسه أو في ملف makefile المضمن. تؤدي محاولات تثبيت الوحدات النمطية على المسارات غير المسموح بها إلى حدوث فواصل في البناء. لإصلاح الفواصل، قم بأحد الإجراءات التالية:
الخيار 1: قم بتضمين وحدة النظام في ملفات makefiles المضمنة في
oem_system.mk
. يؤدي ذلك إلى استيفاء متطلبات المسار المصنوع (حيث أن الوحدات النمطية موجودة الآن في ملف تكوين مضمن) وبالتالي يسمح بالتثبيت على مجموعة المسارات في "require-artifacts-in-path".الخيار 2: تثبيت الوحدات النمطية على قسم
system_ext
أوproduct
(ولا تقم بتثبيت الوحدات النمطية على قسمsystem
).الخيار 3: إضافة وحدات إلى
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
. يسرد هذا الوحدات النمطية المسموح بتثبيتها.
الخطوة 2: إفراغ القائمة المسموح بها
في هذه الخطوة، يمكنك جعل PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
فارغة حتى تتمكن جميع الأجهزة التي تشارك oem_system.mk
أيضًا من مشاركة صورة system
واحدة. لإفراغ القائمة المسموح بها، انقل أي وحدات نمطية في القائمة إلى قسم system_ext
أو product
أو قم بإضافتها إلى ملفات تكوين system
. تعتبر هذه الخطوة اختيارية نظرًا لأن تحديد صورة system
العامة ليس مطلوبًا لتمكين فرض واجهة المنتج. ومع ذلك، فإن إفراغ القائمة المسموح بها مفيد في تحديد حدود system
باستخدام system_ext
.
الخطوة 3: فرض الواجهات الأصلية
في هذه الخطوة، قمت بتعيين PRODUCT_PRODUCT_VNDK_VERSION := current
، ثم ابحث عن أخطاء الإنشاء ووقت التشغيل وقم بحلها. للتحقق من تمهيد الجهاز وسجلاته والعثور على حالات فشل ارتباط وقت التشغيل وإصلاحها:
قم بتعيين
PRODUCT_PRODUCT_VNDK_VERSION := current
.قم ببناء الجهاز وابحث عن أخطاء البناء. من المحتمل أن ترى بعض فواصل البناء لمتغيرات المنتج أو المتغيرات الأساسية المفقودة. تشمل فترات الراحة الشائعة ما يلي:
- أي وحدة
hidl_interface
تحتوي علىproduct_specific: true
لن تكون متاحة لوحدات النظام. لإصلاح هذه المشكلة، استبدلproduct_specific: true
بـsystem_ext_specfic: true
. - قد تفتقد الوحدات متغير المنتج المطلوب لوحدات المنتج. لإصلاح هذه المشكلة، قم بإتاحة هذه الوحدة لقسم
product
عن طريق تعيينproduct_available: true
أو انقل الوحدة إلى قسمproduct
عن طريق تعيينproduct_specific: true
.
- أي وحدة
حل أخطاء البناء والتأكد من بناء الجهاز بنجاح.
قم بفلاش الصورة وابحث عن أخطاء وقت التشغيل في تمهيد الجهاز وسجلاته.
- إذا أظهرت علامة
linker
من سجل حالة الاختبار رسالةCANNOT LINK EXECUTABLE
، فهذا يعني أن ملف التكوين يفتقد التبعية (ولم يتم التقاطه في وقت الإنشاء). - للتحقق من ذلك من نظام البناء، قم بإضافة المكتبة المطلوبة إلى حقل
shared_libs:
أو الحقلrequired:
.
- إذا أظهرت علامة
قم بحل التبعيات المفقودة باستخدام الإرشادات المذكورة أعلاه.
الخطوة 4: فرض واجهات Java
في هذه الخطوة، يمكنك تعيين PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true
، ثم البحث عن أخطاء البناء الناتجة وإصلاحها. ابحث عن نوعين محددين من الأخطاء:
أخطاء في نوع الارتباط. يشير هذا الخطأ إلى أن التطبيق يرتبط بوحدات Java النمطية التي تحتوي على إصدار
sdk_version
أوسع. لإصلاح ذلك، يمكنك توسيعsdk_version
الخاص بالتطبيق أو تقييدsdk_version
الخاص بالمكتبة. خطأ المثال:error: frameworks/base/packages/SystemUI/Android.bp:138:1: module "SystemUI" variant "android_common": compiles against system API, but dependency "telephony-common" is compiling against private API.Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.
أخطاء الرمز. يشير هذا الخطأ إلى أنه لا يمكن العثور على الرمز لأنه موجود في واجهة برمجة تطبيقات مخفية. لإصلاح المشكلة، استخدم واجهة برمجة تطبيقات مرئية (غير مخفية) أو ابحث عن بديل. خطأ المثال:
frameworks/opt/net/voip/src/java/com/android/server/sip/SipSessionGroup.java:1051: error: cannot find symbol ProxyAuthenticate proxyAuth = (ProxyAuthenticate)response.getHeader( ^ symbol: class ProxyAuthenticate location: class SipSessionGroup.SipSessionImpl
الخطوة 5: التحقق من سلوكيات وقت التشغيل
في هذه الخطوة، يمكنك التحقق من أن سلوكيات وقت التشغيل كما هو متوقع. بالنسبة للتطبيقات القابلة للتصحيح، يمكنك مراقبة استخدام واجهة برمجة التطبيقات المخفية عن طريق السجل باستخدام StrictMode.detectNonSdkApiUsage
(الذي ينشئ سجلًا عندما يستخدم التطبيق واجهة برمجة تطبيقات مخفية). وبدلاً من ذلك، يمكنك استخدام أداة التحليل الثابت veridex للحصول على نوع الاستخدام (الربط أو الانعكاس)، ومستوى التقييد، ومكدس الاستدعاءات.
بناء جملة فيريديكس:
./art/tools/veridex/appcompat.sh --dex-file={apk file}
مثال لنتيجة veridex:
#1: Linking greylist-max-o Landroid/animation/AnimationHandler;-><init>()V use(s): Lcom/android/systemui/pip/phone/PipMotionHelper;-><init>(Landroid/content/Context;Landroid/app/IActivityManager;Landroid/app/IActivityTaskManager;Lcom/android/systemui/pip/phone/PipMenuActivityController;Lcom/android/internal/policy/PipSnapAlgorithm;Lcom/android/systemui/statusbar/FlingAnimationUtils;)V #1332: Reflection greylist Landroid/app/Activity;->mMainThread use(s): Landroidx/core/app/ActivityRecreator;->getMainThreadField()Ljava/lang/reflect/Field;
للحصول على تفاصيل حول استخدام veridex، راجع الاختبار باستخدام أداة veridex .
الخطوة 6: تحديث Device.mk
بعد إصلاح جميع حالات فشل البناء ووقت التشغيل، والتحقق من أن سلوكيات وقت التشغيل كما هو متوقع، قم بتعيين ما يلي في device.mk
:
-
PRODUCT_PRODUCT_VNDK_VERSION := current
-
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true