Android 10 推出使用者資料檢查點 (UDC),如果 Android 無線 (OTA) 更新失敗,Android 就能還原至先前的狀態。使用 UDC 時,如果 Android OTA 更新失敗,裝置可以安全地復原為先前的狀態。雖然 A/B 更新可解決早期啟動的問題,但如果使用者資料分割區 (掛接在 /data
上) 經過修改,系統就不支援回溯。
UDC 可讓裝置還原使用者資料分區,即使分區已修改也一樣。UDC 功能會透過檔案系統的檢查點功能達成此目的,如果檔案系統不支援檢查點,則會採用替代實作方式,並與開機載入程式 A/B 機制整合,同時支援非 A/B 更新,以及支援金鑰版本繫結和防止金鑰復原。
對使用者的影響
UDC 功能可改善使用者的 OTA 更新體驗,因為 OTA 更新失敗時,較少使用者會遺失資料。這樣一來,使用者在更新過程中遇到問題時,就不太需要撥打支援電話。不過,如果 OTA 更新失敗,使用者可能會發現裝置多次重新啟動。
運作方式
不同檔案系統中的檢查點功能
針對 F2FS 檔案系統,UDC 會將檢查點功能新增至上游 4.20 Linux 核心,並回溯至 Android 10 裝置支援的所有常見核心。
對於其他檔案系統,UDC 會使用名為 dm_bow
的裝置對應器虛擬裝置,提供檢查點功能。dm_bow
位於裝置和檔案系統之間。掛接分區時,系統會發出修剪指令,導致檔案系統對所有可用區塊發出修剪指令。dm_bow
會攔截這些修剪內容,並用來設定免費封鎖清單。讀取和寫入作業隨後會傳送至裝置,但必須先將還原所需的資料備份到可用區塊,才能進行寫入作業。
查核點程序
掛接具有 checkpoint=fs/block
標記的分區時,Android 會在磁碟上呼叫 restoreCheckpoint
,讓裝置還原任何目前的檢查點。init
接著會呼叫 needsCheckpoint
函式,判斷裝置是否處於系統啟動載入程式 A/B 狀態,或是否已設定更新重試次數。如果其中一個為 true,Android 會呼叫 createCheckpoint
,加入掛接標記或建構 dm_bow
裝置。
掛接分割區後,系統會呼叫檢查點程式碼來發出修剪指令。
開機程序隨後會照常繼續。在 LOCKED_BOOT_COMPLETE
,Android 會呼叫 commitCheckpoint
來提交目前的檢查點,更新作業會照常繼續。
管理 KeyMint (舊稱 Keymaster) 金鑰
KeyMint 金鑰可用於裝置加密或其他用途。為管理這些金鑰,Android 會延遲金鑰刪除呼叫,直到檢查點已提交為止。
監測健康
健康狀態精靈會驗證是否有足夠的磁碟空間來建立檢查點。健康狀態 Daemon 位於 Checkpoint.cpp
的 cp_healthDaemon
。
健康狀態 Daemon 具有下列可設定的行為:
ro.sys.cp_msleeptime
:控管裝置檢查磁碟用量的頻率。ro.sys.cp_min_free_bytes
:控制健康狀況守護程序尋找的最小值。ro.sys.cp_commit_on_full
: 控制健康狀況精靈是否要重新啟動裝置,或在磁碟空間不足時提交檢查點並繼續執行。
檢查點 API
UDC 功能會使用檢查點 API。如要瞭解 UDC 使用的其他 API,請參閱IVold.aidl
。
void startCheckpoint(int retry)
建立檢查點。
架構準備好開始更新時,就會呼叫這個方法。檢查點是在重新啟動後掛接可檢查點的檔案系統 (例如 userdata) R/W 之前建立。如果重試次數為正數,API 會處理追蹤重試,更新程式則會呼叫 needsRollback
,檢查是否需要回溯更新。如果重試次數為 -1
,API 會延後至 A/B 開機載入程式的判斷。
進行一般 A/B 更新時,不會呼叫這個方法。
void commitChanges()
提交變更。
變更準備好要提交時,架構會在重新啟動後呼叫這個方法。系統會在資料 (例如圖片、影片、簡訊、伺服器收到接收確認) 寫入 userdata 之前,以及 BootComplete
之前呼叫這個函式。
如果沒有作用中的檢查點更新,這個方法就不會產生任何作用。
abortChanges()
強制重新啟動並還原至檢查點。放棄第一次重新啟動後的所有使用者資料修改。
架構會在重新啟動後呼叫這個方法,但會在 commitChanges
之前。呼叫這個方法時,retry_counter
會減少。系統會產生記錄項目。
bool needsRollback()
判斷是否需要回溯。
在非檢查點裝置上,傳回 false
。在檢查點裝置上,系統會在非檢查點啟動期間傳回 true
。
導入 UDC
參考實作
如要瞭解如何實作 UDC,請參閱 dm-bow.c。如需這項功能的其他說明文件,請參閱 dm-bow.txt。
設定
在 init.hardware.rc
檔案的 on fs
中,確認您有:
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --early
在 init.hardware.rc
檔案的 on late-fs
中,確認您有:
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late
在 fstab.hardware
檔案中,確認 /data
已標記為 latemount
。
/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier latemount,wait,check,fileencryption=ice,keydirectory=/metadata/vold/metadata_encryption,quota,formattable,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,reservedsize=128M,checkpoint=fs
新增中繼資料分區
UDC 需要中繼資料分區來儲存非開機載入程式重試次數和金鑰。設定中繼資料分割區,並在 /metadata
提前掛接。
在 fstab.hardware
檔案中,確認 /metadata
已標記為 earlymount
或 first_stage_mount
。
/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount
將分區初始化為全零。
在 BoardConfig.mk
中新增下列程式碼:
BOARD_USES_METADATA_PARTITION := true BOARD_ROOT_EXTRA_FOLDERS := existing_folders metadata
更新系統
F2FS 系統
如果系統使用 F2FS 格式化資料,請確認 F2FS 版本支援檢查點。詳情請參閱「不同檔案系統中的檢查點功能」。
將 checkpoint=fs
標記新增至 fstab 的 <fs_mgr_flags>
區段,適用於掛接在 /data
的裝置。
非 F2FS 系統
如果不是 F2FS 系統,則必須在核心設定中啟用 dm-bow
。
將 checkpoint=block
標記新增至 fstab 的 <fs_mgr_flags>
區段,適用於掛接在 /data
的裝置。
檢查記錄
呼叫 Checkpoint API 時,系統會產生記錄項目。
驗證
如要測試 UDC 實作,請執行 VtsKernelCheckpointTest
VTS 測試集。