A/B システム アップデートを実装しようとする OEM や SoC ベンダーは、ブートローダーが boot_control HAL を実装し、正しいパラメータをカーネルに渡すようにします。
ブート コントロール HAL の実装
A/B 対応ブートローダーは、boot_control
HAL を hardware/libhardware/include/hardware/boot_control.h
に実装する必要があります。実装をテストするには、system/extras/bootctl
ユーティリティおよび system/extras/tests/bootloader/
を使用します。
次の状態マシンも実装する必要があります。
カーネルのセットアップ
A/B システム アップデートを実装するには、次の手順を行います。
-
次のカーネルパッチ シリーズから選び出します(必要な場合のみ)。
- 起動に ramdisk を使用せず、「boot as recovery」を使用している場合、android-review.googlesource.com/#/c/158491/ を確認して必要な対応を選びます。
- ramdisk なしで dm-verity を設定するには、android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18 を確認して必要な対応を選びます。
-
カーネル コマンドライン引数に次の追加の引数が含まれていることを確認します。
この引数のskip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
<public-key-id>
値は、verity テーブルの署名の検証に使用する公開鍵の ID です。詳細は、dm-verity をご覧ください。 -
公開鍵を含む .X509 証明書をシステム キーリングに追加します。
-
X509 証明書を
.der
の形式でkernel
ディレクトリのルートにコピーします。X509 証明書が.pem
ファイル形式の場合、次のようにopenssl
コマンドを使用して.pem
形式から.der
形式に変換します。openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
-
zImage
をビルドし、システム キーリングの一部としてこの証明書を含めます。検証するには、procfs
エントリを確認します。KEYS_CONFIG_DEBUG_PROC_KEYS
を有効にする必要があります。 X509 証明書が正常に登録されると、システム キーリングに公開鍵が存在することを示します。ハイライトは公開鍵 ID を示します。angler:/# cat /proc/keys 1c8a217e I------ 1 perm 1f010000 0 0 asymmetri Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f [] 2d454e3e I------ 1 perm 1f030000 0 0 keyring .system_keyring: 1/4
-
スペースを
#
に置き換えて、これをカーネル コマンドラインで<public-key-id>
として渡します。たとえば、<public-key-id>
の代わりにAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
を渡します。
-
X509 証明書を
ビルド変数の設定
A/B 対応ブートローダーは、次のビルド変数基準を満たす必要があります。
A/B ターゲットでの定義が必要 |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk を参照します。コンパイルで説明したインストール後(ただし再起動前)の dex2oat 手順を任意で実行できます。 |
---|---|
A/B ターゲットに強く推奨 |
|
A/B ターゲットでの定義不可 |
|
デバッグビルドの場合は任意 | PRODUCT_PACKAGES_DEBUG += update_engine_client |
パーティション(スロット)の設定
A/B デバイスでは、リカバリ パーティションやキャッシュ パーティションは不要です。Android ではこれらのパーティションを使用しなくなりました。データ パーティションはダウンロードされた OTA パッケージで使用され、リカバリ イメージコードが起動パーティションに追加されました。A/B 化されたパーティションにはすべて、次のような名前を付ける必要があります(スロットには常に a
、b
などを付ける)。boot_a
、boot_b
、system_a
、system_b
、vendor_a
、vendor_b
。
キャッシュ
非 A/B アップデートでは、ダウンロードされた OTA パッケージを保存し、アップデートの適用中にブロックを一時的に保管するためにキャッシュ パーティションを使用していました。キャッシュ パーティションのサイズを決めるのに適した方法はありませんでした。適用するアップデートの種類によって必要なサイズが変わるからです。最悪のケースでは、キャッシュ パーティションがシステム イメージと同じくらいのサイズになります。A/B アップデートでは、ブロックを保存する必要はありません。必ず現在は使用していないパーティションに書き込むからです。また、A/B ストリーミングを行うことで適用前に OTA パッケージ全体をダウンロードする必要はありません。
リカバリ
リカバリ RAM ディスクは、boot.img
ファイルに含まれています。リカバリ中は、ブートローダーはカーネル コマンドラインに skip_initramfs
オプションを使用できません。
非 A/B アップロードの場合、リカバリ パーティションにはアップデートを適用するためのコードが含まれます。A/B アップロードは、通常の起動システム イメージで実行される update_engine
によって適用されます。データの初期化とアップデート パッケージのサイドローディングを行う、「リカバリ」の名前の由来になったリカバリモード(Recovery mode)も残っています。リカバリモード(Recovery mode)のコードとデータは、ramdisk にある通常の起動パーティションに保存されます。システム イメージに起動するため、ブートローダーがカーネルに ramdisk をスキップするように指示します。そうしないと、デバイスはリカバリモード(Recovery mode)で起動します。リカバリモード(Recovery mode)のサイズは小さく、大部分はすでに起動パーティションにあるため、起動パーティションのサイズは大きくなりません。
Fstab
A/B パーティションでは slotselect
引数を指定する必要があります。次に例を示します。
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
パーティションに vendor
という名前を付けないでください。代わりに、パーティション vendor_a
または vendor_b
という名前を選び、/vendor
マウント ポイントにマウントします。
カーネル スロットの引数
現在のスロットの接尾辞は、特定のデバイスツリー(DT)ノード(/firmware/android/slot_suffix
)を介して、あるいは androidboot.slot_suffix
カーネル コマンドラインまたは bootconfig 引数を介して渡す必要があります。
デフォルトでは、fastboot は A/B デバイスに現在のスロットを書き込みます。更新パッケージに現在のスロットではない他のスロットのイメージも含まれている場合、fastboot はそれらのイメージも同様に書き込みます。次のオプションが利用可能です。
-
--slot SLOT
。デフォルトの動作をオーバーライドし、引数として渡されたスロットを書き込むよう fastboot にプロンプトします。 -
--set-active [SLOT]
。スロットをアクティブに設定します。オプションの引数が指定されていない場合、現在のスロットがアクティブとして設定されます。 fastboot --help
。コマンドの詳細を確認します。
ブートローダーが fastboot を実装している場合、指定したスロットを現在のアクティブ スロットに設定する set_active <slot>
コマンドをサポートしている必要があります。これによりスロットの起動不能フラグもクリアされ、再試行回数をデフォルト値にリセットします。ブートローダーは、次の変数もサポートしている必要があります。
-
has-slot:<partition-base-name-without-suffix>
。指定されたパーティションがスロットをサポートしている場合は「yes」、そうでない場合は「no」を返します。 current-slot
。次回から起動するスロットの接尾辞を返します。-
slot-count
。使用可能なスロット数を表す整数を返します。現在、2 つのスロットがサポートされているため、この値は2
です。 -
slot-successful:<slot-suffix>
。指定されたスロットが正常に起動した場合は「yes」を返し、それ以外の場合は「no」を返します。 -
slot-unbootable:<slot-suffix>
。指定されたスロットが起動不可とマークされた場合は「yes」を返し、それ以外の場合は「no」を返します。 -
slot-retry-count:<slot-suffix>
。あと何回、指定スロットの起動を再試行するかを示します。
すべての変数を表示するには、fastboot getvar all
を実行します。
OTA パッケージの生成
OTA パッケージ ツールは、非 A/B デバイスのコマンドと同じコマンドが使用できます。target_files.zip
ファイルは A/B ターゲットのビルド変数を定義して生成する必要があります。OTA パッケージ ツールは、A/B アップデータの形式でパッケージを自動的に識別して生成します。
例:
-
フル OTA を生成するには、次のようにします。
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip
-
増分 OTA を生成するには、次のようにします。
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
パーティションの設定
update_engine
を使用して同じディスク内に定義された A/B パーティションのペアを更新できます。パーティションのペアには、共通の接頭辞(system
や boot
など)とスロットごとの接尾辞(_a
など)が付いています。ペイロード ジェネレータがアップデートを定義するパーティションのリストは、AB_OTA_PARTITIONS
make 変数により設定されます。
たとえば、パーティション bootloader_a
と booloader_b
のペアが含まれる場合(_a
と _b
はスロットの接尾辞)、これらのパーティションを更新するには、サービスまたはボードの設定で次のように指定します。
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
update_engine
により更新されたすべてのパーティションは、システムの他の部分からは変更しないでください。増分アップデートまたは差分アップデートの間、現在のスロットからのバイナリデータは新しいスロットのデータの生成に使用されます。更新処理中に変更を行うと、新しいスロットデータが確認できず、更新が失敗することがあります。
インストール後手順の設定
更新されたパーティションごとに、一連の Key-Value ペアを使用して、インストール後の手順を別々に設定できます。新しいイメージ内の /system/usr/bin/postinst
にあるプログラムを実行するには、システム パーティション内のファイル システムのルートからの相対パスを指定します。
たとえば、usr/bin/postinst
は system/usr/bin/postinst
を表します(RAM ディスクを使用していない場合)。さらに、ファイル システム タイプを指定して、mount(2)
システムコールに渡します。サービスまたはデバイスの .mk
ファイルに次を追加します(該当する場合)。
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
アプリのコンパイル
アプリをバックグラウンドでコンパイルして新しいシステム イメージに再起動できます。バックグラウンドでアプリをコンパイルするには、サービスの device.mk にあるデバイス設定に次の行を追加します。
-
コンパイル スクリプトとバイナリがコンパイルされ、システム イメージに含まれるように、ビルドにネイティブ コンポーネントを含めます。
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
-
コンパイル スクリプトを、インストール後の手順として実行する
update_engine
とひも付けします。# A/B OTA dexopt update_engine hookup AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=system/bin/otapreopt_script \ FILESYSTEM_TYPE_system=ext4 \ POSTINSTALL_OPTIONAL_system=true
未使用の 2 番目のシステム パーティションに事前に選択したファイルをインストールする方法については、DEX_PREOPT ファイルの最初の起動インストールをご覧ください。