在 Android 10 中,根目錄檔案系統不再包含在 ramdisk.img
中,而是併入 system.img
(也就是說,如果已設定 BOARD_BUILD_SYSTEM_ROOT_IMAGE
,系統一律會建立 system.img
)。推出時搭載 Android 10 的裝置:
- 使用系統做為根分區的版面配置 (由版本自動強制執行,且沒有變更行為的選項)。
- 必須使用 dm-linear 所需的 RAM 磁碟。
- 必須將
BOARD_BUILD_SYSTEM_ROOT_IMAGE
設為false
。這項設定只用於區分使用 RAM 磁碟機的裝置,以及不使用 RAM 磁碟機 (而是直接掛載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 的裝置上掛載邏輯系統分區,因此這個作業會由第一階段初始化處理。
以下各節將說明系統專用 OTA 的系統做為根目錄要求,並提供更新裝置以使用系統做為根目錄的操作說明 (包括分割區版面配置變更和 dm-verity 核心要求)。如要進一步瞭解 RAMDISK 的異動,請參閱「RAMDISK 分區」一文。
關於系統專用 OTA
系統專用 OTA 需要系統做為根磁碟分區的版面配置,才能讓 Android 版本更新 system.img
和 product.img
,而不變更其他分區。所有搭載 Android 10 的裝置都必須使用系統為根目錄的分割區版面配置,才能啟用僅限系統的 OTA。
- A/B 裝置會將
system
分區掛載為 rootfs,因此已使用系統做為 root,且無需變更即可支援系統 OTA。 - 非 A/B 裝置會在
/system
上掛載system
分區,因此必須更新為使用系統做為根分區的版面配置,才能支援系統 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
更新為系統-as-root
如要更新非 A/B 裝置以使用系統做為根目錄,您必須更新 boot.img
和 system.img
的分割區配置方案、設定 dm-verity,並移除裝置專屬根目錄的所有啟動依附元件。
更新分區
與 A/B 裝置將 /boot
重新用於復原分區不同,非 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 之前) | 以系統為根 (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 和系統-as-root 都會使用下列分割區配置:
/boot
/system
/system
/recovery
/vendor
等
設定 dm-verity
在以系統為根目錄的情況下,核心必須使用 dm-verity 在 /
(掛載點) 下掛載 system.img
。Android 開放原始碼計畫支援 system.img
的下列 dm-verity 實作項目。
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
的 hashtree 描述元,將其轉換為 dm-verity 參數,最後透過核心指令列將參數傳遞至核心。(/system
的 Hashtree 描述符可能位於 /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) (並在執行供應商測試套件測試之前) 後,使用 BOARD_ROOT_EXTRA_FOLDERS
新增的任何裝置專屬根目錄資料夾都會消失,因為整個根目錄內容已由系統做為根目錄 GSI 取代。如果裝置有特定根資料夾的依附元件 (例如,用作掛載點),移除這些資料夾可能會導致裝置無法啟動。
為避免這個問題,請勿使用 BOARD_ROOT_EXTRA_FOLDERS
新增裝置專屬的根目錄。如果您需要指定裝置專屬的掛載點,請使用 /mnt/vendor/<mount point>
(已新增至這些變更清單)。這些供應商專屬的掛載點可直接在 fstab
裝置樹狀結構 (用於第一階段掛載) 和 /vendor/etc/fstab.{ro.hardware}
檔案中指定,無須額外設定 (因為 fs_mgr
會自動在 /mnt/vendor/*
下建立這些掛載點)。