Android 4.4对VSync机制的一个改进
2015-03-11 21:48
232 查看
在Android4.4中,对VSync机制的实现进行了一些修改,但是总体过程还是一样:
1. HWComposer将底层硬件产生的VSync报告给SurfaceFlinger
2. SurfaceFlinger将VSync又通知给EventThread线程。
3. EventThread收到VSync事件后,调用相应的回调函数。
总体来看,主要的修改有如下几点:
1. 引入了VSync Event Model,通过该模型,来充当VSync的事件源,它的VSync时间戳当然是基于硬件为参考的,具体实现在DispSync类中,它会周期性的调用注册到这个对象上的回调函数。
2. SurfaceFlinger新定义了一个DispSyncSource类,该类继承自VSyncSource和DispSync::Callback,实现了DispSync::Callback定义的回调接口onDispSyncEvent,在该接口里面,会调用注册到DispSyncSource的回调函数接口VSyncSource::Callback对象,并调用其实现的onVSyncEvent函数接口。
3. EventThread的主要改动是构造函数接受一个VSynSource的智能指针对象,其本身也实现了VSyncSource::Callback接口,即其本身也是一个VSyncSource::Callback对象。因为它会将自己注册给DispSyncSource对象作为他的一个周期性回调函数,所以会调用它实现的onVSyncEvent函数。
4. 开启和关闭硬件VSync功能放在一个单独的线程中,叫EventControlThread。
通过SurfaceFlinger的onVSyncReceived代码可以看到:
从代码可知,底层硬件不用周期性地产生VSync信号,而是按需产生。这是一个重要的优化。这一切都与DispSync类有关。 每次从底层收到一个硬件产生的VSync事件,都会进行判断,是否有必要继续产生硬件VSync事件,只有当它认为与硬件VSync事件有偏离时(即时间戳与硬件对应的Fence对象上的时间戳偏移超出预设的值时),才需要启用硬件产生VSync事件,否则,它就可以代表底层的VSync事件,无需硬件产生VSync事件,从而达到省电的目的。对于SurfaceFlinger,EventThread之间消息的传递流程,大体与4.3没有太多变化,所以本文重点关注DispSync及其所代表的VSync事件模型的原理。
1. VSyncSource类分析
Android4.4引入了VSyncSource类,这是一个重大的改变,它降低了SurfaceFlinger与EventThread的逻辑耦合,它的定义如下:
顾名思义,它代表了一个Vsync源,EventThread类目前直接通过VSyncSource获取VSync事件信息。所以,理论上,只有维护好VSync源,EventThread就会源源不断地收到VSync事件,而至于VSync源是否依赖于底层硬件真实的VSync事件信号,则对EventThread来说,是完全透明的。
另外,VSyncSource是一个纯虚类,在SurfaceFlinger中,定义了一个内部类DispSyncSource,该类实际上是通过DispSync类定义的事件模型来维护一个VSync事件源。当有VSync事件需要上报给EventThread类处理时,则会有如下的调用过程:
DispSync类会通过DispSyncThread类调用DispSyncSource的onDispSyncEvent,在该方法中会调用EventThread的onVSyncEvent函数。
2. DispSync
DispSync维护了一个这样的模型(VSync事件模型):利用显示设备的硬件VSync事件周期性的特征,在硬件Vsync事件特定的偏移处周期性地执行回调函数。即只要显示设备的Vsync硬件事件周期性地到来,DispSync就会在Vsync事件到来的特定时间偏移点,执行相应的回调函数。具体实现是通过addResyncSample方法向DispSync对象喂连续的硬件事件时间戳。
通过使用传递给DispSync对象的一系列Fence对象的时间戳,来判定是否启用该模型。
这些Fence对象的时间戳对应于底层硬件Vsync事件时间戳,但是它们不一定是连续的硬件Vsync 时间戳。如果该方法认为当前模型精确地代表了硬件事件时间戳,它将返回false,表明不需要继续进行同步了。
先简单看下DispSync类的定义:
1. 定义了一个内部接口类,Callback,方法接口名称:onDispSyncEvent, DispSync对象会周期性地调用此函数。
2. addPresentFence(constsp<Fence>& fence),引函数主要用于验证当前的VSync模型是否正常,即有没有偏离实际的硬件VSync时间戳。当返回值为true时,表明当前Vsync Event模型已经与硬件Vsync事件偏离,需要重新同步。
3. beginResync(), addResyncSample(),endResync()。
当Vsync事件模型时间戳与硬件对应的Fence对象的时间戳偏离后,需要依次调用上述三个接口来同步,只要addResyncSample()返回false,就表明已经同步完成,此时VSync 事件模型与硬件Vsync事件又保持一致了。
刚开机的时候,底层硬件Vsync是打开的,它会周期性产生Vsync事件,HWComposer会回调SurfaceFlinger的onVSyncReceived()接口,在这个接口里面,每次调用addResyncSample()使Vsync 事件模型时间戳与硬件对应的Fence对象的时间戳趋于同步,当返回true时,此时表明同步已经完成,会关闭底层的VSync事件。底层不再会周期性地调用onVSyncReceived()接口。
另一方面,在每次叠图后,会调用postComposition(), 在该函数中,每次会调用addPresentFence()检查Vsync事件模型与硬件对应的Fence对象的时间戳是否有偏移,当返回true, 表明需要进行同步,此时会开启硬件VSync。
另外,从代码中也可以发现,当缺少Android Sync框架的支持时,则硬件VSync不能关闭,会一直保持打开状态。
1. HWComposer将底层硬件产生的VSync报告给SurfaceFlinger
2. SurfaceFlinger将VSync又通知给EventThread线程。
3. EventThread收到VSync事件后,调用相应的回调函数。
总体来看,主要的修改有如下几点:
1. 引入了VSync Event Model,通过该模型,来充当VSync的事件源,它的VSync时间戳当然是基于硬件为参考的,具体实现在DispSync类中,它会周期性的调用注册到这个对象上的回调函数。
2. SurfaceFlinger新定义了一个DispSyncSource类,该类继承自VSyncSource和DispSync::Callback,实现了DispSync::Callback定义的回调接口onDispSyncEvent,在该接口里面,会调用注册到DispSyncSource的回调函数接口VSyncSource::Callback对象,并调用其实现的onVSyncEvent函数接口。
3. EventThread的主要改动是构造函数接受一个VSynSource的智能指针对象,其本身也实现了VSyncSource::Callback接口,即其本身也是一个VSyncSource::Callback对象。因为它会将自己注册给DispSyncSource对象作为他的一个周期性回调函数,所以会调用它实现的onVSyncEvent函数。
4. 开启和关闭硬件VSync功能放在一个单独的线程中,叫EventControlThread。
通过SurfaceFlinger的onVSyncReceived代码可以看到:
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) { bool needsHwVsync = false; { // Scope for the lock Mutex::Autolock _l(mHWVsyncLock); if (type == 0 && mPrimaryHWVsyncEnabled) { needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp); } } if (needsHwVsync) { enableHardwareVsync(); } else { disableHardwareVsync(false); } }
从代码可知,底层硬件不用周期性地产生VSync信号,而是按需产生。这是一个重要的优化。这一切都与DispSync类有关。 每次从底层收到一个硬件产生的VSync事件,都会进行判断,是否有必要继续产生硬件VSync事件,只有当它认为与硬件VSync事件有偏离时(即时间戳与硬件对应的Fence对象上的时间戳偏移超出预设的值时),才需要启用硬件产生VSync事件,否则,它就可以代表底层的VSync事件,无需硬件产生VSync事件,从而达到省电的目的。对于SurfaceFlinger,EventThread之间消息的传递流程,大体与4.3没有太多变化,所以本文重点关注DispSync及其所代表的VSync事件模型的原理。
1. VSyncSource类分析
Android4.4引入了VSyncSource类,这是一个重大的改变,它降低了SurfaceFlinger与EventThread的逻辑耦合,它的定义如下:
class VSyncSource : public virtual RefBase { public: class Callback: public virtual RefBase { public: virtual ~Callback() {} virtual void onVSyncEvent(nsecs_t when) = 0; }; virtual ~VSyncSource() {} virtual void setVSyncEnabled(bool enable) = 0; virtual void setCallback(const sp<Callback>& callback) = 0; };
顾名思义,它代表了一个Vsync源,EventThread类目前直接通过VSyncSource获取VSync事件信息。所以,理论上,只有维护好VSync源,EventThread就会源源不断地收到VSync事件,而至于VSync源是否依赖于底层硬件真实的VSync事件信号,则对EventThread来说,是完全透明的。
另外,VSyncSource是一个纯虚类,在SurfaceFlinger中,定义了一个内部类DispSyncSource,该类实际上是通过DispSync类定义的事件模型来维护一个VSync事件源。当有VSync事件需要上报给EventThread类处理时,则会有如下的调用过程:
DispSync类会通过DispSyncThread类调用DispSyncSource的onDispSyncEvent,在该方法中会调用EventThread的onVSyncEvent函数。
2. DispSync
DispSync维护了一个这样的模型(VSync事件模型):利用显示设备的硬件VSync事件周期性的特征,在硬件Vsync事件特定的偏移处周期性地执行回调函数。即只要显示设备的Vsync硬件事件周期性地到来,DispSync就会在Vsync事件到来的特定时间偏移点,执行相应的回调函数。具体实现是通过addResyncSample方法向DispSync对象喂连续的硬件事件时间戳。
通过使用传递给DispSync对象的一系列Fence对象的时间戳,来判定是否启用该模型。
这些Fence对象的时间戳对应于底层硬件Vsync事件时间戳,但是它们不一定是连续的硬件Vsync 时间戳。如果该方法认为当前模型精确地代表了硬件事件时间戳,它将返回false,表明不需要继续进行同步了。
先简单看下DispSync类的定义:
class DispSync { public: class Callback: public virtual RefBase { public: virtual ~Callback() {}; virtual void onDispSyncEvent(nsecs_t when) = 0; }; ... bool addPresentFence(const sp<Fence>& fence); ... void beginResync(); bool addResyncSample(nsecs_t timestamp); void endResync(); }
1. 定义了一个内部接口类,Callback,方法接口名称:onDispSyncEvent, DispSync对象会周期性地调用此函数。
2. addPresentFence(constsp<Fence>& fence),引函数主要用于验证当前的VSync模型是否正常,即有没有偏离实际的硬件VSync时间戳。当返回值为true时,表明当前Vsync Event模型已经与硬件Vsync事件偏离,需要重新同步。
3. beginResync(), addResyncSample(),endResync()。
当Vsync事件模型时间戳与硬件对应的Fence对象的时间戳偏离后,需要依次调用上述三个接口来同步,只要addResyncSample()返回false,就表明已经同步完成,此时VSync 事件模型与硬件Vsync事件又保持一致了。
刚开机的时候,底层硬件Vsync是打开的,它会周期性产生Vsync事件,HWComposer会回调SurfaceFlinger的onVSyncReceived()接口,在这个接口里面,每次调用addResyncSample()使Vsync 事件模型时间戳与硬件对应的Fence对象的时间戳趋于同步,当返回true时,此时表明同步已经完成,会关闭底层的VSync事件。底层不再会周期性地调用onVSyncReceived()接口。
另一方面,在每次叠图后,会调用postComposition(), 在该函数中,每次会调用addPresentFence()检查Vsync事件模型与硬件对应的Fence对象的时间戳是否有偏移,当返回true, 表明需要进行同步,此时会开启硬件VSync。
void SurfaceFlinger::postComposition() { ... const HWComposer& hwc = getHwComposer(); sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY); if (presentFence->isValid()) { if (mPrimaryDispSync.addPresentFence(presentFence)) { enableHardwareVsync(); } else { disableHardwareVsync(false); } } if (runningWithoutSyncFramework) { const sp<const DisplayDevice> hw(getDefaultDisplayDevice()); if (hw->isScreenAcquired()) { enableHardwareVsync(); } } ... }
另外,从代码中也可以发现,当缺少Android Sync框架的支持时,则硬件VSync不能关闭,会一直保持打开状态。
相关文章推荐
- 社区开放任务指南-9103-Android应用权限机制的分析和改进-重发
- Android 软件行为监控系统 的原理 主要是利用binder机制原理添加一个filter
- Android 4.4(KitKat)中VSync信号的虚拟化
- 针对4.4短信机制做一个合格的程序
- 用.Net打造一个移动客户端(Android/IOS)的服务端框架NHM(五)——Android端消息处理机制
- Android 4.4 Graphic系统详解(3) 一个view的绘制之旅
- Android 4.4 新特性分析-15项大改进!
- Android 4.4 新特性分析-15项大改进!
- Android 4.4 Graphic系统详解(3) VSYNC的处理
- Android 4.4 (KitKat) SMS Apis Change——Android 4.4的一个重大变化
- Android 4.4 新特性分析-15项大改进!
- Android 4.4 新特性分析-15项大改进!
- [Android 新特性] 15项大改进 Android 4.4新特性解析
- libevent 在 Android 上的一个改进
- 以一个具体的例子,深入剖析一下Android系统的绑定机制
- Android 4.4 新特性分析-15项大改进
- Android 4.4(KitKat)中VSync信号的虚拟化
- 强制老版本SDK编译的应用使用Android 4.4的对齐唤醒机制
- Android 4.4 Graphic系统详解(2) VSYNC的生成