想要導入 A/B 系統更新的 OEM 和 SoC 供應商,必須確保其引導程式導入 boot_control HAL,並將正確的參數傳遞至核心。
實作啟動控制 HAL
支援 A/B 的引導程式必須在 hardware/libhardware/include/hardware/boot_control.h
實作 boot_control
HAL。您可以使用 system/extras/bootctl
公用程式和 system/extras/tests/bootloader/
測試導入作業。
您也必須實作下方所示的狀態機器:

設定核心
如要實作 A/B 系統更新,請按照下列步驟操作:
-
視需要選取下列核心修補程式系列:
- 如果沒有使用 RAM 磁碟啟動,並使用「boot as recovery」,請選取 android-review.googlesource.com/#/c/158491/。
- 如要設定不含 RAM 磁碟的 dm-verity,請選取 android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18。
-
確認核心指令列引數包含下列額外引數:
... 其中skip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
<public-key-id>
值是用於驗證 Verity 資料表簽名的公開金鑰 ID (詳情請參閱 dm-verity)。 -
將含有公開金鑰的 .X509 憑證新增至系統鑰匙圈:
-
將以
.der
格式編寫的 .X509 憑證複製到kernel
目錄的根目錄。如果 .X509 憑證的格式為.pem
檔案,請使用下列openssl
指令,將格式從.pem
轉換為.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
-
建構
zImage
,將憑證納入系統鑰匙圈。如要確認,請檢查procfs
項目 (需要啟用KEYS_CONFIG_DEBUG_PROC_KEYS
): 成功納入 .X509 憑證,表示系統鑰匙圈中含有公開金鑰 (醒目顯示表示公開金鑰 ID)。angler:/# cat /proc/keys 1c8a217e I------ 1 perm 1f010000 0 0 asymmetri Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f [] 2d454e3e I------ 1 perm 1f030000 0 0 keyring .system_keyring: 1/4
-
將空格替換為
#
,並在核心指令列中以<public-key-id>
的形式傳遞。例如,傳遞Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f
取代<public-key-id>
。
-
將以
設定建構變數
支援 A/B 的引導程序必須符合下列建構變數條件:
必須為 A/B 測試目標定義 |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk 。您可以選擇在編譯一節中所述的 dex2oat 步驟後 (但在重新啟動前) 執行。 |
---|---|
強烈建議用於 A/B 目標 |
|
無法為 A/B 測試目標定義 |
|
偵錯版本可選 | PRODUCT_PACKAGES_DEBUG += update_engine_client |
設定分區 (插槽)
A/B 裝置不需要復原分區或快取分區,因為 Android 不再使用這些分區。資料分區現在用於下載的 OTA 套件,而復原映像檔程式碼則位於啟動分區。所有進行 A/B 測試的分區都應命名如下 (運算單元一律命名為 a
、b
等):boot_a
、boot_b
、system_a
、system_b
、vendor_a
、vendor_b
。
快取
對於非 A/B 更新,快取分區用於儲存下載的 OTA 套件,並在套用更新時暫存區塊。我們從未找到適合的方式來設定快取分割區的大小:所需的大小取決於您要套用的更新項目。最糟糕的情況是快取分區的大小與系統映像檔相同。使用 A/B 更新時,您不需要儲存區塊 (因為您一律會寫入目前未使用的分區),而使用串流 A/B 時,您也不需要先下載整個 OTA 套件再套用。
復原
復原 RAM 磁碟現在已包含在 boot.img
檔案中。進入復原模式時,系統啟動載入程式「無法」將 skip_initramfs
選項放入核心指令列。
對於非 A/B 更新,復原分割區會包含用於套用更新的程式碼。系統會在一般啟動的系統映像檔中執行 update_engine
,以套用 A/B 更新。復原模式仍可用於執行原廠資料重設作業,以及側載更新套件 (這就是「復原」這個名稱的由來)。復原模式的程式碼和資料會儲存在 RAM 磁碟中的一般開機分割區;為了開機至系統映像檔,啟動載入程式會告知核心略過 RAM 磁碟 (否則裝置會開機至復原模式)。復原模式很小 (大部分內容都已位於啟動分區),因此啟動分區不會增加。
Fstab
slotselect
引數必須位於 A/B 測試版區塊的行中。例如:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
請勿將分割區命名為 vendor
。而是會選取分區 vendor_a
或 vendor_b
,並掛載至 /vendor
掛載點。
核心插槽引數
您應透過特定裝置樹狀結構 (DT) 節點 (/firmware/android/slot_suffix
) 或 androidboot.slot_suffix
核心指令列或 bootconfig 引數,傳遞目前的插槽後置字串。
根據預設,Fastboot 會在 A/B 裝置上刷新目前的插槽。如果更新套件也包含其他非目前插槽的映像檔,fastboot 也會閃記這些映像檔。可用的選項包括:
-
--slot SLOT
。覆寫預設行為,並提示 fastboot 將傳入做為引數的插槽刷新。 -
--set-active [SLOT]
。將時間間隔設為有效。如果未指定選用引數,則會將目前的空格設為有效。 fastboot --help
:取得指令詳細資料。
如果引導程序實作快速啟動功能,則應支援 set_active <slot>
指令,將目前的有效插槽設為指定的插槽 (這也必須清除該插槽的無法啟動標記,並將重試次數重設為預設值)。引導程式也應支援下列變數:
-
has-slot:<partition-base-name-without-suffix>
。如果指定的分割區支援分頁,就會傳回「是」,否則傳回「否」。 current-slot
。傳回下次將從中啟動的運算單元後置字串。-
slot-count
。傳回整數,代表可用時段的數量。目前支援兩個時段,因此這個值為2
。 -
slot-successful:<slot-suffix>
。如果已將指定的插槽標示為已成功啟動,則會傳回「是」;否則會傳回「否」。 -
slot-unbootable:<slot-suffix>
。如果指定的插槽標示為無法啟動,則會傳回「是」;否則傳回「否」。 -
slot-retry-count:<slot-suffix>
。嘗試啟動指定時段時,剩餘的重試次數。
如要查看所有變數,請執行 fastboot getvar all
。
產生 OTA 套件
OTA 套件工具會遵循與非 A/B 裝置相同的指令。target_files.zip
檔案必須透過定義 A/B 目標的建構變數來產生。OTA 套件工具會自動辨識並產生 A/B 更新程式所需的格式套件。
例如:
-
如要產生完整 OTA,請按照下列步驟操作:
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip
-
如要產生增量 OTA,請按照下列步驟操作:
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
設定分區
update_engine
可更新同一個磁碟中定義的任何一組 A/B 分割區。一組分區具有共同的前置字串 (例如 system
或 boot
) 和每個插槽的後置字串 (例如 _a
)。負載產生器定義更新的分區清單是由 AB_OTA_PARTITIONS
產生變數設定。
舉例來說,如果包含一組分區 bootloader_a
和 booloader_b
(_a
和 _b
是插槽後置字元),您可以在產品或電路板設定中指定下列項目,以更新這些分區:
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
由 update_engine
更新的所有分區不得由系統的其他部分修改。在增量或差異更新期間,系統會使用目前版位的二進位資料,產生新版位中的資料。任何修改都可能導致新版時段資料在更新期間驗證失敗,進而導致更新失敗。
設定安裝後程序
您可以使用一組鍵/值組合,為每個更新的分區設定不同的安裝後步驟。如要在新映像檔中執行位於 /system/usr/bin/postinst
的程式,請指定相對於系統分區中檔案系統根目錄的路徑。
舉例來說,usr/bin/postinst
是 system/usr/bin/postinst
(如果未使用 RAM 磁碟)。此外,請指定要傳遞至 mount(2)
系統呼叫的檔案系統類型。將下列內容新增至產品或裝置 .mk
檔案 (如適用):
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
編譯應用程式
在重新啟動至新的系統映像檔前,應用程式可在背景編譯。如要在背景編譯應用程式,請在產品的裝置設定 (位於產品的 device.mk 中) 中新增下列內容:
-
在建構中加入原生元件,確保編譯指令碼和二進位檔會編譯並納入系統映像檔。
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
-
將編譯指令碼連結至
update_engine
,以便做為安裝後步驟執行。# A/B OTA dexopt update_engine hookup AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=system/bin/otapreopt_script \ FILESYSTEM_TYPE_system=ext4 \ POSTINSTALL_OPTIONAL_system=true
如要瞭解如何在未使用的第二個系統分區中安裝預選檔案,請參閱「首次啟動時安裝 DEX_PREOPT 檔案」。