تنفيذ الظاهري أ / ب

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

بناء الأعلام

يجب تكوين الأجهزة التي تستخدم A / B الظاهري كجهاز A / B ويجب تشغيلها باستخدام أقسام ديناميكية .

بالنسبة للأجهزة التي يتم تشغيلها باستخدام A / B الظاهري ، اضبطها على أن ترث التكوين الأساسي الظاهري لجهاز A / B:

$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)

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

لنظام Android 13 والإصدارات الأحدث ، لتمكين اللقطات المضغوطة باستخدام Virtual A / B ، ورث التكوين الأساسي التالي:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/android_t_baseline.mk)

يتيح ذلك للمستخدمين الحصول على لقطات فضاء باستخدام Virtual A / B أثناء استخدام طريقة ضغط no-op. يمكنك بعد ذلك تكوين طريقة الضغط لإحدى الطرق المدعومة ، gz و brotli .

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := gz

بالنسبة لنظام التشغيل Android 12 ، لتمكين اللقطات المضغوطة باستخدام Virtual A / B ، ورث التكوين الأساسي التالي:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/compression.mk)

ضغط XOR

بالنسبة للأجهزة التي تقوم بالترقية إلى Android 13 والإصدارات الأحدث ، لا يتم تمكين ميزة ضغط XOR افتراضيًا. لتمكين ضغط XOR ، أضف ما يلي إلى ملف .mk الخاص بالجهاز.

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled=true

يتم تمكين ضغط XOR افتراضيًا للأجهزة التي ترث من android_t_baseline.mk .

دمج مساحة المستخدمين

بالنسبة للأجهزة التي تقوم بالترقية إلى Android 13 والإصدارات الأحدث ، لا يتم تمكين عملية دمج مساحة المستخدمين كما هو موضح في طبقات مخطط الجهاز افتراضيًا. لتمكين دمج مساحة المستخدمين ، أضف السطر التالي إلى ملف .mk الخاص بالجهاز:

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true

يتم تمكين دمج مساحة المستخدمين افتراضيًا على الأجهزة التي يتم تشغيلها باستخدام 13 أو أعلى.

التحكم في التمهيد HAL

يوفر HAL للتحكم في التمهيد واجهة لعملاء OTA للتحكم في فتحات التمهيد. يتطلب Virtual A / B ترقية إصدار ثانوي من HAL للتحكم في التمهيد لأن هناك حاجة إلى واجهات برمجة تطبيقات إضافية لضمان حماية أداة تحميل التشغيل أثناء الوميض / إعادة ضبط المصنع. راجع IBootControl.hal و types.hal للحصول على أحدث إصدار من تعريف HAL.

// hardware/interfaces/boot/1.1/types.hal
enum MergeStatus : uint8_t {
    NONE, UNKNOWN, SNAPSHOTTED, MERGING, CANCELLED };

// hardware/interfaces/boot/1.1/IBootControl.hal
package android.hardware.boot@1.1;
interface IBootControl extends @1.0::IBootControl {
    setSnapshotMergeStatus(MergeStatus status)
        generates (bool success);
    getSnapshotMergeStatus()
        generates (MergeStatus status);
}
// Recommended implementation

Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus v) {
    // Write value to persistent storage
    // e.g. misc partition (using libbootloader_message)
    // bootloader rejects wipe when status is SNAPSHOTTED
    // or MERGING
}

التغييرات Fstab

تعد سلامة قسم البيانات الوصفية أمرًا ضروريًا لعملية التمهيد ، خاصة بعد تطبيق تحديث OTA مباشرة. لذلك ، يجب التحقق من قسم البيانات الوصفية قبل أن يقوم first_stage_init بتثبيته. للتأكد من حدوث ذلك ، أضف علامة check fs_mgr إلى إدخال /metadata . يقدم المثال التالي:

/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount,check

متطلبات Kernel

لتمكين الالتقاط ، اضبط CONFIG_DM_SNAPSHOT على true .

بالنسبة للأجهزة التي تستخدم F2FS ، قم بتضمين f2fs: تصدير علامة FS_NOCOW_FL إلى تصحيح kernel للمستخدم لإصلاح تثبيت الملف. تضمين f2fs: دعم تصحيح نواة الملف المثبت المحاذاة أيضًا.

يعتمد Virtual A / B على الميزات المضافة في الإصدار 4.3 من kernel: بت حالة الفائض في snapshot وأهداف snapshot-merge . يجب أن تحتوي جميع الأجهزة التي تعمل بنظام Android 9 والإصدارات الأحدث على إصدار kernel 4.4 أو إصدار أحدث.

لتمكين اللقطات المضغوطة ، يكون الحد الأدنى لإصدار kernel المدعوم هو 4.19. اضبط CONFIG_DM_USER=m أو CONFIG_DM_USER=y . في حالة استخدام السابق (وحدة نمطية) ، يجب تحميل الوحدة في المرحلة الأولى ramdisk. يمكن تحقيق ذلك عن طريق إضافة السطر التالي إلى جهاز Makefile:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

التعديل التحديثي على الأجهزة التي تتم ترقيتها إلى Android 11

عند الترقية إلى Android 11 ، يمكن للأجهزة التي تم إطلاقها باستخدام أقسام ديناميكية تعديل أ / ب الظاهري اختياريًا. تتشابه عملية التحديث في الغالب مع الأجهزة التي يتم تشغيلها باستخدام A / B الظاهري ، مع بعض الاختلافات الطفيفة:

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

  • علامات ميزات وقت الإنشاء - بالنسبة للأجهزة التي تقوم بتعديل A / B الظاهري ، يتم تعيين كل من PRODUCT_VIRTUAL_AB_OTA و PRODUCT_VIRTUAL_AB_OTA_RETROFIT على true ، كما هو موضح أدناه:

    (call inherit-product, \
        (SRC_TARGET_DIR)/product/virtual_ab_ota_retrofit.mk)
    
  • حجم القسم الفائق - يمكن للأجهزة التي يتم تشغيلها باستخدام A / B الظاهري أن تقطع BOARD_SUPER_PARTITION_SIZE إلى النصف لأن فتحات B ليست في القسم الفائق. تحافظ الأجهزة التي تقوم بتعديل A / B الظاهري على حجم القسم الفائق القديم ، لذا فإن BOARD_SUPER_PARTITION_SIZE أكبر من أو يساوي 2 * مجموع (حجم مجموعات التحديث) + النفقات العامة ، والتي بدورها أكبر من أو تساوي 2 * مجموع (حجم الأقسام) + النفقات العامة .

تغييرات Bootloader

أثناء خطوة الدمج لأحد التحديثات ، تحتفظ /data بالمثيل الكامل الوحيد لنظام التشغيل Android. بمجرد بدء الترحيل ، لا يكتمل system الأصلي vendor وأقسام product حتى تنتهي النسخة. إذا تمت إعادة ضبط الجهاز إلى إعدادات المصنع أثناء هذه العملية ، إما عن طريق الاسترداد أو من خلال مربع حوار إعدادات الأنظمة ، فسيكون الجهاز غير قابل للتمهيد.

قبل المسح /data ، قم بإنهاء الدمج في الاسترداد أو التراجع حسب حالة الجهاز:

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

يمكن لكل من أداة تحميل التشغيل و fastbootd مسح قسم /data إذا تم إلغاء قفل الجهاز. بينما يمكن أن يفرض fastbootd اكتمال الترحيل ، لا يستطيع برنامج bootloader ذلك. لا يعرف محمل الإقلاع ما إذا كان الدمج قيد التقدم أم لا ، أو ما هي الكتل الموجودة في /data التي تشكل أقسام نظام التشغيل. يجب أن تمنع الأجهزة المستخدم من جعل الجهاز غير قابل للتشغيل (طوب) دون علمه عن طريق القيام بما يلي:

  1. قم بتطبيق عنصر تحكم التمهيد HAL حتى يتمكن برنامج bootloader من قراءة القيمة التي تم تعيينها بواسطة أسلوب setSnapshotMergeStatus() .
  2. إذا كانت حالة الدمج MERGING ، أو إذا كانت حالة الدمج SNAPSHOTTED وتغيرت الفتحة إلى الفتحة المحدثة حديثًا ، فيجب رفض طلبات مسح userdata أو metadata أو القسم الذي يخزن حالة الدمج في أداة تحميل التشغيل.
  3. قم بتنفيذ الأمر fastboot snapshot-update cancel حتى يتمكن المستخدمون من إرسال إشارة إلى أداة تحميل التشغيل التي يريدون تجاوز آلية الحماية هذه.
  4. قم بتعديل أدوات الوميض المخصصة أو البرامج النصية لإصدار fastboot snapshot-update cancel عند وميض الجهاز بأكمله. هذا أمر آمن للإصدار لأن وميض الجهاز بأكمله يزيل OTA. يمكن للأدوات اكتشاف هذا الأمر في وقت التشغيل عن طريق تنفيذ fastboot getvar snapshot-update-status . يساعد هذا الأمر في التفريق بين حالات الخطأ.

مثال

struct VirtualAbState {
    uint8_t StructVersion;
    uint8_t MergeStatus;
    uint8_t SourceSlot;
};

bool ShouldPreventUserdataWipe() {
    VirtualAbState state;
    if (!ReadVirtualAbState(&state)) ...
    return state.MergeStatus == MergeStatus::MERGING ||
           (state.MergeStatus == MergeStatus::SNAPSHOTTED &&
            state.SourceSlot != CurrentSlot()));
}

تغييرات أدوات Fastboot

يقوم Android 11 بإجراء التغييرات التالية على بروتوكول Fastboot:

  • getvar snapshot-update-status - تُرجع القيمة التي أرسلها عنصر التحكم في التمهيد HAL إلى أداة تحميل التشغيل:
    • إذا كانت الحالة MERGING ، يجب أن يقوم برنامج bootloader بإرجاع merging .
    • إذا كانت الحالة SNAPSHOTTED ، يجب أن يقوم برنامج bootloader بإرجاع snapshotted .
    • خلاف ذلك ، يجب أن يقوم برنامج bootloader بإرجاع none .
  • snapshot-update merge - يكمل عملية الدمج ، التمهيد إلى الاسترداد / fastbootd إذا لزم الأمر. هذا الأمر صالح فقط إذا تم merging snapshot-update-status ، وهو مدعوم فقط في fastbootd.
  • snapshot-update cancel - يعيّن حالة دمج HAL للتحكم في التمهيد على CANCELLED . هذا الأمر غير صالح عند قفل الجهاز.
  • erase أو wipe - يجب أن يتحقق erase أو wipe metadata أو userdata أو القسم الذي يحمل حالة الدمج لعنصر التحكم في التمهيد من حالة دمج اللقطة. إذا كانت الحالة MERGING أو SNAPSHOTTED ، فيجب على الجهاز إجهاض العملية.
  • set_active - يجب أن يتحقق الأمر set_active الذي يغير الفتحة النشطة من حالة دمج اللقطة. إذا كانت الحالة MERGING ، فيجب على الجهاز إجهاض العملية. يمكن تغيير الفتحة بأمان في حالة SNAPSHOTTED .

تم تصميم هذه التغييرات لمنع جعل الجهاز غير قابل للتمهيد عن طريق الخطأ ، ولكنها قد تؤدي إلى تعطيل الأدوات الآلية. عندما يتم استخدام الأوامر كمكون لوميض جميع الأقسام ، مثل تشغيل fastboot flashall ، يوصى باستخدام التدفق التالي:

  1. استعلام عن getvar snapshot-update-status .
  2. في حالة merging أو snapshotted ، يتم snapshot-update cancel .
  3. تابع الخطوات الوامضة.

تقليل متطلبات التخزين

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

طرق ضغط OTA

يمكن ضبط حزم أوتا لمقاييس الأداء المختلفة. يوفر Android حاليًا بعض طرق الضغط المدعومة ( gz و lz4 none ) التي لها مفاضلات بين وقت التثبيت واستخدام مساحة البقرة ووقت التمهيد ووقت دمج اللقطة. الخيار الافتراضي الذي تم تمكينه لـ Virtual ab مع الضغط هو gz compression method . (ملاحظة: يختلف الأداء النسبي بين طرق الضغط اعتمادًا على سرعة وحدة المعالجة المركزية وسعة التخزين التي يمكن أن تتغير اعتمادًا على الجهاز. جميع حزم OTA التي تم إنشاؤها أدناه معطل PostInstall ، مما يؤدي إلى إبطاء وقت التمهيد بشكل طفيف. إجمالي حجم القسم الديناميكي للحجم الكامل بدون ضغط 4.81 جيجابايت )

1. OTA تزايدي على Pixel 6 Pro

وقت التثبيت بدون مرحلة ما بعد التثبيت استخدام مساحة الأبقار بعد وقت التمهيد عبر الهواء وقت دمج اللقطة
gz 24 دقيقة 1.18 جيجا بايت 40.2 ثانية 45.5 ثانية
lz4 13 دقيقة 1.49 غيغابايت 37.4 ثانية 37.1 ثانية
لا أحد 13 دقيقة 2.90 جيجا بايت 37.6 ثانية 40.7 ثانية

2. OTA الكامل على Pixel 6 Pro

وقت التثبيت بدون مرحلة ما بعد التثبيت استخدام مساحة الأبقار بعد وقت التمهيد عبر الهواء وقت دمج اللقطة
gz 23 دقيقة 2.79 غيغابايت 24.9 ثانية 41.7 ثانية
lz4 12 دقيقة 3.46 جيجا بايت 20.0 ثانية 25.3 ثانية
لا أحد 10 دقائق 4.85 غيغابايت 20.6 ثانية 29.8 ثانية