任务快照

任务快照是在 Android 8.0 中引入的基础架构,可将窗口管理器中的最近任务缩略图和已保存表面这两者的屏幕截图进行合并。最近任务缩略图会在“最近”视图中呈现任务的最后状态。

过去,当有 activity 进入停止状态时,只要该 activity 位于任务顶层,窗口管理器就不会销毁该 activity 的 Surface。如果该 activity 必须再次显示,窗口管理器便能够启动相应动画,而无需等待该 activity 绘制完其第一帧,因为它能够使用这个已保存 Surface。

架构

通过任务快照,最近任务缩略图和已保存表面这两个概念合并在了一起。当有任务进入后台时,窗口管理器会将该任务的屏幕截图放入一个图形缓冲区中。只要任务顶层 activity 的应用保留在内存中,该图形缓冲区就会保留在内存中。现在,当同一个 activity 再次回到前面时,窗口管理器将会创建一个起始窗口 (TaskSnapshotSurface) 并附加图形缓冲区,而无需将任何内存复制到起始窗口的缓冲区队列。一旦该 Activity 绘制了其第一帧,任务快照起始窗口就会立即像常规启动画面一样平滑淡出。

系统还会将同一个图形缓冲区通过 Binder 发送到 SystemUI,以用于在“最近”视图中绘制任务的预览状态。由于这只是对缓冲区的引用,因此通过 Binder 发送它只需要多占用很少的资源。当该图形缓冲区到达 SystemUI 时,将会被封装到硬件位图中,然后被绘制到屏幕上,而无需将任何内存上传到显存。

优点

这种新架构有以下三个主要优点:

  • 如果将任务快照用作起始窗口,快照和实际内容之间会有一个很好的交叉淡入淡出过程。
  • 在 SystemUI 中绘制任务快照时,无需进行任何复制操作即可完成。以前则必须将位图复制到 Ashmem 中,然后再复制到图形内存。由于这种方法是将快照直接存储在显存中,因此无需进行任何复制操作。
  • 您在“最近”视图中看到的状态始终会与您在重新打开应用时首先看到的状态一致。拥有相同的缓冲区还能够节省大量内存。这就是“最近”视图现在能够以完整分辨率显示这些图像的原因。以前,系统会将采样减少 64% 以节省内存。

实现

该功能完全位于 Android 平台中。不需要集成,且不支持自定义。不过,设备制造商可以完全停用任务快照功能。

如需停用该功能,请修改以下函数:

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

请注意,如果该功能被停用,“最近”视图将不会显示任何缩略图。

高分辨率快照和低分辨率快照

任务快照以两种比例写入磁盘。从磁盘恢复任务快照时,会先读取低分辨率快照,然后将其替换为对应的高分辨率快照。这项优化可缩短映像加载时间。否则,从磁盘读取快照文件时可能会有轻微的延迟,并且在映像可用之前,用户将看到一张空白任务卡。您可以通过设置 config_highResTaskSnapshotScaleconfig_lowResTaskSnapshotScale,在设备叠加层配置文件 overlay/frameworks/base/core/res/res/values/config.xml 中配置比例。默认情况下,这两个值分别设置为 1.0 和 0.5。将 config_lowResTaskSnapshotScale 设置为 0.0 可停用低分辨率快照。

示例和源代码

您可以在位于以下位置的 TaskSnapshot* 文件中找到该功能的其余代码:

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