如要在新裝置上實作虛擬 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(更新群組的大小) + 負擔,因此必須大於
等於或等於 sum(分區大小) + 負擔。
在 Android 13 以上版本中,啟用壓縮功能 虛擬 A/B 的快照,會繼承下列基本設定:
$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
$(SRC_TARGET_DIR)/product/virtual_ab_ota/android_t_baseline.mk)
這樣在使用免人工管理時,可透過虛擬 A/B 啟用使用者空間快照
。接著,您可以將壓縮方法設為
支援的方法:gz
、zstd
和 lz4
。
PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4
在 Android 12 上,如要透過 虛擬 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
。
使用者空間合併
如果是升級至 Android 13 以上版本的裝置,
使用者空間合併程序,詳情請見「裝置對應程式」一節
分層並未啟用
預設值。如要啟用使用者空間合併功能,請在裝置的 .mk
中新增以下這一行
檔案:
PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true
根據預設, 13 以及更高版本。
啟動控制項 HAL
啟動控制項 HAL 可讓 OTA 用戶端控制啟動運算單元。虛擬 A/B 版本 需要升級啟動控制項 HAL 的子版本,因為其他 API 以確保系統啟動載入程式在刷新或恢復原廠設定時受到保護。詳情請見 IBootControl.hal 和 types.hal 取得最新版本的 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 標記至 使用者核心修補程式即可修正檔案固定問題。 包含 f2fs:支援對齊固定板 檔案核心修補程式。
虛擬 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
升級至 Android 11 的裝置可享受 Retrofit
升級至 Android 11 時,搭載動態分區啟動的裝置可以 可視需要翻新虛擬 A/B更新程序與 以虛擬 A/B 版本啟動的裝置,但有些微差異:
COW 檔案的位置 — 對於推出的裝置,OTA 用戶端會使用 必須先讓超級分區中的所有可用空間
/data
。對懷舊裝置來說,超級系列中有足夠的空間 ,確保 COW 檔案不會在/data
中建立。建構時間功能旗標 - 針對翻新的虛擬 A/B 裝置,
PRODUCT_VIRTUAL_AB_OTA
和PRODUCT_VIRTUAL_AB_OTA_RETROFIT
皆已設定 至true
,如下所示:(call inherit-product, \
(SRC_TARGET_DIR)/product/virtual_ab_ota_retrofit.mk)
超級分區大小 - 搭載虛擬 A/B 的裝置可剪下 一半是
BOARD_SUPER_PARTITION_SIZE
,因為 B 版位不在超級 翻新虛擬 A/B 版本的裝置,會保留舊的超級分區 所以BOARD_SUPER_PARTITION_SIZE
大於或等於 2 * 總和(更新群組的大小) + 負荷,而該數字會大於或等於 2 * 總和(分區大小) +
系統啟動載入程式變更
在更新合併步驟中,/data
會保留整個更新
Android 作業系統。遷移作業開始後,system
、vendor
和
在複製完成前,product
個分區不完整。如果裝置
過程中透過系統還原或重新恢復原廠設定。
設定對話方塊,表示裝置無法啟動。
清除 /data
前,請先完成復原或復原的合併作業,實際情況視下列項目而定
裝置狀態:
- 如果之前成功啟動新版本,請完成遷移程序。
- 否則,請復原至舊運算單元:
- 如果是動態分區,請復原為先前的狀態。
- 如為靜態分區,請將使用中的運算單元設為舊的運算單元。
如果系統啟動載入程式和 fastbootd
,兩者都能清除 /data
分區,
裝置處於解鎖狀態。fastbootd
可以強製完成遷移作業,
系統啟動載入程式無法使用。系統啟動載入程式不知道合併是否處於合併狀態
或 /data
中的哪些區塊會構成 OS 分區。裝置必須
可以防止使用者不知情,在不知情的情況下使裝置無法運作
請按照下列步驟操作:
- 實作啟動控制項 HAL,方便系統啟動載入程式讀取設定的值
setSnapshotMergeStatus()
方法。 - 合併狀態為
MERGING
,或合併狀態為「SNAPSHOTTED
」 版位變更為新更新的運算單元,然後要求抹除資料userdata
、metadata
,或是儲存合併狀態的分區 系統在系統啟動載入程式中拒絕。 - 實作
fastboot snapshot-update cancel
指令,方便使用者 向系統啟動載入程式發出訊號,表明要略過這項保護機制。 - 修改自訂刷新工具或指令碼,在刷新整部裝置時發出
fastboot snapshot-update cancel
。這很安全,因為 刷新裝置會移除 OTA。工具可以偵測這個指令 導入fastboot getvar snapshot-update-status
程式碼這個 指令有助於區分錯誤狀況
示例
struct VirtualAbState {
uint8_t StructVersion;
uint8_t MergeStatus;
uint8_t SourceSlot;
};
bool ShouldPreventUserdataWipe() {
VirtualAbState state;
if (!ReadVirtualAbState(&state)) ...
return state.MergeStatus == MergeStatus::MERGING ||
(state.MergeStatus == MergeStatus::SNAPSHOTTED &&
state.SourceSlot != CurrentSlot()));
}
Fastboot 工具異動
Android 11 會對 Fastboot 進行下列變更 通訊協定:
getvar snapshot-update-status
:傳回啟動程序的值 與系統啟動載入程式通訊的 HAL:- 如果狀態為
MERGING
,則系統啟動載入程式必須傳回merging
。 - 如果狀態為
SNAPSHOTTED
,則系統啟動載入程式必須傳回snapshotted
。 - 否則,系統啟動載入程式必須傳回
none
。
- 如果狀態為
snapshot-update merge
- 完成合併作業,啟動以下作業: 必要時復原和快速啟動只有在下列情況中,這個指令才有效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
)
建議使用以下流程:
- 查詢「
getvar snapshot-update-status
」。 - 如果
merging
或snapshotted
,請核發snapshot-update cancel
。 - 繼續執行刷新步驟。
降低儲存空間需求
並未分配完整 A/B 儲存空間,且在預期
以便視需要使用 /data
,我們強烈建議使用區塊對應
如果偏好在終端機視窗中工作
可使用 Google Cloud CLI gcloud 指令列工具區塊對應工具可讓不同版本之間的區塊配置保持一致,
並減少不必要的寫入快照量這部分已記錄在減少
OTA 大小。
OTA 壓縮方法
OTA 套件可依不同的成效指標進行調整。Android 提供
幾種支援的壓縮方法 (gz
、lz4
、zstd
和 none
),
在安裝時間、COW 空間用量、開機時間和快照之間取得平衡
合併時間。要用於壓縮的虛擬 ADB,預設選項是
gz compression method
。(注意:壓縮方法之間的相對效能)
會因 CPU 速度和儲存空間處理量而異
應用程式。下方產生的所有 OTA 套件都會停用 PostInstall,
也會稍微降低啟動時間陣列的動態分區總大小
未壓縮的完整 ota 即為 4.81 GB)。
Pixel 6 Pro 上的 OTA 增量
安裝後階段的安裝時間 | COW 空間用量 | OTA 啟動時間 | 快照合併時間 | |
---|---|---|---|---|
gz | 24 分鐘 | 1.18 GB | 40.2 秒 | 45.5 秒 |
lz4 | 13 分鐘 | 1.49 GB | 37.4 秒 | 37.1 秒 |
無 | 13 分鐘 | 2.90 GB | 37.6 秒 | 40.7 秒 |
Pixel 6 Pro 的完整 OTA
安裝後階段的安裝時間 | COW 空間用量 | OTA 啟動時間 | 快照合併時間 | |
---|---|---|---|---|
gz | 23 分鐘 | 2.79 GB | 24.9 秒 | 41.7 秒 |
lz4 | 12 min | 3.46 GB | 20.0 秒 | 25.3 秒 |
無 | 10 分鐘 | 4.85 GB | 20.6 秒 | 29.8 秒 |