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

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

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

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

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

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

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

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

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

لتقدير حجم super، أضِف أحجام الأقسام التي يتم حذفها من GPT. بالنسبة إلى أجهزة 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. بالنسبة إلى أجهزة 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
  • بالنسبة إلى الأجهزة التي يتم إطلاقها باستخدام ميزة "الاختبار الافتراضي A/B"، يجب أن يكون مجموع الحد الأقصى لأحجام جميع المجموعات على النحو التالي:
    BOARD_SUPER_PARTITION_SIZE - النفقات العامة
    راجِع تنفيذ ميزة "الاختبار الافتراضي A/B".
  • بالنسبة إلى الأجهزة التي يمكن إجراء اختبار A/B عليها، يجب أن يكون مجموع الحد الأقصى لأحجام جميع المجموعات كما يلي:
    BOARD_SUPER_PARTITION_SIZE / 2 - overhead
  • بالنسبة إلى الأجهزة غير المتوافقة مع تحديثات 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

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

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

يجب ألا تستخدم الأجهزة التي تعمل بالإصدار 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 الرمزي هو /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

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

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

adb remount

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

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

ترقية أجهزة Android

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

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

لإعادة تصميم التقسيم الديناميكي، أضِف العلامات التالية في 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) للأجهزة التي تستخدم بنية أ/ب بدون أقسام ديناميكية.

صور برامج الجهة المصنِّعة

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

لحلّ هذه المشكلة، ينشئ make dist الآن صورة إضافية super.img يمكن نقلها مباشرةً إلى قسم super. ويجمع تلقائيًا محتويات الأقسام المنطقية، ما يعني أنّه يحتوي على 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}