SurfaceFlinger
Android 图形架构使用了生产者——消费者模型。Surface 表示缓冲队列中的生产方,图像流最常见的消耗方是 SurfaceFlinger,该系统服务接收来自于多个源的数据缓冲区,组合它们,并将它们发送给显示设备。
Android 应用程序为了能够将自己的 UI 绘制在系统的帧缓冲区上,它们就必须要与 SurfaceFlinger 服务进行通信。SurfaceFlinger 服务运行在 Android 系统的 System 进程中,它负责管理 Android 系统的帧缓冲区(Frame Buffer)。
SurfaceFlinger 的职责
SurfaceFlinger 主要有以下几个职责:
- 分配图形缓冲区
- 合成图形缓冲区
- 管理 VSYNC 事件
在 Android 平台上创建的每个窗口都由 Surface 提供支持。所有被渲染的可见 Surface 都被 SurfaceFlinger 合成到显示部分。
SurfaceFlinger 是可以修改所显示部分内容的唯一服务。SurfaceFlinger 使用 OpenGL 和 Hardware Composer 来合成一组 Surface。
- 在屏幕处于两次刷新之间时,屏幕会向 SurfaceFlinger 发送 VSYNC 信号。VSYNC 信号表明可对屏幕进行刷新而不会产生撕裂。当 SurfaceFlinger 接收到 VSYNC 信号后,SurfaceFlinger 会遍历其层列表,以查找新的缓冲区。如果 SurfaceFlinger 找到新的缓冲区,SurfaceFlinger 会获取缓冲区;否则,SurfaceFlinger 会继续使用上一次获取的那个缓冲区。SurfaceFlinger 必须始终显示内容,因此它会保留一个缓冲区。如果在某个层上没有提交缓冲区,则该层会被忽略。
- SurfaceFlinger 在收集可见层的所有缓冲区之后,便会询问硬件混合渲染器 (HWC) 应如何进行合成。如果 HWC 将层合成类型标记为客户端合成,则 SurfaceFlinger 将合成这些层。然后,SurfaceFlinger 会将输出缓冲区传递给 HWC。
数据缓冲区
Android 应用程序在通知 SurfaceFlinger 服务来绘制自己的 UI 的时候,需要将 UI 元数据传递给 SurfaceFlinger 服务,例如,要绘制 UI 的区域、位置等信息。一个 Android 应用程序可能会有很多个窗口,而每一个窗口都有自己的 UI 元数据,因此,Android 应用程序需要传递给 SurfaceFlinger 服务的 UI 元数据是相当可观的。在这种情况下,通过 Binder 进程间通信机制来在 Android 应用程序与 SurfaceFlinger 服务之间传递 UI 元数据是不合适的(并且,Binder 传输数据也有大小的限制),这时候 Android 系统的匿名共享内存机制(Anonymous Shared Memory)就派上用场了。
在每一个 Android 应用程序与 SurfaceFlinger 服务之间的连接上加上一块用来传递 UI 元数据的匿名共享内存,如下所示:
但是单纯的匿名共享内存在传递多个窗口数据时缺乏有效的管理,所以匿名共享内存就被抽象为一个更上流的数据结构 SharedClient,如下图所示:
在每个 SharedClient 中,最多有31个 SharedBufferStack,每个 SharedBufferStack 都对应一个 Surface,即一个窗口。这样,我们就可以知道为什么每一个 SharedClient 里面包含的是一系列 SharedBufferStack 而不是单个 SharedBufferStack:一个 SharedClient 对应一个 Android 应用程序,而一个 Android 应用程序可能包含有多个窗口,即 Surface。从这里也可以看出,一个 Android 应用程序至多可以包含31个窗口。
每个 SharedBufferStack 中又包含了 N 个缓冲区(<4.1 N=2; >=4.1 N=3),即显示刷新机制中即将提到的双缓冲和三重缓冲技术。
总结
- Android 图形架构使用了生产者——消费者模型。Surface 表示缓冲队列中的生产方,图像流最常见的消耗方是 SurfaceFlinger,该系统服务接收来自于多个源的数据缓冲区,组合它们,并将它们发送给显示设备。
- SurfaceFlinger 服务运行在 Android 系统的 System 进程中,它负责管理 Android 系统的帧缓冲区(Frame Buffer)。
- SurfaceFlinger 主要有以下几个职责:分配图形缓冲区、合成图形缓冲区、管理 VSYNC 事件。
- 在每一个 Android 应用程序与 SurfaceFlinger 服务之间的连接上加上一块用来传递 UI 元数据的匿名共享内存。匿名共享内存就被抽象为一个更上流的数据结构 SharedClient
- 在每个 SharedClient 中,最多有31个 SharedBufferStack,每个 SharedBufferStack 都对应一个 Surface,即一个窗口。这样,我们就可以知道为什么每一个 SharedClient 里面包含的是一系列 SharedBufferStack 而不是单个 SharedBufferStack:一个 SharedClient 对应一个 Android 应用程序,而一个 Android 应用程序可能包含有多个窗口,即 Surface。从这里也可以看出,一个 Android 应用程序至多可以包含31个窗口。
- 每个 SharedBufferStack 中又包含了 N 个缓冲区(<4.1 N=2; >=4.1 N=3),即显示刷新机制中即将提到的双缓冲和三重缓冲技术。