虛擬 A/B 是 Android 的主要更新機制。虛擬 A/B 版本以舊版 A/B 更新 (請參閱 A/B 系統更新) 和非 A/B 版本為基礎,這些更新已於 15 年淘汰,以減少更新的空間負擔。
虛擬 A/B 實際上沒有額外的動態分區插槽,請參閱「動態分區」。而是將差異寫入快照,並在確認成功啟動後合併至基本分區。虛擬 A/B 會使用 Android 專屬的快照格式。請參閱壓縮快照的 COW 格式,可壓縮快照並盡量減少磁碟空間使用量。在完全 OTA 上,快照大小會壓縮約 45%,而增量 OTA 快照大小則減少約 55%。
Android 12 提供虛擬 A/B 壓縮選項,用於壓縮快照分割區。虛擬 A/B 測試提供下列功能:
- 虛擬 A/B 更新與 A/B 更新一樣無縫 (更新會在裝置運作時完全在背景進行)。虛擬 A/B 更新可縮短裝置離線和無法使用的時間。
- 虛擬 A/B 更新可以回溯。如果新作業系統無法啟動,裝置會自動回復至先前的版本。
- 虛擬 A/B 更新只會複製系統啟動載入程式使用的分區,因此只會使用最少的額外空間。其他可更新的分區則會快照。
背景與術語
本節將定義相關術語,並說明支援虛擬 A/B 測試的技術。在 OTA 安裝期間,系統會將新的作業系統資料寫入實體分區的新運算單元,或 Android 專屬的 COW 裝置。裝置重新啟動後,動態分區資料會透過 dm-user 和 snapuserd 守護程序,重新合併至基礎裝置。這個程序完全在使用者空間中進行。
裝置對應器
裝置對應程式是在 Android 中經常使用的 Linux 虛擬區塊層。就動態分區而言,/system
等分區是分層裝置的堆疊:
- 堆疊底部是實體超級分區 (例如
/dev/block/by-name/super
)。 - 中間是
dm-linear
裝置,可指定超級分區中的哪些區塊會形成指定的動態分區。這會在 A/B 裝置上顯示為/dev/block/mapper/system_[a|b]
,在非 A/B 裝置上則顯示為/dev/block/mapper/system
。 - 頂端是
dm-verity
裝置,這是為已驗證的分區建立的裝置。這個裝置會驗證dm-linear
裝置上的區塊是否已正確簽署。這會顯示為/dev/block/mapper/system-verity
,是/system
掛接點的來源。
圖 1 顯示 /system
掛載點下方的堆疊。
圖 1. 在 /system 掛接點下方建立堆疊
壓縮快照
在 Android 12 以上版本中,由於 /data
分區的空間需求可能較高,因此您可以在建構作業中啟用壓縮快照,以滿足 /data
分區較高的空間需求。
虛擬 A/B 壓縮快照是以下列 Android 12 以上版本提供的元件為基礎建構而成:
這些元件可啟用壓縮功能。如要實作壓縮快照功能,還需要進行其他必要變更,請參閱後續章節:壓縮快照的 COW 格式、dm-user 和 snapuserd。
壓縮快照的 COW 格式
在 Android 12 以上版本中,壓縮快照會使用 Android 專屬的 COW 格式。COW 格式包含 OTA 相關中繼資料,並具有包含 COW 作業和新作業系統資料的獨立緩衝區。與僅允許替換作業 (將快照中的區塊 Y 內容替換為基礎映像檔中的區塊 X) 的核心快照格式相比,Android 壓縮快照 COW 格式更具表達力,且支援下列作業:
- 複製:基礎裝置上的區塊「X」應替換為基礎裝置上的區塊「Y」。
- Replace:基礎裝置中的區塊 X 應替換為快照中的區塊 Y 內容。每個區塊都經過 gz 壓縮。
- 零:基礎裝置中的 X 區塊應全部替換為零。
- XOR:COW 裝置會在區塊 X 和區塊 Y 之間儲存 XOR 壓縮位元組。(適用於 Android 13 以上版本)。
完整的 OTA 更新只包含「取代」和「零」作業。漸進式 OTA 更新可能另外有複製作業。
磁碟的完整快照版面配置如下所示:
圖 2. 磁碟上的 Android COW 格式
dm-user
dm-user 核心模組可讓 userspace
實作裝置對應程式區塊裝置。dm-user 資料表項目會在 /dev/dm-user/<control-name>
下建立其他裝置。userspace
程序可以輪詢裝置,以便接收核心的讀取和寫入要求。每個要求都有一個關聯的緩衝區,供使用者空間填入資料 (讀取) 或傳播資料 (寫入)。
dm-user
核心模組會為核心提供新的使用者可見介面,而這並非上游 kernel.org 程式碼庫的一部分。在此之前,Google 保留修改 Android 中的 dm-user
介面之權利。
snapuserd
dm-user
的 snapuserd
使用者空間元件會實作虛擬 A/B 壓縮。Snapuserd 是負責寫入及讀取 Android COW 裝置的使用者空間守護程式。所有快照 I/O 都必須經過這項服務。在 OTA 安裝期間,系統會透過 snapuserd (壓縮) 將新的作業系統資料寫入快照。這裡也會處理中繼資料的剖析作業,以及解開新的區塊資料。
XOR 壓縮
對於搭載 Android 13 以上版本的裝置,預設啟用的 XOR 壓縮功能可讓使用者空間快照在舊區塊和新區塊之間儲存 XOR 壓縮位元組。在虛擬 A/B 更新中,如果只有區塊中的幾個位元組發生變更,XOR 壓縮儲存空間配置方案所需的空間會比預設儲存空間配置方案少,因為快照不會儲存完整的 4K 位元組。由於 XOR 資料包含許多零,比原始區塊資料更易於壓縮,因此可以縮減快照大小。在 Pixel 裝置上,XOR 壓縮可將快照大小縮減 25% 至 40%。
如果裝置升級至 Android 13 以上版本,則必須啟用 XOR 壓縮功能。詳情請參閱「XOR 壓縮」。
快照合併
對於搭載 Android 13 以上版本的裝置,snapuserd
使用者空間元件會執行虛擬 A/B 壓縮作業中的快照和快照合併程序。如果是升級至 Android 13 以上版本的裝置,必須啟用這項功能。詳情請參閱「使用者空間合併」。
以下說明虛擬 A/B 壓縮程序:
- 此架構會將
/system
分割區掛載至dm-verity
裝置,而該裝置會堆疊在dm-user
裝置上。也就是說,來自根目錄檔案系統的每個 I/O 都會路由至dm-user
。 dm-user
會將 I/O 轉送至處理 I/O 要求的使用者空間snapuserd
守護程式。- 合併作業完成後,架構會在
dm-linear
(system_base
) 頂端收合dm-verity
並移除dm-user
。
圖 3. 虛擬 A/B 壓縮程序
快照合併程序可能會中斷。如果裝置在合併程序期間重新啟動,合併程序會在重新啟動後繼續。
初始轉場效果
使用壓縮快照啟動時,第一階段初始化程序必須啟動 snapuserd
來掛載分區。這會導致問題:當 sepolicy
載入及強制執行時,snapuserd
會放入錯誤的內容,其讀取要求會失敗,並遭到 SELinux 拒絕。
為解決這個問題,snapuserd
會與 init
同步轉換,如下所示:
- 第一階段的
init
會從 RAM 磁碟啟動snapuserd
,並將開放式檔案描述符儲存至環境變數。 - 第一階段
init
會將根檔案系統切換至系統分區,然後執行init
的系統副本。 init
的系統副本會將合併的機構政策讀取為字串。Init
會在所有 ext4 支援的頁面上叫用mlock()
。接著,它會停用快照裝置的所有裝置對應表,並停止snapuserd
。此後,系統會禁止讀取分區,因為這會導致死結。- 使用
snapuserd
的 RAM 磁碟副本的開放描述項,init
會以正確的 selinux 內容重新啟動守護程式。系統會重新啟用快照裝置的裝置-mapper 資料表。 - 叫用
munlockall()
,您可以放心再次執行 IO。
空間使用情形
下表比較了使用 Pixel 作業系統和 OTA 大小的不同 OTA 機制所需的空間。
大小影響 | 非 A/B | A 到 B 罩杯 | 虛擬 A/B 版本 | 虛擬 A/B (壓縮) |
---|---|---|---|---|
原始原廠映像檔 | 4.5GB 超級 (3.8GB 映像檔 + 700MB 保留空間)1 | 超高 9 GB (保留 3.8G + 7 億個運算單元) | 超高 4.5 GB (3.8G 映像檔 + 7 億張空間) | 4.5GB 超級 (3.8G 映像檔 + 700M 保留空間) |
其他靜態分區 | /cache | 無 | 無 | 無 |
OTA 期間的額外儲存空間 (套用 OTA 後返回的空間) | /data 上的 1.4 GB | 0 | 3.8 GB2 位於 /data | 2.1 GB2 /數據流量 |
套用 OTA 所需的總儲存空間 | 5.9 GB3 (超級和資料) | 9 GB (超大) | 8.3 GB3 (超級和資料) | 6.6 GB3 (超級和資料) |
1 表示根據 Pixel 對應方式推測的版面配置。
2假設新系統映像檔的大小與原始映像檔相同。
3 空間需求會在重新啟動前暫時性增加。
Android 11 虛擬 A/B
虛擬 A/B 的 Android 11 使用核心 COW 格式將資料寫入動態分區。由於核心 COW 格式不支援壓縮,因此這個功能最終已淘汰。
Android 12 虛擬 A/B
在 Android 12 中,系統支援 Android 專屬 COW 格式的壓縮方式。這個版本的虛擬 A/B 需要將 Android 專用 COW 轉譯為核心 COW 格式。最終,Android 13 取代了這個功能,移除了對核心 COW 格式和 dm-snapshot
的依賴。
如要實作虛擬 A/B 版本,或使用壓縮快照功能,請參閱「實作虛擬 A/B 版本」