適用於具有動態分割區的非 A/B 裝置的 OTA

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

本頁介紹 OTA 用戶端如何在非 A/B 裝置更新期間調整動態分割區大小。

對於非 A/B 設備,使用更新套件內的updater套用動態分割區的 OTA 更新。

更新啟動設備

本節適用於啟動時支援動態分區的非 A/B 設備;這些設備從 Android 10 升級到更高版本。

產生更新包

OTA 更新套件由ota_from_target_files腳本生成,位於build/make/tools/releasetools下方。預設情況下,該腳本會產生一個更新systemvendor分區的套件。如果還有其他動態分割區,例如productproduct_servicesodm ,則它們的更新必須在裝置特定的程式碼中產生。

若要產生更新,請在擴充的 Python 模組中實作FullOTA_GetBlockDifferences()IncrementalOTA_GetBlockDifferences() 。這兩個函數傳回BlockDifference物件的列表,每個物件都描述將應用於分區的更新補丁。這兩個函數傳回的分割區不應手動修改或在其他地方驗證,例如在*_InstallBegin()*_InstallEnd()

更新產生的範例:

# device/yoyodyne/tardis/releasetools.py

import os
from common import BlockDifference, EmptyImage, GetUserImage

# The joined list of user image partitions of source and target builds.
# - Items should be added to the list if new dynamic partitions are added.
# - Items should not be removed from the list even if dynamic partitions are
#   deleted. When generating an incremental OTA package, this script needs to
#   know that an image is present in source build but not in target build.
USERIMAGE_PARTITIONS = [
    "product",
    "odm",
]

def GetUserImages(input_tmp, input_zip):
  return {partition: GetUserImage(partition, input_tmp, input_zip)
          for partition in USERIMAGE_PARTITIONS
          if os.path.exists(os.path.join(input_tmp,
                                         "IMAGES", partition + ".img"))}

def FullOTA_GetBlockDifferences(info):
  images = GetUserImages(info.input_tmp, info.input_zip)
  return [BlockDifference(partition, image)
          for partition, image in images.items()]

def IncrementalOTA_GetBlockDifferences(info):
  source_images = GetUserImages(info.source_tmp, info.source_zip)
  target_images = GetUserImages(info.target_tmp, info.target_zip)

  # Use EmptyImage() as a placeholder for partitions that will be deleted.
  for partition in source_images:
    target_images.setdefault(partition, EmptyImage())

  # Use source_images.get() because new partitions are not in source_images.
  return [BlockDifference(partition, target_image, source_images.get(partition))
          for partition, target_image in target_images.items()]

更新流程

在幕後,edify 腳本中加入了以下函數:

  • unmap_partition(name)
    • 如果映射了分區,則取消映射,否則不執行任何操作。
    • 成功時傳回字串t ,失敗時傳回空字串。
  • map_partition(name)
    • 映射分區(如果尚未映射)。
    • 成功時傳回映射區塊裝置的絕對路徑,失敗時傳回空字串。
  • update_dynamic_partitions(op_list)
    • 將給定的操作清單套用至動態分割區元數據,必要時取消映射分割區。
    • 成功時回傳t ,失敗時傳回空字串。

update_dynamic_partitionsop_list參數指向更新套件中的檔案。文件中的每一行指定一個操作。如果任何操作失敗, update_dynamic_partitions立即傳回一個空字串。操作是:

  • resize partition-name size
    • 取消映射分割區,然後將其大小調整為size
  • remove partition_name
    • 取消映射分割區,然後將其刪除。
  • add partition-name group-name
    • 將新分區新增至指定群組。
    • 如果群組不存在或分割區已存在,則中止。
  • move partition-name group-name
    • 將分區移動到指定組。
    • 如果群組不存在或分割區不存在則中止。
  • add_group group-name maximum-size
    • 新增具有給定名稱和最大大小的群組。
    • 如果群組已存在則中止。
    • maximum_size為 0 表示群組中的分區沒有大小限制。需要進行額外的測試以確保群組中的分區不會超出裝置上的可用空間。
  • resize_group group-name maximum-size
    • 將群組大小調整為給定的最大大小。
    • 如果群組不存在則中止。
    • maximum_size為 0 表示群組中的分區沒有大小限制。需要進行額外的測試以確保群組中的分區不會超出裝置上的可用空間。
  • remove_group group-name
    • 刪除一個群組。
    • 如果群組中有分割區則中止。
  • remove_all_groups
    • 從裝置映射器中取消所有分割區的對應。
    • 刪除所有分割區和群組。

增量OTA

增量 OTA 更新使用以下邏輯:

  1. 縮小分割區/刪除分割區/將分割區移出群組(以便有足夠的空間來縮小群組)
  2. 縮小組(以便有足夠的空間來增長組)
  3. 增長組(以便我們有足夠的空間來增長/添加分區)
  4. 成長分區/新增分區/將分區移至新群組

詳細來說, update-script是按照以下邏輯產生的:

for each shrinking partition:
    block_image_update(map_partition(name), …)

update_dynamic_partitions(op_list)

for each growing / adding partition:
    block_image_update(map_partition(name), …)

update_dynamic_partitionsop_list檔案是使用下列邏輯產生的:

for each deleting partition:
    remove
for each partition that changes groups:
    move to "default"
for each shrinking partition:
    resize
for each shrinking / removing group:
    resize_group / remove_group
for each growing / adding group:
    resize_group / add_group
for each adding partition:
    add
for each growing / adding partition:
    resize
for each partition that changes groups:
    move to target group

完整OTA

完整的 OTA 更新使用以下邏輯:

  1. 刪除所有現有群組和分割區
  2. 新增群組
  3. 新增分區

詳細來說, update-script是按照以下邏輯產生的:

update_dynamic_partitions(op_list)

for each adding partition:
    block_image_update(map_partition(name), …)

update_dynamic_partitionsop_list檔案是使用下列邏輯產生的:

remove_all_groups
for each adding group:
    add_group
for each adding partition:
    add
for each adding partition:
    resize