在 Android 10 中,根檔案系統不再包含在 ramdisk.img 中,而是併入 system.img (也就是說,system.img 一律會建立,如同已設定 BOARD_BUILD_SYSTEM_ROOT_IMAGE 一樣)。搭載 Android 10 的裝置:
- 使用系統即根分區配置 (建構作業會自動強制執行,且無法變更行為)。
- 必須使用 ramdisk,這是 dm-linear 的必要條件。
- 必須將
BOARD_BUILD_SYSTEM_ROOT_IMAGE設為false。 這項設定僅用於區分使用 ramdisk 的裝置,以及不使用 ramdisk 的裝置 (而是直接掛接system.img)。
Android 9 和 Android 10 的系統即為根目錄設定意義不同。在 Android 9 系統即根目錄設定中,BOARD_BUILD_SYSTEM_ROOT_IMAGE 會設為 true,強制建構作業將根檔案系統合併至 system.img,然後將 system.img 掛接為根檔案系統 (rootfs)。如果裝置搭載 Android 9 推出,則必須進行這項設定;如果裝置升級至 Android 9,或搭載較舊的 Android 版本,則不必進行這項設定。在 Android 10 系統即根目錄設定中,建構作業一律會將 $TARGET_SYSTEM_OUT 和 $TARGET_ROOT_OUT 合併至 system.img;這是所有搭載 Android 10 的裝置預設行為。
Android 10 進一步變更,以支援動態分區,這是一種使用者空間分區系統,可讓無線更新 (OTA) 更新建立、調整大小或刪除分區。這項變更實施後,Linux 核心將無法再掛接 Android 10 裝置上的邏輯系統分割區,因此這項作業會由第一階段的 init 處理。
以下各節說明僅限系統的 OTA 的系統即為根目錄需求,並提供更新裝置以使用系統即為根目錄的指南 (包括分割區配置變更和 dm-verity 核心需求)。如要瞭解 ramdisk 的異動詳情,請參閱「Ramdisk 分區」。
關於僅限系統的無線更新
僅限系統的 OTA 可讓 Android 版本更新 system.img 和 product.img,而不變更其他磁碟分區,但需要以系統為根磁碟分區的版面配置。所有搭載 Android 10 的裝置都必須使用系統即根分割區配置,才能啟用僅限系統的 OTA。
- A/B 裝置會將
system分區掛接為 rootfs,因此已使用系統即為根目錄,不需要變更即可支援系統 OTA。 - 非 A/B 裝置會在
/system掛接system分區,必須更新為使用 system-as-root 分區配置,才能支援系統 OTA。
如要瞭解 A/B 和非 A/B 裝置的詳細資訊,請參閱「A/B (無縫) 系統更新」。
使用供應商疊加層 (<=AOSP 14)
供應商疊加層可讓您在裝置啟動時,疊加對分割區的變更。vendor供應商疊加層是 product 分區中的一組供應商模組,會在裝置啟動時疊加在 vendor 分區上,取代並新增現有模組。
裝置啟動時,init 程序會完成第一階段的掛接作業,並讀取預設屬性。然後搜尋 /product/vendor_overlay/<target_vendor_version>,並在對應的 vendor 分割區目錄上掛接每個子目錄 (如符合下列條件):
- 「
/vendor/<overlay_dir>」已存在。 /product/vendor_overlay/<target_vendor_version>/<overlay_dir>與/vendor/<overlay_dir>具有相同檔案內容。init可掛接在/vendor/<overlay_dir>的檔案環境中。
實作供應商重疊畫面
在 /product/vendor_overlay/<target_vendor_version> 中安裝供應商疊加檔案。裝置啟動時,這些檔案會覆蓋 vendor 分割區,取代同名檔案並新增任何檔案。供應商疊加層無法從 vendor 分割區移除檔案。
供應商疊加檔案必須與 vendor 分區中取代的目標檔案具有相同檔案內容。根據預設,/product/vendor_overlay/<target_vendor_version> 目錄中的檔案具有 vendor_file 內容。如果供應商疊加層檔案與取代的檔案之間存在檔案內容不符的情況,請在裝置專屬的 sepolicy 中指定。檔案環境是在目錄層級設定。如果供應商疊加目錄的檔案內容與目標目錄不符,且裝置專屬 sepolicy 中未指定正確的檔案內容,該供應商疊加目錄就不會疊加到目標目錄。
如要使用供應商重疊層,核心必須透過設定 CONFIG_OVERLAY_FS=y 啟用 OverlayFS。此外,核心必須從通用核心 4.4 以上版本合併,或以 "overlayfs:
override_creds=off option bypass creator_cred" 修補。
廠商重疊畫面導入範例
這個程序會示範如何實作供應商疊加層,疊加目錄 /vendor/lib/*、/vendor/etc/* 和 /vendor/app/*。
-
在
device/<vendor>/<target>/vendor_overlay/<target_vendor_version>/中新增預先建立的供應商檔案:device/google/device/vendor_overlay/28/lib/libfoo.so device/google/device/vendor_overlay/28/lib/libbar.so device/google/device/vendor_overlay/28/etc/baz.xml device/google/device/vendor_overlay/28/app/qux.apk
-
將預先建構的供應商檔案安裝至
device/google/device/device.mk中的product/vendor_overlay:PRODUCT_COPY_FILES += \ $(call find-copy-subdir-files,*,device/google/device/vendor_overlay,$(TARGET_COPY_OUT_PRODUCT)/vendor_overlay)
-
如果目標
vendor分區檔案的內容不是vendor_file,請定義檔案內容。由於/vendor/lib/*使用vendor_file環境,因此這個範例不包含該目錄。在
device/google/device-sepolicy/private/file_contexts中新增下列項目:/(product|system/product)/vendor_overlay/[0-9]+/etc(/.*)? u:object_r:vendor_configs_file:s0 /(product|system/product)/vendor_overlay/[0-9]+/app(/.*)? u:object_r:vendor_app_file:s0
-
允許
init程序在vendor_file以外的檔案環境中掛接供應商疊加層。由於init程序已具備在vendor_file環境中掛接的權限,因此這個範例不會定義vendor_file的政策。在
device/google/device-sepolicy/public/init.te中新增下列項目:allow init vendor_configs_file:dir mounton; allow init vendor_app_file:dir mounton;
驗證供應商重疊畫面
如要驗證供應商疊加設定,請在 /product/vendor_overlay/<target_vendor_version>/<overlay_dir> 中新增檔案,並檢查檔案是否疊加在 /vendor/<overlay_dir> 中的檔案上。
如果是 userdebug 建構版本,則有 Atest 的測試模組:
$ atest -v fs_mgr_vendor_overlay_test
更新至以系統為根目錄
如要更新非 A/B 裝置,使其使用系統即為根目錄,您必須更新 boot.img 和 system.img 的分割區配置、設定 dm-verity,並移除裝置專屬根資料夾的任何啟動依附元件。
更新分區
與將 /boot 重新用於復原分割區的 A/B 裝置不同,非 A/B 裝置必須將 /recovery 分割區分開,因為這類裝置沒有備援插槽分割區 (例如從 boot_a 到 boot_b)。如果移除非 A/B 裝置上的 /recovery,並使其類似於 A/B 方案,在更新 /boot 分割區失敗時,復原模式可能會中斷。因此,非 A/B 裝置的 /recovery 分割區必須與 /boot 分割區分開,這表示系統會繼續以延遲方式更新復原映像檔 (也就是說,與搭載 Android 8.1.0 以下版本的裝置相同)。
下表列出 Android 9 推出前後,非 A/B 裝置的映像檔分割區差異。
| 圖片 | Ramdisk (Android 9 之前的版本) | 以系統做為根目錄 (Android 9 之後) |
|---|---|---|
boot.img |
包含核心和 ramdisk.img:
ramdisk.img
-/
- init.rc
- init
- etc -> /system/etc
- system/ (mount point)
- vendor/ (mount point)
- odm/ (mount point)
... |
只包含一般開機核心。 |
recovery.img |
包含復原核心和復原
ramdisk.img。 |
|
system.img |
包含下列項目:
system.img
-/
- bin/
- etc
- vendor -> /vendor
- ... |
包含原始 system.img 和 ramdisk.img 的合併內容:
system.img
-/
- init.rc
- init
- etc -> /system/etc
- system/
- bin/
- etc/
- vendor -> /vendor
- ...
- vendor/ (mount point)
- odm/ (mount point)
... |
分區本身不會變更;ramdisk 和 system-as-root 都使用下列分區配置:
/boot/system/system/recovery/vendor等
設定 dm-verity
在以系統做為根目錄的設定中,核心必須在 / (掛接點) 下掛接 system.img,並使用 dm-verity。AOSP 支援下列 dm-verity system.img 實作項目。
vboot 1.0
如果是 vboot 1.0,核心必須剖析 /system 上的 Android 專屬中繼資料,然後轉換為 dm-verity 參數,以設定 dm-verity (需要這些核心修補程式)。以下範例顯示核心指令列中,與系統即為根目錄相關的 dm-verity 設定:
ro root=/dev/dm-0 rootwait skip_initramfs init=/init dm="system none ro,0 1 android-verity /dev/sda34" veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f
vboot 2.0
如果是 vboot 2.0 (AVB),系統啟動載入程式必須整合 external/avb/libavb,然後剖析 /system 的 雜湊樹狀結構描述元,並轉換為 dm-verity 參數,最後透過核心指令列將參數傳遞至核心。(Hashtree 描述元可能位於 /system
或 /vbmeta 本身)。
/system
vboot 2.0 需要下列核心修補程式:
以下範例顯示核心指令列中,與系統即為根目錄相關的 dm-verity 設定:
ro root=/dev/dm-0 rootwait skip_initramfs init=/init dm="1 vroot none ro 1,0 5159992 verity 1 PARTUUID=00000016-0000-0000-0000-000000000000 PARTUUID=00000016-0000-0000-0000-000000000000 4096 4096 644999 644999 sha1 d80b4a8be3b58a8ab86fad1b498640892d4843a2 8d08feed2f55c418fb63447fec0d32b1b107e42c 10 restart_on_corruption ignore_zero_blocks use_fec_from_device PARTUUID=00000016-0000-0000-0000-000000000000 fec_roots 2 fec_blocks 650080 fec_start 650080"
使用裝置專屬的根資料夾
採用系統即根目錄後,在裝置上刷入通用系統映像檔 (GSI) (以及執行 Vendor Test Suite 測試之前),使用 BOARD_ROOT_EXTRA_FOLDERS 新增的任何裝置專屬根資料夾都會消失,因為整個根目錄內容已由系統即根目錄 GSI 取代。如果裝置專屬的根資料夾存在依附元件 (例如用做掛接點),移除這些資料夾可能會導致裝置無法開機。
為避免這個問題,請勿使用 BOARD_ROOT_EXTRA_FOLDERS 新增裝置專屬的根資料夾。如需指定裝置專用的掛接點,請使用 /mnt/vendor/<mount point> (已在這些變更清單中新增)。這些供應商專屬的掛接點可直接在 fstab 裝置樹狀結構 (適用於第一階段掛接) 和 /vendor/etc/fstab.{ro.hardware} 檔案中指定,無需額外設定 (因為 fs_mgr 會在 /mnt/vendor/* 下自動建立這些掛接點)。