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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

قد تعمل وحدة "محاكي الجهاز" بكفاءة أقل في حال عدم محاذاة قسم super بشكل صحيح. يجب أن يكون تنسيق ملف super متوافقًا مع الحد الأدنى لحجم طلب الإدخال/الإخراج الذي تحدّده طبقة الكتل. يفترض نظام الإنشاء (من خلال lpmake الذي ينشئ super صورة القسم) تلقائيًا أنّ محاذاة 1 ميغابايت كافية لكل قسم ديناميكي. ومع ذلك، على المورّدين التأكّد من محاذاة قسم 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

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

عليك ضبط حجم قسم super:

BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>

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

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

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

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

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

بالنسبة إلى صور 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، التي تقع في ذاكرة الوصول العشوائي.

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

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

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

تغييرات في إعدادات بروتوكول AVB

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

في ما يلي مثال على الإعداد لجهاز يربط 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: تتيح استخدام ملفات vbmeta في بداية القسم".

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

يجب إضافة مَعلمة جديدة، androidboot.boot_devices، إلى سطر أوامر kernel. يستخدم 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، التي تمّ طرحها في الإصدار 10 من Android، والتي تشير إلى أنّه يجب تركيب قسم في المرحلة الأولى.
  • قد يحدّد أحد الأقسام 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 إلى ذاكرة الوصول العشوائي (RAM) في المرحلة الأولى.

تغييرات SELinux

يجب وضع علامة التصنيف super_block_device على جهاز حظر القسم الفائق. على سبيل المثال، إذا كان الرابط الرمزي للقسم الفائق بالاسم هو /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 و تضمين ميزة توافق الأقسام الديناميكية في التحديثات عبر الهواء، لن تحتاج إلى تغيير جدول الأقسام المضمّن. يجب إجراء بعض الإعدادات الإضافية.

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

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

PRODUCT_USE_DYNAMIC_PARTITIONS := true
PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true

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

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

  • اضبط 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;

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

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

صور المصنع

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

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

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

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

ضبط مساحة تخزين جهاز "محاكي الأجهزة"

تتيح عملية التقسيم الديناميكي استخدام عدد من عناصر أداة ربط الأجهزة غير الحتمية. قد لا يتم إنشاء جميع هذه العناصر على النحو المتوقّع، لذا عليك تتبُّع جميع عمليات التثبيت وتعديل سمات 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 في kernel كافيًا إلى أن يتم استبداله من خلال النصوص البرمجية 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}