不含動態分割區的 A/B 裝置的 OTA

Android 10 支援動態分割區,這是一種使用者空間分區系統,可在無線 (OTA) 更新期間建立、調整大小和銷毀分割區。

本頁面介紹了 OTA 用戶端如何在不支援動態分區支援的情況下啟動的 A/B 裝置更新期間調整動態分割區大小,以及 OTA 用戶端如何升級至 Android 10。

背景

在更新 A/B 裝置以支援動態分割區期間,裝置上的 GUID 分割區表 (GPT) 會被保留,因此裝置上沒有super分割區。元資料儲存在system_asystem_b中,但這可以透過更改BOARD_SUPER_PARTITION_METADATA_DEVICE進行自訂。

在每個區塊設備中,有兩個元資料槽。每個區塊設備中僅使用一個元資料槽。例如, system_a處的元資料 0 和system_b的元資料 1 分別對應於 A 和 B 插槽處的分區。在運行時,更新哪個槽並不重要。

在此頁面中,元資料槽稱為元資料 S(來源)和元資料 T(目標)。同樣,分區稱為system_svendor_t等。

有關建置系統配置的更多信息,請參閱升級設備

有關分區如何屬於更新群組的更多信息,請參閱新設備的主機板配置變更

設備上的元資料範例如下:

  • 物理塊設備system_a
    • 元資料 0
      • foo_a
        • 邏輯(動態)分區system_a
        • 邏輯(動態)分割區product_services_a
        • Foo 更新的其他分割區
      • bar_a
        • 邏輯(動態)分區vendor_a
        • 邏輯(動態)分區product_a
        • Bar 更新的其他分區
    • 元資料1(未使用)
  • 實體塊設備system_b
    • 元資料 0(未使用)
    • 元數據1
      • 組 foo_b
        • 邏輯(動態)分區system_b
        • 邏輯(動態)分割區product_services_b
        • Foo 更新的其他分割區
      • 組 bar_b
        • 邏輯(動態)分區vendor_b
        • 邏輯(動態)分割區product_b
        • Bar 更新的其他分區

您可以使用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.imgsuper_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 用戶端已更新為可使用動態分割區。來源分區的範圍永遠不會跨越目標實體分區。

使用常規更新套件更新流程

  1. 初始化super分區元資料。
    1. 從元資料 S(源元資料)建構新的元資料 M。例如,如果元資料S使用[ system_svendor_sproduct_s ]作為區塊設備,則新元資料M使用[ system_tvendor_tproduct_t ]作為區塊設備。 M 中的所有群組和分區均被丟棄。
    2. 根據更新清單中的dynamic_partition_metadata欄位新增目標群組和分區。每個分割區的大小可以在new_partition_info中找到。
    3. 將 M 寫入元資料 T。
    4. 將裝置映射器上新增的分區映射為可寫入。
  2. 在區塊設備上套用更新。
    1. 如有必要,將裝置映射器上的來源分區對應為唯讀。這對於旁加載是必要的,因為來源分區在更新之前沒有映射。
    2. 對目標槽上的所有區塊裝置套用完整更新或增量更新。
    3. 裝載分區以運行安裝後腳本,然後卸載分區。
  3. 取消映射目標分割區。

使用改造更新包更新流程

如果改造更新套件應用在已經開啟動態分割的裝置上,OTA客戶端會直接將分割後的super.img檔案套用到區塊裝置上。更新流程類似改造更新。有關詳細信息,請參閱改造更新

例如,假設以下情況:

  • 插槽 A 是活動插槽。
  • system_a包含插槽 0 處的活動元資料。
  • system_avendor_aproduct_a用作塊設備。

當 OTA 用戶端收到改造更新套件時,它會在實體system_b上應用super_system.img ,在實體vendor_b上套用super_vendor.img ,在實體product_b上應用super_product.img 。實體塊設備system_b包含正確的元數據,以在引導時映射邏輯system_bvendor_bproduct_b

產生更新包

增量OTA

為改造設備產生增量 OTA 時,更新取決於基礎版本是否定義PRODUCT_USE_DYNAMIC_PARTITIONSPRODUCT_RETROFIT_DYNAMIC_PARTITIONS

  • 如果基礎版本未定義變量,則這是一個改造更新。更新包包含拆分的super.img檔案並停用安裝後步驟。
  • 如果基礎建置確實定義了變量,則這與動態分區的典型更新相同。更新包包含邏輯(動態)分割區的映像。可以啟用安裝後步驟。

完整OTA

為改造設備產生兩個完整的 OTA 套件。

  • $(PRODUCT)-ota-retrofit-$(TAG).zip始終包含 split super.img並停用用於改造更新的安裝後步驟。
    • 它是透過ota_from_target_files腳本的附加參數--retrofit_dynamic_partitions產生的。
    • 它可以應用於所有建置。
  • $(PRODUCT)-ota-$(TAG).zip包含用於將來更新的邏輯映像。
    • 僅將此應用於啟用了動態分區的建置。請參閱下面有關執行此操作的詳細資訊。

拒絕舊版的非改造更新

僅將常規完整 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作為安裝後步驟並拒絕更新。