APEX الخاص بالمورّد

يمكنك استخدام تنسيق ملف APEX لحزم وحدات نظام التشغيل Android من المستوى الأدنى و تثبيتها. ويسمح هذا الإطار بإنشاء و تثبيت المكونات بشكل مستقل، مثل الخدمات والمكتبات الأصلية وتنفيذ HAL والبرامج الثابتة وملفات الإعدادات وما إلى ذلك.

يُثبِّت نظام الإنشاء وحدات APEX الخاصة بالمورّدين تلقائيًا في القسم /vendor ويفعّلها apexd أثناء التشغيل تمامًا مثل وحدات APEX في الأقسام الأخرى.

حالات الاستخدام

تجميع صور المورّدين في وحدات

تسهِّل حِزم APEX تجميع عمليات تنفيذ الميزات وتصميمها بشكل طبيعي على صور المورّدين.

عند إنشاء صور المورّدين كمجموعة من منصّات APEX التي أنشأها المورّدون بشكل مستقل، يمكن لمصنعي الأجهزة اختيار عمليات تنفيذ محددة للمورّدين على أجهزتهم بسهولة. يمكن للشركات المصنّعة أيضًا إنشاء وحدة APEX جديدة للمورّد إذا لم تكن أي من وحدات APEX المقدّمة تلبي احتياجاتها، أو إذا كانت لديها جهاز جديد تمامًا مخصّص.

على سبيل المثال، قد يختار المصنّع الأصلي للجهاز إنشاء جهازه باستخدام حزمة APEX لتطبيق WiFi في AOSP وحزمة APEX لتطبيق البلوتوث في شريحة المعالجة SoC وحزمة APEX مخصّصة لتطبيق الهاتف في المصنّع الأصلي للجهاز.

في حال عدم توفّر خطط APEX الخاصة بالمورّدين، يتطلّب التنفيذ الذي يتضمّن العديد من التبعيات بين مكونات المورّد تنسيقًا وتتبُّعًا دقيقَين. من خلال تجميع كل المكونات (بما في ذلك ملفات الإعدادات والمكتبات الإضافية) في وحدات APEX باستخدام واجهات محدّدة بوضوح في أيّ نقطة من نقاط التواصل بين الميزات المختلفة، تصبح المكونات المختلفة قابلة للتبديل.

تكرار المطوّر

تساعد حِزم APEX الخاصة بالمورّدين المطوّرين على إجراء عمليات تكرار أسرع أثناء تطوير وحدات المورّدين من خلال تجميع تنفيذ ميزة بالكامل، مثل HAL للواي فاي، داخل حِزمة APEX الخاصة بالمورّد. يمكن للمطوّرين بعد ذلك إنشاء حِزم APEX الخاصة بالمورّد ودفعها بشكلٍ فردي لاختبار التغييرات، بدلاً من إعادة إنشاء صورة المورّد بالكامل.

وهذا يبسط دورة تكرار المطوّرين ويسرعها للمطوّرين الذين يعملون بشكل أساسي في مجال ميزة واحدة ويريدون تكرار هذا المجال فقط.

إنّ تجميع منطقة ميزات في حزمة APEX يبسّط أيضًا عملية إنشاء التغييرات ودفعها واختبارها لهذه المنطقة. على سبيل المثال، يؤدي إعادة تثبيت حزمة APEX إلى تعديل أي مكتبة أو ملفات ضبط مضمّنة في حزمة APEX تلقائيًا.

يؤدي تجميع منطقة ميزة في APEX أيضًا إلى تبسيط تصحيح الأخطاء أو الرجوع إلى الإصدار السابق عند ملاحظة سلوك سيئ للجهاز. على سبيل المثال، إذا كان الاتصال الهاتفي يعمل بشكلٍ سيئ في إصدار جديد، يمكن للمطوّرين محاولة تثبيت إصدار قديم من APEX لتطبيق الاتصال الهاتفي (بدون الحاجة إلى تحديث الإصدار الكامل) والتحقّق مما إذا كان الأداء قد تحسّن.

مثال على سير العمل:

# Build the entire device and flash. OR, obtain an already-flashed device.
source build/envsetup.sh && lunch oem_device-userdebug
m
fastboot flashall -w

# Test the device.
... testing ...

# Check previous behavior using a vendor APEX from one week ago, downloaded from
# your continuous integration build.
... download command ...
adb install <path to downloaded APEX>
adb reboot
... testing ...

# Edit and rebuild just the APEX to change and test behavior.
... edit APEX source contents ...
m <apex module name>
adb install out/<path to built APEX>
adb reboot
... testing ...

أمثلة

الأساسيات

اطّلِع على صفحة تنسيق ملف APEX الرئيسية للحصول على معلومات عامة عن APEX، بما في ذلك متطلبات الجهاز وتفاصيل تنسيق الملف وخطوات التثبيت.

في Android.bp، يؤدي ضبط السمة vendor: true إلى جعل وحدة APEX وحدة APEX تابعة للمورّد.

apex {
  ..
  vendor: true,
  ..
}

الملفات الثنائية والمكتبات المشتركة

تتضمّن حزمة APEX تبعيات قابلة للنقل داخل الحمولة، ما لم يكن لديها واجهات ثابتة.

تشمل الواجهات الأصلية الثابتة لموارد APEX التابعة للمورّد مكتبتَي cc_library مع stubs وLLNDK. ويتم استبعاد هذه التبعيات من عملية التجميع، ويتم تسجيل التبعيات في بيان APEX. يعالج linkerconfig البيان لكي تكون التبعيات الأصلية الخارجية متوفرة أثناء التشغيل.

في المقتطف التالي، يحتوي حِزمة APEX على كلّ من الملف الثنائي (my_service) وملفات التبعيات غير المستقرة (*.so).

apex {
  ..
  vendor: true,
  binaries: ["my_service"],
  ..
}

في المقتطف التالي، يحتوي APEX على المكتبة المشترَكة my_standalone_lib وأيّ من التبعيات غير المستقرة (كما هو موضّح أعلاه).

apex {
  ..
  vendor: true,
  native_shared_libs: ["my_standalone_lib"],
  ..
}

تصغير APEX

قد يزداد حجم APEX لأنّه يجمع بين التبعيات غير المستقرة. ننصحك باستخدام الربط الثابت. يمكن ربط المكتبات الشائعة، مثل libc++.so وlibbase.so، بشكل ثابت بملفّات HAL الثنائية. يمكن أن يكون إنشاء عنصر تابع لتقديم واجهة مستقرة خيارًا آخر. لن يتم تجميع العنصر المُستخدَم في APEX.

عمليات تنفيذ HAL

لتحديد عملية تنفيذ HAL، قدِّم الملفات الثنائية والمكتبات المقابلة داخل ملف APEX الخاص بالمورّد على غرار الأمثلة التالية:

لتضمين تنفيذ HAL بالكامل، يجب أن يحدّد APEX أيضًا أي أجزاء VINTF وبرامج نصية لبدء التشغيل ذات الصلة.

أجزاء VINTF

يمكن عرض أجزاء VINTF من APEX الخاص بالمورّد عندما تكون الأجزاء متوفّرة في etc/vintf من APEX.

استخدِم السمة prebuilts لتضمين أجزاء VINTF في APEX.

apex {
  ..
  vendor: true,
  prebuilts: ["fragment.xml"],
  ..
}

prebuilt_etc {
  name: "fragment.xml",
  src: "fragment.xml",
  sub_dir: "vintf",
}

واجهات برمجة التطبيقات لطلبات البحث

عند إضافة أجزاء VINTF إلى APEX، استخدِم واجهات برمجة تطبيقات libbinder_ndk للحصول على عمليات الربط بين واجهات HAL وأسماء APEX.

  • AServiceManager_isUpdatableViaApex("com.android.foo.IFoo/default") : true إذا تم تعريف مثيل HAL في APEX.
  • AServiceManager_getUpdatableApexName("com.android.foo.IFoo/default", ...) : يحصل على اسم APEX الذي يحدِّد مثيل HAL.
  • AServiceManager_openDeclaredPassthroughHal("mapper", "instance", ...) : استخدِم هذا الخيار لفتح HAL للمرور.

النصوص البرمجية لبدء التشغيل

يمكن أن تتضمّن حِزم APEX نصوصًا برمجية لبدء التشغيل بطريقتَين: (أ) ملف نصي مُعدّ مسبقًا ضمن حمولة APEX، أو (ب) نص برمجي عادي لبدء التشغيل في /vendor/etc. يمكنك ضبط كلاهما لوحدة APEX نفسها.

نص التشغيل في APEX:

prebuilt_etc {
  name: "myinit.rc",
  src: "myinit.rc"
}

apex {
  ..
  vendor: true,
  prebuilts: ["myinit.rc"],
  ..
}

يمكن أن تحتوي نصوص التشغيل في ملفات APEX الخاصة بالمورّدين على تعريفات service وتوجيهات on <property or event>.

تأكَّد من أنّ تعريف service يشير إلى ملف ثنائي في APEX نفسه. على سبيل المثال، يمكن أن تحدِّد com.android.foo APEX خدمة باسم foo-service.

on foo-service /apex/com.android.foo/bin/foo
  ...

يُرجى توخّي الحذر عند استخدام توجيهات on. بما أنّ نصوص التشغيل المبدئي في وحدات APEX يتم تحليلها وتنفيذها بعد تفعيل وحدات APEX، لا يمكن استخدام بعض الأحداث أو السمات. استخدِم apex.all.ready=true لبدء الإجراءات في أقرب وقت ممكن. يمكن أن تستخدم عمليات Bootstrap APEX الرمز on init، ولكن ليس on early-init.

البرامج الثابتة

مثال:

يمكنك تضمين البرامج الثابتة في ملف APEX الخاص بالمورّد بنوع الوحدة prebuilt_firmware على النحو التالي:

prebuilt_firmware {
  name: "my.bin",
  src: "path_to_prebuilt_firmware",
  vendor: true,
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.bin"],  // installed inside APEX as /etc/firmware/my.bin
  ..
}

يتم تثبيت prebuilt_firmware وحدة في الدليل <apex name>/etc/firmware للحزمة APEX. يفحص ueventd الدلائل /apex/*/etc/firmware للعثور على وحدات البرامج الثابتة.

يجب أن يصنِّف file_contexts في APEX أي إدخالات حمولة البرامج الثابتة بشكل صحيح لضمان إمكانية وصول ueventd إلى هذه الملفات أثناء التشغيل، وعادةً ما يكون تصنيف vendor_file كافيًا. مثلاً:

(/.*)? u:object_r:vendor_file:s0

وحدات النواة

يمكنك تضمين وحدات kernel في APEX الخاصة بالمورّد كوحدات مُسبقة الإنشاء، على النحو التالي.

prebuilt_etc {
  name: "my.ko",
  src: "my.ko",
  vendor: true,
  sub_dir: "modules"
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.ko"],  // installed inside APEX as /etc/modules/my.ko
  ..
}

يجب أن يصنِّف file_contexts في APEX أي إدخالات حمولة وحدة نواة بشكل صحيح. مثلاً:

/etc/modules(/.*)? u:object_r:vendor_kernel_modules:s0

يجب تثبيت وحدات kernel بشكل صريح. يعرض المثال التالي لملف نص التشغيل التمهيدي في قسم المورّد عملية التثبيت من خلال insmod:

my_init.rc:

on early-boot
  insmod /apex/myapex/etc/modules/my.ko
  ..

تراكب الموارد في وقت التشغيل

مثال:

تضمين تراكبات موارد وقت التشغيل في ملف APEX للمورّد باستخدام السمة rros

runtime_resource_overlay {
    name: "my_rro",
    soc_specific: true,
}


apex {
  ..
  vendor: true,
  rros: ["my_rro"],  // installed inside APEX as /overlay/my_rro.apk
  ..
}

ملفات الإعداد الأخرى

تتيح أنظمة APEX الخاصة بالمورّدين استخدام ملفات ضبط أخرى مختلفة يمكن العثور عليها عادةً في ملف مشاركة ملف الوسائط الخاص بالمورّد كتطبيقات مُعدّة مسبقًا داخل أنظمة APEX الخاصة بالمورّدين، ويتم إضافة المزيد من هذه الملفات.

أمثلة:

عناوين URL لبرنامج Bootstrap Vendor APEX

يجب أن تكون بعض خدمات HAL، مثل keymint، متاحة قبل تفعيل وحدات APEX. وعادةً ما تضبط واجهات HAL هذه القيمة early_hal في تعريف الخدمة في ملف برمجة بدء التشغيل. ومن الأمثلة الأخرى فئة animation التي يبدأ تشغيلها عادةً قبل الحدث post-fs-data. عند تجميع خدمة HAL في مرحلة مبكرة في حزمة APEX الخاصة بالبائع، يجب ضبط القيمة "vendorBootstrap": true في بيان APEX ليكون بالإمكان تفعيلها في وقت أبكر. يُرجى العِلم أنّه لا يمكن سوى تفعيل نطاقات APEX لبدء التشغيل من الموقع الجغرافي المُنشئ مسبقًا، مثل /vendor/apex، وليس من /data/apex.

خصائص النظام

في ما يلي سمات النظام التي يقرأها إطار العمل لتتوافق مع ملفّات APEX الخاصة بالمورّدين:

  • input_device.config_file.apex=<apex name> - عند ضبطه، يتم البحث في ملفات الإعدادات (*.idc و*.kl و*.kcm) من دليل /etc/usr في APEX.
  • ro.vulkan.apex=<apex name> - عند ضبط هذا الخيار، يتم تحميل برنامج تشغيل Vulkan من APEX. بما أنّ برامج تشغيل Vulkan تُستخدَم من قِبل واجهات HAL في الإصدارات القديمة، عليك جعل حِزمة APEX Bootstrap APEX مرئية وضبط مساحة الاسم الخاصة ببرنامج الربط.

اضبط سمات النظام في النصوص البرمجية لبدء التشغيل باستخدام الأمر setprop.

ميزات تطوير إضافية

اختيار APEX عند بدء التشغيل

مثال:

يمكن للمطوّرين أيضًا تثبيت إصدارات متعدّدة من ملفات APEX الخاصة بالمورّدين التي تتشارك اسم APEX ومفتاحه نفسهما، ثم اختيار الإصدار الذي سيتم تفعيله أثناء كل عملية تشغيل باستخدام sysprops الثابتة. في بعض حالات استخدام المطوّرين، قد يكون هذا الإجراء أسهل من تثبيت نسخة جديدة من APEX باستخدام adb install.

أمثلة على حالات الاستخدام:

  • تثبيت 3 إصدارات من حزمة APEX الخاصة بمورّد HAL لشبكة Wi-Fi: يمكن لفِرق ضمان الجودة إجراء اختبارات يدوية أو مبرمَجة باستخدام إصدار واحد، ثم إعادة التشغيل إلى إصدار آخر ومحاولة مجددًا إجراء الاختبارات، ثم مقارنة النتائج النهائية
  • تثبيت إصدارَين من حزمة APEX الخاصة بمورّد HAL للكاميرا، وهما الإصدار الحالي والتجريبي: يمكن للمختبِرين الداخليين استخدام الإصدار التجريبي بدون تنزيل ملف إضافي وتثبيته، ما يتيح لهم التبديل بسهولة.

أثناء عملية التشغيل، يبحث apexd عن sysprops وفقًا لتنسيق معيّن ل activation وتفعيل الإصدار الصحيح من APEX.

التنسيقات المتوقّعة لمفتاح السمة هي:

  • Bootconfig
    • تُستخدَم لضبط القيمة التلقائية، في BoardConfig.mk.
    • androidboot.vendor.apex.<apex name>
  • sysprop الثابت
    • تُستخدَم لتغيير القيمة التلقائية التي تم ضبطها على جهاز تم تشغيله من قبل.
    • تلغي قيمة bootconfig في حال توفّرها.
    • persist.vendor.apex.<apex name>

يجب أن تكون قيمة السمة هي اسم ملف APEX الذي يجب تفعيله.

// Default version.
apex {
  name: "com.oem.camera.hal.my_apex_default",
  vendor: true,
  ..
}

// Non-default version.
apex {
  name: "com.oem.camera.hal.my_apex_experimental",
  vendor: true,
  ..
}

يجب أيضًا ضبط الإصدار التلقائي باستخدام bootconfig في BoardConfig.mk:

# Example for APEX "com.oem.camera.hal" with the default above:
BOARD_BOOTCONFIG += \
    androidboot.vendor.apex.com.oem.camera.hal=com.oem.camera.hal.my_apex_default

بعد تشغيل الجهاز، يمكنك تغيير الإصدار المفعَّل من خلال ضبط sysprop الدائم:

$ adb root;
$ adb shell setprop \
    persist.vendor.apex.com.oem.camera.hal \
    com.oem.camera.hal.my_apex_experimental;
$ adb reboot;

إذا كان الجهاز يتيح تعديل bootconfig بعد الفلاش (مثلاً من خلال أوامر fastboot oem)، يؤدي تغيير سمة bootconfig لملف APEX المثبَّت بشكل متعدّد أيضًا إلى تغيير الإصدار الذي يتم تفعيله عند بدء التشغيل.

بالنسبة إلى الأجهزة المرجعية الافتراضية المستندة إلى Cuttlefish، يمكنك استخدام الأمر --extra_bootconfig_args لضبط سمة bootconfig مباشرةً أثناء الإطلاق. مثلاً:

launch_cvd --noresume \
  --extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";