任务快照

Task Snapshots(任务快照)是在 Android 8.0 中引入的基础架构,它将 Recents Thumbnails(最近使用的应用缩略图)的屏幕截图与 Window Manager 中的 Saved Surfaces(已保存 Surface)相结合。“最近使用的应用缩略图”表示最近使用应用视图中任务的最后状态。

当 Activity 进入停止状态时,只要该 Activity 位于任务顶部,WindowManager 就不会销毁该 Activity 的 Surface。如果必须再次显示此 Activity,WindowManager 就能够启动动画,而无需等待 Activity 完成绘制第一帧,因为它能够使用此“已保存 Surface”。

架构

通过“任务快照”,最近使用的应用缩略图和已保存 Surface 这两个概念得以统一。当任务转入后台时,WindowManager 会将此任务的屏幕截图放入 GraphicBuffer 中。只要任务顶部 Activity 的应用仍在内存中,此 GraphicBuffer 就会保留在内存中。现在,当再次将同一 Activity 带到前台时,WindowManager 将创建一个启动窗口 (TaskSnapshotSurface),并将 GraphicBuffer 附加到该窗口,而无需将任何内存复制到启动窗口的缓冲区队列。一旦 Activity 绘制完第一帧,“任务快照”启动窗口就会像常规启动画面一样平滑地淡出。

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

优势

这种新架构有三个主要优势

  • 如果将任务快照用作启动窗口,则快照与实际内容之间会有一个漂亮的交叉淡入淡出效果。
  • 在 SystemUI 中绘制任务快照时,可以无需任何复制操作。以前,位图必须先复制到 Ashmem 中,然后再复制到图形内存中。由于此方法将快照直接存储在图形内存中,因此无需复制。
  • 您在“最近使用的应用”中看到的状态始终与您重新打开应用时首先看到的状态一致。在此处使用相同的缓冲区还可以节省大量内存。这就是“最近使用的应用”现在能够以全分辨率显示这些图像的原因。以前,为了节省内存,图像会被降采样 64%。

实现

此功能完全存在于 Android 平台中。无需集成,也不支持自定义。但是,设备制造商可以完全禁用“任务快照”功能。

要禁用此功能,请修改此函数

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

请注意,如果禁用此功能,“最近使用的应用”视图将不会显示任何缩略图。

高分辨率和低分辨率快照

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

示例和源代码

在此功能的 TaskSnapshot* 文件中查找其余代码:

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