Google はどのデバイスでも A/B OTA を使用していますか?
はい。A/B アップデートのマーケティング名は「シームレス アップデート」です。2016 年 10 月以降の Google Pixel および Google Pixel XL スマートフォンでは A/B が使用されており、すべての Chromebook では A/B の同じ update_engine
実装が使用されています。必要なプラットフォーム コードの実装は Android 7.1 以上で公開されています。
A/B OTA のメリットは何ですか?
A/B OTA により、アップデート時のユーザー エクスペリエンスが向上します。毎月のセキュリティ アップデートの統計を見ると、この機能が効果を上げていることがわかります。2017 年 5 月現在、Google Pixel ユーザーの 95% が最新のセキュリティ アップデートを 1 か月以内に実施しているのに対し、Nexus ユーザーでは 87% です。さらに、Google Pixel ユーザーは Nexus ユーザーより早くアップデートを実施しています。OTA でブロックのアップデートが失敗するとデバイスが起動しない問題は解消しました。Android は、新しいシステム イメージが正常に起動するまで、以前の正常に機能するシステム イメージにフォールバックする機能を維持します。
system_other とは何ですか?
アプリは .apk ファイルに格納され、.apk は実際には ZIP アーカイブされます。各 .apk ファイルの内部には、移植可能な Dalvik バイトコードを含む 1 つ以上の .dex ファイルがあります。.odex(最適化された .dex)ファイルは .apk ファイルとは別に存在し、デバイス固有のマシンコードを含むことができます。.odex ファイルが利用可能な場合、Android はアプリを起動するたびにコードがコンパイルされるのを待たずに、事前コンパイルによりアプリの実行を高速化できます。.odex ファイルは厳密には必須ではありません。Android は、実際にはインタープリテーションまたはジャストインタイム(JIT)コンパイルにより .dex コードを直接実行できますが、.odex ファイルを利用すると、空き領域がある場合は起動時間と実行速度の最適な組み合わせを達成できます。
たとえば、Android 7.1 を搭載した Nexus 6P の installed-files.txt の合計システム イメージ サイズが 2,628 MiB(2,755,792,836 バイト)である場合、ファイル形式をシステム イメージ サイズ全体に占める内訳が大きい順に並べると、次のようになります。
.odex | 1,391,770,312 バイト | 50.5% |
.apk | 846,878,259 バイト | 30.7% |
.so(ネイティブ C/C++ コード) | 202,162,479 バイト | 7.3% |
.oat ファイルまたは .art イメージ | 163,892,188 バイト | 5.9% |
フォント | 38,952,361 バイト | 1.4% |
icu ロケールデータ | 27,468,687 バイト | 0.9% |
上記の数値は他のデバイスでも同様であり、Nexus / Google Pixel デバイスの場合、.odex ファイルがシステム パーティションの約半分を占めます。したがって、Google は引き続き ext4 を使用する予定ですが、出荷時に .odex ファイルを B パーティションに書き込み、初回起動時に /data
にコピーします。ext4 A/B で使用されている実際のストレージは、SquashFS A/B と同等です。なぜなら、仮に SquashFS を使用したとすれば、system_b ではなく system_a に事前最適化済みの .odex ファイルを書き込んで出荷したはずだからです。
/data に .odex ファイルをコピーするということは、/system で削減した容量が /data で使用されることになりませんか?
必ずしもそうではありません。Google Pixel では、.odex ファイルが占める領域のほとんどはアプリ用であり、通常は /data
に存在します。これらのアプリは Google Play でアップデートされるので、システム イメージ上の .apk ファイルと .odex ファイルは、デバイスの耐用期間のほとんどで使用されません。ユーザーが実際に個々のアプリを使用するとき、このようなファイルは完全に除外して小さなプロファイル ドリブンの .odex ファイルに置き換えることができます(したがって、ユーザーが使用しないアプリに空き領域は必要ありません)。詳細については、Google I/O 2016 の ART の進化に関する講演をご覧ください。
比較が難しい主な理由は次のとおりです。
- Google Play でアップデートされるアプリは、最初のアップデートを受信した時点で、必ず .odex ファイルを
/data
にすでに保持しています。 - ユーザーが実行しないアプリでは、.odex ファイルはまったく必要ありません。
- プロファイル ドリブン コンパイルでは、事前コンパイルの場合より小さい .odex ファイルが生成されます(これは、前者ではパフォーマンスに直結するコードのみが最適化されるためです)。
OEM が利用できる調整オプションの詳細については、ART を設定するをご覧ください。
.odex ファイルのコピーが /data に 2 つあることになりませんか?
これは少々複雑です。新しいシステム イメージが書き込まれると、新しいバージョンの dex2oat が新しい .dex ファイルに対して実行され、新しい .odex ファイルが生成されます。これは、古いシステムがまだ稼働しているときに行われるので、古い .odex ファイルと新しい .odex ファイルの両方が同時に /data
に存在することになります。
OtaDexoptService(frameworks/base/+/main/services/core/java/com/android/server/pm/OtaDexoptService.java
)のコードは、/data
が容量不足になるのを防ぐため、getAvailableSpace
を呼び出した後で各パッケージを最適化します。なお、ここでの Available(利用可能)というのは大まかな表現であり、厳密には通常のシステム最小容量しきい値に達するまでに残っている空き容量を指します(パーセンテージとバイト数の両方で測定されます)。/data
がいっぱいの場合、すべての .odex ファイルのコピーが 2 つ保持されることはありません。同じコードには BULK_DELETE_THRESHOLD も含まれています。前述のようにデバイスの空き領域がなくなりそうになると、使用されていないアプリに属する .odex ファイルは削除されます。この場合も、すべての .odex ファイルのコピーが 2 つ保持されることはありません。
最悪のケースとして /data
の空き領域が完全になくなった場合、デバイスが新しいシステムで再起動して古いシステムの .odex ファイルが不要になるまで、アップデートは保留になります。これは PackageManager によって処理されます(frameworks/base/+/main/services/core/java/com/android/server/pm/PackageManagerService.java#7215
)。新しいシステムが正常に起動したら、installd
(frameworks/native/+/main/cmds/installd/dexopt.cpp#2422
)は、古いシステムで使用されていた .odex ファイルを削除し、デバイスをコピーが 1 つのみの定常状態に戻すことができます。
このように、/data
にすべての .odex ファイルのコピーが 2 つ存在する状況が発生することはありますが、それは(a)一時的であり、(b)/data
に十分な空き容量がある場合に限られます。アップデート中を除けば、存在するコピーは 1 つだけです。また、ART の一般的な堅牢性機能が原因で、/data
が .odex ファイルでいっぱいになることはありません(そうなれば、非 A/B システムでも問題になるからです)。
この書き込みとコピーでフラッシュ メモリの摩耗が激しくなりませんか?
書き換えられるのはフラッシュ メモリのごく一部です。Google Pixel システムのフル アップデートでは、約 2.3 GiB が書き込まれます(アプリも再コンパイルされますが、これは非 A/B でも同じです)。従来のブロックベースのフル OTA でも同様の量のデータを書き込んでいたため、フラッシュ メモリの摩耗率は同程度です。
2 つの system パーティションにフラッシュすることで、出荷時にフラッシュする時間は増えますか?
いいえ。Google Pixel ではシステム イメージのサイズは増えていません(領域が 2 つのパーティションに分割されただけです)。
B パーティションに .odex ファイルを保持することで、データの初期化後の再起動は遅くなりませんか?
はい。実際にデバイスを使用して OTA アップデートを行い、データを初期化した場合、Google Pixel XL では最初の再起動は 1 分 40 秒かかり、初期化しなかった場合の 40 秒より遅くなります。これは、最初の OTA 後に B から .odex ファイルがなくなっているため、/data
にコピーできないからです。これはトレードオフの問題です。
データの初期化は通常の起動と異なり、まれにしか行わないので、所要時間はそれほど重要な問題にはなりません(この問題は、工場出荷状態のデバイスを入手したユーザーまたはレビューアには影響しません。その場合、B パーティションが利用可能だからです)。JIT コンパイラを使用しているということは、すべてを再コンパイルする必要がないことを意味します。したがって、トレードオフとしてはそれほど悪くありません。また、マニフェスト(frameworks/base/+/main/packages/SystemUI/AndroidManifest.xml#23
)で coreApp="true"
を指定して、アプリを「事前コンパイルが必要」としてマークすることもできます。これは現在 system_server
で使用されています。セキュリティ上の理由から JIT コンパイルが許可されていないからです。
.odex ファイルを /system ではなく /data で保持することで、OTA 後の再起動が遅くなりませんか?
いいえ。前述のように、古いシステム イメージがまだ稼働している間に新しい dex2oat が実行され、新しいシステムで必要なファイルが生成されます。その作業が完了するまで、アップデートは利用不可と見なされます。
32 GiB の A/B デバイスを出荷できますか(出荷するべきですか)?16 GiB や 8 GiB はどうですか?
32 GiB で問題がないことは Google Pixel で実証済みです。16 GiB 中の 320 MiB は 2% の減少に相当します。同様に、8 GiB 中の 320 MiB は 4% の減少に相当します。320 MiB のオーバーヘッドは利用可能な全容量のほぼ 10% であるため、4 GiB のデバイスでは A/B をおすすめしません。
AVB2.0 では A/B OTA が必要ですか?
いいえ。Android の確認付きブートでは、ブロックベースのアップデートは必須ですが、A/B アップデートは必須ではありません。
A/B OTA には AVB2.0 が必要ですか?
いいえ。必要ありません。
A/B OTA によって AVB2.0 のロールバック保護は無効になりますか?
いいえ。A/B システムが新しいシステム イメージで起動できない場合、(ブートローダーによって決められた回数だけ再試行された後で)自動的に「以前の」システム イメージに戻りますが、この点が誤解を招いているようです。ここで重要なのは、A/B にとっての「以前」とは、実際には「現在」のシステム イメージであるということです。デバイスが新しいイメージを正常に起動すると、直ちにロールバック保護が起動し、元に戻せなくなります。しかし、実際に新しいイメージの起動が正常に完了するまで、ロールバック保護は新しいイメージを現在のシステム イメージと見なしません。
システムの稼働中にアップデートをインストールすると、動作が遅くなりますか?
非 A/B アップデートでは、アップデートの適用中はユーザーがデバイスを使用できずに待機しているため、できるだけ早くアップデートをインストールしようとします。A/B アップデートではその逆です。ユーザーがデバイスを使用中であるため、できるだけ影響を少なくするようにアップデートを意図的に遅くします。また、Android は、Java システム アップデート クライアント(Google の場合は、GMS が提供するコアパッケージである GmsCore)のロジックを使用して、ユーザーがデバイスをまったく使用していない時間を選択しようと試みます。プラットフォームはアップデートの一時停止と再開をサポートしています。クライアントはそれを利用して、ユーザーがデバイスの使用を開始したらアップデートを一時停止し、デバイスが再びアイドル状態になったらアップデートを再開できます。
実行中の OTA には 2 つのフェーズがあり、UI の進行状況バーの下に [Step 1 of 2] および [Step 2 of 2] として表示されます。ステップ 1 はデータブロックの書き込みに対応し、ステップ 2 は .dex ファイルのプリコンパイルに対応します。この 2 つのフェーズでは、パフォーマンスへの影響が大きく異なります。1 つ目のフェーズはシンプルな I/O です。ブロックを低速でコピーするだけであるため、リソース(RAM、CPU、I/O)はそれほど必要ありません。
2 つ目のフェーズでは dex2oat が実行され、新しいシステム・イメージがプリコンパイルされます。実際のアプリをコンパイルするので、必要なリソースに明確な限度はありません。フェーズ 1 では、他のディスク ブロックより大きいディスク ブロックや複雑なディスク ブロックはありません。一方、フェーズ 2 では、大規模で複雑なアプリをコンパイルする場合、小規模で単純なアプリをコンパイルする場合より、当然ながらはるかに多くの作業が行われます。
このプロセスは、Google Play によってアプリのアップデートがバックグラウンドでインストールされ、5 個のアプリがアップデートされたという通知が表示されるときのプロセス(これまで数年間行われているプロセス)と同様です。
ユーザーがアップデートを待っている場合はどうなりますか?
GmsCore の現在の実装では、バックグラウンド アップデートとユーザーが開始するアップデートは区別されませんが、将来的には区別される可能性があります。ユーザーがアップデートのインストールを明確に要求している場合、またはアップデートの進行状況画面を表示している場合は、ユーザーが実際にアップデートの完了を待っていると仮定して、アップデート処理を優先する予定です。
アップデートの適用に失敗した場合はどうなりますか?
非 A/B アップデートでは、アップデートの適用に失敗した場合、通常はデバイスが使用できないままでした。唯一の例外は、(パッケージが検証で不合格だったなどの原因で)アプリの開始前にエラーが発生した場合でした。A/B アップデートでは、アップデートの適用に失敗しても、現在稼働中のシステムには影響しません。後で簡単にアップデートを再試行できます。