動態分區是透過 dm-Linear 裝置對應程式執行
與 Linux kernel 中執行模組類似super
分區包含
列出每個動態分區的名稱和區塊範圍的中繼資料
在 super
內。在 init
第一階段中,這個
都會經過剖析和驗證,並透過建立虛擬區塊裝置
每個動態分區
套用 OTA 時,系統會自動建立動態分區 或視需要刪除A/B 裝置有兩個副本: 而您所做的變更只會套用到代表 目標版位。
動態分區會在使用者空間中實作,因此
就無法將系統啟動載入程式進行動態化例如 boot
系統啟動載入程式會讀取 dtbo
和 vbmeta
因此必須保持為實體分區
每個動態分區都可以隸屬於一個更新群組。這些
群組會限制該群組中分區可使用的空間上限。
舉例來說,system
和 vendor
可以屬於
可限制 system
和
vendor
。
在新裝置實作動態分區
本節詳細說明如何在新裝置中實作動態分區 搭載 Android 10 以上版本更新 現有裝置,請參閱:升級 Android 裝置。
分區變更
如果是搭載 Android 10 的裝置,請建立
名為 super
的分區super
分區會在內部處理 A/B 運算單元,因此 A/B 裝置不需要
super_a
和 super_b
分區。
系統啟動載入程式未使用的所有唯讀 Android 開放原始碼計畫分區
必須是動態值,且必須從 GUID 分區表 (GPT) 中移除。
供應商專屬的分區不必動態,且可放置在
加入清單
如要預估「super
」的大小,請將
卻會從 GPT 中刪除分區A/B 裝置:
應包含兩個版位的大小。圖 1 顯示
轉換為動態前後的分區表範例
多個分區
支援的動態分區如下:
- 系統
- 供應商
- 產品
- 系統延伸模組
- ODM
針對搭載 Android 10 的裝置,
核心指令列選項 androidboot.super_partition
必須為空白,這樣指令 sysprop
ro.boot.super_partition
是空的,
分區對齊
如果
super
個分區未正確對齊。
「super
」分區必須對齊 I/O 下限
要求大小;根據預設,
建構系統 (透過 lpmake
)
super
分區映像檔),此假設是透過 1 MiB 對齊
足以應付每個動態分區不過,如果供應商
確認 super
分區已正確對齊。
您可以透過下列方式決定封鎖裝置的最小要求大小:
正在檢查 sysfs
。例如:
# ls -l /dev/block/by-name/super lrwxrwxrwx 1 root root 16 1970-04-05 01:41 /dev/block/by-name/super -> /dev/block/sda17 # cat /sys/block/sda/queue/minimum_io_size 786432
您可以驗證 super
分區在
類似的方式:
# cat /sys/block/sda/sda17/alignment_offset
對齊偏移量必須為 0。
裝置設定變更
如要啟用動態分區,請在
device.mk
:
PRODUCT_USE_DYNAMIC_PARTITIONS := true
主面板設定變更
您必須設定 super
分區的大小:
BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>
在 A/B 裝置上,如果總大小總和,建構系統會擲回錯誤
動態分區映像檔的比例超過 super
的一半
分區大小
您可以按照下列方式設定動態分區清單。適用對象
請列出要更新群組的裝置
BOARD_SUPER_PARTITION_GROUPS
變數。每個群組名稱
則具有 BOARD_group_SIZE
和 BOARD_group_PARTITION_LIST
變數。
如果是 A/B 裝置,群組大小上限只能涵蓋一個
因為群組名稱是內部加上運算單元的結尾。
以下裝置範例會將所有分區分組
名稱為 example_dynamic_partitions
:
BOARD_SUPER_PARTITION_GROUPS := example_dynamic_partitions BOARD_EXAMPLE_DYNAMIC_PARTITIONS_SIZE := 6442450944 BOARD_EXAMPLE_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product
以下範例裝置將系統和產品服務導入
group_foo
,以及vendor
、product
,
並將 odm
轉換為 group_bar
:
BOARD_SUPER_PARTITION_GROUPS := group_foo group_bar BOARD_GROUP_FOO_SIZE := 4831838208 BOARD_GROUP_FOO_PARTITION_LIST := system product_services BOARD_GROUP_BAR_SIZE := 1610612736 BOARD_GROUP_BAR_PARTITION_LIST := vendor product odm,瞭解如何調查及移除這項存取權。
-
針對虛擬 A/B 啟動裝置,所有群組的大小上限總和
最多:
BOARD_SUPER_PARTITION_SIZE
- 負擔
請參閱「實作虛擬 A/B」一節。 -
對於 A/B 上市裝置,所有群組的大小上限總和
為:
BOARD_SUPER_PARTITION_SIZE
/ 2 - 經常性費用 -
如果是非 A/B 裝置和翻新 A/B 裝置,則
所有群組的大小都必須是:
BOARD_SUPER_PARTITION_SIZE
- 經常使用 - 在建構期間,每個分區的映像檔大小總和 更新群組中的不得超過群組大小上限。
- 系統在計算過程中需要負擔,才能將中繼資料納入考量, 等對齊方式合理的負擔為 4 MiB,不過您 可以依據裝置需求 增加更多的負荷
大小動態分區的大小
在動態分區之前,分區大小會過度分配到 確保他們有足夠的空間,可容納日後的更新內容。實際大小 且大部分唯讀分區都提供一些免費 空間在動態分區中,可用空間是 並可用於 OTA 期間增加分區。 請務必確保分區不會浪費空間 分配到最小可用大小
如果是唯讀 ext4 映像檔,建構系統會自動分配 未指定硬式編碼分區大小時的最小大小。 建構系統能配合映像檔 未使用的空間這可確保裝置不會浪費 可用於網路旅行社
此外,只要啟用 block- 簡化或簡化作業如要啟用這項功能,請使用下列設定:
BOARD_EXT4_SHARE_DUP_BLOCKS := true
如果您不想自動分配分區大小下限
控管分區大小的方法有兩種您可以指定
最低可用空間
BOARD_partitionIMAGE_PARTITION_RESERVED_SIZE
,
也可以指定
BOARD_partitionIMAGE_PARTITION_SIZE
即可強制
達到特定大小的動態分區這些都不是
建議上傳
例如:
BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800
這會強制 product.img
中的檔案系統
未使用 50 MiB 的空間。
對系統進行變更
搭載 Android 10 的裝置不得 我們要使用系統權限
具有動態分區的裝置 (無論是使用或翻新的裝置)
動態分區) 不得使用系統式根層級。Linux kernel 無法
會解讀 super
分區,因此無法掛接
system
本身。system
目前掛接於
第一階段 init
,位於 ramdisk 中。
不要設定 BOARD_BUILD_SYSTEM_ROOT_IMAGE
。於
Android 10、
BOARD_BUILD_SYSTEM_ROOT_IMAGE
標記只會用於
區分系統是由核心或
第一階段 init
進入 ramdisk 中。
將BOARD_BUILD_SYSTEM_ROOT_IMAGE
設為true
會導致建構錯誤
PRODUCT_USE_DYNAMIC_PARTITIONS
也是true
。
當 BOARD_USES_RECOVERY_AS_BOOT
設為 true 時,
復原映像檔為 boot.img,內含復原作業的
ramdisk。系統先前使用 skip_initramfs
核心
決定要啟動的模式適用對象
Android 10 裝置,「不得」通過系統啟動載入程式
skip_initramfs
傳送至核心指令列。而是系統啟動載入程式
應通過 androidboot.force_normal_boot=1
,略過復原程序
並啟動一般的 Android搭載 Android 12 的裝置
或之後的版本必須使用 bootconfig 傳遞 androidboot.force_normal_boot=1
。
AVB 設定變更
使用 Android 時 驗證開機程序 2.0 (如果裝置未使用鏈結分區) 描述元,則無須變更。如果使用鏈結 但其中一個已驗證分區是動態的 必須做出變更
以下為鏈結的裝置設定範例
針對 system
和 vbmeta
vendor
個分區。
BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048 BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1 BOARD_AVB_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_VENDOR_ALGORITHM := SHA256_RSA2048 BOARD_AVB_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_VENDOR_ROLLBACK_INDEX_LOCATION := 1
使用此設定時,系統啟動載入程式預期會找到 vbmeta
system
結尾和
vendor
個分區。由於這些分區
系統啟動載入程式向 (位於 super
中) 顯示,其中兩個
需要修改
-
新增
vbmeta_system
和vbmeta_vendor
分割為裝置分區表。如果是 A/B 裝置,請新增vbmeta_system_a
、vbmeta_system_b
、vbmeta_vendor_a
和vbmeta_vendor_b
。如果 新增一或多個分區的大小 做為vbmeta
分區。 -
透過新增
VBMETA_
和 指定鏈結延伸至哪些分區:BOARD_AVB_VBMETA_SYSTEM := system BOARD_AVB_VBMETA_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_VBMETA_SYSTEM_ALGORITHM := SHA256_RSA2048 BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX_LOCATION := 1 BOARD_AVB_VBMETA_VENDOR := vendor BOARD_AVB_VBMETA_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_VBMETA_VENDOR_ALGORITHM := SHA256_RSA2048 BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX_LOCATION := 1
裝置可能正在使用其中一個、兩個分區,或全都不使用。變更內容 只有在鏈結至邏輯分區時才需要使用
AVB 系統啟動載入程式變更
如果系統啟動載入程式已嵌入 libavb, 包含下列修補程式:
- 818cf56740775446285466eda984acedd4baeac0 — "libavb:僅在 cmdline 需要時查詢分區 GUID 。」
- 5abd6bc2578968d24406d834471adfd995a0c2e9 —「允許缺少系統分區」
- 9ba3b6613b4e5130fa01a11d984c6b5f0eb3af05 — 「Fix AvbSlotVerifyData->cmdline 可能為 NULL」
如果使用鏈結分區,請加入其他修補程式:
- 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — "libavb:支援分區開頭的 vbmeta blob。"
核心指令列變更
必須加入新參數「androidboot.boot_devices
」
加入核心指令列init
會使用這項資訊:
啟用 /dev/block/by-name
符號連結。這應該是
裝置路徑元件連結至
ueventd
,那是
/dev/block/platform/device-path/by-name/partition-name
。
搭載 Android 12 以上版本的裝置必須使用
Bootconfig 將 androidboot.boot_devices
傳遞至 init
。
舉例來說,如果超級分區的依名稱符號連結
/dev/block/platform/soc/100000.ufshc/by-name/super
,
只要在 BoardConfig.mk 檔案中新增指令列參數,
如下:
BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshc您可以在 BoardConfig.mk 檔案中新增 bootconfig 參數,如下所示:
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc
Fstab 變更
裝置樹狀結構和裝置樹狀結構疊加層不得包含 fstab 項目。請使用屬於 ramdisk 的 fstab 檔案。
必須對 fstab 檔案進行邏輯分區的變更:
-
fs_mgr 旗標欄位必須包含
logical
旗標 和first_stage_mount
旗標, Android 10,表示分區設定為 都會掛接到第一個階段 -
分區可以指定
以「
avb=vbmeta partition name
」表示fs_mgr
標記,然後是指定的vbmeta
系統會先從第一個階段init
初始化分區 再嘗試掛接任何裝置 -
dev
欄位必須是分區名稱。
下列 fstab 項目會將系統、供應商和產品設為邏輯 都會在兩個可用區中運作
#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags> system /system ext4 ro,barrier=1 wait,slotselect,avb=vbmeta,logical,first_stage_mount vendor /vendor ext4 ro,barrier=1 wait,slotselect,avb,logical,first_stage_mount product /product ext4 ro,barrier=1 wait,slotselect,avb,logical,first_stage_mount
將 fstab 檔案複製到第一個階段 ramdisk。
SELinux 變更
超級分區區塊裝置必須標有標籤
super_block_device
。舉例來說,如果超級分區的依名稱符號連結
/dev/block/platform/soc/100000.ufshc/by-name/super
,
在 file_contexts
中新增下列程式碼:
/dev/block/platform/soc/10000\.ufshc/by-name/super u:object_r:super_block_device:s0
Fastbootd
系統啟動載入程式 (或任何非使用者空間刷新工具) 無法辨識 因而無法刷新這些區域為瞭解決這個問題,裝置 必須使用快速啟動通訊協定的使用者空間實作 (稱為 Fastbootd。
如要進一步瞭解如何實作 Fastbootd,請參閱將 Fastboot 移至使用者空間。
ADB 儲值
針對使用 eng 或 userdebug 版本的開發人員,adb remount
非常適合快速疊代動態分區具有
由於您已經停止免費,因此發生 adb remount
的問題
空間如要解決這個問題,裝置可以啟用
疊加層只要超級分區中有足夠的空間
adb remount
會自動建立臨時動態
也會使用 Overlayfs 進行寫入暫時性分區為
名為 scratch
,因此請勿將這個名稱用於其他產品
多個分區
如要進一步瞭解如何啟用疊加層,請參閱疊加層 Android 開放原始碼計畫中的 README 檔案。
升級 Android 裝置
如果您將裝置升級至 Android 10 想要在 OTA 中加入動態分區支援,就不需要 變更內建分區資料表。一些額外設定 這通常代表交易 不會十分要求關聯語意
裝置設定變更
如要調整動態分區,請在
device.mk
:
PRODUCT_USE_DYNAMIC_PARTITIONS := true PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true
主面板設定變更
您必須設定下列 Jamboard 變數:
- 將
BOARD_SUPER_PARTITION_BLOCK_DEVICES
設為使用的封鎖裝置清單 儲存動態分區的範圍這是現有實體 多個分區 - 將
BOARD_SUPER_PARTITION_partition_DEVICE_SIZE
設為大小 每個區塊裝置的BOARD_SUPER_PARTITION_BLOCK_DEVICES
權限。 以下是裝置上現有實體分區的大小清單。這通常BOARD_partitionIMAGE_PARTITION_SIZE
在現有主面板中 儲存空間設定 - 為所有使用者取消設定現有
BOARD_partitionIMAGE_PARTITION_SIZE
在BOARD_SUPER_PARTITION_BLOCK_DEVICES
中使用多個分區。 - 將
BOARD_SUPER_PARTITION_SIZE
設為BOARD_SUPER_PARTITION_partition_DEVICE_SIZE
。 - 將
BOARD_SUPER_PARTITION_METADATA_DEVICE
設為符合以下條件的封鎖裝置: 儲存動態分區中繼資料。必須是以下任一個值:BOARD_SUPER_PARTITION_BLOCK_DEVICES
。通常這個參數會設為system
。 - 設定
BOARD_SUPER_PARTITION_GROUPS
:BOARD_group_SIZE
和BOARD_group_PARTITION_LIST
。詳情請見 在新裝置上變更主面板設定 。
舉例來說,如果裝置已有系統和廠商分區,而您想要轉換 到動態分區中新增產品分區,並在更新期間新增產品分區,請採用下列設定:
BOARD_SUPER_PARTITION_BLOCK_DEVICES := system vendor BOARD_SUPER_PARTITION_METADATA_DEVICE := system # Rename BOARD_SYSTEMIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE. BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE := <size-in-bytes> # Rename BOARD_VENDORIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE := <size-in-bytes> # This is BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE + BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE BOARD_SUPER_PARTITION_SIZE := <size-in-bytes> # Configuration for dynamic partitions. For example: BOARD_SUPER_PARTITION_GROUPS := group_foo BOARD_GROUP_FOO_SIZE := <size-in-bytes> BOARD_GROUP_FOO_PARTITION_LIST := system vendor product
SELinux 變更
超級分區區塊裝置必須標上屬性
super_block_device_type
。舉例來說,如果裝置已
system
和 vendor
分區,您想要將其做為區塊使用
裝置儲存動態分區的範圍,且依名稱的符號連結會標示為
system_block_device
:
/dev/block/platform/soc/10000\.ufshc/by-name/system u:object_r:system_block_device:s0 /dev/block/platform/soc/10000\.ufshc/by-name/vendor u:object_r:system_block_device:s0
接著在 device.te
中新增下列程式碼:
typeattribute system_block_device super_block_device_type;
如需其他設定的資訊,請參閱實作 動態分區
如要進一步瞭解 Retrofit 更新,請參閱 適用於無動態 A/B 裝置裝置的 OTA 分區。
原廠映像檔
如果是支援動態分區功能的裝置,請避免使用 啟動使用者空間時,使用者空間 Fastboot 連線至原廠映像檔 速度較其他快閃方法慢
為解決這個問題,make dist
現在建構了
super.img
圖片可直接刷新至超級
自動封裝邏輯內容
也就是包含 system.img
vendor.img
等等,除了 super
以外
分區中繼資料。此圖像可直接刷新至
super
個分區,無須任何額外工具或使用
Fastbootd。建構之後,super.img
會放入
${ANDROID_PRODUCT_OUT}
。
針對推出內含動態分區的 A/B 裝置
super.img
包含位置中的圖片。刷新
請直接在超映像檔中將版位 A 標示為可開機,再重新啟動
裝置。
對於 Retrofit 裝置,make dist
會建構一組
super_*.img
圖像可直接刷新至
對應的實體分區例如:make dist
版本 super_system.img
和 super_vendor.img
系統是 BOARD_SUPER_PARTITION_BLOCK_DEVICES
時
供應商。這些映像檔會存放在
target_files.zip
。
裝置對應裝置儲存空間裝置調整
動態分區支援多種非確定性的裝置對應工具 如需儲存大量結構化物件 建議使用 Cloud Bigtable這些方法不一定都會如預期地例項化,因此您必須追蹤所有 並在掛接時更新所有相關聯分區的 Android 屬性 妥善管理基礎儲存裝置
init
中的機制可追蹤掛接,並以非同步方式追蹤。
會更新 Android 屬性。時間量不保證會達到
。
,讓所有 on property
觸發事件做出回應。這些屬性
dev.mnt.blk.<partition>
,其中
<partition>
為 root
,
system
、data
或
例如 vendor
。每項資源都會與
基本 Storage 裝置名稱,如以下範例所示:
taimen:/ % getprop | grep dev.mnt.blk [dev.mnt.blk.data]: [sda] [dev.mnt.blk.firmware]: [sde] [dev.mnt.blk.metadata]: [sde] [dev.mnt.blk.persist]: [sda] [dev.mnt.blk.root]: [dm-0] [dev.mnt.blk.vendor]: [dm-1] blueline:/ $ getprop | grep dev.mnt.blk [dev.mnt.blk.data]: [dm-4] [dev.mnt.blk.metadata]: [sda] [dev.mnt.blk.mnt.scratch]: [sda] [dev.mnt.blk.mnt.vendor.persist]: [sdf] [dev.mnt.blk.product]: [dm-2] [dev.mnt.blk.root]: [dm-0] [dev.mnt.blk.system_ext]: [dm-3] [dev.mnt.blk.vendor]: [dm-1] [dev.mnt.blk.vendor.firmware_mnt]: [sda]
init.rc
語言可讓 Android 屬性
將裝置納入規則,且儲存空間裝置可由平台調整
使用以下指令:
write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb 128 write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb 128
指令在第二階段 init
開始處理後,
epoll loop
會生效,並開始更新這些值。不過
因為屬性觸發條件要到 init
後才會啟用,
無法用於初始啟動階段處理 root
,
system
或 vendor
。您可能會想
保留核心預設值 read_ahead_kb
,直到有
early-fs
中的 init.rc
指令碼可覆寫
包括各種 Daemon 和設施因此,Google 建議
您是使用 on property
功能,再加上
由 init.rc
控制的資源,例如 sys.read_ahead_kb
,
處理作業時間並防止競爭狀況,就像這些
範例:
on property:dev.mnt.blk.root=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.system=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.system}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.vendor=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.vendor}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.product=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.system_ext}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.oem=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.oem}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.data=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on early-fs: setprop sys.read_ahead_kb ${ro.read_ahead_kb.boot:-2048} on property:sys.boot_completed=1 setprop sys.read_ahead_kb ${ro.read_ahead_kb.bootcomplete:-128}