تنفيذ اختبار A/B الافتراضي

لتنفيذ 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 لأنّ الخانات "ب" لم تعُد في ميزة Super. أي، يجب أن تكون قيمة BOARD_SUPER_PARTITION_SIZE أكبر من أو تساوي sum(size of Update groups) + النفقات العامة، والتي يجب أن تكون أكبر. من أو يساوي sum(حجم القسمة) + النفقات العامة.

لتفعيل الملفات المضغوطة على نظام التشغيل Android 13 والإصدارات الأحدث تكتسب اللقطات باستخدام مقياس 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 وzstd وlz4.

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4

على نظام التشغيل Android 12، يمكن تفعيل اللقطات المضغوطة باستخدام يجب أن تكتسب لغة 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 للتحكم في خانات التمهيد. أ/ب افتراضي يتطلب ترقية بسيطة للإصدار من طبقة تجريد الأجهزة (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: Export FS_NOCOW_FL إلى تصحيح النواة (kernel) الخاصة بالمستخدم لإصلاح تثبيت الملف. تضمين f2fs: الدعم المتوافق مثبَّت ملف تصحيح النواة kernel أيضًا.

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

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

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

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

عند الترقية إلى Android 11، يمكن للأجهزة التي تم تشغيلها باستخدام أقسام ديناميكية أن تعديل A/B الافتراضي اختياريًا. تتشابه عملية التحديث غالبًا مع الأجهزة التي يتم إطلاقها بنظام 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 في النصف لأن الخانات "ب" ليست في المستوى الفائق قسم القرص. تحتفظ الأجهزة المعدَّلة بإصدارات A/B الافتراضية لتحتفظ بالقسم الفائق القديم. لذا، فإن BOARD_SUPER_PARTITION_SIZE أكبر من أو يساوي 2 * sum(حجم مجموعات التحديث) + العرض الزائد، الذي يكون بدوره أكبر من أو يساوي 2 * sum(حجم الأقسام) + النفقات العامة.

التغييرات التي طرأت على برنامج الإقلاع

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

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

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

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

  1. تنفيذ بروتوكول HAL للتحكم في التشغيل حتى يتمكن برنامج الإقلاع من قراءة مجموعة القيم في الطريقة setSnapshotMergeStatus().
  2. إذا كانت حالة الدمج هي MERGING أو إذا كانت حالة الدمج SNAPSHOTTED وتم تغيير الخانة إلى الخانة التي تم تحديثها مؤخرًا، ثم يتم طلب حجب البيانات يجب أن يكون userdata أو metadata أو القسم الذي يخزّن حالة الدمج تم رفضه في برنامج الإقلاع.
  3. نفِّذ الأمر fastboot snapshot-update cancel ليتمكّن المستخدمون من برنامج الإقلاع الذي يشير إلى أنّهم يريدون تجاوز آلية الحماية هذه.
  4. عدِّل أدوات الفلاش أو النصوص البرمجية المخصّصة لإصدار fastboot snapshot-update cancel عند تثبيت نسخة من الجهاز بالكامل. هذا آمن لأن المشكلة ويؤدي وميض الجهاز بالكامل إلى إزالة التحديث عبر الهواء. يمكن للأدوات اكتشاف هذا الأمر في وقت التشغيل من خلال تنفيذ 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، يجب أن يعرض برنامج الإقلاع merging.
    • إذا كانت الحالة هي SNAPSHOTTED، يجب أن يعرض برنامج الإقلاع snapshotted.
    • وبخلاف ذلك، يجب أن يعرض برنامج الإقلاع none.
  • snapshot-update merge — لإكمال عملية الدمج، والتشغيل في الاسترداد/Fastbootd إذا لزم الأمر. يكون هذا الأمر صالحًا فقط إذا تبلغ قيمة snapshot-update-status merging، وهي متاحة فقط في Fastbootd.
  • snapshot-update cancel — لضبط حالة دمج HAL لعنصر التحكم في التشغيل على CANCELLED هذا الأمر غير صالح في حال قفل الجهاز.
  • erase أو wipeerase أو wipe من metadata أو userdata أو يجب التحقق من وجود قسم يحتفظ بحالة الدمج لعنصر التحكم في التشغيل HAL. حالة دمج اللقطة. إذا كانت الحالة هي MERGING أو SNAPSHOTTED، سيتم يجب أن يلغي الجهاز العملية.
  • set_active: أمر set_active يغيّر الخانة النشطة التحقق من حالة دمج اللقطة. إذا كانت الحالة هي MERGING، تكون يجب أن يلغي الجهاز العملية. يمكن تغيير الخانة بأمان في ولاية SNAPSHOTTED.

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

  1. طلب البحث getvar snapshot-update-status
  2. إذا كانت merging أو snapshotted، يتم إصدار العدد snapshot-update cancel.
  3. استمِر في تنفيذ الخطوات الوامضة.

تقليل متطلبات مساحة التخزين

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

طرق ضغط الهواء عبر اتصال لاسلكي

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

زيادة التحديث عبر الهواء على هاتف Pixel 6 Pro

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

التحديث عبر الهواء بالكامل على 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 ثانية