具有動態分割區的 A/B 裝置的 OTA

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

本頁面介紹如何在針對執行Android 9 及更低版本的裝置啟動時支援動態分割區的 A/B 裝置的更新期間調整動態分割區的大小。

背景

設備上有一個super分區。該分割區沒有插槽後綴。區塊裝置必須與fstab/miscblk_device條目一起存在。例如,如果fstab檔案列出:

/dev/block/bootdevice/by-name/misc    /misc    # Other fields

那麼super的區塊裝置必須存在於/dev/block/bootdevice/by-name/super中,但super分割區不需要在fstab檔案中列出。

super分割區中,有兩個元資料槽,編號為0和1,對應分割區的A/B槽。在此頁面中,元資料槽稱為元資料 S(來源)和元資料 T(目標)。同樣,分區稱為system_svendor_t等。

升級前,元資料 S 包含正在使用的動態分區的資訊(通常為system_svendor_sproduct_s等)。系統在更新過程中會讀取這些分割區的磁碟區,因此無法刪除它們。

分區屬於更新群組。有關詳細信息,請參閱實現動態分區

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

  • 元資料 0
    • foo_a
      • 分區system_a
      • 分區product_services_a
      • Foo 更新的其他分割區
    • 組 bar_a
      • 分區vendor_a
      • 分區product_a
      • Bar 更新的其他分區
    • foo_b (上次升級剩餘的)
    • bar_b (上次升級剩餘的)
  • 元數據1
    • foo_a (上次升級剩餘的)
    • bar_a (上次升級剩餘的)
    • 群組foo_b
      • 分區system_b
      • 分割區product_services_b
      • Foo 更新的其他分割區
    • bar_b
      • 分區vendor_b
      • 分區product_b
      • Bar 更新的其他分區

您可以使用lpdump工具(原始碼位於system/extras/partition_tools下)將元資料轉儲到裝置上。例如:

lpdump --slot 0 /dev/block/bootdevice/by-name/super
lpdump --slot 1 /dev/block/bootdevice/by-name/super

更新流程

  1. 初始化super分區元資料。
    1. 從元資料 S 載入來源動態分割區的範圍。令 M 為載入的元資料。
    2. 從 M 中刪除目標群組和分割區(例如foo_tbar_t ),以便 M 只包含帶有_s後綴的分割區和群組。
    3. 根據更新清單中的dynamic_partition_metadata欄位新增目標群組和分區。
      每個分割區的大小可以在new_partition_info中找到。
    4. 將 M 寫入元資料 T。
    5. 將裝置映射器上新增的分區映射為可寫入。
  2. 在區塊設備上套用更新。
    1. 如有必要,將裝置映射器上的來源分區對應為唯讀。這對於旁加載是必要的,因為來源分區在更新之前沒有映射。
    2. 對目標槽上的所有區塊裝置套用完整更新或增量更新。
    3. 裝載分區以運行安裝後腳本,然後卸載分區。
  3. 取消映射目標分割區。

更新前後,以下系統屬性應具有各自的值:

ro.boot.dynamic_partitions=true
ro.boot.dynamic_partitions_retrofit=true

將群組和分區新增至更新清單

在具有動態分割區的 A/B 裝置或新增動態分割區支援的 A/B 裝置上執行 OTA 更新時,您需要將群組和分割區新增至更新清單。下面的程式碼片段顯示了有關支援動態分割區的更新清單的其他資訊。有關每個欄位的詳細文檔,請參閱update_metadata.proto

message DeltaArchiveManifest {
    optional DynamicPartitionMetadata dynamic_partition_metadata;
}

message DynamicPartitionMetadata {
    repeated DynamicPartitionGroup groups;
}

message DynamicPartitionGroup {
    required string name;
    optional uint64 size; // maximum size of group
    repeated string partition_names;
}