實作虛擬 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 所需的主機板大小只有一半,因為 B 槽已不再位於超級主機板中。也就是說,BOARD_SUPER_PARTITION_SIZE 必須大於或等於 sum(size of update groups) + overhead,而 sum(size of partitions) + overhead 也必須大於或等於 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/vabc_features.mk)

這可在使用無操作壓縮法時,透過虛擬 A/B 版本啟用使用者空間快照。接著,您可以將壓縮方法設為 zstdlz4 等支援的方法之一。針對 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

對於繼承自 android_t_baseline.mk 的裝置,系統預設會啟用 XOR 壓縮功能。

使用者空間合併

在最新版本的虛擬 A/B 中 (Android T 以上版本),快照合併程序會完全在使用者空間中執行。這項變更是由 snapuserd 和 dm-user 所實現。搭載 Android 13 以上版本的裝置預設會啟用使用者空間合併功能,而針對舊版裝置升級,則可透過以下方式設定此屬性:

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

啟動控制 HAL

boot control HAL 提供介面,讓 OTA 用戶端控制啟動槽。虛擬 A/B 需要升級 boot control HAL 的次要版本,因為需要額外的 API 來確保系統啟動載入程式在閃燈或恢復原廠設定期間受到保護。如需 HAL 定義的最新版本,請參閱 IBootControl.haltypes.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 才能掛載該分割區。為確保這項操作,請在 /metadata 的項目中新增 check fs_mgr 標記。以下提供範例:

/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 核心修補程式。

Virtual A/B 會依賴核心 4.3 版新增的功能:snapshotsnapshot-merge 目標中的溢位狀態位元。所有搭載 Android 9 以上版本的裝置,都應已搭載 4.4 以上版本的核心。

如要啟用壓縮快照,最低支援的核心版本為 4.19。請設定 CONFIG_DM_USER=mCONFIG_DM_USER=y。如果使用前者 (模組),則必須在第一階段的 RAM 磁碟中載入模組。如要達成這一目標,請在裝置 Makefile 中加入下列程式行:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Fastboot 工具變更

Android 11 對 Fastboot 通訊協定進行下列變更:

  • getvar snapshot-update-status:傳回啟動控制 HAL 傳送至啟動載入程式的值:
    • 如果狀態為 MERGING,則啟動載入程式必須傳回 merging
    • 如果狀態為 SNAPSHOTTED,則啟動載入程式必須傳回 snapshotted
    • 否則,Bootloader 必須傳回 none
  • snapshot-update merge:完成合併作業,並視需要啟動至復原/快速啟動模式。這個指令僅在 snapshot-update-statusmerging 時有效,且僅支援在 fastbootd 中執行。
  • snapshot-update cancel:將啟動控制 HAL 的合併狀態設為 CANCELLED。裝置鎖定時,這個指令無效。
  • erasewipemetadatauserdata 或分區的 erasewipe,應檢查快照合併狀態。如果狀態為 MERGINGSNAPSHOTTED,裝置應中止作業。
  • set_active:變更有效時段的 set_active 指令應檢查快照合併狀態。如果狀態為 MERGING,裝置應中止作業。您可以在 SNAPSHOTTED 狀態下安全地變更時段。

這些異動旨在避免裝置意外無法啟動,但可能會影響自動化工具。如果指令用於刷新所有分區的元件 (例如執行 fastboot flashall),建議您使用下列流程:

  1. 查詢 getvar snapshot-update-status
  2. 如果是 mergingsnapshotted,請發出 snapshot-update cancel
  3. 繼續執行閃爍步驟。

降低儲存空間需求

如果裝置未在 super 中分配完整的 A/B 儲存空間,且預計視需要使用 /data,強烈建議使用區塊對應工具。區塊對應工具可確保各版本的區塊分配一致,減少對快照的非必要寫入作業。詳情請參閱「減少 OTA 大小」一節。

OTA 壓縮演算法

OTA 套件可針對不同的成效指標進行調整。Android 提供多種支援的壓縮方法 (lz4zstdnone),這些方法會在安裝時間、COW 空間使用量、啟動時間和快照合併時間之間取得平衡。對於採用壓縮功能的虛擬 AB 測試,預設會啟用 lz4 compression method 選項。

微調壓縮

您可以透過兩種方法進一步自訂壓縮演算法:(壓縮等級) (犧牲速度以達到壓縮程度) 和 (壓縮係數) (可壓縮的最大視窗大小)。壓縮等級可用於 zstd 等特定演算法,變更等級會在速度和壓縮率之間產生取捨。壓縮係數會說明 OTA 安裝期間使用的最大壓縮視窗大小。預設值為 64k,但您可以自訂建構參數 PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR 來覆寫。支援的壓縮係數為 4k、8k、16k、32k、64k、128k 和 256k。

PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Pixel 8 Pro 的漸進式 OTA

不含安裝後階段的安裝時間 COW 空間用量 發布 OTA 啟動時間 快照合併時間
lz4 18 分 15 秒 2.5 GB 32.7 秒 98.6 秒
zstd 24 分 49 秒 2.05 GB 36.3 秒 133.2 秒
16 分 42 秒 4.76 GB 28.7 秒 76.6 秒

Pixel 8 Pro 上的完整 OTA

不含安裝後階段的安裝時間 COW 空間用量 發布 OTA 啟動時間 快照合併時間
lz4 15 分 11 秒 4.16 GB 17.6 秒 82.2 秒
zstd 16 分 19 秒 3.46 GB 21.0 秒 106.3 秒
13 分 33 秒 6.39 GB 18.5 秒 92.5 秒