無動態分區的 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_b system_a元數據 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_s , vendor_s , product_s ] 作為塊設備,則新元數據 M 使用 [ system_t , vendor_t , product_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 客戶端收到改造更新包時,它會在物理super_vendor.img上應用super_system.img ,在物理system_b上應用vendor_b ,在物理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始終包含拆分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並拒絕更新。