Android 10 支援動態分區,這是一種使用者空間分區系統,可在無線 (OTA) 更新期間建立、調整大小及刪除分區。
本頁說明 OTA 用戶端如何在更新期間為未支援動態分區的 A/B 裝置調整動態分區大小,以及 OTA 用戶端如何升級至 Android 10。
背景
在更新 A/B 裝置以支援動態分區時,裝置上的 GUID 分區表 (GPT) 會保留,因此裝置上不會有 super
分區。中繼資料會儲存在 system_a
和 system_b
,但您可以變更 BOARD_SUPER_PARTITION_METADATA_DEVICE
來自訂中繼資料。
每個區塊裝置都有兩個中繼資料插槽。只會使用每個區塊裝置中單一的中繼資料插槽。舉例來說,system_a
的中繼資料 0 和 system_b
的中繼資料 1 分別對應 A 運算單元和 B 運算單元的分區。在執行階段,無論哪個時段正在更新,都沒有關係。
在這個頁面中,中繼資料版位稱為「中繼資料 S」(來源) 和「中繼資料 T」(目標)。同樣地,分區會稱為 system_s
、vendor_t
等。
如要進一步瞭解建構系統設定,請參閱「升級裝置」。
如要進一步瞭解分區如何屬於更新群組,請參閱新裝置的板卡設定變更。
裝置上的中繼資料範例:
- 實體區塊裝置
system_a
- 中繼資料 0
- 群組
foo_a
- 邏輯 (動態) 分割區
system_a
- 邏輯 (動態) 區隔
product_services_a
- 由 Foo 更新的其他分區
- 邏輯 (動態) 分割區
- 群組
bar_a
- 邏輯 (動態) 分割區
vendor_a
- 邏輯 (動態) 分區
product_a
- 由 Bar 更新的其他分區
- 邏輯 (動態) 分割區
- 群組
- 中繼資料 1 (未使用)
- 中繼資料 0
- 實體區塊裝置
system_b
- 中繼資料 0 (未使用)
- 中繼資料 1
- 群組 foo_b
- 邏輯 (動態) 區隔
system_b
- 邏輯 (動態) 區隔
product_services_b
- 由 Foo 更新的其他分區
- 邏輯 (動態) 區隔
- 群組 bar_b
- 邏輯 (動態) 區隔
vendor_b
- 邏輯 (動態) 區隔
product_b
- 已透過長條更新其他分區
- 邏輯 (動態) 區隔
- 群組 foo_b
您可以使用 system/extras/partition_tools
底下的 lpdump
工具轉儲裝置上的中繼資料。例如:
lpdump --slot 0 /dev/block/by-name/system_a
lpdump --slot 1 /dev/block/by-name/system_b
翻新更新
在搭載 Android 9 以下版本的裝置上,裝置的 OTA 用戶端不支援更新前對應動態分區。系統會建立另一組修補程式,以便將對應關係直接套用至現有的實體分區。
OTA 產生器會建構最終的 super.img
檔案,其中包含所有動態分割區的內容,然後將映像檔分割成多個映像檔,以符合系統、供應商等對應實體區塊裝置的大小。這些圖片的名稱為 super_system.img
、super_vendor.img
等。OTA 用戶端會將這些映像檔套用至實體分區,而非套用邏輯 (動態) 分區。
由於 OTA 用戶端不知道如何對應動態分區,因此在產生更新套件時,系統會自動為這些分區停用所有安裝後步驟。詳情請參閱「設定安裝後程序」。
更新流程與 Android 9 相同。
更新前:
ro.boot.dynamic_partitions= ro.boot.dynamic_partitions_retrofit=
更新後:
ro.boot.dynamic_partitions=true ro.boot.dynamic_partitions_retrofit=true
日後的修舊更新
在進行復舊更新後,OTA 用戶端會更新為搭配動態分區運作。來源分區的範圍絕不會跨越目標實體分區。
使用一般更新套件進行更新流程
- 初始化
super
分區中繼資料。-
從中繼資料 S (來源中繼資料) 建構新的中繼資料 M。舉例來說,如果中繼資料 S 使用 [
system_s
、vendor_s
、product_s
] 做為區塊裝置,那麼新的中繼資料 M 就會使用 [system_t
、vendor_t
、product_t
] 做為區塊裝置。所有群組和分區都會在 M 中遭到捨棄。 -
根據更新資訊清單中的
dynamic_partition_metadata
欄位新增目標群組和分區。您可以在new_partition_info
中找到每個分區的大小。 - 將 M 寫入中繼資料 T。
- 將裝置對應工具新增的分區對應至可寫入的分區。
-
從中繼資料 S (來源中繼資料) 建構新的中繼資料 M。舉例來說,如果中繼資料 S 使用 [
- 在區塊裝置上套用更新。
- 視需要將裝置對應器上的來源分區設為唯讀。這是側載作業的必要步驟,因為更新前並未對來源分區進行對應。
- 將完整或差異更新套用至目標時段的所有區塊裝置。
- 接著掛接分區以執行安裝後指令碼,然後卸載分區。
- 取消對應目標分區。
使用 Retrofit 更新套件更新流程
如果 Retrofit 更新套件套用至已啟用動態分區的裝置,OTA 用戶端會直接將分割的 super.img
檔案套用至區塊裝置。更新流程與 Retrofit 更新流程類似。詳情請參閱「翻新更新」。
舉例來說,假設:
- 插槽 A 是有效插槽。
-
system_a
會在 0 個插槽中包含有效的中繼資料。 -
system_a
、vendor_a
和product_a
會用做區塊裝置。
當 OTA 用戶端收到復古更新套件時,會在實體 system_b
上套用 super_system.img
,在實體 vendor_b
上套用 super_vendor.img
,以及在實體 product_b
上套用 super_product.img
。實體區塊裝置 system_b
包含正確的中繼資料,可在開機時對應邏輯 system_b
、vendor_b
和 product_b
。
產生更新套件
增量 OTA
為改裝裝置產生增量 OTA 時,更新內容取決於基本版本是否定義 PRODUCT_USE_DYNAMIC_PARTITIONS
和 PRODUCT_RETROFIT_DYNAMIC_PARTITIONS
。
-
如果基本版本未定義變數,則為回溯更新。更新套件包含分割的
super.img
檔案,並停用安裝後步驟。 - 如果基礎版本確實定義變數,這就與動態分區的一般更新相同。更新套件包含邏輯 (動態) 分區的映像檔。可以啟用安裝後步驟。
完整 OTA
系統會為復古裝置產生兩個完整的 OTA 套件。
-
$(PRODUCT)-ota-retrofit-$(TAG).zip
一律包含分割的super.img
,並停用安裝後步驟,以便回溯更新。-
系統會在
ota_from_target_files
指令碼中加入額外參數--retrofit_dynamic_partitions
來產生此指令碼。 - 此設定可套用至所有版本。
-
系統會在
-
$(PRODUCT)-ota-$(TAG).zip
包含日後更新的邏輯圖片。- 僅將這項設定套用至已啟用動態分區的建構作業。請參閱下文,瞭解如何強制執行這項規定。
拒絕舊版本的非 Retrofit 更新
請只將一般完整 OTA 套件套用至已啟用動態分區的版本。如果 OTA 伺服器設定有誤,並將這些套件推送至搭載 Android 9 以下版本的裝置,裝置將無法啟動。Android 9 以下版本的 OTA 用戶端無法區分復古 OTA 套件和一般完整 OTA 套件,因此用戶端不會拒絕完整套件。
為避免裝置接受完整的 OTA 套件,您可以要求在安裝後執行步驟,以便檢查現有的裝置設定。例如:
device/device_name/dynamic_partitions/check_dynamic_partitions
#!/system/bin/sh DP_PROPERTY_NAME="ro.boot.dynamic_partitions" DP_RETROFIT_PROPERTY_NAME="ro.boot.dynamic_partitions_retrofit" DP_PROPERTY=$(getprop ${DP_PROPERTY_NAME}) DP_RETROFIT_PROPERTY=$(getprop ${DP_RETROFIT_PROPERTY_NAME}) if [ "${DP_PROPERTY}" != "true" ] || [ "${DP_RETROFIT_PROPERTY}" != "true" ] ; then echo "Error: applied non-retrofit update on build without dynamic" \ "partitions." echo "${DP_PROPERTY_NAME}=${DP_PROPERTY}" echo "${DP_RETROFIT_PROPERTY_NAME}=${DP_RETROFIT_PROPERTY}" exit 1 fi
device/device_name/dynamic_partitions/Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:= check_dynamic_partitions LOCAL_MODULE_TAGS := optional LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_SRC_FILES := check_dynamic_partitions LOCAL_PRODUCT_MODULE := true include $(BUILD_PREBUILT)
device/device_name/device.mk
PRODUCT_PACKAGES += check_dynamic_partitions # OPTIONAL=false so that the error in check_dynamic_partitions will be # propagated to OTA client. AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_product=true \ POSTINSTALL_PATH_product=bin/check_dynamic_partitions \ FILESYSTEM_TYPE_product=ext4 \ POSTINSTALL_OPTIONAL_product=false \
當一般 OTA 套件套用至未啟用動態分區的裝置時,OTA 用戶端會將 check_dynamic_partitions
當做安裝後步驟執行,並拒絕更新。