在 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 之間的 system-as-root 配置的含義有所不同。在 Android 9 system-as-root 配置中, BOARD_BUILD_SYSTEM_ROOT_IMAGE
設定為true
,這會強制建置將根檔案系統合併到system.img
中將system.img
掛載為根檔案系統 (rootfs)。對於使用 Android 9 啟動的設備,此配置是強制性的,但對於升級到 Android 9 的設備以及運行較低版本 Android 的設備來說,此配置是可選的。在 Android 10 system-as-root 配置中,建置始終將$TARGET_SYSTEM_OUT
和$TARGET_ROOT_OUT
合併到system.img
中;此配置是運行 Android 10 的所有裝置的預設行為。
Android 10 進行了進一步更改以支援動態分區,這是一種用戶空間分區系統,支援透過無線 (OTA) 更新來建立、調整大小或銷毀分區。作為此變更的一部分,Linux 核心無法再在執行 Android 10 的裝置上掛載邏輯系統分割區,因此此操作由第一階段 init 處理。
以下部分描述了僅係統 OTA 的系統作為根要求,提供有關更新設備以使用系統作為根的指南(包括分區佈局更改和 dm-verity 核心要求)。有關 ramdisk 更改的詳細信息,請參閱Ramdisk 分區。
關於僅限系統的 OTA
僅系統 OTA 使 Android 版本能夠更新system.img
和product.img
而無需更改其他分區,需要係統作為根分區佈局。所有運行 Android 10 的裝置都必須使用系統作為根分區佈局來啟用僅限系統的 OTA。
- 將
system
分割區掛載為 rootfs 的 A/B 裝置已使用 system-as-root,無需進行變更即可支援系統 OTA。 - 在
/system
掛載system
分區的非 A/B 設備必須更新為使用系統作為根分區佈局來支援系統 OTA。
有關 A/B 和非 A/B 設備的詳細信息,請參閱A/B(無縫)系統更新。
使用供應商覆蓋
供應商覆蓋允許您在設備啟動時覆蓋對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
更新到 root 系統
若要更新非 A/B 裝置以使用 system-as-root,您必須更新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(9 之前) | 系統作為 root(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-as-root 中,核心必須使用dm-verity將system.img
掛載到/
(掛載點)下。 AOSP 支援system.img
的以下 dm-verity 實作。
虛擬啟動1.0
對於vboot 1.0 ,核心必須解析/system
上的 Android 特定元數據,然後轉換為dm-verity 參數以設定 dm-verity (需要這些核心補丁)。以下範例顯示了核心命令列中 system-as-root 的 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
虛擬啟動2.0
對於 vboot 2.0 ( AVB ),引導程式必須整合external/avb/libavb ,然後解析/system
哈希樹描述符,將其轉換為dm-verity params ,最後透過核心命令列將參數傳遞給核心。 ( /system
的雜湊樹描述符可能位於/vbmeta
或/system
本身上。)
vboot 2.0 需要以下核心補丁:
以下範例顯示了核心命令列中 system-as-root 的 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"
使用設備特定的根資料夾
使用 system-as-root,在裝置上刷新通用系統映像 (GSI)後(執行供應商測試套件測試之前),使用BOARD_ROOT_EXTRA_FOLDERS
新增的任何特定於裝置的根資料夾都會消失,因為整個根目錄內容已被替換由系統作為根 GSI。如果存在對特定於裝置的根資料夾的依賴性(例如,它們用作裝載點),則刪除這些資料夾可能會導致裝置無法啟動。
為了避免此問題,請勿使用BOARD_ROOT_EXTRA_FOLDERS
新增裝置特定的根資料夾。如果您需要指定特定於設備的安裝點,請使用/mnt/vendor/<mount point>
(在這些變更清單中新增)。這些特定於供應商的掛載點可以直接在fstab
設備樹(用於第一階段掛載)和/vendor/etc/fstab.{ro.hardware}
檔案中指定,無需額外設定(因為fs_mgr
在/mnt/vendor/*
)。