تنفيذ الأقسام الديناميكية

يتم تنفيذ التقسيم الديناميكي باستخدام وحدة dm-linear الخاصة ببرنامج device-mapper في نواة Linux. يحتوي القسم super على بيانات وصفية تسرد أسماء ونطاقات الحظر لكل قسم ديناميكي ضمن super. أثناء المرحلة الأولى init، يتم تحليل هذه البيانات الوصفية والتحقّق من صحتها، ويتم إنشاء أجهزة تخزين بالكتل الافتراضية لتمثيل كل قسم ديناميكي.

عند تطبيق تحديث عبر الأثير (OTA)، يتم تلقائيًا إنشاء الأقسام الديناميكية أو تغيير حجمها أو حذفها حسب الحاجة. بالنسبة إلى الأجهزة التي تستخدم نظام التشغيل A/B، تتوفّر نسختان من البيانات الوصفية، ويتم تطبيق التغييرات على النسخة التي تمثّل الخانة المستهدَفة فقط.

بما أنّ الأقسام الديناميكية يتم تنفيذها في مساحة المستخدم، لا يمكن إنشاء أقسام ديناميكية يحتاج إليها برنامج التشغيل. على سبيل المثال، يقرأ برنامج الإقلاع boot وdtbo وvbmeta، لذا يجب أن تظل هذه الأقسام مادية.

يمكن أن ينتمي كل قسم ديناميكي إلى مجموعة تحديث. تحدّد هذه المجموعات الحد الأقصى للمساحة التي يمكن أن تستهلكها الأقسام في تلك المجموعة. على سبيل المثال، يمكن أن ينتمي system وvendor إلى مجموعة تفرض قيودًا على الحجم الإجمالي لكل من system وvendor.

تنفيذ الأقسام الديناميكية على الأجهزة الجديدة

يوضّح هذا القسم بالتفصيل كيفية تنفيذ الأقسام الديناميكية على الأجهزة الجديدة التي تعمل بالإصدار Android 10 والإصدارات الأحدث. لتحديث الأجهزة الحالية، يُرجى الاطّلاع على مقالة ترقية أجهزة Android.

تغييرات الأقسام

بالنسبة إلى الأجهزة التي تعمل بنظام التشغيل Android 10، أنشئ قسمًا باسم super. يتعامل القسم super مع خانات A/B داخليًا، لذا لا تحتاج أجهزة A/B إلى قسمَين منفصلَين super_a وsuper_b. يجب أن تكون جميع أقسام AOSP للقراءة فقط وغير المستخدَمة من قِبل برنامج التشغيل قابلة للتغيير، ويجب إزالتها من جدول أقسام GUID. لا يجب أن تكون الأقسام الخاصة بالمورّدين ديناميكية، ويمكن وضعها في GPT.

لتقدير حجم super، أضِف أحجام الأقسام التي يتم حذفها من GPT. بالنسبة إلى الأجهزة التي تستخدم نظام التشغيل Android A/B، يجب أن يشمل ذلك حجم كلا الفتحتين. يعرض الشكل 1 مثالاً على جدول أقسام قبل وبعد التحويل إلى أقسام ديناميكية.

تنسيق جدول الأقسام
الشكل 1. تنسيق جديد لجدول الأقسام الثابتة عند التحويل إلى أقسام ديناميكية

في ما يلي الأقسام الديناميكية المتوافقة:

  • النظام
  • المورّد
  • المنتَج
  • System Ext
  • ODM

بالنسبة إلى الأجهزة التي تعمل بنظام التشغيل Android 10، يجب أن يكون خيار سطر أوامر kernel androidboot.super_partition فارغًا حتى يكون الأمر sysprop ro.boot.super_partition فارغًا.

محاذاة الأقسام

قد يعمل وحدة device-mapper بكفاءة أقل إذا لم تتم محاذاة القسم super بشكل صحيح. يجب أن يكون قسم super متوافقًا مع الحد الأدنى لحجم طلب الإدخال/الإخراج الذي تحدّده طبقة الحظر. بشكلٍ تلقائي، يفترض نظام الإنشاء (من خلال lpmake، الذي ينشئ صورة قسم super) أنّ محاذاة 1 MiB كافية لكل قسم ديناميكي. ومع ذلك، يجب أن يحرص المورّدون على محاذاة القسم super بشكل صحيح.

يمكنك تحديد الحد الأدنى لحجم الطلب لجهاز الحظر من خلال فحص sysfs. مثلاً:

# ls -l /dev/block/by-name/super
lrwxrwxrwx 1 root root 16 1970-04-05 01:41 /dev/block/by-name/super -> /dev/block/sda17
# cat /sys/block/sda/queue/minimum_io_size
786432

يمكنك التحقّق من محاذاة القسم super بطريقة مشابهة:

# cat /sys/block/sda/sda17/alignment_offset

يجب أن تكون إزاحة المحاذاة 0.

تغييرات في إعدادات الجهاز

لتفعيل التقسيم الديناميكي، أضِف العلامة التالية في device.mk:

PRODUCT_USE_DYNAMIC_PARTITIONS := true

تغييرات في إعدادات لوحة Jamboard

يجب تحديد حجم القسم super:

BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>

على أجهزة A/B، يعرض نظام الإنشاء خطأً إذا كان الحجم الإجمالي لصور الأقسام الديناميكية أكبر من نصف حجم القسم super.

يمكنك ضبط قائمة الأقسام الديناميكية على النحو التالي. بالنسبة إلى الأجهزة التي تستخدم مجموعات التحديث، أدرِج المجموعات في المتغيّر BOARD_SUPER_PARTITION_GROUPS. يحتوي كل اسم مجموعة بعد ذلك على BOARD_group_SIZE ومتغيّر BOARD_group_PARTITION_LIST. بالنسبة إلى الأجهزة التي تستخدم نظام التشغيل Android A/B، يجب أن يغطي الحد الأقصى لحجم المجموعة فتحة واحدة فقط، لأنّ أسماء المجموعات يتم إلحاقها بفتحات داخليًا.

في ما يلي مثال على جهاز يضع جميع الأقسام في مجموعة باسم example_dynamic_partitions:

BOARD_SUPER_PARTITION_GROUPS := example_dynamic_partitions
BOARD_EXAMPLE_DYNAMIC_PARTITIONS_SIZE := 6442450944
BOARD_EXAMPLE_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product

في ما يلي مثال على جهاز يضع خدمات النظام والمنتج في group_foo وvendor وproduct وodm في group_bar:

BOARD_SUPER_PARTITION_GROUPS := group_foo group_bar
BOARD_GROUP_FOO_SIZE := 4831838208
BOARD_GROUP_FOO_PARTITION_LIST := system product_services
BOARD_GROUP_BAR_SIZE := 1610612736
BOARD_GROUP_BAR_PARTITION_LIST := vendor product odm
  • بالنسبة إلى الأجهزة التي يتم إطلاقها باستخدام ميزة "اختبار أ/ب الافتراضي"، يجب أن يكون مجموع الحد الأقصى لأحجام جميع المجموعات على النحو التالي:
    BOARD_SUPER_PARTITION_SIZE - النفقات العامة
    راجِع تنفيذ ميزة "اختبار أ/ب الافتراضي".
  • بالنسبة إلى الأجهزة التي يمكن إجراء اختبار الإطلاق عليها، يجب أن يكون مجموع الحد الأقصى لأحجام جميع المجموعات كما يلي:
    BOARD_SUPER_PARTITION_SIZE / 2 - النفقات العامة
  • بالنسبة إلى الأجهزة غير المتوافقة مع نظام التشغيل A/B والأجهزة المتوافقة مع نظام التشغيل A/B التي تم تعديلها، يجب أن يكون مجموع الحد الأقصى لأحجام جميع المجموعات كما يلي:
    BOARD_SUPER_PARTITION_SIZE - النفقات العامة
  • في وقت الإنشاء، يجب ألا يتجاوز مجموع أحجام صور كل قسم في مجموعة التحديث الحد الأقصى لحجم المجموعة.
  • النفقات العامة مطلوبة في عملية الحساب لتفسير البيانات الوصفية وعمليات المحاذاة وما إلى ذلك. يبلغ الحد المعقول للزيادة في الحجم 4 MiB، ولكن يمكنك اختيار زيادة أكبر في الحجم حسب ما يحتاج إليه الجهاز.

تقسيمات ديناميكية حسب الحجم

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

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

بالإضافة إلى ذلك، يمكن ضغط صور ext4 بشكل أكبر من خلال تفعيل ميزة إزالة البيانات المكررة على مستوى الحظر. لتفعيل ذلك، استخدِم الإعداد التالي:

BOARD_EXT4_SHARE_DUP_BLOCKS := true

إذا كان التخصيص التلقائي للحد الأدنى لحجم القسم غير مرغوب فيه، هناك طريقتان للتحكّم في حجم القسم. يمكنك تحديد الحد الأدنى لمقدار المساحة الحرة باستخدام BOARD_partitionIMAGE_PARTITION_RESERVED_SIZE، أو يمكنك تحديد BOARD_partitionIMAGE_PARTITION_SIZE لفرض حجم معيّن على الأقسام الديناميكية. ولا ننصح بأي من هذين الإجراءين إلا عند الضرورة.

مثلاً:

BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800

يؤدي ذلك إلى فرض توفّر مساحة غير مستخدَمة تبلغ 50 ميغابايت في نظام الملفات في product.img.

التغييرات على النظام كجذر

يجب ألا تستخدم الأجهزة التي تعمل بالإصدار 10 من نظام التشغيل Android نظام التشغيل كجذر.

يجب ألا تستخدم الأجهزة ذات الأقسام الديناميكية (سواء تم إطلاقها مع أقسام ديناميكية أو تم تعديلها لتشمل أقسامًا ديناميكية) نظام التشغيل كجذر. لا يمكن لنواة Linux تفسير القسم super، وبالتالي لا يمكنها تحميل system. يتم الآن تحميل system بواسطة init في المرحلة الأولى، والذي يقع في ramdisk.

لا تضبط BOARD_BUILD_SYSTEM_ROOT_IMAGE. في نظام التشغيل Android 10، لا يتم استخدام العلامة BOARD_BUILD_SYSTEM_ROOT_IMAGE إلا للتمييز بين ما إذا كان النظام مثبّتًا بواسطة النواة أو بواسطة init في المرحلة الأولى في ramdisk.

يؤدي ضبط BOARD_BUILD_SYSTEM_ROOT_IMAGE على true إلى حدوث خطأ في الإنشاء عندما تكون قيمة PRODUCT_USE_DYNAMIC_PARTITIONS هي true أيضًا.

عند ضبط BOARD_USES_RECOVERY_AS_BOOT على "صحيح"، يتم إنشاء صورة الاسترداد كملف boot.img يحتوي على ملف ramdisk الخاص بالاسترداد. في السابق، كان برنامج Bootloader يستخدم مَعلمة سطر الأوامر skip_initramfs الخاصة بالنواة لتحديد الوضع الذي سيتم التشغيل فيه. بالنسبة إلى أجهزة Android 10، يجب ألا يمرّر برنامج التشغيل skip_initramfs إلى سطر أوامر النواة. بدلاً من ذلك، يجب أن يمرِّر برنامج التحميل androidboot.force_normal_boot=1 لتخطّي وضع الاسترداد وتشغيل نظام Android العادي. يجب أن تستخدم الأجهزة التي تعمل بالإصدار 12 من نظام التشغيل Android أو الإصدارات الأحدث bootconfig لتمرير androidboot.force_normal_boot=1.

تغييرات في إعدادات AVB

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

في ما يلي مثال على إعدادات جهاز يربط بين vbmeta لقسمَي system وvendor.

BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048
BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1

BOARD_AVB_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_VENDOR_ALGORITHM := SHA256_RSA2048
BOARD_AVB_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_VENDOR_ROLLBACK_INDEX_LOCATION := 1

باستخدام هذا الإعداد، يتوقّع برنامج التحميل العثور على تذييل vbmetaفي نهاية القسمين system وvendor. وبما أنّ هذه الأقسام لم تعُد مرئية لبرنامج التحميل (لأنّها تقع في super)، يجب إجراء تغييرَين.

  • أضِف قسمَي vbmeta_system وvbmeta_vendor إلى جدول الأقسام على الجهاز. بالنسبة إلى أجهزة اختبار A/B، أضِف vbmeta_system_a وvbmeta_system_b وvbmeta_vendor_a وvbmeta_vendor_b. في حال إضافة قسم واحد أو أكثر من هذه الأقسام، يجب أن يكون حجمها مماثلاً لحجم القسم vbmeta.
  • أعِد تسمية علامات الإعداد من خلال إضافة VBMETA_ وحدِّد الأقسام التي يمتد إليها الربط:
    BOARD_AVB_VBMETA_SYSTEM := system
    BOARD_AVB_VBMETA_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
    BOARD_AVB_VBMETA_SYSTEM_ALGORITHM := SHA256_RSA2048
    BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
    BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
    
    BOARD_AVB_VBMETA_VENDOR := vendor
    BOARD_AVB_VBMETA_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
    BOARD_AVB_VBMETA_VENDOR_ALGORITHM := SHA256_RSA2048
    BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
    BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX_LOCATION := 1

قد يستخدم الجهاز أحد هذين القسمَين أو كليهما أو لا يستخدم أيًا منهما. لا تكون التغييرات مطلوبة إلا عند الربط بقسم منطقي.

تغييرات برنامج إقلاع AVB

إذا كان برنامج التشغيل الأوّلي يتضمّن libavb، يجب تضمين التصحيحات التالية:

في حال استخدام الأقسام المتسلسلة، أدرِج رمز تصحيح إضافيًا:

  • 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — "libavb: Support vbmeta blobs in beginning of partition."

التغييرات على سطر أوامر النواة

يجب إضافة مَعلمة جديدة، androidboot.boot_devices، إلى سطر أوامر النواة. يتم استخدام هذا الخيار بواسطة init لتفعيل الروابط الرمزية /dev/block/by-name. يجب أن يكون مكوّن مسار الجهاز إلى الرابط الرمزي الأساسي الذي تم إنشاؤه بواسطة ueventd، أي /dev/block/platform/device-path/by-name/partition-name. يجب أن تستخدم الأجهزة التي تعمل بالإصدار 12 من نظام التشغيل Android أو الإصدارات الأحدث bootconfig لتمرير androidboot.boot_devices إلى init.

على سبيل المثال، إذا كان الرابط الرمزي الخاص بالقسم الفائق حسب الاسم هو /dev/block/platform/soc/100000.ufshc/by-name/super، يمكنك إضافة مَعلمة سطر الأوامر في ملف BoardConfig.mk على النحو التالي:

BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshc
يمكنك إضافة المَعلمة bootconfig في ملف BoardConfig.mk على النحو التالي:
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc

تغييرات fstab

يجب ألا يحتوي كل من شجرة الأجهزة وتراكبات شجرة الأجهزة على إدخالات fstab. استخدِم ملف fstab الذي سيكون جزءًا من ramdisk.

يجب إجراء تغييرات على ملف fstab للأقسام المنطقية:

  • يجب أن يتضمّن حقل العلامات fs_mgr العلامة logical والعلامة first_stage_mount التي تم طرحها في نظام التشغيل Android 10، وتشير إلى أنّه سيتم تثبيت أحد الأقسام في المرحلة الأولى.
  • قد يحدّد القسم avb=vbmeta partition name كعلامة fs_mgr، ثم يتم تهيئة القسم vbmeta المحدّد بواسطة المرحلة الأولى init قبل محاولة ربط أي أجهزة.
  • يجب أن يكون الحقل dev هو اسم القسم.

تضبط إدخالات fstab التالية النظام والمورّد والمنتج كأقسام منطقية وفقًا للقواعد المذكورة أعلاه.

#<dev>  <mnt_point> <type>  <mnt_flags options> <fs_mgr_flags>
system   /system     ext4    ro,barrier=1        wait,slotselect,avb=vbmeta,logical,first_stage_mount
vendor   /vendor     ext4    ro,barrier=1        wait,slotselect,avb,logical,first_stage_mount
product  /product    ext4    ro,barrier=1        wait,slotselect,avb,logical,first_stage_mount

انسخ ملف fstab إلى ramdisk في المرحلة الأولى.

تغييرات SELinux

يجب وضع التصنيف super_block_device على جهاز حظر التقسيم الفائق. على سبيل المثال، إذا كان رابط super partition by-name symlink هو /dev/block/platform/soc/100000.ufshc/by-name/super، أضِف السطر التالي إلى file_contexts:

/dev/block/platform/soc/10000\.ufshc/by-name/super   u:object_r:super_block_device:s0

fastbootd

لا يفهم برنامج التشغيل الأوّلي (أو أي أداة أخرى غير خاصة بمساحة المستخدم) الأقسام الديناميكية، لذا لا يمكنه تثبيتها. ولحلّ هذه المشكلة، يجب أن تستخدم الأجهزة تنفيذًا لمساحة المستخدمين لبروتوكول fastboot، يُعرف باسم fastbootd.

لمزيد من المعلومات حول كيفية تنفيذ fastbootd، يُرجى الاطّلاع على نقل Fastboot إلى مساحة المستخدم.

adb remount

بالنسبة إلى المطوّرين الذين يستخدمون إصدارات eng أو userdebug، يكون adb remount مفيدًا للغاية للتكرار السريع. تسبّب الأقسام الديناميكية مشكلة في adb remount لأنّه لم تعُد هناك مساحة حرة داخل كل نظام ملفات. لحلّ هذه المشكلة، يمكن للأجهزة تفعيل overlayfs. طالما توفّرت مساحة حرة ضمن القسم الفائق، ينشئ adb remount تلقائيًا قسمًا ديناميكيًا مؤقتًا ويستخدم overlayfs لعمليات الكتابة. اسم القسم المؤقت هو scratch، لذا لا تستخدِم هذا الاسم لأقسام أخرى.

لمزيد من المعلومات حول كيفية تفعيل overlayfs، يُرجى الاطّلاع على ملف overlayfs README في مشروع AOSP.

ترقية أجهزة Android

إذا تمت ترقية جهاز إلى Android 10 وأردت تضمين إمكانية استخدام الأقسام الديناميكية في التحديث عبر الأثير (OTA)، لن تحتاج إلى تغيير جدول الأقسام المضمّن. يجب إجراء بعض عمليات الضبط الإضافية.

تغييرات في إعدادات الجهاز

لإعادة تصميم التقسيم الديناميكي، أضِف العلامات التالية في device.mk:

PRODUCT_USE_DYNAMIC_PARTITIONS := true
PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true

تغييرات في إعدادات لوحة Jamboard

يجب ضبط متغيّرات اللوحة التالية:

  • اضبط BOARD_SUPER_PARTITION_BLOCK_DEVICES على قائمة أجهزة التخزين بالكتل المستخدَمة لتخزين مدى الأقسام الديناميكية. هذه هي قائمة بأسماء الأقسام الفعلية الحالية على الجهاز.
  • اضبط BOARD_SUPER_PARTITION_partition_DEVICE_SIZE على أحجام كل جهاز تخزين بالكتل في BOARD_SUPER_PARTITION_BLOCK_DEVICES، على التوالي. هذه هي قائمة بأحجام الأقسام الفعلية الحالية على الجهاز. يحدث ذلك عادةً BOARD_partitionIMAGE_PARTITION_SIZE في إعدادات اللوحة الحالية.
  • إلغاء ضبط BOARD_partitionIMAGE_PARTITION_SIZE الحالي لجميع الأقسام في BOARD_SUPER_PARTITION_BLOCK_DEVICES
  • اضبط BOARD_SUPER_PARTITION_SIZE على مجموع BOARD_SUPER_PARTITION_partition_DEVICE_SIZE.
  • اضبط BOARD_SUPER_PARTITION_METADATA_DEVICE على جهاز التخزين الكتلي الذي يتم فيه تخزين البيانات الوصفية للأقسام الديناميكية. يجب أن يكون أحد القيم التالية: BOARD_SUPER_PARTITION_BLOCK_DEVICES. عادةً، يتم ضبط هذا الخيار على system.
  • اضبط BOARD_SUPER_PARTITION_GROUPS وBOARD_group_SIZE وBOARD_group_PARTITION_LIST على التوالي. يمكنك الاطّلاع على تغييرات في إعدادات اللوحة على الأجهزة الجديدة للحصول على التفاصيل.

على سبيل المثال، إذا كان الجهاز يتضمّن أقسامًا للنظام والمورّد، وأردت تحويلها إلى أقسام ديناميكية وإضافة قسم منتج جديد أثناء التحديث، اضبط إعدادات اللوحة على النحو التالي:

BOARD_SUPER_PARTITION_BLOCK_DEVICES := system vendor
BOARD_SUPER_PARTITION_METADATA_DEVICE := system

# Rename BOARD_SYSTEMIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE.
BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE := <size-in-bytes>

# Rename BOARD_VENDORIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE
BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE := <size-in-bytes>

# This is BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE + BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE
BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>

# Configuration for dynamic partitions. For example:
BOARD_SUPER_PARTITION_GROUPS := group_foo
BOARD_GROUP_FOO_SIZE := <size-in-bytes>
BOARD_GROUP_FOO_PARTITION_LIST := system vendor product

تغييرات SELinux

يجب وضع العلامة super_block_device_type على أجهزة حظر الأقسام الفائقة باستخدام السمة. على سبيل المثال، إذا كان الجهاز يحتوي على القسمَين system وvendor، وتريد استخدامهما كأجهزة حظر لتخزين نطاقات الأقسام الديناميكية، يتم وضع علامة system_block_device على الروابط الرمزية الخاصة بهما:

/dev/block/platform/soc/10000\.ufshc/by-name/system   u:object_r:system_block_device:s0
/dev/block/platform/soc/10000\.ufshc/by-name/vendor   u:object_r:system_block_device:s0

بعد ذلك، أضِف السطر التالي إلى device.te:

typeattribute system_block_device super_block_device_type;

للاطّلاع على عمليات الضبط الأخرى، يُرجى الرجوع إلى تنفيذ الأقسام الديناميكية على الأجهزة الجديدة.

لمزيد من المعلومات حول تحديثات التوافق مع الإصدارات القديمة، يُرجى الاطّلاع على التحديث عبر الهواء (OTA) للأجهزة التي تستخدم بنية A/B بدون أقسام ديناميكية.

صور المصنع

بالنسبة إلى جهاز يتم إطلاقه مع توفير إمكانية استخدام الأقسام الديناميكية، تجنَّب استخدام fastboot في مساحة المستخدم لتثبيت صور المصنع، لأنّ عملية الإقلاع إلى مساحة المستخدم تستغرق وقتًا أطول من طرق التثبيت الأخرى.

لحلّ هذه المشكلة، ينشئ make dist الآن صورة super.img إضافية يمكن نقلها مباشرةً إلى القسم الفائق. ويجمع تلقائيًا محتويات الأقسام المنطقية، ما يعني أنّه يحتوي على system.img وvendor.img وما إلى ذلك، بالإضافة إلى البيانات الوصفية الخاصة بالقسم super. يمكن نقل هذه الصورة مباشرةً إلى القسم super بدون أي أدوات إضافية أو استخدام fastbootd. بعد اكتمال عملية الإنشاء، يتم وضع super.img في ${ANDROID_PRODUCT_OUT}.

بالنسبة إلى أجهزة A/B التي يتم تشغيلها باستخدام الأقسام الديناميكية، يحتوي super.img على صور في الفتحة A. بعد نقل صورة super مباشرةً، ضَع علامة على الفتحة A باعتبارها قابلة للتشغيل قبل إعادة تشغيل الجهاز.

بالنسبة إلى الأجهزة التي تم تعديلها، ينشئ make dist مجموعة من صور super_*.img التي يمكن نقلها مباشرةً إلى الأقسام المادية المقابلة. على سبيل المثال، تنشئ make dist super_system.img وsuper_vendor.img عندما تكون BOARD_SUPER_PARTITION_BLOCK_DEVICES هي مورّد النظام. يتم وضع هذه الصور في مجلد OTA في target_files.zip.

ضبط جهاز التخزين في أداة Device Mapper

تستوعب عملية التقسيم الديناميكي عددًا من عناصر device-mapper غير المحدّدة. وقد لا يتم إنشاء مثيل لجميع هذه الأقسام على النحو المتوقّع، لذا عليك تتبُّع جميع عمليات الربط وتعديل خصائص Android لجميع الأقسام المرتبطة بأجهزة التخزين الأساسية.

تتضمّن init آلية تتتبّع عمليات الربط وتعدّل بشكل غير متزامن خصائص Android. لا يمكن ضمان أن يتم ذلك خلال فترة زمنية محددة، لذا عليك توفير وقت كافٍ لتتفاعل جميع مشغّلات on property. السمات هي dev.mnt.blk.<partition> حيث <partition> هي root أو system أو data أو vendor، على سبيل المثال. يرتبط كل موقع باسم جهاز التخزين الأساسي، كما هو موضّح في الأمثلة التالية:

taimen:/ % getprop | grep dev.mnt.blk
[dev.mnt.blk.data]: [sda]
[dev.mnt.blk.firmware]: [sde]
[dev.mnt.blk.metadata]: [sde]
[dev.mnt.blk.persist]: [sda]
[dev.mnt.blk.root]: [dm-0]
[dev.mnt.blk.vendor]: [dm-1]

blueline:/ $ getprop | grep dev.mnt.blk
[dev.mnt.blk.data]: [dm-4]
[dev.mnt.blk.metadata]: [sda]
[dev.mnt.blk.mnt.scratch]: [sda]
[dev.mnt.blk.mnt.vendor.persist]: [sdf]
[dev.mnt.blk.product]: [dm-2]
[dev.mnt.blk.root]: [dm-0]
[dev.mnt.blk.system_ext]: [dm-3]
[dev.mnt.blk.vendor]: [dm-1]
[dev.mnt.blk.vendor.firmware_mnt]: [sda]

تسمح لغة init.rc بتوسيع خصائص Android كجزء من القواعد، ويمكن ضبط أجهزة التخزين من خلال النظام الأساسي حسب الحاجة باستخدام أوامر مثل ما يلي:

write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb 128
write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb 128

بعد بدء معالجة الأمر في المرحلة الثانية init، يصبح epoll loop نشطًا، وتبدأ القيم في التعديل. ومع ذلك، بما أنّ مشغّلات الخصائص لا تكون نشطة إلا في أواخر init، لا يمكن استخدامها في مراحل التشغيل الأولية للتعامل مع root أو system أو vendor. يمكنك توقّع أن يكون الإعداد التلقائي للنواة read_ahead_kb كافيًا إلى أن تتمكّن البرامج النصية init.rc من إلغاء الإعداد في early-fs (عندما تبدأ العديد من البرامج الخفية والمرافق). لذلك، تنصح Google باستخدام الميزة on property مع عنصر تحكّم init.rc مثل sys.read_ahead_kb للتعامل مع توقيت العمليات ومنع حالات التنافس، كما في الأمثلة التالية:

on property:dev.mnt.blk.root=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.system=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.system}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.vendor=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.vendor}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.product=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.system_ext}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.oem=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.oem}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.data=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on early-fs:
    setprop sys.read_ahead_kb ${ro.read_ahead_kb.boot:-2048}

on property:sys.boot_completed=1
   setprop sys.read_ahead_kb ${ro.read_ahead_kb.bootcomplete:-128}