减少图形内存消耗

在图形堆栈中,每层缓冲区缓存位于 Composer HAL 和 SurfaceFlinger 之间,以减少通过 IPC 发送文件描述符相关的开销。在 Android 14 之前,当 GraphicBufferProducer 与 SurfaceFlinger GraphicBufferConsumer 断开连接时(例如当 MediaCodec 与 SurfaceView 断开连接时),此缓冲区缓存不会被清除。从 Android 14 开始,您可以强制清除此缓冲区缓存,以减少图形内存消耗。

从以下两个选项中选择一个

  • 对于搭载 Android 14 及更高版本推出的设备,您必须实现新的 Composer HAL API 版本 3.2。默认情况下,此选项处于启用状态,并且可以节省最多的内存。升级到 14 及更高版本的设备也可以使用此选项来实现全面的内存优势。
  • 对于要升级到 Android 14 但又不想实现 Composer HAL 3.2 API 的设备,您可以启用向后兼容选项。此选项几乎可以节省与之前选项一样多的内存。

以下两节将介绍如何实现每个选项。

实现 Composer HAL 3.2 API

要实现完整的图形缓冲区内存优势,您必须

  1. 将您的 Composer HAL 实现更新到 3.2 版本。
  2. 处理 LayerCommand::bufferSlotsToClear,方法是清除列表中指示的槽号所指示的缓冲区缓存条目。

与图形缓冲区内存相关的 Composer HAL 3.2 API,包括 LayerCommand:bufferSlotsToClear,位于 LayerCommand.aidl- 中。

启用向后兼容选项

向后兼容的内存缩减选项会将缓存槽中的真实缓冲区替换为 1x1 占位符缓冲区,从而为所有清除的槽(当前活动缓冲区槽除外)节省内存。要实现部分内存节省优势,请将 surface_flinger.clear_slots_with_set_layer_buffer 系统属性设置为 true,从而启用向后兼容选项。此系统属性位于 property_contexts 文件中。

设置此系统属性要求您的 Composer HAL 实现正确处理单个 present 周期中同一图层的多个 setLayerBuffer 命令。

启用向后兼容选项具有以下影响

  • 对于 AIDL HAL:SurfaceFlinger 为单个图层发送多个 LayerCommand 实例,每个实例都包含单个 BufferCommandBufferCommand 包含 1x1 占位符缓冲区句柄和需要清除的缓存缓冲区槽的槽号。

  • 对于 HIDL HAL:SurfaceFlinger 发送多个 SELECT_DISPLAYSELECT_LAYERSET_BUFFER 命令。这些命令包含 1x1 占位符缓冲区句柄和需要清除的缓存缓冲区槽的槽号。

向后兼容选项可能会导致 Composer HAL 在某些设备上崩溃。您或许可以修改您的 Composer HAL 来解决此问题。控制此行为的代码在此处

测试图形缓冲区缓存内存消耗

测试无法验证 HAL 实现是否清除了缓存槽。但是,您可以使用调试工具来监控图形缓冲区使用情况。在监控时,您应该注意到,在 YouTube 上快速连续停止和启动多个不同视频的场景中,内存不足错误会减少。

VTS 测试可用于验证 HAL 实现是否在功能上能够接收新的 API 调用(HAL 版本 3.2+)或向后兼容实现的多个 setLayerBuffer 命令。但是,这不应被视为充分的功能测试,因为某些设备通过了这些 VTS 测试,但在实际使用场景中却失败了。

对于新的 VTS 测试,请导航到以下链接