實(shí)現(xiàn) A/B 更新
想要實(shí)現(xiàn) A/B 系統(tǒng)更新的原始設(shè)備制造商 (OEM) 和 SoC 供應(yīng)商必須確保其引導(dǎo)加載程序?qū)崿F(xiàn) boot_control HAL教硫,并將正確的參數(shù)傳遞到內(nèi)核兄纺。
實(shí)現(xiàn)啟動(dòng)控件 HAL
支持 A/B 更新的引導(dǎo)加載程序必須在 boot_control
中實(shí)現(xiàn) [hardware/libhardware/include/hardware/boot_control.h](https://android.googlesource.com/platform/hardware/libhardware/+/master/include/hardware/boot_control.h)
HAL瓶盛。您可以使用 [system/extras/bootctl](https://android.googlesource.com/platform/system/extras/+/master/bootctl/)
實(shí)用工具和 [system/extras/tests/bootloader/](https://android.googlesource.com/platform/system/extras/+/refs/heads/master/tests/bootloader/)
來測試實(shí)現(xiàn)。
您還必須實(shí)現(xiàn)狀態(tài)機(jī)删壮,如下所示:
設(shè)置內(nèi)核
要實(shí)現(xiàn) A/B 系統(tǒng)更新,請執(zhí)行以下操作:
- 擇優(yōu)挑選下列內(nèi)核補(bǔ)丁程序系列(如果需要):
- 如果在沒有使用 ramdisk 的情況下啟動(dòng)并使用“以恢復(fù)方式啟動(dòng)”,請?jiān)L問 android-review.googlesource.com/#/c/158491/ 根據(jù)需要進(jìn)行選擇销钝。
- 要在沒有使用 ramdisk 的情況下設(shè)置 dm-verity,請?jiān)L問 android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18 根據(jù)需要進(jìn)行選擇琐簇。
- 確保內(nèi)核命令行參數(shù)包含中以下額外參數(shù):
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>
值是用于驗(yàn)證 verity 表簽名的公鑰 ID(有關(guān)詳情蒸健,請參閱 dm-verity)。
- 將包含公鑰的 .X509 證書添加到系統(tǒng)密鑰環(huán):
- 將設(shè)置為
.der
格式的 .X509 證書復(fù)制到kernel
的根目錄鸽嫂。如果 .X509 證書的格式為.pem
文件纵装,請使用以下openssl
命令將證書格式從.pem
轉(zhuǎn)換為.der
:
- 將設(shè)置為
openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
2. 構(gòu)建 `zImage` 以將該證書添加為系統(tǒng)密鑰環(huán)的一部分。要進(jìn)行驗(yàn)證据某,請檢查 `procfs` 條目(需要啟用 `KEYS_CONFIG_DEBUG_PROC_KEYS`):
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
如果 .X509 證書添加成功橡娄,則表示系統(tǒng)密鑰環(huán)中存在相應(yīng)公鑰(突出顯示的部分為公鑰 ID)。
3. 將空格替換為 #
癣籽,并將其作為 <public-key-id>
在內(nèi)核命令行中傳遞挽唉。例如滤祖,傳遞 Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f
而非 <public-key-id>
。
設(shè)置編譯變量
支持 A/B 更新的引導(dǎo)加載程序必須滿足以下編譯變量條件:
要查看示例瓶籽,請參閱 [/device/google/marlin/+/android-7.<wbr style="box-sizing: inherit;">1.<wbr style="box-sizing: inherit;">0_r1/device-common.<wbr style="box-sizing: inherit;">mk](https://android.googlesource.com/device/google/marlin/+/android-7.1.0_r1/device-common.mk)
匠童。 您可以選擇執(zhí)行編譯中所述的安裝后(但在重新啟動(dòng)前)dex2oat 步驟。
設(shè)置分區(qū)(插槽)
A/B 設(shè)備不需要恢復(fù)分區(qū)或緩存分區(qū)塑顺,因?yàn)?Android 已不再使用這些分區(qū)汤求。數(shù)據(jù)分區(qū)現(xiàn)在用于存儲(chǔ)下載的 OTA 軟件包,而恢復(fù)映像代碼位于啟動(dòng)分區(qū)严拒。 A/B 化的所有分區(qū)都應(yīng)按以下方法命名(插槽始終被命名為 a
扬绪、b
等):boot_a
、boot_b
裤唠、system_a
挤牛、system_b
、vendor_a
种蘸、vendor_b
墓赴。
緩存
對于非 A/B 更新,緩存分區(qū)用于存儲(chǔ)下載的 OTA 軟件包航瞭,并在應(yīng)用更新時(shí)暫時(shí)隱藏塊诫硕。調(diào)整緩存分區(qū)大小從來沒有好辦法:所需的大小取決于您想要應(yīng)用的更新。最糟糕的情況是緩存分區(qū)與系統(tǒng)映像一樣大沧奴。如果使用 A/B 更新痘括,則無需隱藏塊(因?yàn)槟冀K在向當(dāng)前未使用的分區(qū)寫入數(shù)據(jù));如果流式傳輸 A/B 更新滔吠,則無需在應(yīng)用之前下載整個(gè) OTA 軟件包纲菌。
恢復(fù)
恢復(fù) RAM 磁盤現(xiàn)已包含在 boot.img
文件中。進(jìn)入恢復(fù)模式時(shí)疮绷,引導(dǎo)加載程序無法在內(nèi)核命令行中添加 skip_initramfs
選項(xiàng)翰舌。
對于非 A/B 更新,恢復(fù)分區(qū)包含用于應(yīng)用更新的代碼冬骚。A/B 更新由在正常啟動(dòng)的系統(tǒng)映像中運(yùn)行的 update_engine
應(yīng)用椅贱。同時(shí),仍有一種用于實(shí)現(xiàn)恢復(fù)出廠設(shè)置和旁加載更新軟件包的恢復(fù)模式(“恢復(fù)”就由此而來)只冻”勇螅恢復(fù)模式的代碼和數(shù)據(jù)存儲(chǔ)在 ramdisk 的常規(guī)啟動(dòng)分區(qū)中;為啟動(dòng)進(jìn)入系統(tǒng)映像喜德,引導(dǎo)加載程序會(huì)指示內(nèi)核跳過 ramdisk(否則山橄,設(shè)備會(huì)啟動(dòng)進(jìn)入恢復(fù)模式)∩崦酰恢復(fù)模式很泻嚼狻(其中大部分已在啟動(dòng)分區(qū)上)睡雇,所以啟動(dòng)分區(qū)的大小不會(huì)增加。
Fstab
slotselect
參數(shù)必須位于進(jìn)行 A/B 更新的分區(qū)對應(yīng)的行中饮醇。例如:
<path-to-block-device>/vendor /vendor ext4 ro
wait,verify=<path-to-block-device>/metadata,slotselect
不得將任何分區(qū)命名為 vendor
它抱,而應(yīng)選擇 vendor_a
或 vendor_b
分區(qū)并將其裝載到 /vendor
裝載點(diǎn)上。
內(nèi)核插槽參數(shù)
應(yīng)通過特定的設(shè)備樹 (DT) 節(jié)點(diǎn) (/firmware/android/slot_suffix
) 或 androidboot.slot_suffix
命令行參數(shù)傳遞當(dāng)前插槽后綴朴艰。
默認(rèn)情況下观蓄,fastboot 只會(huì)閃存 A/B 設(shè)備上的插槽 a
,并將當(dāng)前插槽設(shè)置為 a
呵晚。如果更新軟件包還包含插槽 b
的映像蜘腌,則 fastboot 也會(huì)閃存這些映像沫屡《叮可用選項(xiàng)包括:
-
--slot
。提示 fastboot 使用插槽b
沮脖,而非插槽a
金矛。 -
--set-active
。將插槽設(shè)置為活動(dòng)插槽勺届。 -
fastboot --help
驶俊。獲取有關(guān)命令的詳細(xì)信息。
如果引導(dǎo)加載程序?qū)崿F(xiàn) fastboot免姿,則應(yīng)該支持命令 set_active <slot>
饼酿,該命令將當(dāng)前活動(dòng)插槽設(shè)置為指定插槽(此外,還必須清除該插槽的不可啟動(dòng)標(biāo)記胚膊,并將重試計(jì)數(shù)重置為默認(rèn)值)故俐。引導(dǎo)加載程序還應(yīng)支持以下變量:
-
has-slot:<partition-base-name-without-suffix>
。如果指定分區(qū)支持插槽紊婉,則返回“yes”药版,否則返回“no”。 -
current-slot
喻犁。返回接下來將從中啟動(dòng)的插槽后綴槽片。 -
slot-count
。返回一個(gè)表示可用插槽數(shù)量的整數(shù)肢础。目前支持兩個(gè)插槽还栓,因此該值為2
。 -
slot-successful:<slot-suffix>
传轰。如果指定插槽已標(biāo)記為成功啟動(dòng)剩盒,則返回“yes”,否則返回“no”路召。 -
slot-unbootable:<slot-suffix>
勃刨。如果指定插槽已標(biāo)記為不可引導(dǎo)波材,則返回“yes”,否則返回“no”身隐。 -
slot-retry-count
廷区。啟動(dòng)指定插槽的剩余重試次數(shù)。
要查看所有變量贾铝,請運(yùn)行
fastboot getvar all
隙轻。
生成 OTA 軟件包
OTA 軟件包工具遵循的命令與不采取 A/B 更新的設(shè)備相同。target_files.zip
文件必須通過為 A/B 更新目標(biāo)定義編譯變量生成垢揩。OTA 軟件包工具會(huì)自動(dòng)識(shí)別并生成格式適用于 A/B 更新程序的軟件包玖绿。
例如:
- 生成完整 OTA:
./build/tools/releasetools/ota_from_target_files \
dist_output/tardis-target_files.zip ota_update.zip
- 生成增量 OTA:
./build/tools/releasetools/ota_from_target_files \
-i PREVIOUS-tardis-target_files.zip \
dist_output/tardis-target_files.zip incremental_ota_update.zip
配置分區(qū)
update_engine
可以更新同一磁盤中定義的任何一對 A/B 分區(qū)。一對分區(qū)共用一個(gè)前綴(例如 system
或 boot
)叁巨,每個(gè)插槽設(shè)置一個(gè)后綴(例如 _a
)斑匪。有效負(fù)載生成器為其定義更新的分區(qū)列表由 AB_OTA_PARTITIONS
make 變量配置。
例如锋勺,如果磁盤中有一對分區(qū) bootloader_a
和 booloader_b
(_a
和 _b
為插槽后綴)蚀瘸,則您可以通過在產(chǎn)品或單板配置中指定以下變量來更新這些分區(qū):
AB_OTA_PARTITIONS := \
boot \
system \
bootloader
由 update_engine
更新的所有分區(qū)不得由系統(tǒng)的其余部分修改。在增量更新期間庶橱,來自當(dāng)前插槽的二進(jìn)制數(shù)據(jù)將用于在新插槽中生成數(shù)據(jù)贮勃。任何修改都可能導(dǎo)致新插槽數(shù)據(jù)在更新過程中無法通過驗(yàn)證,從而導(dǎo)致更新失敗苏章。
配置安裝后步驟
對于每個(gè)已更新的分區(qū)寂嘉,您可以使用一組鍵值對配置不同的安裝后步驟。要在新映像中運(yùn)行位于 /system/usr/bin/postinst
的程序枫绅,請指定相對于系統(tǒng)分區(qū)中文件系統(tǒng)的根目錄的路徑泉孩。
例如,usr/bin/postinst
的對應(yīng)路徑為 system/usr/bin/postinst
(如果未使用 RAM 磁盤)撑瞧。此外棵譬,請指定要傳遞到 mount(2)
系統(tǒng)調(diào)用的文件系統(tǒng)類型。 請將以下代碼添加到產(chǎn)品或設(shè)備的 .mk
文件中(如果適用):
AB_OTA_POSTINSTALL_CONFIG += \
RUN_POSTINSTALL_system=true \
POSTINSTALL_PATH_system=usr/bin/postinst \
FILESYSTEM_TYPE_system=ext4
編譯
出于安全考慮预伺,system_server
無法使用即時(shí) (JIT) 編譯订咸。 這意味著,您必須至少為 system_server
及其依賴項(xiàng)提前編譯 odex 文件酬诀;其他內(nèi)容則可以先不編譯脏嚷。
要在后臺(tái)編譯應(yīng)用,您必須將以下內(nèi)容添加到產(chǎn)品的設(shè)備配置(位于產(chǎn)品的 device.mk 中):
- 向版本中添加原生組件瞒御,以確保編譯腳本和二進(jìn)制文件能夠編譯并添加到系統(tǒng)映像中父叙。
# A/B OTA dexopt package
PRODUCT_PACKAGES += otapreopt_script
- 將編譯腳本與
update_engine
相關(guān)聯(lián),以便后者可以作為安裝后步驟運(yùn)行。
# 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
要獲取有關(guān)將預(yù)先優(yōu)化的文件安裝到未使用的第二個(gè)系統(tǒng)分區(qū)的幫助趾唱,請參閱 DEX_PREOPT 文件的首次啟動(dòng)安裝涌乳。
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License, and code samples are licensed under the Apache 2.0 License. For details, see our Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
上次更新日期:四月 17, 2018