减少图形的内存消耗

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

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

  • 对于发布时搭载 Android 14 及更高版本的设备,您必须实现新的 3.2 版混合渲染器 HAL API。此选项在默认情况下处于启用状态,并能最大限度地节省内存。升级到 Android 14 及更高版本的设备也可以使用此选项来实现全部内存优势。
  • 对于升级到 Android 14 的设备,如果您不想实现混合渲染器 HAL 3.2 API,可以改为启用向后兼容选项。此选项节省的内存几乎与上一个选项一样多。

以下两部分介绍了如何实现各个选项。

实现混合渲染器 HAL 3.2 API

如需实现全部图形缓冲区内存优势,您必须:

  1. 将混合渲染器 HAL 实现更新到版本 3.2。
  2. 在列表中找到相应的槽号,通过完全清除其所指示的缓冲区缓存条目来处理 LayerCommand::bufferSlotsToClear

与图形缓冲区内存相关的混合渲染器 HAL 3.2 API(包括 LayerCommand:bufferSlotsToClear)位于 LayerCommand.aidl-

启用向后兼容选项

向后兼容的内存节省选项将缓存槽中的实际缓冲区替换为 1x1 占位符缓冲区,从而节省所有已完全清除的槽(当前活跃缓冲区槽除外)的内存。如需实现部分内存节省优势,请通过将 surface_flinger.clear_slots_with_set_layer_buffer sysprop 设为 true来启用向后兼容选项。此 sysprop 位于 property_contexts 文件内。

若要设置此 sysprop,您的混合渲染器 HAL 实现必须能在单个当前周期中正确处理同一层的多个 setLayerBuffer 命令。

启用向后兼容选项会产生以下影响:

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

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

向后兼容的选项可能会导致混合渲染器 HAL 在某些设备上崩溃。您或许可以通过修改混合渲染器 HAL 来解决此问题。用于控制此行为的代码的位置如下:

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

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

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

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