android 使用SurfaceFlinger 服务的流程分析,基于4.4(二)---- vsync 机制

Vsync(Vertical Synchronization,垂直同步)是一种在PC上很早就广泛使用的技术,可以理解为是一种定时中断。而在Android 4.1(JB)中已经开始引入VSync机制来同步渲染,让App和SurfaceFlinger可以按硬件产生的VSync节奏进行工作。 Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,屏幕的刷新过程是每一行从左到右(行刷新,水平刷新,Horizontal Scanning),从上到下(屏幕刷新,垂直刷新,Vertical Scanning)。当整个屏幕刷新完毕,即一个垂直刷新周期完成,会有短暂的空白期,此时发出 VSync 信号。surfaceflinger 将不同layer 的 ui数据元素合成,需要精密的时间控制,不然屏幕就会很卡。在相同的信号指令下进行处理数据,屏幕才会呈现出正常的图像。这个信号就是vsync 信号。只有在引入了vsync 信号后,android 的CPU ,GPU 才能在恰当的时候工作,不会导致操作ui卡顿的现象.总的来说这个Vsync 的作用就是使得CPU/GPU/Display同步。

目录

一、VSYNC 虚拟化

二、几个线程的创建

三、vsync 在几个线程之间的交互过程


一、VSYNC 虚拟化

经过 android 使用SurfaceFlinger 服务的流程分析,基于4.4(一)------SurfaceFlinger 使用步骤 分析,知道调用 unlockAndPost ,将UI buffer 入队后,最终通过 layer层调用surfaceflinger 的signalLayerUpdate 函数 ,通知surfaceflinger 处理。想知道surfaceflinger 处理怎么处理的,还需要分析了解vsync 机制。

虽然vsync使得CPU/GPU/Display同步了,但App UI和SurfaceFlinger的工作显然是一个流水线的模型。即对于一帧内容,先等App UI画完了,SurfaceFlinger再出场对其进行合并渲染后放入framebuffer,最后整到屏幕上。而现有的VSync模型是让大家一起开始干活,这样对于同一帧内容,第一个VSync信号时App UI的数据开始准备,第二个VSync信号时SurfaceFlinger工作,第三个VSync信号时用户看到Display内容,这样就两个VSync period(每个16ms)过去了,影响用户体验。解决这个问题的思路是:SurfaceFlinger在App UI准备好数据后及时开工做合成。Android 4.4(KitKat)中引入了VSync的虚拟化,即把硬件的VSync信号先同步到一个本地VSync模型中,再从中一分为二,引出两条VSync时间与之有固定偏移的线程。示意图如下:

android 使用SurfaceFlinger 服务的流程分析,基于4.4(二)---- vsync 机制_第1张图片

即 App开始工作的时候是Vsync+offset1,surfaceflinger工作的时刻在Vsync+offset1+offset2。而这个offset1 和 offset2 都是可调的。

虚拟化的工作框图如下:

android 使用SurfaceFlinger 服务的流程分析,基于4.4(二)---- vsync 机制_第2张图片

 

看这个图的下半部分 vsync 这个信号,可以由硬件产生,也可以由软件产生!软件产生是由VSyncThread 这个类负责产生信号。

DispSyncThread 这个类的作用是虚拟化底层产生的Vsync信号,将vsync 信号拆分成两个信号,一个Vsync(APP),一个Vsync 用于SF .

看图片右部分:

当应用程序需要更新UI时会主动告诉EventThread线程,我需要更新画面,这个消息放在connection 里面,而EventThread收到某个APP的请求后,转发给DispSyncThread线程,DispSyncThread 线程接受到VSyncThread产生的vsync 信后,会偏移offset1这么一个时间,把Vsync-APP发送给EventThread线程,EventThread线程在发送给APP,APP这个时候可以构建数据了。

同理看图片左侧部分:

当某个应用构建好了buffer,通过queuebuffer,告诉surfaceflinger线程,需要处理buffer了,这个时候,通知EventThread线程,而EventThread收到surfaceflinger请求后,转发给DispSyncThread线程,ispSyncThread 线程接受到VSyncThread产生的vsync 信后,会偏移offset1这么一个时间,把Vsync-SF发送给EventThread线程,EventThread线程在发送给Surfaceflinger线程,Surfaceflinger线程就可以处理buffer里面的数据了。

二、几个线程的创建

上图可以看出,一共有五个线程在协同处理,这些线程创建的UML图如下:

(1)DispSyncThread 线程创建时序图:

android 使用SurfaceFlinger 服务的流程分析,基于4.4(二)---- vsync 机制_第3张图片

(2)VSyncThread 、两个EventThread线程创建时序图:

android 使用SurfaceFlinger 服务的流程分析,基于4.4(二)---- vsync 机制_第4张图片

mSFEventThread 创建后会调用MessageQueue::setEventThread函数,在这里面会创建一个链接Connection ,然后获取一个mEventTube ,最后把EventThread里面的fd 添加到mLooper里面。所以surfaceflinger线程和 mSFEventThread 线程可以通过这个文件句柄FD进行通信。

(3)surfaceflinger 线程就不用说怎么创建的了

flinger->run();

void SurfaceFlinger::run() {
    do {
        waitForEvent();
    } while (true);
}

surfaceflinger 线程调用waitForEvent()  后,就一直等待APP 的消息,和 mSFEventThread 发过来的消息了。

 

三、vsync 在几个线程之间的交互过程

调用 unlockAndPost ,将UI buffer 入队后,最终通过 layer层调用surfaceflinger 的signalLayerUpdate 函数 ,接着这个函数调用了mEventQueue.invalidate() 函数。

(1)surfaceflinger 进程向EventThread 发送一个需要vsync 信号的请求:

android 使用SurfaceFlinger 服务的流程分析,基于4.4(二)---- vsync 机制_第5张图片

最后是一个mCondition.broadcast() 的调用,唤醒了EventThread线程,即完成了surfaceflinger 进程向EventThread 发送一个需要vsync 信号的请求。接着EventThread::threadLoop() 函数会处理,即向DispSyncThread 线程请求一个sfvsync 信号。

(2)EventThread 线程向DispSyncThread发出vsync信号请求:

android 使用SurfaceFlinger 服务的流程分析,基于4.4(二)---- vsync 机制_第6张图片

waitForEvent(&event) 干了两件事情:

①、向DispSyncThread线程请求vsync信号,

②、并且等待vsync信号。

最后通过mCond.signal()函数,DispSyncThread 那边那个线程就可以收到请求消息了。我们可以看到UML图中的 mVSyncSource->setCallback(static_cast(this)) ;他这个函数的本质就是设置一个回调函数给DispSyncThread ,当DispSyncThread 收到VSyncThread 软件产生的信号以后,会调用之前设置的回调函数。

(3)VSyncThread 软件产生的信号:

android 使用SurfaceFlinger 服务的流程分析,基于4.4(二)---- vsync 机制_第7张图片

可以看出VSyncThread产生一个vsync 信号后,最终会唤醒通过mCond.signal()的方式唤醒DispSyncThread线程。

(4)DispSyncThread线程接受到vsync 信号:

android 使用SurfaceFlinger 服务的流程分析,基于4.4(二)---- vsync 机制_第8张图片

DispSyncThread::threadloop函数干了4件事情:

①、nextEventTime = computeNextEventTimeLocked(now)  ,这个函数是在计算最近的EventThread的时间,即获得在(2)的UML图中,最后获得Listener的时间。

②、err = mCond.waitRelative(mMutex, targetTime - now) 等待VsyncThread 产生一个vsync信号。

③、 callbackInvocations = gatherCallbackInvocationsLocked(now) ,收到VsyncThread 产生的vsync信号后,收集所有的callback函数。

④、fireCallbackInvocations(callbackInvocations) ,调用callback 函数,最终调用到EventThread 里面的 onVSyncEvent 函数。用mCondition.broadcast()的方式唤醒休眠的EventThread线程,告诉它收到了Vsync信号,你可以通知surfaceflinger进程处理buffer了

(5)EventThread 线程收到DispSyncThread线程发过来的Vsync:

android 使用SurfaceFlinger 服务的流程分析,基于4.4(二)---- vsync 机制_第9张图片

 

通过UML 图看出,当EventThread收到DispSyncThread线程发过来的Vsync信号后,最终会调用到Surfaceflinger线程的 onMessageReceived 函数,并走MessageQueue::INVALIDATE case。之后Surfaceflinger会调用  handleMessageTransaction(); handleMessageInvalidate();signalRefresh();处理UI buffer等事务。

 

你可能感兴趣的:(Android,系统)