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

ב-Android מגרסה 13 ואילך, כדי להפעיל קובצי snapshot דחוסים עם בדיקת 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)

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

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4
PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

ב-Android 12, כדי להפעיל קובצי snapshot דחוסים עם בדיקת 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 ואילך), תהליך המיזוג של קובץ ה-snapshot מתרחש כולו במרחב המשתמש. השינוי הזה מתאפשר באמצעות snapuserd ו-dm-user. במכשירים שפועלים עם Android מגרסה 13 ואילך, המיזוג של מרחב המשתמש מופעל כברירת מחדל. במכשירים ישנים יותר ששודרגו, אפשר להגדיר את המאפיין הזה באמצעות הקוד הבא:

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

HAL לבקרת אתחול

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

דרישות הליבה

כדי להפעיל את יצירת קובצי ה-snapshot, מגדירים את 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 ואילך.

כדי להפעיל קובצי snapshot דחוסים, הגרסה המינימלית של הליבה שנתמכת היא 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 — השלמת פעולת מיזוג, הפעלה ל-recovery/fastbootd אם יש צורך. הפקודה הזו תקפה רק אם הערך של snapshot-update-status הוא merging, והיא נתמכת רק ב-fastbootd.
  • snapshot-update cancel — מגדיר את סטטוס המיזוג של HAL לבקרת האתחול לערך CANCELLED. הפקודה הזו לא תקפה כשהמכשיר נעול.
  • erase או wipeerase או wipe של metadata,‏ userdata או מחיצה שמכילה את סטטוס המיזוג של HAL לבקרת האתחול צריכים לבדוק את סטטוס המיזוג של קובץ ה-snapshot. אם הסטטוס הוא MERGING או SNAPSHOTTED, המכשיר אמור לבטל את הפעולה.
  • set_active – פקודה set_active שמשנה את החריץ הפעיל צריכה לבדוק את סטטוס המיזוג של קובץ ה-snapshot. אם הסטטוס הוא MERGING, המכשיר צריך לבטל את הפעולה. אפשר לשנות את החריץ בבטחה במצב SNAPSHOTTED.

השינויים האלה נועדו למנוע הפעלה בטעות של מכשיר שלא ניתן להפעיל אותו, אבל הם עלולים להפריע לכלים אוטומטיים. כשמשתמשים בפקודות כחלק מהאיכולת להפעיל את כל המחיצות, כמו הפעלת fastboot flashall, מומלץ להשתמש בתהליך הבא:

  1. שאילתת getvar snapshot-update-status.
  2. אם הערך הוא merging או snapshotted, פותחים את הבעיה snapshot-update cancel.
  3. ממשיכים בשלבים של העדכון.

הפחתת דרישות האחסון

במכשירים שלא הוקצה להם נפח אחסון A/B מלא ב-super, ומצופה שייעשה בהם שימוש ב-/data לפי הצורך, מומלץ מאוד להשתמש בכלי למיפוי בלוקים. כלי מיפוי הבלוק שומר על עקביות בהקצאת בלוקים בין גרסאות build, ומפחית את כמות הכתיבה המיותרת ב-snapshot. המידע הזה מופיע בקטע צמצום הגודל של OTA.

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

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

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

אפשר להתאים אישית את אלגוריתמי הדחיסה בשתי שיטות: (רמת דחיסה) (כמות הדחיסה שהושגה על חשבון המהירות) ו-(גורם דחיסה) (גודל החלון המקסימלי שניתן לדחוס). רמת הדחיסה זמינה לאלגוריתמים מסוימים, כמו 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

זמן ההתקנה ללא שלב ההתקנה לאחר ההתקנה שימוש במרחב של מכונה משותפת ליצירת קובצי אימג' זמן האתחול לאחר OTA זמן המיזוג של קובץ ה-snapshot
lz4 18 דקות ו-15 שניות 2.5 GB 32.7 שניות 98.6 שניות
zstd 24 דקות 49 שניות 2.05 GB 36.3 שניות 133.2 שניות
none 16 דקות 42 שניות 4.76 GB 28.7 שניות 76.6 שניות

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

זמן ההתקנה ללא שלב ההתקנה לאחר ההתקנה שימוש במרחב של מכונה משותפת ליצירת קובצי אימג' זמן האתחול לאחר OTA זמן המיזוג של קובץ ה-snapshot
lz4 15 דק' 11 שניות 4.16 GB 17.6 שניות 82.2 שניות
zstd 16 דקות 19 שניות 3.46 GB 21.0 שניות 106.3 שניות
none 13 דקות 33 שניות 6.39 GB 18.5 שניות 92.5 שניות