Android 10 は動的パーティションをサポートしています。これは無線(OTA)アップデート時にパーティションの作成、サイズ変更、破棄ができるユーザー空間パーティショニング システムです。
このページでは、動的パーティションをサポートせずにリリースされた A/B デバイスの更新時に OTA クライアントが動的パーティションのサイズを変更する方法と、OTA クライアントを Android 10 にアップグレードする方法について説明します。
背景
動的パーティションをサポートする A/B デバイスの更新中は、デバイスの GUID パーティション テーブル(GPT)が保持されるので、デバイスに super
パーティションはありません。メタデータは system_a
と system_b
に保存され、BOARD_SUPER_PARTITION_METADATA_DEVICE
を変更することでカスタマイズできます。
各ブロック デバイスには、2 つのメタデータ スロットがあります。各ブロック デバイスのメタデータ スロットは 1 つのみが使用されます。たとえば、system_a
のメタデータ 0 と system_b
のメタデータ 1 は、それぞれ A スロットと B スロットのパーティションに対応します。ランタイムには、どちらのスロットが更新中かは関係ありません。
このページでは、メタデータ スロットはメタデータ S(ソース)とメタデータ T(ターゲット)と呼ばれます。同様に、パーティションは system_s
、vendor_t
などと呼びます。
ビルドシステム設定の詳細については、デバイスのアップグレードをご覧ください。
パーティションがアップデート グループに属する方法については、新しいデバイスのボード設定の変更をご覧ください。
デバイス上のメタデータの例を次に示します。
- 物理ブロック デバイス
system_a
- メタデータ 0
- グループ
foo_a
- 論理(動的)パーティション
system_a
- 論理(動的)パーティション
product_services_a
- Foo によって更新されたその他のパーティション
- 論理(動的)パーティション
- グループ
bar_a
- 論理(動的)パーティション
vendor_a
- 論理(動的)パーティション
product_a
- Bar によって更新されたその他のパーティション
- 論理(動的)パーティション
- グループ
- メタデータ 1(使用しない)
- メタデータ 0
- 物理ブロック デバイス
system_b
- メタデータ 0(使用しない)
- メタデータ 1
- グループ foo_b
- 論理(動的)パーティション
system_b
- 論理(動的)パーティション
product_services_b
- Foo によって更新されたその他のパーティション
- 論理(動的)パーティション
- グループ bar_b
- 論理(動的)パーティション
vendor_b
- 論理(動的)パーティション
product_b
- Bar によって更新されたその他のパーティション
- 論理(動的)パーティション
- グループ foo_b
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.img
、super_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 クライアントは動的パーティションを使用できるように更新されます。ソース パーティションの範囲は、ターゲットの物理パーティションにまたがりません。
定期アップデート パッケージを使用した更新フロー
super
パーティション メタデータを初期化します。-
メタデータ S(ソース メタデータ)から新しいメタデータ M を作成します。
たとえば、メタデータ S が [
system_s
、vendor_s
、product_s
] をブロック デバイスとして使用する場合、新しいメタデータ M は [system_t
、vendor_t
、product_t
] をブロック デバイスとして使用します。すべてのグループとパーティションは M で破棄されます。 -
アップデート マニフェストの
dynamic_partition_metadata
フィールドに従ってターゲット グループとパーティションを追加します。各パーティションのサイズは、new_partition_info
にあります。 - M をメタデータ T に書き込みます。
- デバイス マッパー上に追加されたパーティションを書き込み可能としてマッピングします。
-
メタデータ S(ソース メタデータ)から新しいメタデータ M を作成します。
たとえば、メタデータ S が [
- ブロック デバイスにアップデートを適用します。
- 必要に応じて、デバイス マッパー上のソース パーティションを読み取り専用としてマッピングします。更新前にはソース パーティションがマッピングされていないため、サイドローディングにはこの処理が必要です。
- ターゲット スロットのすべてのブロック デバイスにフル アップデートまたは差分アップデートを適用します。
- パーティションをマウントしてインストール後のスクリプトを実行し、その後パーティションをマウント解除します。
- ターゲット パーティションのマッピングを解除します。
レトロフィット アップデート パッケージを使用した更新フロー
動的パーティションをすでに有効にしているデバイスにレトロフィット アップデート パッケージが適用されている場合、OTA クライアントは分割された super.img
ファイルをブロック デバイスに直接適用します。更新フローはレトロフィット アップデートと同様です。詳しくはアップデートのレトロフィットをご覧ください。
たとえば、次のような状況を考えます。
- スロット A はアクティブ スロットです。
-
system_a
にはスロット 0 のアクティブなメタデータを含みます。 -
system_a
、vendor_a
、product_a
はブロック デバイスとして使用されます。
レトロフィット アップデート パッケージを受け取った OTA クライアントは、super_system.img
を物理 system_b
に、super_vendor.img
を物理 vendor_b
に、super_product.img
を物理 product_b
に適用します。
物理ブロック デバイス system_b
には、起動時に論理 system_b
、vendor_b
、product_b
にマッピングを行うための正しいメタデータが含まれています。
アップデート パッケージを生成する
増分 OTA
レトロフィット デバイスの増分 OTA を生成する場合、アップデートはベースビルドで PRODUCT_USE_DYNAMIC_PARTITIONS
および PRODUCT_RETROFIT_DYNAMIC_PARTITIONS
を定義しているかどうかによって異なります。
-
ベースビルドが変数を定義していない場合、これはレトロフィット アップデートです。アップデート パッケージには分割された
super.img
ファイルが含まれ、インストール後の手順が無効になります。 - ベースビルドで変数を定義している場合は、動的パーティションの通常の更新と同じです。アップデート パッケージには、論理(動的)パーティションのイメージが含まれます。インストール後の手順を有効にできます。
フル OTA
2 つのフル 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 パッケージを拒否しません。
デバイスがフル 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
を実行し、アップデートを拒否します。