概念
SurfaceFlinger
是一个系统服务,如:AudioFlinger、AudioPolicyService
等等,系统的服务。 SurfaceFlinger
服务负责管理系统的帧缓冲区设备,并且负责渲染系统的 UI
,即各个应用程序的 UI
。SurfaceFlinger
服务运行在 System
进程中,用来统一管理系统的帧缓冲区设备。由于 SurfaceFlinger
服务运行在 System
进程中,因此,Android
应用程序为了能够将自己的 UI
绘制在系统的帧缓冲区上,它们就必须通过 Binder
与 SurfaceFlinger
服务进行通信,如图所示:
Android 应用程序与 SurfaceFlinger 服务的关系
每一个 Android
应用程序与 SurfaceFlinger
服务都有一个连接,这个连接都是通过一个类型为 Client
的 Binder
对象来描述的。这些 Client
对象是 Android
应用程序连接到 SurfaceFlinger
服务的时候由 SurfaceFlinger
服务创建的,而当 Android
应用程序成功连接到 SurfaceFlinger
服务之后,就可以获得一个对应的 Client
对象的 Binder
代理接口了。有了这些 Binder
代理接口之后,Android
应用程序就可以通知 SurfaceFlinger
服务来绘制自己的 UI
了。
Android
应用程序在通知 SurfaceFlinger
服务来绘制自己的 UI
的时候,需要将 UI
元数据传递给 SurfaceFlinger
服务,例如,要绘制 UI
的区域、位置等信息。一个 Android
应用程序可能会有很多个窗口,而每一个窗口都有自己的 UI
元数据,因此,Android
应用程序需要传递给 SurfaceFlinger
服务的 UI
元数据是相当大的。在这种情况下,通过 Binder
进程间通信机制来在 Android
应用程序与 SurfaceFlinger
服务之间传递 UI
元数据是不合适的,这时候 Android
系统的 匿名共享内存机制(Anonymous Shared Memory)
就派上用场了。(这里暂时不做过多介绍,等待后续更新)
SurfaceFlinger 类的定义
SurfaceFlinger 类
重点成员变量
mCurrentState
:用来描述系统下一次要渲染的UI
的状态。mDrawingState
:用来描述当前正要渲染的 UI
的状态。mVisibleLayerSortedByZ
:是一个类型为sp
的Vector
,它是用来保存SurfaceFlinger
服务下一次要渲染的、处于可见状态的Surface
的,它们是来自SurfaceFlinger
类的成员变量mDrawingState
所描述的一个State
对象的成员变量layersSortedByZ
的。mGraphicPlanes
:是一个类型为GraphicPlane
的数组,它是用来描述系统所有的显示设备的。从这个数组的大小等于1
可以知道,当前Android
系统只支持一个显示设备。
重点函数
SurfaceFlinger
类中有这些比较重要的函数 threadLoop
、waitForEvent
、signalEvent
、handleConsoleEvents
、handleTransaction
、handlePageFlip
、handleRepaint
、postFramebuffer
。我们看下这些函数的执行流程并且分析每个函数的作用
执行流程
那么 SurfaceFlinger 的执行流程是怎样的?
SurfaceFlinger
服务虽然是在 System
进程中启动的,但是它在启动的时候创建一个线程来专门负责渲染UI
。为了方便描述,我们将这个线程称为 UI渲染线程
。UI渲染线程
的执行函数就为 SurfaceFlinger
类的成员函数 threadLoop
,同时它有一个消息队列。当 UI渲染线程
不需要渲染UI时,它就会在SurfaceFlinger
类的成员函数 waitForEvent
中睡眠等待,直到 SurfaceFlinger
服务需要执行新的 UI
渲染操作为止。
SurfaceFlinger服务什么时候会需要执行新的UI渲染操作呢?
当系统显示屏属性发生变化,或者应用程序窗口发生变化时,它就需要重新渲染系统的 UI
。这时候SurfaceFlinger
服务就会从 SurfaceFlinger
类的成员函数 waitEvent
中唤醒,并且依次执行SurfaceFlinger
类的成员函数 handleConsoleEvents
、handleTransaction
、handlePageFlip
、handleRepaint
和 postFramebuffer
来具体执行渲染 UI
的操作。
- 函数
handleConsoleEvents
用来处理控制台事件; - 函数
handleTransaction
用来处理系统显示屏属性变化以及应用程序窗口属性变化; - 函数
handlePageFlip
用来获得应用程序窗口下一次要渲染的图形缓冲区,即设置应用程序窗口的活动图形缓冲区; - 函数
handleRepaint
用来重绘应用程序窗口; - 函数
postFramebuffer
用来将系统UI渲染到硬件帧缓冲区中去。
我们知道,应用程序是运行在与 SurfaceFlinger
服务不同的进程中的,每当应用程序需要更新自己的 UI
时,它们就会通过 Binder
进程间通信机制来通知 SurfaceFlinger
服务。SurfaceFlinger
服务接到这个通知之后,就会调用 SurfaceFlinger
类的成员函数signalEvent
来唤醒UI渲染线程,以便它可以执行渲染UI的操作。注意,SurfaceFlinger
服务是通过 Binder
线程来获得应用程序的请求的,因此,这时候SurfaceFlinger
服务的UI渲染线程实际上是被 Binder
线程唤醒的。SurfaceFlinger
类的成员函数 signalEvent
实际上是通过向UI渲染线程的消息队列发送一个类型为 INVALIDATE
的消息来唤醒 UI
渲染线程的。
前面提到, SurfaceFlinger服务在在执行UI渲染操作时,需要调用SurfaceFlinger类的成员函数handleConsoleEvents来处理控制台事件。这怎么理解呢?
SurfaceFlinger
服务在启动的时候,还会创建另外一个线程来监控由内核发出的帧缓冲区硬件事件。为了方便描述,我们将这个线程称为控制台事件监控线程。每当帧缓冲区要进入睡眠状态时,内核就会发出一个睡眠事件,这时候 SurfaceFlinger
服务就会执行一个释放屏幕的操作;而当帧缓冲区从睡眠状态唤醒时,内核就会发出一个唤醒事件,这时候 SurfaceFlinger
服务就会执行一个获取屏幕的操作。
State 类
-
layersSortedByZ
:是一个类型为LayerVector
的向量,里面保存的系统所包含的Surface
,每一个Surface
使用一个LayerBase
对象来描述,并且它们按照Z轴
顺序来排列。 -
orientation
、orientationType
:类型均为uint8_t
,它们用来描述屏幕的方向。 -
freezeDisplay
:类型是uint8_t
,用来描述屏幕是否处于被冻结状态。
GraphicPlane 类
重要成员
-
mHw
:指向一个DisplayHardware对象,用来描述一个硬件显示设备; -
mOrientation
、mWidth
、mHeight
:均为int
,分别用来描述一个硬件显示设备的旋转方向、宽度和高度。
重要函数
setDisplayHardware
:设置一个GraphicPlane
对象内部所包含的一个硬件显示设备。displayHardware
:获取一个GraphicPlane
对象内部所包含的一个硬件显示设备。
DisplayHardware 类
重要成员
mNativeWindow
:它是一个类型为FramebufferNativeWindow
的强指针。
重要函数
flip
:用来渲染系统UI
的,即将后端的图形缓冲区翻转为前端的图形缓冲区,并且渲染在硬件帧缓冲区去。
FramebufferNativeWindow 类
是用来描述一个 Android
系统本地窗口,而这个窗口代表的是系统的硬件帧缓冲区。它是 OpenGL
库和Android
的 UI
系统之间的一个桥梁。
重要成员
-
fbDev
、grDev
:fbDev
和grDev
分别指向一个framebuffer_device_t
设备和一个alloc_device_t
设备。framebuffer_device_t
设备和一个alloc_device_t
设备是由 HAL模块Gralloc
来提供的,它们分别用来分配图形缓冲区和渲染图形缓冲区 -
buffers
:类型为NativeBuffer
的数组,这个数组用来描述一个图形缓冲区堆栈,堆栈的大小为NUM_FRAME_BUFFERS
,这些图形缓冲区是直接在硬件帧缓冲区中分配的,有别于Surface
类所使用的图形缓冲区,因为后者所使用的图形缓冲区是在匿名共享内存分配的。
重要函数
-
dequeueBuffer
来获得一个用来填充UI
数据的图形缓冲区,而通过它的成员函数 -
queueBuffer
来将一个已经填充好UI
数据的图形缓冲区渲染到系统的帧缓冲区中去。