Google はどのデバイスでも A/B OTA を使用していますか?
はい。A/B アップデートのマーケティング名は「シームレス アップデート」です。2016 年 10 月以降の Pixel および Pixel XL スマートフォンでは A/B が使用されており、すべての Chromebook では A/B の同じ update_engine
実装が使用されています。必要なプラットフォーム コードの実装は Android 7.1 以上で公開されています。
A/B OTA のメリットは何ですか?
A/B OTA により、アップデート時のユーザー エクスペリエンスが向上します。毎月のセキュリティ アップデートの統計を見ると、この機能が効果を上げていることがわかります。2017 年 5 月現在、Pixel ユーザーの 95% が最新のセキュリティ アップデートを 1 か月以内に実施しているのに対し、Nexus ユーザーでは 87% です。さらに、Pixel ユーザーは Nexus ユーザーより早くアップデートを実施しています。OTA でブロックのアップデートが失敗するとデバイスが起動しない問題は解消しました。Android は、新しいシステム イメージが正常に起動するまで、以前の正常に機能するシステム イメージにフォールバックする機能を維持します。
A/B は 2016 年版の Pixel のパーティション サイズにどのような影響を与えましたか?
出荷時の A/B 構成と、内部的にテストされた非 A/B 構成の詳細な比較を次の表に示します。
Pixel のパーティション サイズ | A/B | 非 A/B |
---|---|---|
ブートローダー | 50×2 | 50 |
boot | 32×2 | 32 |
recovery | 0 | 32 |
cache | 0 | 100 |
radio | 70×2 | 70 |
vendor | 300×2 | 300 |
system | 2,048×2 | 4,096 |
合計 | 5,000 | 4,680 |
A/B アップデートに必要なフラッシュ メモリの増加はわずか 320 MiB であり、recovery パーティションの削除により 32 MiB、cache パーティションの削除により 100 MiB が削減されました。この削減により、ブートローダー、boot パーティション、radio パーティションにおける B パーティションの増加が相殺されます。vendor パーティションのサイズが倍増しました(これが全体のサイズ増加の大部分を占めています)。Pixel の A/B システム イメージのサイズは、元の非 A/B システム イメージの半分です。
内部的にテストされた Pixel A/B と非 A/B のバリアント(出荷されたのは A/B のみ)では、使用された領域の違いはわずか 320 MiB でした。32 GiB デバイスの場合、これは 1% 未満にすぎません。16 GiB デバイスの場合は 2% 未満、8 GiB デバイスの場合は 4% 近くになります(3 種類のデバイスがすべて同じシステム イメージを持つと仮定した場合)。
なぜ SquashFS を使用しなかったのですか?
SquashFS をテストしましたが、高性能デバイスに求められるパフォーマンスを達成できませんでした。Google は、ハンドヘルド デバイスに SquashFS を使用せず、おすすめもしません。
具体的には、SquashFS により system パーティションのサイズを約 50% 削減できましたが、効果的に圧縮できたファイルの大半はプリコンパイル済みの .odex ファイルでした。これらのファイルの圧縮率は非常に高い数値(80% 近く)に達しましたが、残りの system パーティションの圧縮率はかなり低いものでした。さらに、Android 7.0 では、SquashFS により次のようなパフォーマンス上の懸念事項が確認されました。
- Pixel は以前のデバイスと比べて非常に高速のフラッシュ メモリを搭載していますが、予備の CPU サイクル数はそれほど多くありません。そのため、フラッシュ メモリから読み取れるバイト数は比較的少なく、I/O 用にもっと多くの CPU が必要になることが潜在的なボトルネックになりました。
- 負荷のないシステムでの人為的なベンチマークでは高い成績を示す I/O の変更は、Nexus 6 における暗号化のような実際の負荷がかかる現実的なユースケースでは、うまく機能しません。
- ベンチマークでは、85% の回帰を示すケースもありました。
SquashFS は成熟しつつあり、CPU への影響を軽減する機能(圧縮すべきでない、よくアクセスされるファイルのホワイトリストなど)を追加しているため、Google は今後も評価を継続してデバイス メーカーに推奨する予定です。
SquashFS なしでどのように system パーティションのサイズを半分にしたのですか?
アプリは .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 / Pixel デバイスの場合、.odex ファイルがシステム パーティションの約半分を占めます。したがって、Google は引き続き ext4 を使用する予定ですが、出荷時に .odex ファイルを B パーティションに書き込み、初回起動時に /data
にコピーします。ext4 A/B で使用されている実際のストレージは、SquashFS A/B と同等です。なぜなら、仮に SquashFS を使用したとすれば、system_b ではなく system_a に事前最適化済みの .odex ファイルを書き込んで出荷したはずだからです。
/data に .odex ファイルをコピーするということは、/system で削減した容量が /data で使用されることになりませんか?
必ずしもそうではありません。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/+/master/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/+/master/services/core/java/com/android/server/pm/PackageManagerService.java#7215
)。新しいシステムが正常に起動したら、installd
(frameworks/native/+/master/cmds/installd/dexopt.cpp#2422
)は、古いシステムで使用されていた .odex ファイルを削除し、デバイスをコピーが 1 つのみの定常状態に戻すことができます。
このように、/data
にすべての .odex ファイルのコピーが 2 つ存在する状況が発生することはありますが、それは(a)一時的であり、(b)/data
に十分な空き容量がある場合に限られます。アップデート中を除けば、存在するコピーは 1 つだけです。また、ART の一般的な堅牢性機能が原因で、/data
が .odex ファイルでいっぱいになることはありません(そうなれば、非 A/B システムでも問題になるからです)。
この書き込みとコピーでフラッシュ メモリの摩耗が激しくなりませんか?
書き換えられるのはフラッシュ メモリのごく一部です。Pixel システムのフル アップデートでは、約 2.3 GiB が書き込まれます(アプリも再コンパイルされますが、これは非 A/B でも同じです)。従来のブロックベースのフル OTA でも同様の量のデータを書き込んでいたため、フラッシュ メモリの摩耗率は同程度です。
2 つの system パーティションにフラッシュすることで、出荷時にフラッシュする時間は増えますか?
いいえ。Pixel ではシステム イメージのサイズは増えていません(領域が 2 つのパーティションに分割されただけです)。
B パーティションに .odex ファイルを保持しないと、データの初期化後の再起動は遅くなりますか?
はい。実際にデバイスを使用して OTA アップデートを行い、データを初期化した場合、Pixel XL では最初の再起動は 1 分 40 秒かかり、初期化しなかった場合の 40 秒より遅くなります。これは、最初の OTA 後に B から .odex ファイルがなくなっているため、/data
にコピーできないからです。これはトレードオフの問題です。
データの初期化は通常の起動と異なり、まれにしか行わないので、所要時間はそれほど重要な問題にはなりません(この問題は、工場出荷状態のデバイスを入手したユーザーまたはレビューアには影響しません。その場合、B パーティションが利用可能だからです)。JIT コンパイラを使用しているということは、すべてを再コンパイルする必要がないことを意味します。したがって、トレードオフとしてはそれほど悪くありません。また、マニフェスト(frameworks/base/+/master/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 で問題がないことは 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 アップデートでは、アップデートの適用に失敗しても、現在稼働中のシステムには影響しません。後で簡単にアップデートを再試行できます。
どのシステム オン チップ(SoC)が A/B に対応していますか?
2017 年 3 月 15 日現在の情報は次のとおりです。
Android 7.x 以前 | Android 8.x 以降 | |
Qualcomm | OEM のリクエストに依存 | すべてのチップセットのサポートを予定 |
Mediatek | OEM のリクエストに依存 | すべてのチップセットのサポートを予定 |
スケジュールの詳細については、SoC の連絡先にお問い合わせください。上記以外の SoC については、SoC に直接お問い合わせください。