تم تقديم تنسيق حاوية Android Pony EXpress (APEX) في Android 10 ويتم استخدامه في تدفق التثبيت لوحدات النظام ذات المستوى الأدنى. يسهل هذا التنسيق تحديثات مكونات النظام التي لا تتناسب مع نموذج تطبيق Android القياسي. من أمثلة المكونات الخدمات والمكتبات الأصلية وطبقات تجريد الأجهزة ( HALs ) ووقت التشغيل ( ART ) ومكتبات الفئات.
يمكن أن يشير المصطلح "APEX" أيضًا إلى ملف APEX.
خلفية
على الرغم من أن Android يدعم تحديثات الوحدات النمطية التي تتلاءم مع نموذج التطبيق القياسي (على سبيل المثال ، الخدمات والأنشطة) عبر تطبيقات مثبت الحزمة (مثل تطبيق متجر Google Play) ، فإن استخدام نموذج مشابه لمكونات نظام التشغيل منخفضة المستوى له العيوب التالية:
- لا يمكن استخدام الوحدات المستندة إلى APK في وقت مبكر من تسلسل التمهيد. مدير الحزم هو المستودع المركزي للمعلومات حول التطبيقات ولا يمكن تشغيله إلا من مدير النشاط ، والذي يصبح جاهزًا في مرحلة لاحقة من إجراء التمهيد.
- تم تصميم تنسيق APK (خاصة البيان) لتطبيقات Android ولا تكون وحدات النظام مناسبة دائمًا.
تصميم
يصف هذا القسم التصميم عالي المستوى لتنسيق ملف APEX ومدير APEX ، وهي خدمة تدير ملفات APEX.
لمزيد من المعلومات حول سبب اختيار هذا التصميم لـ APEX ، راجع البدائل التي تم أخذها في الاعتبار عند تطوير APEX .
شكل APEX
هذا هو تنسيق ملف APEX.
الشكل 1. تنسيق ملف APEX
في المستوى الأعلى ، ملف APEX هو ملف مضغوط يتم فيه تخزين الملفات غير المضغوطة والموجودة في حدود 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 Store). على سبيل المثال ، يمكن لملف APEX استخدام أداة موجودة مثل aapt
لفحص البيانات الأولية الأساسية من الملف. يحتوي الملف على اسم الحزمة ومعلومات الإصدار. هذه المعلومات متاحة أيضًا بشكل عام في apex_manifest.json
.
يوصى باستخدام apex_manifest.json
على AndroidManifest.xml
للحصول على كود وأنظمة جديدة تتعامل مع APEX. قد يحتوي AndroidManifest.xml
على معلومات استهداف إضافية يمكن استخدامها بواسطة أدوات نشر التطبيق الحالية.
apex_payload.img
هي صورة نظام ملفات ext4 مدعومة بـ dm-verity. يتم تثبيت الصورة في وقت التشغيل عبر جهاز استرجاع. على وجه التحديد ، يتم إنشاء شجرة التجزئة وكتلة البيانات الوصفية باستخدام مكتبة libavb
. لم يتم تحليل حمولة نظام الملفات (لأن الصورة يجب أن تكون قابلة للتركيب في مكانها). يتم تضمين الملفات العادية داخل ملف apex_payload.img
.
apex_pubkey
هو المفتاح العام المستخدم لتوقيع صورة نظام الملفات. في وقت التشغيل ، يضمن هذا المفتاح أن يتم توقيع APEX الذي تم تنزيله بنفس الكيان الذي يوقع نفس APEX في الأقسام المضمنة.
إرشادات تسمية APEX
للمساعدة في منع تعارض التسمية بين APEXes الجديدة مع تقدم النظام الأساسي ، استخدم إرشادات التسمية التالية:
-
com.android.*
- محفوظة لـ AOSP APEXes. ليس فريدًا لأي شركة أو جهاز.
-
com.<companyname>.*
- محجوز لشركة. يُحتمل استخدامه بواسطة أجهزة متعددة من تلك الشركة.
-
com.<companyname>.<devicename>.*
- محجوزة لـ APEXes الفريدة لجهاز معين (أو مجموعة فرعية من الأجهزة).
مدير APEX
مدير APEX (أو apexd
) هو عملية أصلية قائمة بذاتها مسؤولة عن التحقق من ملفات APEX وتثبيتها وإلغاء تثبيتها. تم إطلاق هذه العملية وهي جاهزة في وقت مبكر من تسلسل التمهيد. عادةً ما يتم تثبيت ملفات APEX مسبقًا على الجهاز تحت /system/apex
. يتم تعيين مدير APEX افتراضيًا لاستخدام هذه الحزم في حالة عدم توفر تحديثات.
يستخدم تسلسل التحديث الخاص بـ APEX فئة PackageManager وهو على النحو التالي.
- يتم تنزيل ملف APEX عبر تطبيق مثبت الحزمة أو ADB أو أي مصدر آخر.
- يبدأ مدير الحزم إجراء التثبيت. عند التعرف على أن الملف هو APEX ، يقوم مدير الحزم بنقل التحكم إلى مدير APEX.
- يتحقق مدير APEX من ملف APEX.
- إذا تم التحقق من ملف APEX ، يتم تحديث قاعدة البيانات الداخلية لمدير APEX لتعكس تنشيط ملف APEX عند التمهيد التالي.
- يتلقى طالب التثبيت بثًا عند التحقق من الحزمة بنجاح.
- لمتابعة التثبيت ، يجب إعادة تشغيل النظام.
في التمهيد التالي ، يبدأ مدير APEX ، ويقرأ قاعدة البيانات الداخلية ، ويقوم بما يلي لكل ملف APEX مدرج:
- يتحقق من ملف APEX.
- يقوم بإنشاء جهاز استرجاع من ملف APEX.
- ينشئ جهاز حظر مخطط الجهاز أعلى جهاز الاسترجاع.
- يقوم بتركيب جهاز حظر مخطط الجهاز على مسار فريد (على سبيل المثال ،
/apex/ name @ ver
).
عندما يتم تحميل جميع ملفات APEX المدرجة في قاعدة البيانات الداخلية ، يوفر مدير APEX خدمة ربط لمكونات النظام الأخرى للاستعلام عن معلومات حول ملفات APEX المثبتة. على سبيل المثال ، يمكن لمكونات النظام الأخرى الاستعلام عن قائمة ملفات APEX المثبتة في الجهاز أو الاستعلام عن المسار الدقيق حيث يتم تثبيت APEX معين ، بحيث يمكن الوصول إلى الملفات.
ملفات APEX هي ملفات APK
ملفات APEX هي ملفات APK صالحة لأنها أرشيفات مضغوطة موقعة (باستخدام مخطط توقيع APK) تحتوي على ملف AndroidManifest.xml
. يتيح ذلك لملفات APEX استخدام البنية الأساسية لملفات APK ، مثل تطبيق مثبت الحزمة ، وأداة التوقيع ، ومدير الحزم.
ملف AndroidManifest.xml
داخل ملف APEX هو الحد الأدنى ، ويتكون من name
الحزمة versionCode
و targetSdkVersion
الاختياري و minSdkVersion
و maxSdkVersion
للاستهداف الدقيق. تسمح هذه المعلومات بتسليم ملفات APEX عبر القنوات الحالية مثل تطبيقات مثبت الحزم و ADB.
أنواع الملفات المدعومة
يدعم تنسيق APEX أنواع الملفات التالية:
- أصلية مشتركة libs
- الملفات التنفيذية الأصلية
- ملفات JAR
- ملفات البيانات
- ملفات التكوين
هذا لا يعني أنه يمكن لـ APEX تحديث جميع أنواع الملفات هذه. تعتمد إمكانية تحديث نوع الملف على النظام الأساسي ومدى استقرار تعريفات الواجهات لأنواع الملفات.
خيارات التوقيع
يتم توقيع ملفات APEX بطريقتين. أولاً ، يتم توقيع الملف apex_payload.img
(على وجه التحديد ، واصف vbmeta الملحق بالملف apex_payload.img
) بمفتاح. بعد ذلك ، يتم توقيع APEX بالكامل باستخدام نظام توقيع APK v3 . يتم استخدام مفتاحين مختلفين في هذه العملية.
على جانب الجهاز ، يتم تثبيت مفتاح عام يتوافق مع المفتاح الخاص المستخدم لتوقيع واصف vbmeta. يستخدم مدير APEX المفتاح العام للتحقق من APEXes المطلوب تثبيتها. يجب توقيع كل APEX بمفاتيح مختلفة ويتم فرضها في وقت الإنشاء ووقت التشغيل.
APEX في أقسام مدمجة
يمكن أن توجد ملفات APEX في أقسام مدمجة مثل /system
. القسم بالفعل فوق dm-verity ، لذلك يتم تحميل ملفات APEX مباشرة فوق جهاز الاسترجاع.
إذا كان APEX موجودًا في قسم مضمن ، فيمكن تحديث APEX من خلال توفير حزمة APEX بنفس اسم الحزمة وأكبر من رمز الإصدار أو مساوٍ له. يتم تخزين APEX الجديد في /data
، وعلى غرار ملفات APK ، يقوم الإصدار المثبت حديثًا بتظليل الإصدار الموجود بالفعل في القسم المدمج. ولكن على عكس ملفات APK ، لا يتم تنشيط الإصدار المثبت حديثًا من APEX إلا بعد إعادة التشغيل.
متطلبات Kernel
لدعم وحدات APEX mainline على جهاز Android ، فإن ميزات Linux kernel التالية مطلوبة: برنامج تشغيل الاسترجاع و dm-verity. يقوم برنامج تشغيل الاسترجاع بتثبيت صورة نظام الملفات في وحدة APEX النمطية ويتحقق dm-verity من وحدة APEX.
يعد أداء برنامج تشغيل الاسترجاع و dm-verity مهمين في تحقيق أداء جيد للنظام عند استخدام وحدات APEX.
إصدارات kernel المدعومة
يتم دعم وحدات APEX الرئيسية على الأجهزة التي تستخدم إصدارات kernel 4.4 أو أعلى. يجب أن تستخدم الأجهزة الجديدة التي تعمل بنظام Android 10 أو أعلى إصدار kernel 4.9 أو أعلى لدعم وحدات APEX.
تصحيحات النواة المطلوبة
يتم تضمين تصحيحات kernel المطلوبة لدعم وحدات APEX في شجرة Android الشائعة. للحصول على التصحيحات لدعم APEX ، استخدم أحدث إصدار من شجرة Android الشائعة.
إصدار Kernel 4.4.2
هذا الإصدار مدعوم فقط للأجهزة التي تمت ترقيتها من Android 9 إلى Android 10 وتريد دعم وحدات APEX. للحصول على التصحيحات المطلوبة ، يوصى بشدة بإجراء دمج لأسفل من فرع android-4.4
. فيما يلي قائمة بالتصحيحات الفردية المطلوبة للإصدار 4.4 من kernel.
- UPSTREAM: حلقة: إضافة ioctl لتغيير حجم الكتلة المنطقية ( 4.4 )
- BACKPORT: كتلة / حلقة: ضبط hw_sectors ( 4.4 )
- UPSTREAM: حلقة: إضافة LOOP_SET_BLOCK_SIZE في التوافق ioctl ( 4.4 )
- ANDROID: mnt: إصلاح next_descendent ( 4.4 )
- ANDROID: mnt: يجب أن ينتشر remount على عبيد العبيد ( 4.4 )
- ANDROID: mnt: نشر إعادة التحميل بشكل صحيح ( 4.4 )
- العودة إلى "ANDROID: dm verity: إضافة الحد الأدنى لحجم الجلب المسبق" ( 4.4 )
- UPSTREAM: حلقة: إسقاط ذاكرة التخزين المؤقت إذا تم تغيير الإزاحة أو block_size ( 4.4 )
إصدارات Kernel 4.9 / 4.14 / 4.19
للحصول على التصحيحات المطلوبة لإصدارات kernel 4.9 / 4.14 / 4.19 ، قم بإجراء دمج لأسفل من فرع android-common
.
خيارات تكوين النواة المطلوبة
توضح القائمة التالية متطلبات التكوين الأساسية لدعم وحدات APEX التي تم تقديمها في Android 10. العناصر التي تحمل علامة النجمة (*) هي متطلبات حالية من Android 9 والإصدارات الأقدم.
(*) 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 ، تأكد من أن معلمات سطر أوامر kernel تفي بالمتطلبات التالية:
- يجب عدم تعيين
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 |
مكتبات جافا | /javalib |
التجهيز المسبق | /etc |
التبعيات المتعدية
تتضمن ملفات APEX تلقائيًا تبعيات متعدية من libs أو الملفات التنفيذية الأصلية المشتركة. على سبيل المثال ، إذا كان libFoo
يعتمد على libBar
، فسيتم تضمين libFoo عند إدراج libFoo
فقط في الخاصية native_shared_libs
.
التعامل مع العديد من ABIs
قم بتثبيت خاصية native_shared_libs
لكل من واجهات التطبيق الثنائية (ABI) الأساسية والثانوية للجهاز. إذا كان APEX يستهدف أجهزة بها ABI واحد (أي 32 بت فقط أو 64 بت فقط) ، يتم تثبيت المكتبات التي تحتوي على ABI المقابل فقط.
قم بتثبيت خاصية binaries
فقط لـ ABI الأساسي للجهاز كما هو موضح أدناه:
- إذا كان الجهاز 32 بت فقط ، يتم تثبيت متغير 32 بت فقط من الثنائي.
- إذا كان الجهاز 64 بت فقط ، فسيتم تثبيت الإصدار 64 بت فقط من البرنامج الثنائي.
لإضافة تحكم دقيق في ABI للمكتبات والثنائيات الأصلية ، استخدم multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries]
.
-
first
: يطابق ABI الأساسي للجهاز. هذا هو الإعداد الافتراضي للثنائيات. -
lib32
: يطابق 32 بت ABI للجهاز ، إذا كان مدعومًا. -
lib64
: يطابق 64 بت ABI للجهاز ، وهو مدعوم. -
prefer32
: يطابق 32 بت ABI للجهاز ، إذا كان مدعومًا. إذا كان 32 بت ABI غير مدعوم ، يتطابق مع 64 بت ABI. -
both
: يطابق كلا من ABIs. هذا هو الإعداد الافتراضي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
للتوقيع على 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
قم بالتوقيع على APEXes بنفس طريقة توقيعك على ملفات APK. توقيع APEXes مرتين ؛ مرة واحدة لنظام الملفات المصغرة (ملف 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 المثبت حاليًا غير مستخدم (على سبيل المثال ، تم إيقاف أي خدمات يحتوي عليها) ، فيمكن عندئذٍ تثبيت APEX جديد بدون إعادة تشغيل بعلامة --force-non-staged
.
adb install --force-non-staged apex_file_name
استخدم APEX
بعد إعادة التشغيل ، يتم تحميل APEX في الدليل /apex/<apex_name>@<version>
. يمكن تركيب إصدارات متعددة من نفس APEX في نفس الوقت. من بين مسارات التحميل ، المسار الذي يتوافق مع أحدث إصدار مُثبت بالربط في /apex/<apex_name>
.
يمكن للعملاء استخدام مسار الربط لقراءة أو تنفيذ الملفات من APEX.
عادةً ما يتم استخدام APEXes على النحو التالي:
- يقوم OEM أو ODM بتحميل 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. مشغلات الإجراءات غير مدعومة في APEXes.
إذا بدأت إحدى الخدمات التي تم وضع علامة عليها على أنها قابلة للتحديث قبل تنشيط APEXes ، فسيتم تأخير البدء حتى يكتمل تنشيط APEXes.
تكوين النظام لدعم تحديثات 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 بشكل كامل. على سبيل المثال ، ربما تم بناء النواة بدون CONFIG_BLK_DEV_LOOP=Y
، وهو أمر بالغ الأهمية لتركيب صورة نظام الملفات داخل APEX.
APEX المسطح عبارة عن APEX مبني خصيصًا ويمكن تنشيطه على الأجهزة ذات النواة القديمة. يتم تثبيت الملفات الموجودة في APEX المسطح مباشرة إلى دليل أسفل القسم المدمج. على سبيل المثال ، lib/libFoo.so
في APEX المسطح مثبت my.apex
على /system/apex/my.apex/lib/libFoo.so
.
لا يتضمن تنشيط APEX المسطح جهاز الحلقة. يتم ربط الدليل بالكامل /system/apex/my.apex
مباشرة بـ /apex/name@ver
.
لا يمكن تحديث واجهات APEX المسطحة عن طريق تنزيل إصدارات محدثة من APEXes من الشبكة لأنه لا يمكن تسوية APEXes التي تم تنزيلها. لا يمكن تحديث أجهزة APEX المسطحة إلا عبر OTA العادي.
APEX المسطح هو التكوين الافتراضي. هذا يعني أن جميع أجهزة APEX يتم تسويتها افتراضيًا إلا إذا قمت بتكوين جهازك بشكل صريح لإنشاء واجهات APEX غير مسطحة لدعم تحديثات APEX (كما هو موضح أعلاه).
لا يتم دعم الخلط بين أجهزة APEX المسطحة وغير المسطحة في الجهاز. يجب أن تكون أجهزة APEX في الجهاز إما غير مسطحة أو كلها مسطحة. هذا مهم بشكل خاص عند شحن أعمدة APEX مسبقة التوقيع لمشاريع مثل Mainline. يجب أيضًا أن تكون APEX التي لم يتم تعيينها مسبقًا (أي التي تم إنشاؤها من المصدر) غير مسطحة وموقعة بالمفاتيح المناسبة. يجب أن يرث الجهاز من updatable_apex.mk
كما هو موضح في تحديث الخدمة باستخدام APEX .
أبكس مضغوط
يتميز نظام Android 12 والإصدارات الأحدث بضغط APEX لتقليل تأثير التخزين لحزم APEX القابلة للتحديث. بعد تثبيت تحديث لـ APEX ، على الرغم من أن نسخته المثبتة مسبقًا لم تعد مستخدمة ، إلا أنها لا تزال تشغل نفس القدر من المساحة. تلك المساحة المشغولة لا تزال غير متوفرة.
يقلل ضغط APEX من تأثير التخزين هذا باستخدام مجموعة مضغوطة للغاية من ملفات APEX على أقسام للقراءة فقط (مثل قسم /system
). يستخدم Android 12 والإصدارات الأحدث خوارزمية ضغط DEFLATE.
لا يوفر الضغط تحسينًا لما يلي:
Bootstrap APEXes المطلوب تركيبها في وقت مبكر جدًا في تسلسل التمهيد.
APEXes غير قابلة للتحديث. يكون الضغط مفيدًا فقط إذا تم تثبيت إصدار محدث من APEX على قسم
/data
. تتوفر قائمة كاملة بأجهزة APEX القابلة للتحديث في صفحة مكونات النظام المعيارية .ديناميكية libs المشتركة APEXes. نظرًا لأن
apexd
يقوم دائمًا بتنشيط كلا الإصدارين من مثل APEXes (مثبتة مسبقًا ومُحدَّثة) ، فإن ضغطهما لا يضيف قيمة.
تنسيق ملف APEX المضغوط
هذا هو تنسيق ملف APEX المضغوط.
الشكل 2. تنسيق ملف APEX المضغوط
في المستوى الأعلى ، ملف 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 مضغوطة.
بالنسبة للتجارب المحلية ، يمكنك إجبار التصميم على ضغط APEXes عن طريق تعيين OVERRIDE_PRODUCT_COMPRESSED_APEX=
إلى true
.
تحتوي ملفات APEX المضغوطة التي تم إنشاؤها بواسطة نظام الإنشاء على الامتداد .capex
. يسهل الامتداد التمييز بين الإصدارات المضغوطة وغير المضغوطة لملف APEX.
خوارزميات الضغط المدعومة
يدعم Android 12 فقط ضغط الانكماش المضغوط.
قم بتنشيط ملف 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 المضغوطة لها آثار على تسليم وتطبيق OTA. نظرًا لأن تحديث OTA قد يحتوي على ملف APEX مضغوط بمستوى إصدار أعلى مما هو نشط على الجهاز ، يجب حجز قدر معين من المساحة الحرة قبل إعادة تشغيل الجهاز لتطبيق تحديث OTA.
لدعم نظام OTA ، تكشف apexd
هاتين واجهتي API الموثقين:
-
calculateSizeForCompressedApex
- حساب الحجم المطلوب لفك ضغط ملفات APEX في حزمة OTA. يمكن استخدام هذا للتحقق من أن الجهاز به مساحة كافية قبل تنزيل OTA. -
reserveSpaceForCompressedApex
- يحتفظ بمساحة على القرص للاستخدام المستقبلي بواسطةapexd
لفك ضغط ملفات APEX المضغوطة داخل حزمة OTA.
في حالة تحديث A / B OTA ، يحاول apexd
فك الضغط في الخلفية كجزء من روتين OTA بعد التثبيت. في حالة فشل إلغاء الضغط ، يقوم apexd
بإلغاء الضغط أثناء التمهيد الذي يطبق تحديث OTA.
البدائل التي تم أخذها في الاعتبار عند تطوير APEX
فيما يلي بعض الخيارات التي أخذتها AOSP في الاعتبار عند تصميم تنسيق ملف APEX ، ولماذا تم تضمينها أو استبعادها.
أنظمة إدارة الحزم العادية
تحتوي توزيعات Linux على أنظمة إدارة الحزم مثل dpkg
و rpm
، وهي قوية وناضجة وقوية. ومع ذلك ، لم يتم اعتمادها لـ APEX لأنها لا تستطيع حماية الحزم بعد التثبيت. يتم التحقق فقط عندما يتم تثبيت الحزم. يمكن للمهاجمين كسر تكامل الحزم المثبتة دون أن يلاحظها أحد. هذا هو الانحدار لنظام Android حيث تم تخزين جميع مكونات النظام في أنظمة ملفات للقراءة فقط والتي يتم حماية سلامتها بواسطة dm-verity لكل I / O. يجب إما حظر أي تلاعب في مكونات النظام ، أو يمكن اكتشافه بحيث يمكن للجهاز رفض التمهيد إذا تم اختراقه.
dm-crypt من أجل النزاهة
الملفات الموجودة في حاوية APEX هي من أقسام مدمجة (على سبيل المثال ، قسم /system
) محمية بواسطة dm-verity ، حيث يُحظر إجراء أي تعديل على الملفات حتى بعد تثبيت الأقسام. لتوفير نفس مستوى الأمان للملفات ، يتم تخزين جميع الملفات الموجودة في APEX في صورة نظام ملفات مقترنة بشجرة تجزئة وموصف vbmeta. بدون dm-verity ، يكون APEX الموجود في قسم /data
عرضة للتعديلات غير المقصودة التي يتم إجراؤها بعد التحقق من صحتها وتثبيتها.
في الواقع ، قسم /data
محمي أيضًا بطبقات تشفير مثل dm-crypt. على الرغم من أن هذا يوفر مستوى معينًا من الحماية ضد العبث ، إلا أن الغرض الأساسي منه هو الخصوصية وليس النزاهة. عندما يحصل مهاجم على حق الوصول إلى قسم /data
، فلا يمكن أن يكون هناك مزيد من الحماية ، وهذا مرة أخرى يعد تراجعًا مقارنة بكل مكون من مكونات النظام الموجودة في قسم /system
. توفر شجرة التجزئة داخل ملف APEX جنبًا إلى جنب مع dm-verity نفس مستوى حماية المحتوى.
إعادة توجيه المسارات من / النظام إلى / قمة
يمكن الوصول إلى ملفات مكونات النظام التي تم حزمها في APEX عبر مسارات جديدة مثل /apex/<name>/lib/libfoo.so
. عندما كانت الملفات جزءًا من قسم /system
، كان يمكن الوصول إليها عبر مسارات مثل /system/lib/libfoo.so
. يجب أن يستخدم عميل ملف APEX (ملفات APEX الأخرى أو النظام الأساسي) المسارات الجديدة. قد تحتاج إلى تحديث التعليمات البرمجية الموجودة كنتيجة لتغيير المسار.
على الرغم من أن إحدى الطرق لتجنب تغيير المسار تتمثل في تراكب محتويات الملف في ملف APEX على قسم /system
، فقد قرر فريق Android عدم تراكب الملفات على قسم /system
لأن هذا قد يؤثر على الأداء نظرًا لأن عدد الملفات التي يتم تراكبها ( ربما مكدسة واحدة تلو الأخرى).
هناك خيار آخر يتمثل في اختطاف وظائف الوصول إلى الملفات مثل open
و stat
و readlink
، بحيث تتم إعادة توجيه المسارات التي تبدأ بـ /system
إلى المسارات المقابلة لها ضمن /apex
. تجاهل فريق Android هذا الخيار لأنه من غير الممكن تغيير جميع الوظائف التي تقبل المسارات. على سبيل المثال ، تربط بعض التطبيقات Bionic بشكل ثابت ، والتي تقوم بتنفيذ الوظائف. في مثل هذه الحالات ، لا تتم إعادة توجيه هذه التطبيقات.