非 A/B システム アップデート

非 AB アップデートは、古い Android デバイス(Android 6 以前)で使用されていた廃止された OTA 手法です。これらのデバイスには専用のリカバリ パーティションがあり、ダウンロードしたアップデート パッケージを解凍して他のパーティションにアップデートを適用するために必要なソフトウェアがそこに含まれています。

A/B パーティションのない古い Android デバイスでは、通常、フラッシュ領域に次のパーティションが含まれます。

boot
Linux カーネルと最小限のルート ファイル システム(RAM ディスクに読み込まれる)が格納されています。system パーティションとその他のパーティションをマウントし、system パーティション上でランタイムを開始します。
system
Android オープンソース プロジェクト(AOSP)で利用できるソースコードを含むシステム アプリケーションとライブラリが格納されています。通常のオペレーションでは、このパーティションは読み取り専用としてマウントされ、そのコンテンツは OTA アップデート中にのみ変更されます。
vendor
Android オープンソース プロジェクト(AOSP)で利用できるソースコードを含まない、システム アプリケーションとライブラリが格納されています。通常のオペレーションでは、このパーティションは読み取り専用としてマウントされ、そのコンテンツは OTA アップデート中にのみ変更されます。
userdata
ユーザーがインストールしたアプリによって保存されたデータが格納されています。通常、このパーティションは OTA アップデート プロセスでは処理されません。
cache
一部のアプリケーションにより、ダウンロードされた OTA アップデート パッケージの保存に使用される一時保留領域です。このパーティションへのアクセスには特別なアプリ権限が必要です。他のプログラムがこの領域を使用する場合は、ファイルがすぐに消えてしまうことを想定します。一部の OTA パッケージのインストールにより、このパーティションが完全にワイプされることがあります。この cache には、OTA アップデートのアップデート ログも格納されます。
recovery
予備の Linux システム完全版が格納されています。このシステムには、カーネル、パッケージを読み取ってそのコンテンツを使用して他のパーティションを更新する特殊なリカバリ バイナリが含まれます。
misc
OTA パッケージを適用している間にデバイスが再起動された場合に、リカバリが、その時点で行われていたオペレーションに関する情報を保管できる小さなパーティションです。

OTA アップデートのライフサイクル

一般的な OTA アップデートには、次の手順が含まれます。

  1. デバイスにより OTA サーバーが定期的にチェックされます。アップデート パッケージの URL とユーザーに表示する説明文などとともに、更新の可否が通知されます。
  2. アップデートは cashe パーティションまたはデータ パーティションにダウンロードされ、その暗号署名を /system/etc/security/otacerts.zip にある証明書を使用して検証します。ユーザーはアップデートをインストールするよう求められます。
  3. デバイスがリカバリモードで再起動し、起動パーティションのカーネルではなく、リカバリ パーティションのカーネルとシステムが起動します。
  4. リカバリ バイナリは init によって開始され、ダウンロードされたパッケージにそれをポイントするコマンドライン引数を、/cache/recovery/command 内で検出します。
  5. リカバリでは、パッケージの暗号署名が /res/keys(recovery パーティションに含まれる RAM ディスクの一部)にある公開鍵と照合されます。
  6. データはパッケージから取得され、必要に応じて boot、system、vendor パーティションの更新に使用されます。system パーティションに残っている新しいファイルの 1 つに、新しい recovery パーティションのコンテンツが格納されます。
  7. デバイスは通常どおり再起動します。
    1. 新たに更新された boot パーティションが読み込まれ、新たに更新された system パーティション内のバイナリをマウントして開始します。
    2. 通常の起動時に、システムは recovery パーティションのコンテンツを、以前 /system 内にファイルとして保存されていたコンテンツと照合します。これらは異なるため、recovery パーティションは必要なコンテンツで再読み込みされます。次の起動時には、recovery パーティションにはすでに新しいコンテンツが含まれているため、再読み込みは必要ありません。

システム アップデートが完了しました。アップデート ログは /cache/recovery/last_log.# にあります。

アップデート パッケージ

アップデート パッケージは実行可能なバイナリ META-INF/com/google/android/update-binary を含む .zip ファイルです。パッケージの署名を確認したら、recovery はこのバイナリを /tmp に抽出してバイナリを実行し、次の引数を渡します。

  • アップデート バイナリ API のバージョン番号。引数がアップデート バイナリの変更に渡された場合、この数値が増えます。
  • コマンドパイプのファイル記述子。アップデート プログラムはこのパイプを使用して、リカバリ バイナリにコマンドを返信できます。多くの場合はユーザーに進行状況を知らせるなどの UI の変更についてです。
  • アップデート パッケージの .zip ファイルのファイル名

アップデート パッケージは、静的にリンクされたバイナリをアップデート バイナリとして使用できます。OTA パッケージ構築ツールでは、多数のインストール作業を実行できる簡単なスクリプト言語を提供するアップデータ プログラム(bootable/recovery/updater)を使用します。デバイス上で動作している他のバイナリに置き換えることができます。

アップデータ バイナリ、edify 構文、組み込み関数の詳細については、OTA パッケージの詳細を参照してください。

以前のリリースからの移行

Android 2.3 / 3.0 / 4.0 リリースからの移行での大きな変更点は、デバイス固有のすべての機能を C 関数のセットから C++ オブジェクトに変換したことです。次の表に、ほぼ同じ目的に使用する古い関数と新しいメソッドを示します。

C 関数 C++ メソッド
device_recovery_start() Device::RecoveryStart()
device_toggle_display()
device_reboot_now()
RecoveryUI::CheckKey()
(RecoveryUI::IsKeyPressed() も同様)
device_handle_key() Device::HandleMenuKey()
device_perform_action() Device::InvokeMenuItem()
device_wipe_data() Device::WipeData()
device_ui_init() ScreenRecoveryUI::Init()

古い関数を新しいメソッドに変換するのは簡単です。新しい make_device() 関数を追加して、新しいデバイスのサブクラスにインスタンスを作成して返すことを忘れないでください。