Android 10 は、無線(OTA)アップデート時にパーティションの作成、サイズ変更、破棄を行えるユーザー空間パーティショニング システムである動的パーティションをサポートしています。
このページでは、OTA クライアントが非 A/B デバイスのアップデート時に動的パーティションのサイズを変更する方法について説明します。
非 A/B デバイスの場合、動的パーティションの OTA アップデートは、アップデート パッケージ内の updater
を使用して適用されます。
リリース デバイスをアップデートする
このセクションは、動的パーティションをサポートする状態でリリースされた非 A/B デバイスに適用されます。そうしたデバイスは、Android 10 から、それより上位のリリースにアップグレードされます。
アップデート パッケージを生成する
OTA アップデート パッケージは、build/make/tools/releasetools
にある ota_from_target_files
スクリプトによって生成されます。デフォルトでは、このスクリプトは system
パーティションと vendor
パーティションをアップデートするパッケージを生成します。product
、product_services
、odm
などの追加の動的パーティションが存在する場合、それらのアップデートはデバイス固有のコードで生成する必要があります。
アップデートを生成するには、拡張 Python モジュールで、FullOTA_GetBlockDifferences()
と IncrementalOTA_GetBlockDifferences()
を実装します。これら 2 つの関数は、BlockDifference
オブジェクトのリストを返します。各オブジェクトには、パーティションに適用されるアップデート パッチが記述されています。これら 2 つの関数から返されるパーティションは、手動で変更しないでください。また、*_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_partitions
の op_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 アップデートでは、次のロジックが使用されます。
- パーティションを縮小する / パーティションを削除する / グループからパーティションを移動する(グループを縮小するのに十分な空き容量を確保するため)
- グループを縮小する(グループを拡張するのに十分な空き領域を確保するため)
- グループを拡張する(パーティションを拡張または追加するのに十分な空き容量を確保するため)
- パーティションを拡張する / パーティションを追加する / 新しいグループにパーティションを移動する
具体的には、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_partitions
の op_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 アップデートでは、次のロジックが使用されます。
- 既存のグループとパーティションをすべて削除する
- グループを追加する
- パーティションを追加する
具体的には、update-script
は次のロジックで生成されます。
update_dynamic_partitions(op_list) for each adding partition: block_image_update(map_partition(name), …)
update_dynamic_partitions
の op_list
ファイルは次のロジックで生成されます。
remove_all_groups for each adding group: add_group for each adding partition: add for each adding partition: resize