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

يتم تنفيذ التقسيم الديناميكي باستخدام وحدة مخطط الجهاز الخطي dm في Linux kernel. يحتوي القسم 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). ليس من الضروري أن تكون الأقسام الخاصة بالمورد ديناميكية ويمكن وضعها في 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 - النفقات العامة
    راجع تنفيذ 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 ، الموجودة في قرص الذاكرة.

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

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

عند تعيين BOARD_USES_RECOVERY_AS_BOOT على true، يتم إنشاء صورة الاسترداد كـ boot.img، والتي تحتوي على قرص الاسترداد الخاص بالاسترداد. في السابق، كان برنامج تحميل التشغيل يستخدم معلمة سطر أوامر kernel skip_initramfs لتحديد الوضع الذي سيتم التمهيد فيه. بالنسبة للأجهزة التي تعمل بنظام التشغيل Android 10، يجب ألا يقوم برنامج تحميل التشغيل بتمرير 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 blobs في بداية التقسيم."

تغييرات سطر أوامر 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 الذي سيكون جزءًا من قرص الذاكرة.

يجب إجراء التغييرات على ملف 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 إلى قرص ذاكرة الوصول العشوائي للمرحلة الأولى.

تغييرات 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 إلى مساحة المستخدم .

إعادة تحميل بنك التنمية الآسيوي

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

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

ترقية أجهزة أندرويد

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

بالنسبة لأجهزة A/B التي يتم تشغيلها بأقسام ديناميكية، يحتوي super.img على صور في الفتحة A. بعد وميض الصورة الفائقة مباشرة، حدد الفتحة 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 الافتراضي للنواة كافيًا حتى تتمكن البرامج النصية 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}