Andriod中VSync的分发

描述

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自己用的。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分