如要在新裝置上實作虛擬 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 也必須大於或等於 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)
這可在使用無操作壓縮法時,透過虛擬 A/B 版本啟用使用者空間快照。接著,您可以將壓縮方法設為其中一種支援的方法,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
對於繼承自 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.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 中新增的功能: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
。 - 否則,Bootloader 必須傳回
none
。
- 如果狀態為
snapshot-update merge
:完成合併作業,並視需要啟動至復原/快速啟動模式。只有在snapshot-update-status
為merging
時,此指令才有效,且僅支援在 fastbootd 中執行。snapshot-update cancel
:將開機控制 HAL 的合併狀態設為CANCELLED
。裝置鎖定時,這個指令無效。erase
或wipe
:metadata
、userdata
或分區的erase
或wipe
應檢查快照合併狀態,以便保留啟動控制 HAL 的合併狀態。如果狀態為MERGING
或SNAPSHOTTED
,裝置應中止作業。set_active
:變更使用中運算單元的set_active
指令應檢查快照合併狀態。如果狀態為MERGING
,裝置應中止作業。在SNAPSHOTTED
狀態下,您可以安全地變更時段。
這些異動旨在避免裝置意外無法啟動,但可能會影響自動化工具。若將指令做為刷新所有分區的元件 (例如執行 fastboot flashall
) 時,建議使用下列流程:
- 查詢
getvar snapshot-update-status
。 - 如果
merging
或snapshotted
,請核發snapshot-update cancel
。 - 繼續執行閃燈步驟。
降低儲存空間需求
如果裝置未在 super 中分配完整的 A/B 儲存空間,且預計視需要使用 /data
,強烈建議使用區塊對應工具。區塊對應工具可確保各版本的區塊分配一致,減少對快照的非必要寫入作業。詳情請參閱「縮減 OTA 大小」一節。
OTA 壓縮演算法
OTA 套件可針對不同的成效指標進行調整。Android 提供多種支援的壓縮方法 (lz4
、zstd
和 none
),這些方法會在安裝時間、COW 空間使用量、啟動時間和快照合併時間之間取得平衡。透過壓縮功能啟用虛擬 ADB 的預設選項為 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 秒 |