تم تقديم تنسيق الحاوية Android Pony EXpress (APEX) في الإصدار 10 من Android، ويتم استخدامه في عملية تثبيت وحدات النظام ذات المستوى الأدنى. يسهّل هذا التنسيق تحديثات مكوّنات النظام التي لا تتوافق مع نموذج تطبيق Android العادي. تشمل بعض الأمثلة على المكوّنات الخدمات والمكتبات المدمجة، وطبقات تجريد الأجهزة (HALs)، ووقت التشغيل (ART)، ومكاتب الفئات.
يمكن أن يشير مصطلح APEX أيضًا إلى ملف APEX.
خلفية
على الرغم من أنّ نظام التشغيل Android يتيح تحديث الوحدات التي تتوافق مع نموذج التطبيق العادي (مثل الخدمات والأنشطة) من خلال تطبيقات مثبّتي الحِزم (مثل تطبيق "متجر Google Play")، فإنّ استخدام نموذج مماثل لمكوّنات النظام الأساسية يؤدي إلى العيوب التالية:
- لا يمكن استخدام الوحدات المستندة إلى حِزم APK في وقت مبكر من تسلسل التشغيل. مدير الحِزم هو المستودع المركزي للمعلومات عن التطبيقات ولا يمكن بدؤه إلا من مدير الأنشطة الذي يصبح جاهزًا في مرحلة لاحقة من عملية التمهيد.
- تم تصميم تنسيق APK (وخاصة ملف البيان) لتطبيقات Android، ولا تتوافق وحدات النظام معه دائمًا.
التصميم
يصف هذا القسم التصميم العام لتنسيق ملف APEX و مدير APEX، وهو خدمة تدير ملفات APEX.
لمزيد من المعلومات عن سبب اختيار هذا التصميم لبرنامج APEX، يُرجى الاطّلاع على البدائل التي تمّ النظر فيها عند تطوير برنامج APEX.
تنسيق APEX
هذا هو تنسيق ملف APEX.
الشكل 1: تنسيق ملف APEX
في المستوى الأعلى، يكون ملف APEX هو ملف zip يتم تخزين الملفات فيه بدون ضغط وتقع في حدود 4 كيلوبايت.
الملفات الأربعة في ملف APEX هي:
apex_manifest.json
AndroidManifest.xml
apex_payload.img
apex_pubkey
يحتوي ملف apex_manifest.json
على اسم الحزمة وإصدارها، ما
يحدّد ملف APEX. هذا هو ملف جدول بروتوكول
ApexManifest
بتنسيق JSON.
يسمح ملف AndroidManifest.xml
لملف APEX باستخدام الأدوات والبنية الأساسية ذات الصلة بحِزم APK، مثل أداة ADB وPackageManager وتطبيقات تثبيت الحِزم (مثل
متجر Play). على سبيل المثال، يمكن أن يستخدم ملف APEX أداة حالية مثل aapt
لفحص البيانات الوصفية الأساسية من الملف. يحتوي الملف على اسم الحزمة ومعلومات
الإصدار. تتوفّر هذه المعلومات بشكل عام أيضًا في
apex_manifest.json
.
يُنصح باستخدام apex_manifest.json
بدلاً من AndroidManifest.xml
للرموز البرمجية الجديدة والأنظمة التي تتعامل مع APEX. AndroidManifest.xml
قد تحتوي على معلومات إضافية
حول الاستهداف يمكن استخدامها من خلال أدوات نشر التطبيقات الحالية.
apex_payload.img
هي صورة نظام ملفات ext4 مدعومة ببرنامج dm-verity. يتم تركيب الصورة
أثناء التشغيل من خلال جهاز loopback. على وجه التحديد، يتم إنشاء شجرة التجزئة و
كتلة البيانات الوصفية باستخدام مكتبة libavb
. لا يتم تحليل الحمولة في نظام الملفات (لأنّه يجب أن تكون الصورة قابلة للتركيب في مكانها). يتم تضمين الملفات العادية
داخل ملف apex_payload.img
.
apex_pubkey
هو المفتاح العام المستخدَم لتوقيع صورة نظام الملفات. أثناء التشغيل،
يضمن هذا المفتاح توقيع حزمة APEX التي تم تنزيلها باستخدام الكيان نفسه
الذي يوقع حزمة APEX نفسها في الأقسام المضمّنة.
إرشادات تسمية APEX
للمساعدة في منع حدوث تعارضات في الأسماء بين عناوين APEX الجديدة مع تطوّر المنصة، يُرجى اتّباع إرشادات التسمية التالية:
com.android.*
- محجوزة لتطبيقات APEX في AOSP لا يكون فريدًا لأي شركة أو جهاز.
com.<companyname>.*
- محجوزة لشركة. من المحتمل أن يتم استخدامه من خلال أجهزة متعددة من هذه الشركة.
com.<companyname>.<devicename>.*
- محجوزة لنقاط APEX الفريدة لجهاز معيّن (أو مجموعة فرعية من الأجهزة).
مدير APEX
مدير APEX (أو apexd
) هو عملية أساسية مستقلة مسؤولة عن
التحقّق من ملفات APEX وتثبيتها وإلغاء تثبيتها. يتم تشغيل هذه العملية وتكون جاهزة في وقت مبكر من تسلسل بدء التشغيل. تكون ملفات APEX عادةً مثبّتة مسبقًا على
الجهاز ضمن /system/apex
. يستخدم مدير APEX هذه
الحِزم تلقائيًا في حال عدم توفّر أي تحديثات.
يستخدم تسلسل التحديث لتطبيق APEX فئة PackageManager يليه الخطوات التالية:
- يتم تنزيل ملف APEX من خلال تطبيق تثبيت الحِزم أو أداة ADB أو مصدر آخر.
- يبدأ مدير الحِزم إجراء التثبيت. عند التعرّف على أنّه ملف APEX، ينقل مدير الحِزم التحكّم إلى مدير APEX.
- يُجري مدير APEX عملية التحقّق من ملف APEX.
- في حال إثبات صحة ملف APEX، تتم تحديث قاعدة البيانات الداخلية لإدارة APEX لعرض أنّه تم تفعيل ملف APEX عند بدء التشغيل التالي.
- يتلقّى مقدّم طلب التثبيت رسالة بثّ عند إتمام عملية التحقّق من الحزمة بنجاح.
- يجب إعادة تشغيل النظام لمواصلة عملية التثبيت.
عند إعادة التشغيل، يبدأ مدير APEX بقراءة قاعدة البيانات الداخلية وتنفيذ الخطوات التالية لكل ملف APEX مدرَج:
- للتحقّق من ملف APEX
- يُنشئ جهاز loopback من ملف APEX.
- ينشئ جهازًا لوحدة تحكُّم في الأجهزة فوق جهاز إعادة التوجيه.
- تركيب جهاز حظر أداة ربط الأجهزة على مسار فريد (على سبيل المثال،
/apex/name@ver
)
عند ربط جميع ملفات APEX المدرَجة في قاعدة البيانات الداخلية، يقدّم مدير APEX خدمة ربط لمكوّنات النظام الأخرى من أجل طلب معلومات عن ملفات APEX المثبّتة. على سبيل المثال، يمكن لمكونات النظام الأخرى البحث في قائمة ملفات APEX المثبَّتة على الجهاز أو البحث في المسار الدقيق الذي تم تثبيت حزمة APEX عليه، حتى يمكن الوصول إلى الملفات.
ملفات APEX هي حِزم APK
ملفات APEX هي ملفات APK صالحة لأنّها أرشيفات ZIP موقَّعة (باستخدام
نظام توقيع APK) تحتوي على ملف AndroidManifest.xml
. يسمح ذلك لملفات APEX
باستخدام البنية الأساسية لملفات APK، مثل تطبيق مُثبِّت الحِزم،
وأداة التوقيع، ومدير الحِزم.
ملف AndroidManifest.xml
داخل ملف APEX هو ملف صغير يتألّف من
الحزمة name
وversionCode
وtargetSdkVersion
وminSdkVersion
وmaxSdkVersion
الاختيارية
وmaxSdkVersion
لاستهداف دقيق. تسمح هذه المعلومات بتسليم ملفات APEX
من خلال القنوات الحالية، مثل تطبيقات أدوات تثبيت الحِزم و IDE IDE.
أنواع الملفات المتوافقة
يتوافق تنسيق APEX مع أنواع الملفات التالية:
- المكتبات المشتركة الأصلية
- ملفات التشغيل الأصلية
- ملفات JAR
- ملفات البيانات
- ملفات الإعداد
ولا يعني ذلك أنّه يمكن لخدمة APEX تحديث جميع أنواع الملفات هذه. يعتمد ما إذا كان يمكن تعديل نوع الملف على النظام الأساسي ومدى ثبات تعريفات واجهات أنواع الملفات.
خيارات التوقيع
يتم توقيع ملفات APEX بطريقتَين. أولاً، يتم توقيع ملف apex_payload.img
(على وجه التحديد،
وصف vbmeta المُرفَق بملف apex_payload.img
) باستخدام مفتاح.
بعد ذلك، يتم توقيع حزمة APEX بالكامل باستخدام
الإصدار 3 من مخطّط توقيع حِزم APK. يتم استخدام مفتاحَين مختلفَين
في هذه العملية.
على جانب الجهاز، يتم تثبيت مفتاح عام يتوافق مع المفتاح الخاص المستخدَم لتوقيع وصف vbmeta. يستخدم مدير APEX المفتاح العام للتحقّق من صحة وحدات APEX المطلوب تثبيتها. يجب توقيع كل ملف APEX باستخدام مفاتيح مختلفة، ويتم فرض ذلك في وقت الإنشاء ووقت التشغيل.
APEX في الأقسام المضمّنة
يمكن العثور على ملفات APEX في أقسام مضمّنة مثل /system
. تم تثبيت القسم
بالفعل على dm-verity، لذا يتم تثبيت ملفات APEX مباشرةً
على جهاز loopback.
إذا كانت حزمة APEX متوفّرة في قسم مضمّن، يمكن تعديل حزمة APEX من خلال
توفير حزمة APEX تحمل اسم الحزمة نفسه ورمز إصدار أكبر أو يساوي
رمز الإصدار. يتم تخزين حزمة APEX الجديدة في /data
، ومثل حِزم APK، يؤدي الإصدار المُثبَّت حديثًا إلى حجب الإصدار المُتاح حاليًا في القسم المُدمَج. ولكن على عكس حِزم APK، لا يتم تفعيل الإصدار المثبَّت حديثًا من حِزمة APEX إلا بعد إعادة التشغيل.
متطلبات النواة
لتفعيل وحدات APEX الرئيسية على جهاز Android، يجب توفُّر ميزات Linux kernel التالية: برنامج تشغيل loopback وdm-verity. يُثبِّت برنامج تشغيل loopback صورة نظام الملفات في وحدة APEX ويتحقّق dm-verity من وحدة APEX.
يُعدّ أداء برنامج تشغيل loopback وdm-verity مهمًا لتحقيق أداء جيد للنظام عند استخدام وحدات APEX.
إصدارات النواة المتوافقة
تتوفّر وحدات APEX الرئيسية على الأجهزة التي تستخدم إصدارات 4.4 من kernel أو إصدارات أحدث. بالنسبة إلى الأجهزة الجديدة التي تعمل بالإصدار 10 من نظام التشغيل Android أو إصدار أحدث، يجب استخدام الإصدار 4.9 من kernel أو إصدار أحدث لتتوافق مع وحدات APEX.
تصحيحات kernel المطلوبة
يتم تضمين تصحيحات النواة المطلوبة لتفعيل وحدات APEX في شجرة Android الشائعة. للحصول على الرموز البرمجية الإضافية التي تتيح استخدام APEX، استخدِم أحدث إصدار من شجرة Android الشائعة.
إصدار النواة 4.4
لا يتوفّر هذا الإصدار إلا للأجهزة التي تمت ترقيتها من Android 9 إلى
Android 10 وتريد إتاحة وحدات APEX. للحصول على
التصحيحات المطلوبة، ننصح بشدة
بإجراء دمج للأسفل من فرع android-4.4
. في ما يلي قائمة بالإصلاحات الفردية المطلوبة
لإصدار kernel 4.4.
- UPSTREAM: loop: add ioctl for changing logical block size (4.4)
- BACKPORT: block/loop: set hw_sectors (4.4)
- UPSTREAM: loop: Add LOOP_SET_BLOCK_SIZE in compat ioctl (4.4)
- ANDROID: mnt: Fix next_descendent (4.4)
- ANDROID: mnt: remount should propagate to slaves of slaves (4.4)
- ANDROID: mnt: Propagate remount correctly (4.4)
- التراجع عن "ANDROID: dm verity: add minimum prefetch size" (4.4)
- UPSTREAM: loop: drop caches if offset or block_size are changed (4.4)
إصدارات النواة 4.9/4.14/4.19
للحصول على الرقع المطلوبة لإصدارات kernel 4.9/4.14/4.19، عليك دمج الإصدارات القديمة من
فرع android-common
.
خيارات ضبط النواة المطلوبة
تعرض القائمة التالية متطلبات الإعداد الأساسية للسماح باستخدام وحدات APEX التي تم طرحها في Android 10. إنّ العناصر التي تحمل علامة النجمة (*) هي متطلبات حالية من الإصدار 9 من Android والإصدارات الأقدم.
(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
CONFIG_BLK_DEV_LOOP=Y # for loop device support
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
CONFIG_DM_VERITY=Y # DM-verity support
متطلبات مَعلمات سطر أوامر kernel
لتفعيل APEX، تأكَّد من استيفاء مَعلمات سطر الأوامر للنواة لل requirements التالية:
- يجب عدم ضبط
loop.max_loop
. - يجب أن يكون
loop.max_part
أقل من أو يساوي 8
إنشاء نموذج APEX
يوضّح هذا القسم كيفية إنشاء حزمة APEX باستخدام نظام إنشاء تطبيقات Android.
في ما يلي مثال على Android.bp
لنقطة اتصال APEX باسم apex.test
.
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
// libc.so and libcutils.so are included in the apex
native_shared_libs: ["libc", "libcutils"],
binaries: ["vold"],
java_libs: ["core-all"],
prebuilts: ["my_prebuilt"],
compile_multilib: "both",
key: "apex.test.key",
certificate: "platform",
}
apex_manifest.json
مثال:
{
"name": "com.android.example.apex",
"version": 1
}
file_contexts
مثال:
(/.*)? u:object_r:system_file:s0
/sub(/.*)? u:object_r:sub_file:s0
/sub/file3 u:object_r:file3_file:s0
أنواع الملفات ومواقعها في APEX
نوع الملف | الموقع الجغرافي في APEX |
---|---|
المكتبات المشتركة | /lib و/lib64 (/lib/arm لمعالج ARM المُترجَم في x86) |
الملفات التنفيذية | /bin |
مكتبات Java | /javalib |
الأجهزة المُجمَّعة مسبقًا | /etc |
التبعيات الانتقالية
تتضمّن ملفات APEX تلقائيًا التبعيات الانتقالية للمكتبات المشترَكة الأصلية
أو الملفات التنفيذية. على سبيل المثال، إذا كانت libFoo
تعتمد على libBar
، يتم تضمين المكتبتَين عند إدراج libFoo
فقط في موقع native_shared_libs
.
التعامل مع واجهات ABI متعددة
ثبِّت سمة native_shared_libs
لكلٍّ من
واجهات التطبيق الثنائية (ABI) الأساسية والثانوية للجهاز. إذا كان حِزم APEX تستهدف الأجهزة التي تستخدم IDE واحدة (أي 32 بت فقط أو 64 بت فقط)، لا يتم تثبيت سوى المكتبات التي تستخدم IDE المقابلة.
ثبِّت موقع binaries
لواجهة ABI الأساسية للجهاز فقط على النحو الموضح أدناه:
- إذا كان الجهاز يعمل بنظام 32 بت فقط، لن يتم تثبيت سوى الإصدار 32 بت من الملف الثنائي.
- إذا كان الجهاز يعمل بنظام 64 بت فقط، سيتم تثبيت الإصدار 64 بت من الملف الثنائي فقط.
لإضافة تحكم دقيق في واجهات برمجة التطبيقات لنظام التشغيل (ABI) للمكتبات الأصلية والملفات الثنائية،
استخدِم سمات
multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries]
.
-
first
: يتطابق مع ABI الأساسي للجهاز. هذا هو الإعداد التلقائي لملفّات ملفّات برمجية ثنائية. -
lib32
: يتطابق مع معيار ABI لنظام التشغيل 32 بت على الجهاز، في حال توفّره. lib64
: يتطابق مع ABI 64 بت للجهاز، وهو متوافق.-
prefer32
: يتطابق مع معيار ABI لنظام التشغيل 32 بت على الجهاز، في حال توفّره. إذا كانت واجهة برمجة التطبيقات (ABI) المتوافقة مع 32 بت غير متاحة، يجب أن تتطابق مع واجهة برمجة التطبيقات المتوافقة مع 64 بت. both
: تتطابق مع كلتا قيمتَي ABI. هذه هي القيمة التلقائية لحالةnative_shared_libraries
.
لا تعتمد سمات java
وlibraries
وprebuilts
على معرّف ABI.
هذا المثال لجهاز متوافق مع 32/64 ولا يفضّل 32:
apex {
// other properties are omitted
native_shared_libs: ["libFoo"], // installed for 32 and 64
binaries: ["exec1"], // installed for 64, but not for 32
multilib: {
first: {
native_shared_libs: ["libBar"], // installed for 64, but not for 32
binaries: ["exec2"], // same as binaries without multilib.first
},
both: {
native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
binaries: ["exec3"], // installed for 32 and 64
},
prefer32: {
native_shared_libs: ["libX"], // installed for 32, but not for 64
},
lib64: {
native_shared_libs: ["libY"], // installed for 64, but not for 32
},
},
}
توقيع vbmeta
وقِّع كل ملف APEX باستخدام مفاتيح مختلفة. عندما يكون مفتاح جديد مطلوبًا، أنشئ
مفتاحَي تشفير عام وخاص وأنشئ وحدة apex_key
. استخدِم السمة key
ل signing the APEX باستخدام المفتاح. يتم تضمين المفتاح العام تلقائيًا في
APEX بالاسم avb_pubkey
.
# create an rsa key pairopenssl genrsa -out foo.pem 4096
# extract the public key from the key pairavbtool extract_public_key --key foo.pem --output foo.avbpubkey
# in Android.bpapex_key { name: "apex.test.key", public_key: "foo.avbpubkey", private_key: "foo.pem", }
في المثال أعلاه، يصبح اسم المفتاح العام (foo
) هو معرّف
المفتاح. يتم إدراج رقم تعريف المفتاح المستخدَم لتوقيع شهادة APEX في شهادة APEX. أثناء التشغيل، يتحقق
apexd
من APEX باستخدام مفتاح عام يحمل رقم التعريف نفسه في الجهاز.
توقيع APEX
وقِّع حِزم APEX بالطريقة نفسها التي تُوقِّع بها حِزم APK. وقِّع على ملفّات APEX مرّتين، مرّة واحدة لملفّ
نظام الملفّات المصغّر (ملفّ apex_payload.img
) ومرّة واحدة للملفّ بأكمله.
لتوقيع ملف APEX على مستوى الملف، اضبط السمة certificate
بإحدى
الطرق الثلاث التالية:
- لم يتم ضبطه: في حال عدم ضبط أي قيمة، يتم توقيع APEX باستخدام الشهادة المتوفّرة
في
PRODUCT_DEFAULT_DEV_CERTIFICATE
. إذا لم يتم ضبط أي علامة، يكون المسار التلقائيbuild/target/product/security/testkey
. <name>
: تم توقيع APEX باستخدام شهادة<name>
في الدليل نفسه الذي يحتوي علىPRODUCT_DEFAULT_DEV_CERTIFICATE
.:<name>
: يتم توقيع APEX باستخدام الشهادة التي تحدّدها ملفّة "Soong" باسم<name>
. يمكن تعريف وحدة الشهادة على النحو التالي:
android_app_certificate {
name: "my_key_name",
certificate: "dir/cert",
// this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
}
تثبيت وحدة APEX
لتثبيت حزمة APEX، استخدِم أداة ADB.
adb install apex_file_name
adb reboot
إذا تم ضبط supportsRebootlessUpdate
على true
في apex_manifest.json
ولم يكن
APEX المثبَّت حاليًا قيد الاستخدام (على سبيل المثال، تم stopped أي خدمات يحتوي عليها)، يمكن تثبيت APEX جديد بدون إعادة تشغيل باستخدام العلامة
--force-non-staged
.
adb install --force-non-staged apex_file_name
استخدام APEX
بعد إعادة التشغيل، يتم تثبيت APEX في الدليل /apex/<apex_name>@<version>
. يمكن تركيب عدة إصدارات من APEX نفسه في الوقت نفسه.
من بين مسارات التثبيت، يكون المسار الذي يتوافق مع أحدث إصدار هو
التثبيت باستخدام الربط في /apex/<apex_name>
.
يمكن للعملاء استخدام المسار المثبَّت بالربط لقراءة الملفات أو تنفيذها من APEX.
يتم استخدام نطاقات APEX عادةً على النحو التالي:
- يُحمِّل المصنّع الأصلي للجهاز أو المصنّع المحدّد للمنتج مسبقًا حزمة APEX التي تقلّ مساحتها عن
/system/apex
عند شحن الجهاز. - يتم الوصول إلى الملفات في APEX من خلال مسار
/apex/<apex_name>/
. - عند تثبيت إصدار مُحدَّث من حزمة APEX في
/data/apex
، يشير المسار إلى حزمة APEX الجديدة بعد إعادة التشغيل.
تعديل خدمة باستخدام نقطة نهاية APEX
لتعديل خدمة باستخدام APEX:
ضَع علامة على الخدمة في قسم النظام تشير إلى أنّها قابلة للتحديث. أضِف الخيار
updatable
إلى تعريف الخدمة./system/etc/init/myservice.rc: service myservice /system/bin/myservice class core user system ... updatable
أنشئ ملف
.rc
جديدًا للخدمة المعدَّلة. استخدِم الخيارoverride
لإعادة تحديد الخدمة الحالية./apex/my.apex/etc/init.rc: service myservice /apex/my.apex/bin/myservice class core user system ... override
لا يمكن تحديد تعريفات الخدمات إلا في ملف .rc
الخاص بملف APEX. لا تتوفّر عوامل التفعيل
الإجراء في قواعد بيانات APEX.
إذا بدأت خدمة تم وضع علامة عليها على أنّها قابلة للتحديث قبل تفعيل وحدات APEX، يتم تأجيل البدء إلى أن يكتمل تفعيل وحدات APEX.
ضبط النظام لتتوافق مع تحديثات APEX
اضبط سمة النظام التالية على true
لتفعيل تعديلات ملفات APEX.
<device.mk>:
PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true
BoardConfig.mk:
TARGET_FLATTEN_APEX := false
أو
<device.mk>:
$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
APEX المُبسَّط
في الأجهزة القديمة، قد يكون من المستحيل أو غير الممكن أحيانًا تحديث ملف التمهيد
القديم ليتيح استخدام APEX بالكامل. على سبيل المثال، قد تم إنشاء kernel
بدون CONFIG_BLK_DEV_LOOP=Y
، وهو أمر مهم لتركيب ملف VMIMG داخل APEX.
حزمة APEX المسطّحة هي حزمة APEX مصمّمة خصيصًا ويمكن تفعيلها على الأجهزة التي تعمل
بنظام تشغيل قديم. يتم تثبيت الملفات في ملف APEX مسطّح مباشرةً في دليل
ضمن القسم المضمّن. على سبيل المثال، lib/libFoo.so
في ملف APEX مسطّح
my.apex
تم تثبيته على /system/apex/my.apex/lib/libFoo.so
.
لا يتطلّب تفعيل APEX المسطّح استخدام جهاز حلقة. يتم ربط directory /system/apex/my.apex
بالكامل مباشرةً بـ /apex/name@ver
.
لا يمكن تعديل ملفات APEX المسطّحة من خلال تنزيل إصدارات معدَّلة من ملفات APEX من الشبكة لأنّه لا يمكن تسطيح ملفات APEX التي تم تنزيلها. لا يمكن تعديل نطاقات APEX المسطّحة إلا من خلال عملية OTA عادية.
ويكون "النموذج المسطّح للنقطة العليا للصفحة" هو الإعداد التلقائي. وهذا يعني أنّه يتم تسطيح كل ملفات APEX تلقائيًا ما لم تضبط جهازك بوضوح لإنشاء ملفات APEX غير مسطّحة لتتوافق مع تحديثات APEX (كما هو موضّح أعلاه).
لا يُسمح بشدَّة بمزج تصاميم APEX المسطّحة وغير المسطّحة في جهاز معيّن. يجب أن تكون نقاط APEX في الجهاز إما غير مسطّحة أو مسطّحة بالكامل.
ويُعدّ ذلك مهمًا بشكل خاص عند شحن الإصدارات المُعدّة مسبقًا من APEX الموقَّعة مسبقًا لمشاريع مثل Mainline. يجب أيضًا عدم تسطيح ملفات APEX التي لم يتم توقيعها مسبقًا (أي التي تم إنشاؤها من
المصدر) وتوقيعها باستخدام مفاتيح صحيحة. يجب أن يرث
الجهاز من updatable_apex.mk
كما هو موضّح في مقالة
تعديل خدمة باستخدام APEX.
مجموعات APEX المضغوطة
يتضمّن نظام التشغيل Android 12 والإصدارات الأحدث ميزة ضغط APEX بهدف تقليل تأثير حِزم APEX القابلة للتحديث في مساحة التخزين. بعد تثبيت تحديث لتطبيق APEX، يظلّ التطبيق يشغل المساحة نفسها، على الرغم من أنّه لم يعُد يتم استخدام الإصدار المثبَّت مسبقًا. تظل المساحة المُشغَّلة غير متاحة.
يقلل ضغط APEX من تأثير مساحة التخزين هذا باستخدام مجموعة مضغوطة للغاية
من ملفات APEX على الأقسام المخصّصة للقراءة فقط (مثل القسم /system
). يستخدم الإصدار 12 من Android
والإصدارات الأحدث خوارزمية ضغط ملفات ZIP من نوع DEFLATE.
لا يقدّم الضغط تحسينًا للعناصر التالية:
وحدات APEX لبدء التشغيل التي يجب تثبيتها في وقت مبكر جدًا من تسلسل التمهيد
حِزم APEX غير القابلة للتحديث لا يكون الضغط مفيدًا إلا إذا تم تثبيت إصدار مُحدَّث من APEX على قسم
/data
. تتوفّر قائمة كاملة بنقاط APEX القابلة للتحديث في صفحة مكونات النظام المُركّب.مكتبات APEX المشترَكة الديناميكية بما أنّ
apexd
ينشط دائمًا كلا الإصدارَين من هذه الوحدات (المُثبَّتة مسبقًا والمُعدَّلة)، لا يضيف ضغطها أي قيمة.
تنسيق ملف APEX المضغوط
هذا هو تنسيق ملف APEX المضغوط.
الشكل 2: تنسيق ملف APEX المضغوط
في المستوى الأعلى، يكون ملف APEX المضغوط هو ملف zip يحتوي على ملف APEX الأصلي بتنسيق مضغوط بمستوى ضغط 9، بالإضافة إلى ملفات أخرى يتم تخزينها بدون ضغط.
يتألّف ملف APEX من أربعة ملفات:
-
original_apex
: تم ضغطه بمستوى ضغط 9 هذا هو ملف APEX الأصلي غير المضغوَط. apex_manifest.pb
: يتم تخزينها فقطAndroidManifest.xml
: يتم تخزينها فقطapex_pubkey
: يتم تخزينها فقط
إنّ ملفات apex_manifest.pb
وAndroidManifest.xml
وapex_pubkey
هي
نُسخ من الملفات المقابلة لها في original_apex
.
إنشاء ملف APEX مضغوط
يمكن إنشاء نموذج APEX مضغوط باستخدام أداة apex_compression_tool.py
المتوفّرة في
system/apex/tools
.
تتوفّر في نظام الإنشاء عدة مَعلمات ذات صلة بضغط APEX.
في Android.bp
، يتم التحكّم في إمكانية ضغط ملف APEX من خلال السمة
compressible
:
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
compressible: true,
}
تتحكّم علامة المنتج PRODUCT_COMPRESSED_APEX
في ما إذا كانت صورة النظام التي تم إنشاؤها
من المصدر يجب أن تحتوي على ملفات APEX مضغوطة.
بالنسبة إلى التجارب المحلية، يمكنك فرض تجميع لضغط ملفات APEX من خلال ضبط
OVERRIDE_PRODUCT_COMPRESSED_APEX=
على true
.
تحتوي ملفات APEX المضغوطة التي أنشأها نظام الإنشاء على امتداد .capex
.
يسهّل هذا التمييز بين الإصدارين المضغوَط وغير المضغوَط من ملف APEX.
خوارزميات الضغط المتوافقة
لا يتيح نظام التشغيل Android 12 سوى ضغط deflate-zip.
تفعيل ملف APEX مضغوط أثناء عملية التشغيل
قبل تفعيل ملف APEX مضغوط، تتم أولاً إزالة ضغط ملف original_apex
المضمّن فيه ونقله إلى الدليل /data/apex/decompressed
. يتم ربط ملف APEX الذي تم فك ضغطه برابط ثابت بالدليل /data/apex/active
.
إليك المثال التالي لتوضيح العملية الموضّحة أعلاه.
يمكنك اعتبار /system/apex/com.android.foo.capex
كملف APEX مضغوط يتم
تفعيله، مع رمز الإصدار 37.
- يتم إزالة ضغط ملف
original_apex
داخل/system/apex/com.android.foo.capex
ونقله إلى/data/apex/decompressed/com.android.foo@37.apex
. - يتم تنفيذ
restorecon /data/apex/decompressed/com.android.foo@37.apex
لتأكيد أنّه يحتوي على تصنيف SELinux صحيح. - يتم إجراء عمليات التحقّق من
/data/apex/decompressed/com.android.foo@37.apex
لضمان صحتها: تحقّقapexd
من المفتاح العام المُضمّن في/data/apex/decompressed/com.android.foo@37.apex
للتأكّد من أنّه مماثل للمفتاح المُضمّن في/system/apex/com.android.foo.capex
. - تم ربط ملف
/data/apex/decompressed/com.android.foo@37.apex
بدليل/data/apex/active/com.android.foo@37.apex
. - يتم تنفيذ منطق التفعيل العادي لملفات APEX غير المضغوطة في
/data/apex/active/com.android.foo@37.apex
.
التفاعل مع OTA
تؤثر ملفات APEX المضغوطة في عملية إرسالها عبر الهواء وتطبيقها. بما أنّه قد يحتوي التحديث عبر شبكة غير سلكية على ملف APEX مضغوط بمستوى إصدار أعلى من الإصدار النشط على الجهاز، يجب حجز مساحة تخزين فارغة معيّنة قبل إعادة تشغيل الجهاز لتطبيق تحديث عبر شبكة غير سلكية.
ليتيح نظام OTA، يعرِض apexd
واجهات برمجة التطبيقات Binder API التالية:
-
calculateSizeForCompressedApex
- تُحتسب هذه السمة الحجم المطلوب لفك ضغطملفات APEX في حزمة OTA. يمكن استخدام هذا الإجراء للتأكّد من توفّر مساحة تخزين كافية على الجهاز قبل تنزيل تحديث OTA. -
reserveSpaceForCompressedApex
- تحجز مساحة على القرص لاستخدامها في المستقبل من قِبلapexd
لفك ضغط ملفات APEX المضغوطة داخل حزمة OTA.
في حال توفّر تحديث عبر الهواء (OTA) من النوع A/B، يحاول apexd
إزالة الضغط في
الخلفية كجزء من الإجراء العادي للتحديث عبر الهواء بعد التثبيت. إذا تعذّر فك الضغط،
ينفِّذ apexd
عملية فك الضغط أثناء عملية التمهيد التي تُطبِّق التحديث عبر الهواء.
البدائل التي تمّ أخذها في الاعتبار عند تطوير APEX
في ما يلي بعض الخيارات التي أخذها فريق AOSP في الاعتبار عند تصميم تنسيق ملف APEX، وسبب تضمينها أو استبعادها.
أنظمة إدارة الحِزم العادية
تتضمّن توزيعات Linux أنظمة لإدارة الحِزم، مثل dpkg
وrpm
،
وهي أنظمة فعّالة وموثوقة وقوية. ومع ذلك، لم يتم اعتمادها في APEX لأنّها لا يمكنها حماية الحِزم بعد
التثبيت. ولا يتم إجراء عملية التحقّق إلا عند تثبيت الحِزم.
يمكن للمهاجمين إزالة سلامة الحِزم المثبَّتة بدون أن يلاحظها أحد. يُعدّ ذلك
تراجعًا في نظام التشغيل Android حيث كان يتم تخزين جميع مكوّنات النظام في أنظمة ملفات قراءة فقط
تتم حماية سلامتها من خلال dm-verity لكل عملية إدخال/إخراج. يجب أن يكون أي محاولة للتلاعب بمكونات النظام محظورة أو يمكن رصدها كي يتمكّن الجهاز من رفض التشغيل في حال اختراقه.
dm-crypt للحفاظ على السلامة
تكون الملفات في حاوية APEX من أقسام مدمجة (مثل القسم
/system
) محمية من خلال dm-verity، حيث يُحظر إجراء أي تعديل على
الملفات حتى بعد تركيب الأقسام. لتوفير
المستوى نفسه من الأمان للملفات، يتم تخزين جميع الملفات في ملف APEX في ملف
صورة نظام مقترن بشجرة تجزئة ووصف vbmeta. بدون ملف Dm-verity، يكون حِزمة APEX في القسم /data
عرضة للتعديلات العميقة غير المقصودة التي يتم إجراؤها بعد إثبات صحتها وتثبيتها.
في الواقع، يتم أيضًا حماية قسم /data
من خلال طبقات التشفير، مثل
dm-crypt. على الرغم من أنّ هذا يقدّم مستوى معيّنًا من الحماية ضد التلاعب، إلا أنّ
الغرض الأساسي منه هو الخصوصية وليس السلامة. عندما يصبح المهاجم قادرًا على الوصول إلى القسم
/data
، لا يمكن توفير أي حماية إضافية، وهذا بدوره يمثّل تدهورًا مقارنةً بوضع كل مكوّنات النظام في القسم /system
.
توفّر شجرة التجزئة داخل ملف APEX مع dm-verity
مستوى الحماية نفسه للمحتوى.
إعادة توجيه المسارات من /system إلى /apex
يمكن الوصول إلى ملفات مكوّنات النظام المُجمَّعة في حزمة APEX من خلال مسارات جديدة مثل
/apex/<name>/lib/libfoo.so
. عندما كانت الملفات جزءًا من القسم /system
، كان بالإمكان الوصول إليها من خلال مسارات مثل /system/lib/libfoo.so
. يجب أن يستخدم العميل الذي يستخدم ملف APEX (ملفات APEX الأخرى أو المنصة) المسارات الجديدة. قد تحتاج إلى تعديل الرمز الحالي نتيجةً لتغيير المسار.
على الرغم من أنّ إحدى الطرق لتجنُّب تغيير المسار هي تراكب محتوى الملف فيملف APEX على القسم /system
، قرّر فريق Android عدم تراكب الملفات على القسم /system
لأنّ ذلك قد يؤثر في الأداء مع زيادة عدد الملفات التي يتم تداخلها (ربما يتم تجميعها واحدة تلو الأخرى).
كان الخيار الآخر هو الاستيلاء على دوال الوصول إلى الملفات، مثل open
وstat
و
readlink
، بحيث تتم إعادة توجيه المسارات التي تبدأ بـ /system
إلى
مساراتها المقابلة ضمن /apex
. رفض فريق Android هذا الخيار
لأنّه من غير الممكن تغيير جميع الدوال التي تقبل المسارات.
على سبيل المثال، تربط بعض التطبيقات Bionic بشكل ثابت، وهو ما يؤدي إلى تنفيذ الوظائف.
وفي هذه الحالات، لا تتم إعادة توجيه هذه التطبيقات.