APEX للمورّد

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

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

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

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

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

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

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

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

التكرار التحسيني للمطوّر

يساعد مورد APEXes المطورين في تكرار المهام بشكل أسرع أثناء تطوير وحدات الموردين، وذلك من خلال دمج عملية تنفيذ ميزة كاملة، مثل HAL wifi، داخل واجهة 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 أيضًا أي fragmentos 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 بشكل صريح. يوضح المثال التالي نص init البرمجي في قسم المورِّد التثبيت من خلال 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.

خصائص النظام

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

  • 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 الثابتة
    • تُستخدَم لتغيير القيمة التلقائية التي يتم ضبطها على جهاز تم تشغيله من قبل.
    • تلغي هذه السياسة قيمة الضبط الأوّلي في حال توفّرها.
    • 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";