Android Q
前面分析了Vsync信号的始末,其实还有很多可以细究的部分。比如硬件vsync是什么时候开始,什么时候结束?校准算法的原理等等。
接下来我们先看看SurfaceFlinger合成帧的部分。
一. SF EventThread接收vsync的准备
在SFEventThread一文中已经探明,当产生Vsync信号后,会通过BitTube发送事件(EventThreadConnection.postEvent):
1 | status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) { |
这里我们就需要知道 mChannel 是被谁监听了。
1.1 SurfaceFlinger.init
1 | void SurfaceFlinger::init() { |
这里的mEventQueue是在SurfaceFlinger.onFirstRef中初始化的。
1 | void SurfaceFlinger::onFirstRef() |
这个Looper就是SurfaceFlinger主线程的Looper.
1.1.1 Scheduler.createConnection
1 | sp<Scheduler::ConnectionHandle> Scheduler::createConnection( |
1.1.2 EventThread.createEventConnection
1 | sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback) const { |
1.2 MessageQueue.setEventConnection
1 | void MessageQueue::setEventConnection(const sp<EventThreadConnection>& connection) { |
这里的mLooper就是SurfaceFlinger主线程的Looper.
1.2.1 EventThreadConnection.stealReceiveChannel
1 | status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) { |
二. SF EventThread接收vsync
上面我们知道了,当SFEventThread发出Vsync信号时,会通过BitTube发送该消息至SurfaceFlinger主线程,并调用MessageQueue.cb_eventReceiver方法处理。
2.1 MessageQueue.cb_eventReceiver
1 | int MessageQueue::cb_eventReceiver(int fd, int events, void* data) { |
2.2 MessageQueue.Handler.dispatchInvalidate
1 | void MessageQueue::Handler::dispatchInvalidate() { |
2.3 SurfaceFlinger.onMessageReceived
1 | void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { |
这里我们先忽略Fence机制,先看看大致流程。
2.4 SurfaceFlinger.handleMessageInvalidate
1 | bool SurfaceFlinger::handleMessageInvalidate() { |
2.5 SurfaceFlinger.handlePageFlip
1 | bool SurfaceFlinger::handlePageFlip() |
2.6 SurfaceFlinger.handleMessageRefresh
1 | void SurfaceFlinger::handleMessageRefresh() { |
再继续分析之前,我们需要先了解Layer的结构,以及他是如何被添加至SurfaceFlinger中的。
三. Layer的产生
Layer, 即图层。Layer是图像合成中最重要的单元。图层是Surface和SurfaceControl的组合。
说到底也就是每个Window都有对应Surface,也就对应一个Layer;SurfaceFlinger的合成就是将所有图层按照顺序和特定属性合成一帧画面。
每个图层都有一组属性,用于定义它与其他图层的交互方式。
| 属性 | 描述 |
|---|---|
| Positional | 定义图层在其显示屏上显示的位置。 包括诸如图层边缘的位置及其相对于其他图层的Z顺序的信息 |
| Content | 定义图层上显示的内容应如何在位置属性定义的边界内显示。 包括裁剪和变换等信息 |
| Composition | 定义图层应如何与其他图层合成。 包括混合模式和alpha合成的图层范围Alpha值等信息 |
| Optimization | 提供正确合成图层非必要的信息,但硬件编写器(HWC)设备可以使用该信息来优化其执行合成的方式。 包括诸如图层的可见区域以及自上一帧以来图层的哪个部分已更新的信息。 |
在创建Window或者Window产生变化时就会更新对应的Surface所属的Layer.
1 | ViewRootImpl.performTraversals() --[App进程] 绘制三部曲 |

Surface FLAG一览
| 名称 | 值 | 作用 |
|---|---|---|
| HIDDEN | 0x00000004 | Surface是隐藏的 |
| SECURE | 0x00000080 | 包含安全内容,禁止内容被其他进程复制。而且屏幕截图和VNC服务器将被禁用,但可能不会采用硬件加速。Window带有FLAG_SECURE标签,或者该应用禁止截图就会带有这个FLAG |
| NON_PREMULTIPLIED | 0x00000100 | 预乘透明度,创建一个Surface,其中颜色分量被Alpha通道解释为“非预乘”。对于没有alpha通道的Surface,这个标志是没有意义的。 默认情况下,Surface是预乘的,这意味着每个颜色分量已经乘以其alpha值。 |
| OPAQUE | 0x00000400 | 表示Surface必须为不透明,即使其像素格式包含Alpha通道。 |
| PROTECTED_APP | 0x00000800 | 应用程序需要通过外部显示接收器的硬件保护路径。 如果硬件保护路径不可用,则此表面将不会显示在外部接收器上。 |
| CURSOR_WINDOW | 0x00002000 | 窗口表示光标字形。 |
| FX_SURFACE_NORMAL | 0x00000000 | 创建一个默认Surface |
| FX_SURFACE_DIM | 0x00020000 | 创建一个暗淡的Surface。 此Surface后面的所有内容都会被{@link #setAlpha}中指定的数量调暗。 锁定Dim Surface是错误的,因为它没有后备存储。 |
| FX_SURFACE_CONTAINER | 创建容器Surface。 此Surface将没有缓冲区,仅用作其他Surface或其InputInfo的容器。 | |
| SURFACE_HIDDEN | 0x01 | 隐藏该Surface, 等同于调用Surface.hide() |
| SURFACE_OPAQUE | 0x02 | 尽可能不混合的复合材料。 更新Surface创建期间设置的值(请参阅{@link #OPAQUE})。 |
3.1 SurfaceFlinger:createLayer
当上次Window变化时,或者会创建Layer,并保存在SurfaceFlinger中.
1 | status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w, |
3.1.1 SurfaceFlinger.createBufferQueueLayer
中间细琐流程略过,最终是创建了一个Layer对象
1 | Layer::Layer(const LayerCreationArgs& args) |
重点关注的是:
| 名称 | 作用 |
|---|---|
| z | z-order,表示x,y,z轴的z轴上的顺序。数字越大,表示越在上面,数字越小,表示越在下面。 |
| layerStack | layerStack是存储layer的容器,我们知道每个display只会有一个layerstack来存储他要显示的layer,但是不同的display可以使用同一个layerStack,也可以使用不同的layerStack。可以理解为组的含义。也就是说属于不同组的layer之间互不干扰。SurfaceFlinger中有一个DisplayDevice类,他表示用来显示的设备,譬如LCD或者是HDMI。DisplayDevice里也有一个成员变量mLayerStack,在进行composition的时候,只有和这个device的layerstack相同的layer才可能被显示在这个设备上。 |
| sequence | sSequence是一个static的变量,所以递加的效果就是为每一个layer设置一个唯一且递增的序列号。 |
3.2 SurfaceFlinger.addClientLayer
1 | status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle, |
搞清楚Layer的Z轴顺序,对与我们理解Layer合成过程有很大帮助。
Layer排序建议参考:https://www.cnblogs.com/riskyer/p/3297226.html
3.2.1 LayerVector.add
将新创建的Layer按照Z轴顺序存储至队列中.
LayerVector继承了SortedVector,并且重载了函数 do_compare.
1 | int LayerVector::do_compare(const void* lhs, const void* rhs) const |
先比较layerstack,不同的layerstack分开。然后再比较z,假设都相同,就比较唯一的layer序列号。
但是至今为止,layerStack和z都还只是初始化时的0,所以在创建layer的时候,只是把他根据序列号放进layersSortedByZ而已,其实他的顺序还是没有设置的。
3.2.2 SurfaceFlinger:addClientLayer
1 | void Client::attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer) |
3.4 Layer更新流程
当java层调用setLayer时就会确定对应Layer的Z-Order顺序。
1 | ViewRootImpl.performTraversals() --[App进程] 绘制三部曲 |
如图:
到目前为止还只是创建了一个SurfaceControl,对应SurfaceFlinger中的BufferQueueLayer。
真正的Surface还没有被创建,那是什么时候创建的呢?
四. Surface的生成
一个ViewRootImpl对应一个Suface, 也就是一个Layer.
当我们创建了Layer之后,总要向其中填充数据内容,SurfaceFlinger才好做合成。
在RendererThread中,我们知道了Surface数据是通过渲染引擎OpenGL(android Q上是Vulkan)生成的。
4.1 Suface的生成
参阅:RenderThread深入分析(三)–绑定窗口对应的Surface到RenderThread的过程
1 | ViewRootImpl.performTraversals(...) --[App UI进程] 绘制三部曲 |
大致流程如下图:
现在我们已经获取了渲染引擎中的Surface,向其中填充数据的过程就是performDraw的流程;
这个部分在RenderThread中有分析,不在赘述。
那当我们的Surface中已经被填充了数据后,是如何传递给SurfaceFlinger做合成的呢?
这个部分我们稍后详细分析,目前仅从trace上也可以看出来:

上图中eglSwapBuffer最终就是通过binder通知到surfaceflinger中处理的:

五. Layer实例
以如下图为例,看看对应Layer:
1 | Display 19260235133379457 HWC layers: |
示意图如下:

总的来说就是,树形结构+Z order排序。
六. 类图

现在我们Surface有了,也有渲染的内容了,那SurfaceFlinger是如何将这些Surface对应的Layer合成为一帧并显示出来的呢?
参考资料
- [Android Synchronization Fences – An Introduction]http://netaz.blogspot.com/2013/10/android-fences-introduction-in-any.html
- [Android中的GraphicBuffer同步机制-Fence]https://blog.csdn.net/jinzhuojun/article/details/39698317
- [深入浅出Android BufferQueue]https://blog.51cto.com/13591395/2380727
- [从systrace看app冷启动过程(三)-首帧的合成与送显]https://www.jianshu.com/p/3829158b4699
- [Android显示Surface]https://www.jianshu.com/p/fc3c3d6f9bf7
- [surfaceflinger中各个layer的排序]https://www.cnblogs.com/riskyer/p/3297226.html
- [Android 4.0.3 显示系统深入理解]https://www.linuxidc.com/Linux/2012-03/55898p4.htm
- [Android窗口管理分析(3):窗口分组及Z-order的确定]https://www.jianshu.com/p/90ede7b2a64a