App与SurfaceFlinger是不同的进程,它们之间传递VSync的话涉及到进程间通信,而且VSync频率很高,App很多,所以VSync的分发效率要很高才行。Linux进程间通信方式总共就那么几种,Android选择了Domain Socket,应该是因为其高效、简单、且有序吧,并将其封装成了更易用的BitTube。
VSync-app/sf
Android绘制、显示各个环节均是由VSync驱动,具体来说就是App的每一帧的绘制是从收到VSync信号(VSync-app)开始的,SurfaceFlinger合成当前图层也是从收到VSync信号(VSync-sf)开始的。为了避免浪费,VSync的分发是按需的,即只有用户需要(requestNextVsync)的时候,DisplayVSync才会给它发送VSync。
Vsync相关类简介
首先来介绍一些vsync相关的类,基本上所有vsync相关方法,都是实现在这三个类当中的(以下代码均为Anrdoid T版本源码)。
VsyncTracker:其实际上是创建了一个VSyncPredictor对象,这个对象的作用是基于之前的VSync信号时间戳来预测未来VSync时间戳。也就是基于HWVsync来训练Vsync模型。从而能够在HWVsync关闭的情况下依然能够预测未来的VSync时间。
VsyncDispatcher:顾名思义,这个类是用来分发Vsync信号的。实际上最终创建了一个VSyncDispatchTimerQueue对象,负责分发vsync callback事件,需要接收Vsync事件的模块可以通过registerCallback向其中注册回调,当有Vsync事件发生时就会遍历已注册的回调分发Vsync。
VSyncController:最终方法的实现是在一个VSyncReactor对象中,从代码中看,这个对象的主要作用是负责传递HWVsync,presentFence信号。
sf申请vsync
当sf需要请求刷新时,会调用MessageQueue中的scheduleFrame函数
进而直接调用到VSyncCallbackRegistration中的schedule函数,进一步再到VSyncDispatchTimerQueue中的schedule函数。
这其中rearmTimerSkippingUpdateFor是一个比较关键的函数,这个函数会拿到下次触发vsync的时间戳,并通过setTimer函数向定时器设置这个时间戳,等到定时器被唤醒时,触发callback以发送vsync。
下面我们来看callback是怎么被层层触发的。
当定时器到来时,首先回调的是VSyncDispatchTimerQueue中的timerCallback函数
它持有的结构体Invocation中持有一个VSyncDispatchTimerQueueEntry对象,进一步追下去,可以知道这个mCallback最终调到的是MessageQueue中的VsyncCallback函数。
最后的这个红框的部分,就是我们通常在trace里看到的vsync-sf跳变的地方啦!
app申请vsync
相比于sf的申请,app的申请就显得要复杂一些。app通常是通过调用requestNextVsync这个binder接口来进行vsync的申请。
这个接口会调用到eventthread中的requestNextVsync函数,此函数会通过mCondition发送广播。
当threadMain监听到广播后,便会继续执行循环。
eventThread会执行什么呢,关键性的函数就是dispSyncSource中的setVSyncEnabled函数,当传入参数为true时,会调用到CallbackRepeater中的start函数。
继续往下看,会调用到VSyncCallbackRegistration中的Schedule函数,进一步到VSyncDispatchTimerQueue中的schedule函数。
下面的流程和sf申请vsync基本就是大同小异了,它回调的地方是这里
调用CallbackRepeater中的callback;
最终调用到DispSyncSource中的onVsyncCallback,这也就是我们在trace中看到的vsync-app跳变的地方啦。
相比于vsync-sf,vsync-app还多了一个向申请方发送vsync的过程。继续往下看,调用到了EventThread中的onVSyncEvent,其会把VsyncEvent保存到mPendingEvents中。
那么这些event在哪里分发呢?答案是还在threadMain中,这个dispatchEvent函数就是用来负责向每个consumer分发vsync的。
说到这里,大家肯定会有一个疑问,为什么vsync-app和vsync-sf都是由同一个定时器触发的,但是最终回调的位置确不一样呢?
答案是,这两种vsync本身注册回调的位置就不一样。
vsync-sf是在messagequeue中注册的
而vsync-app是在callbackRepeater中注册的。
这也是google在Android T上才做出来的改动,究其原因,应该是谷歌认为应该简化vsync-sf在内部的传递流程,反正也是只给sf自己用的。
-
Android
+关注
关注
12文章
3935浏览量
127355 -
定时器
+关注
关注
23文章
3246浏览量
114744 -
函数
+关注
关注
3文章
4329浏览量
62579
发布评论请先 登录
相关推荐
评论