タスク スナップショット

タスク スナップショットは、Android 8.0 で導入されたインフラストラクチャで、Recents Thumbnails のスクリーンショットと、Window Manager からの Saved Surfaces を組み合わせたものです。Recents Thumbnails は、[最近] ビュー内のタスクの最後の状態を表します。

アクティビティが停止状態になったとき、そのアクティビティがタスクの一番上に配置されている限り、Window Manager はアクティビティのサーフェスを破棄しません。このアクティビティを再度表示する必要がある場合、Window Manager は、この Saved Surfaces を使用できるため、最初のフレームの描画が完了するのを待たずにアニメーションを開始できます。

アーキテクチャ

Recents Thumbnails と Saved Surfaces という 2 つのコンセプトは、タスク スナップショットに統合されています。タスクがバックグラウンドに移行すると、このタスクのスクリーンショットが GraphicsBuffer に配置されます。タスクのトップレベルのアクティビティがメモリに残っている限り、この GraphicsBuffer はメモリに保持されます。同じアクティビティがもう一度前面に表示されると、Window Manager が開始ウィンドウ(TaskSnapshotSurface)を作成し、開始ウィンドウのバッファキューにメモリをコピーせずに GraphicsBuffer をアタッチします。アクティビティが最初のフレームを描画するとすぐに、タスク スナップショットの開始ウィンドウが通常のスプラッシュ画面のようにスムーズにフェードアウトします。

また、同じ GraphicsBuffer がバインダを介して SystemUI にも送信され、Recents ビューにタスクのプレビュー状態を描画するために使用されます。これはあくまでバッファへの参照であるため、Binder 経由で送信すると、一部のリソースが消費されます。GraphicBuffer が SystemUI に届くと、ハードウェア ビットマップにラップされ、グラフィック メモリにメモリをアップロードせずに画面に描画されます。

メリット

この新しいアーキテクチャには主に 3 つのメリットがあります。

  • タスク スナップショットが開始ウィンドウとして使用される場合は、スナップショットと実際のコンテンツの間に効果的なクロスフェードが生じます。
  • タスク スナップショットを SystemUI で描画する場合は、コピーせずに実行できます。以前は、ビットマップを Ashmem にコピーし、次にグラフィック メモリにコピーしなければなりませんでした。このメソッドではスナップショットをグラフィック メモリに直接保存するため、コピーは必要ありません。
  • [最近] の状態は、アプリを再起動すると最初に表示される状態と常に一致します。同じバッファがあることで多くのメモリを節約できます。 そのため、[最近] ビューでは画像をフル解像度で表示できます。 以前は、メモリを節約するために画素数が 64% 間引きされていました。

実装

この機能は、すべて Android プラットフォームに組み込まれています。統合は不要です。また、カスタマイズはサポートされていません。ただし、デバイス メーカーはタスク スナップショット機能を完全に無効にできます。

この機能を無効にするには、次の関数を変更します。

frameworks/base/services/core/java/com/android/server/wm/TaskSnapshotController.java#215

なお、この機能を無効にすると、[最近] ビューにサムネイルが表示されなくなります。

高解像度と低解像度のスナップショット

タスク スナップショットは、2 つのスケールでディスクに書き込まれます。ディスクからタスク スナップショットを復元すると、低解像度のスナップショットが読み取られ、その後対応する高解像度のスナップショットに置換されます。この最適化によって画像の読み込み時間を短縮できます。 そうしないと、ディスクからスナップショット ファイルを読み取るときに少し時間がかかることがあります。また、画像が使用可能になるまでユーザーに空白のタスクカードが表示されることもあります。 デバイス オーバーレイ構成ファイル overlay/frameworks/base/core/res/res/values/config.xmlconfig_highResTaskSnapshotScaleconfig_lowResTaskSnapshotScale を設定することで、スケーリングを構成できます。デフォルトでは、1.0 と 0.5 にそれぞれ設定されています。低解像度のスナップショットを無効にするには、config_lowResTaskSnapshotScale を 0.0 に設定します。

例とソース

この機能に関する他のコードは、次の場所にある TaskSnapshot* ファイル内で検索してください。

frameworks/base/+/master/services/core/java/com/android/server/wm/