הטמעת 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

כדי להפעיל קובצי snapshot דחוסים באמצעות Virtual A/B ב-Android 12, צריך לרשת את ההגדרות הבסיסיות הבאות:

$(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.

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

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

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

HAL לבקרת אתחול

HAL לבקרת אתחול מספק ממשק ללקוחות OTA כדי לשלוט בחריצי האתחול. כדי להשתמש ב-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

דרישות הליבה

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

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

Virtual 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. אפשרות ברירת המחדל שמופעלת עבור ab וירטואלי עם דחיסה היא 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

שעת ההתקנה ללא השלב לאחר ההתקנה שימוש במרחב של COW זמן אתחול 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

שעת ההתקנה ללא השלב לאחר ההתקנה שימוש במרחב של COW זמן אתחול 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 שניות