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

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

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

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

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

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

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

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

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

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

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

الأقسام الديناميكية المدعومة هي:

  • نظام
  • بائع
  • منتج
  • تحويلة النظام
  • التصميم

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

محاذاة التقسيم

قد تعمل وحدة مخطط الجهاز بكفاءة أقل إذا لم تتم محاذاة القسم 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

تغييرات تكوين المجلس

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

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

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

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

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

BOARD_EXT4_SHARE_DUP_BLOCKS := true

إذا كان التخصيص التلقائي للحد الأدنى لحجم القسم غير مرغوب فيه ، فهناك طريقتان للتحكم في حجم القسم. يمكنك تحديد الحد الأدنى من المساحة الخالية باستخدام BOARD_ partition IMAGE_PARTITION_RESERVED_SIZE ، أو يمكنك تحديد BOARD_ partition IMAGE_PARTITION_SIZE لفرض الأقسام الديناميكية على حجم معين. لا ينصح بأي من هذه إلا إذا لزم الأمر.

فمثلا:

BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800

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

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

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

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

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

يؤدي تعيين BOARD_BUILD_SYSTEM_ROOT_IMAGE على القيمة true إلى حدوث خطأ في الإصدار عندما يكون PRODUCT_USES_DYNAMIC_PARTITIONS true أيضًا.

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

تغييرات تكوين AVB

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

فيما يلي مثال على تكوين جهاز 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 في بداية القسم."

تغييرات سطر أوامر Kernel

يجب إضافة معامل جديد ، androidboot.boot_devices ، إلى سطر أوامر kernel. يتم استخدام هذا بواسطة init لتمكين /dev/block/by-name . يجب أن يكون مكون مسار الجهاز للرابط الرمزي الأساسي الذي تم إنشاؤه بواسطة ueventd ، أي /dev/block/platform/ device-path /by-name/ partition-name . يجب أن تستخدم الأجهزة التي تعمل بنظام Android 12 أو إصدار أحدث 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 flags على العلم 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 . على سبيل المثال ، إذا كان الارتباط الرمزي للقسم الفائق بالاسم هو /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

لا يفهم برنامج bootloader (أو أي أداة فلاش خاصة بمساحة المستخدمين) الأقسام الديناميكية ، لذا لا يمكنه وميضها. لمعالجة هذا الأمر ، يجب أن تستخدم الأجهزة تطبيق مساحة المستخدم لبروتوكول Fastboot ، المسمى fastbootd.

لمزيد من المعلومات حول كيفية تنفيذ fastbootd ، راجع نقل Fastboot إلى User Space .

adb remount

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

لمزيد من المعلومات حول كيفية تمكين التراكبات ، راجع التراكبات README في AOSP.

ترقية أجهزة Android

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

تغييرات تكوين الجهاز

لتعديل التقسيم الديناميكي ، أضف العلامات التالية في 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_ partition IMAGE_PARTITION_SIZE في تكوينات اللوحة الحالية.
  • قم بإلغاء BOARD_ partition IMAGE_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 إضافية يمكن وميضها مباشرةً إلى القسم super. يقوم تلقائيًا بتجميع محتويات الأقسام المنطقية ، مما يعني أنه يحتوي على system.img و vendor.img وما إلى ذلك ، بالإضافة إلى البيانات الوصفية للقسم super . يمكن وميض هذه الصورة مباشرة إلى القسم super دون أي أدوات إضافية أو استخدام fastbootd. بعد الإنشاء ، تم وضع super.img في ${ANDROID_PRODUCT_OUT} .

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

بالنسبة للأجهزة make dist بإنشاء مجموعة من الصور super_*.img التي يمكن وميضها مباشرة إلى الأقسام المادية المقابلة. على سبيل المثال ، make dist builds 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

بمجرد أن تبدأ معالجة الأمر في المرحلة الثانية ، فإن epoll loop init نشطة ، وتبدأ القيم في التحديث. ومع ذلك ، نظرًا لأن مشغلات الخاصية ليست نشطة حتى وقت init ، لا يمكن استخدامها في مراحل التمهيد الأولية للتعامل مع root أو system أو vendor . قد تتوقع أن يكون kernel الافتراضي 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}