הטמעת ניסוי A/B וירטואלי

כדי להטמיע בדיקות A/B וירטואליות במכשיר חדש או במכשיר שכבר הושק, צריך לבצע שינויים בקוד שספציפי למכשיר.

התראות על שינויים ב-Build

מכשירים שמשתמשים ב-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 כבר לא נמצאות ב-super. כלומר, הערך של BOARD_SUPER_PARTITION_SIZE חייב להיות גדול מהערך של sum(size of update groups) + overhead או שווה לו, והערך של sum(size of update groups) + overhead חייב להיות גדול מהערך של sum(size of partitions) + overhead או שווה לו.

ב-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/vabc_features.mk)

התכונה הזו מאפשרת ליצור תמונות מצב של מרחב המשתמשים באמצעות Virtual A/B, תוך שימוש בשיטת דחיסה מסוג no-op. לאחר מכן תוכלו להגדיר את שיטת הדחיסה לאחת מהשיטות הנתמכות,zstd וlz4. ב-Android 15, אפשר להתאים אישית את הדחיסה עוד יותר כדי שתתאים לצרכים של המכשיר. מידע נוסף זמין במאמר בנושא התאמה עדינה של דחיסה.

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4
PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

ב-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.

מיזוג של מרחבי משתמשים

בגרסה המודרנית של Virtual A/B (Android T ואילך), תהליך המיזוג של תמונת המצב מתרחש כולו במרחב המשתמש. השינוי הזה מתאפשר בזכות snapuserd ו-dm-user. במכשירים שהושקו עם Android מגרסה 13 ואילך, מיזוג מרחב המשתמשים מופעל כברירת מחדל. במכשירים ישנים יותר שמשדרגים, אפשר להגדיר את המאפיין הזה באמצעות הפקודה הבאה:

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

שכבת הפשטת חומרה (HAL) של בקרת הפעלה

שכבת ההפשטה של החומרה (HAL) של בקרת האתחול מספקת ממשק ללקוחות OTA כדי לשלוט במשבצות האתחול. כדי להשתמש ב-Virtual A/B, צריך לשדרג את גרסת המשנה של HAL של בקר האתחול, כי נדרשים ממשקי API נוספים כדי לוודא שמטען האתחול מוגן במהלך ההפעלה או האיפוס להגדרות המקוריות. הגרסה העדכנית של הגדרת ה-HAL זמינה בקבצים IBootControl.hal ו-types.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

דרישות ליבה

כדי להפעיל את צילום תמונות המצב, מגדירים את CONFIG_DM_SNAPSHOT לערך true.

במכשירים שמשתמשים ב-F2FS, צריך לכלול את תיקון הליבה f2fs: export FS_NOCOW_FL flag to user כדי לתקן את הצמדת הקבצים. צריך לכלול גם את תיקון הליבה f2fs: support aligned pinned file.

התכונה 'בדיקת A/B וירטואלית' מסתמכת על תכונות שנוספו בגרסת ליבת 4.3: ביט הסטטוס overflow ביעדים snapshot ו-snapshot-merge. בכל המכשירים שמופעלת בהם Android מגרסה 9 ואילך, כבר אמורה להיות גרסת ליבה 4.4 ואילך.

כדי להפעיל צילומי מסך דחוסים, הגרסה המינימלית של ליבת המערכת שנתמכת היא 4.19. מגדירים את CONFIG_DM_USER=m או CONFIG_DM_USER=y. אם משתמשים באפשרות הראשונה (מודול), צריך לטעון את המודול ב-ramdisk של השלב הראשון. כדי לעשות את זה, צריך להוסיף את השורה הבאה לקובץ ה-Makefile של המכשיר:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

שינויים בכלי 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 או wipe – אם יש erase או 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 ב-super, וצפויים להשתמש ב-/data לפי הצורך. כלי מיפוי הבלוקים שומר על הקצאת הבלוקים באופן עקבי בין גרסאות build, ומפחית כתיבות מיותרות לתמונת המצב. ההסבר מופיע במאמר בנושא הקטנת הגודל של עדכוני OTA.

אלגוריתמים לדחיסת נתונים ב-OTA

אפשר לשנות את החבילות של OTA כדי לשפר מדדי ביצועים שונים. ‫Android מספקת כמה שיטות דחיסה נתמכות (lz4,‏ zstd ו-none) שבהן יש פשרות בין זמן ההתקנה, השימוש במרחב COW, זמן האתחול וזמן המיזוג של התמונה. אפשרות ברירת המחדל שמופעלת עבור מחיצה וירטואלית עם דחיסה היא lz4 compression method.

כוונון עדין של הדחיסה

אפשר להתאים אישית אלגוריתמים של דחיסה בשתי דרכים: (רמת הדחיסה) (כמות הדחיסה שמושגת על חשבון המהירות) ו (גורם הדחיסה) (גודל החלון המקסימלי שניתן לדחיסה). רמת הדחיסה זמינה לאלגוריתמים מסוימים כמו zstd, ושינוי הרמה כרוך בפשרה בין מהירות לבין יחס הדחיסה. גורם הדחיסה מתאר את הגודל המקסימלי של חלון הדחיסה שנעשה בו שימוש במהלך התקנת OTA. ברירת המחדל היא 64k, אבל אפשר לשנות אותה על ידי התאמה אישית של פרמטר ה-build‏ PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR. גורמי דחיסה נתמכים: 4k, ‏ 8k, ‏ 16k, ‏ 32k, ‏ 64k, ‏ 128k ו-256k.

PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

עדכון OTA מצטבר ב-Pixel 8 Pro

Install time w/o postinstall phase ניצול שטח האחסון ב-COW זמן האתחול אחרי עדכון OTA זמן המיזוג של תמונת המצב
lz4 ‫18 דקות ו-15 שניות ‫2.5GB ‫32.7 שניות ‫98.6 שניות
zstd ‫24 דקות ו-49 שניות ‫2.05GB ‫36.3 שניות ‫133.2 שניות
none ‫16 דקות ו-42 שניות ‫4.76GB ‫28.7 שניות ‫76.6 שניות

עדכון OTA מלא ב-Pixel 8 Pro

Install time w/o postinstall phase ניצול שטח האחסון ב-COW זמן האתחול אחרי עדכון OTA זמן המיזוג של תמונת המצב
lz4 ‫15 דקות ו-11 שניות ‫4.16GB ‫17.6 שניות ‫82.2 שניות
zstd ‫16 דקות ו-19 שניות ‫3.46GB ‫21.0 שניות ‫106.3 שניות
none ‫13 דקות ו-33 שניות ‫6.39GB ‫18.5 שניות ‫92.5 שניות