Android SurfaceFlinger vsync信号产生与分发
原址
以下分析基于android 4.4代码
vsync信号的产生、分发涉及到以下几个类,先主要了解下他们各自的功能:
HWComposer:产生hardware vsync,post fb
VSyncThread : 如果没有硬件支持,那么通过软件方式模拟hw vsync
DispSync,DispSyncThread: 接受HWComposer的hw vsync信号作为校准,开始模拟产生vsync信号+偏移,并且会不时地进行校准,如postComposition后。
EventControlThread:sf中的一个线程,仅用来控制hw vsync开关
EventThread:负责分发vsync到sf或app
DispSyncSource:EventThread和DispSyncThread的信息传递者, 把vsync信号从DispSyncThread传递到EventThread;同时可以用来设置相位偏移参数。
在4.4之后,vsync信号不再完全由硬件产生,hw vsync信号主要用来做时间校准,vsync信号发生者是DispSyncThread, 当DispSyncThread产生的信号得到校准后,hw vsync会被关闭。
几个问题分析:
1.硬件vsync开启-关闭过程
(1)HWComposer在hwc_composer_device_1中注册回调:
mCBContext->procs.vsync = &hook_vsync;
mHwc->registerProcs(mHwc, &mCBContext->procs);
(2)vsync过来:HWComposer::hook_vsync => HWComposer::vsync
(3)HWComposer::vsync=>mEventHandler.onVSyncReceived(disp, timestamp);
mEventHandler即surfaceflinger
(4)SurfaceFlinger::onVSyncReceived:
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp); //加入样本,校准mPrimaryDispSync(DispSync),返回是否还需要hwsync if (needsHwVsync) { enableHardwareVsync(); //未同步,接续接受hw vsync } else { disableHardwareVsync(false); //已同步,关闭hw vsync }
开启或关闭硬vsync:
SurfaceFlinger::enableHardwareVsync() => mEventControlThread->setVsyncEnabled(true); //sf专门启动了一个线程EventControlThread来开关硬件vsync
2.DispSyncThread 信号的产生:
(1) 在sf类中声明一个成员变量:
class SurfaceFlinger {...DispSync mPrimaryDispSync;... }
(2) 构造函数里启动DispSyncThread线程
DispSync::DispSync() {mThread = new DispSyncThread();mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);reset();beginResync();... }
(3) 进入DispSyncThread::threadLoop(): 计算vsync周期,调用所有存在mEventListeners的Listener的callback
fireCallbackInvocations()方法中调用callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
mCallback的类型为DispSync::Callback
(4) mEventListeners的注册通过调用DispSync::addEventListener()
(5) 谁注册成为了vsync事件的监听者? 是DispSyncSource
DispSyncSource继承自DispSync::Callback, 在它setVSysncEnabled(true)中调用:
status_t err = mDispSync->addEventListener(mPhaseOffset, static_cast<DispSync::Callback*>(this)); //DispSyncSource把自己设为了DispSyncThread vsync信号的监听者所以vsync消息传到了DispSyncSource中的onDispSyncEvent(nsecs_t when)中:
virtual void onDispSyncEvent(nsecs_t when) { sp<VSyncSource::Callback> callback; {Mutex::Autolock lock(mMutex);callback = mCallback;if (mTraceVsync) {mValue = (mValue + 1) % 2;ATRACE_INT("VSYNC", mValue);} }if (callback != NULL) {callback->onVSyncEvent(when); //又把vsync事件传递到了它自己的mCallback里, 这个mCallback 在EventThread::enableVSyncLocked()中设置, 就是EventThread, 这样vsync传递到了EventThread里 } }
(6)继续看谁又调用了DispSyncSource::setVSyncEnabled()?
是EventThread::enableVSyncLocked():
void EventThread::enableVSyncLocked() { if (!mUseSoftwareVSync) { // never enable h/w VSYNC when screen is offif (!mVsyncEnabled) {mVsyncEnabled = true;mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this)); //EventThread设为DispSyncSource的callbackmVSyncSource->setVSyncEnabled(true);mPowerHAL.vsyncHint(true); } } mDebugVsyncEnabled = true; }
(7)EventThread::enableVSyncLocked()又被EventThread::waitForEvent()调用
Vector< sp<EventThread::Connection> > EventThread::waitForEvent(DisplayEventReceiver::Event* event) {...// Here we figure out if we need to enable or disable vsyncsif (timestamp && !waitForVSync) {// we received a VSYNC but we have no clients// don't report it, and disable VSYNC events disableVSyncLocked();} else if (!timestamp && waitForVSync) {// we have at least one client, so we want vsync enabled// (TODO: this function is called right after we finish// notifying clients of a vsync, so this call will be made// at the vsync rate, e.g. 60fps. If we can accurately// track the current state we could avoid making this call// so often.) enableVSyncLocked();}... }
waitForEvent()的逻辑是:
接到vsync信号,但是当前EventThread中没有请求 vsync 的connection, EventThread向下不再监听vsync
EventThread中有请求 vsync 的connection, EventThread继续监听vsync
总结: vsync传递路径 DispSyncThread => DispSyncSource => EventThread
DispSyncSource: 这个类比较简单,其实就是vsync传递者, 同时负责传递相位偏移phase offset到dispsyncThread。
EventThread: 负责接收vsync, 分发给sf或者app
所以在Sf init中的代码就比较好理解了
// start the EventThread sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true); mEventThread = new EventThread(vsyncSrc); sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, false); mSFEventThread = new EventThread(sfVsyncSrc); //上面代码注册了两个vsync信号的监听者, 当vsync产生时,分发给EventThread,这里有两个,一个处理sf,一个处理app mEventQueue.setEventThread(mSFEventThread); // mEventControlThread = new EventControlThread(this); mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
3. 两个EventThread 线程是怎样把vsync分发给sf和app的?
(1)app与EventThread
EventThread里有一个 class Connection : public BnDisplayEventConnection,
BnDisplayEventConnection 继承自 IDisplayEventConnection
这个接口实现了:
getDataChannel()
setVsyncRate()
requestNextVsync()
App端请求vsync:
app端通过DisplayEventReceiver 中的sp<IDisplayEventConnection> mEventConnection 来requestNextVsync
mEventConnection实际上是BpDisplayEventConnection, 所以requestNextVsync是通过Binder通信从app端传递到EventThread并由它来处理。
同时通过mEventConnection->getDataChannel(); 保存一个BitTube类型的mDataChannel。
在EventThread端:
app调用createEventConnection创建DisplayEventConnection时,EventThread将这个connection注册到它的mDisplayEventConnections集合里
当vsync过来时,通知所有connection
App端接受vsync是通过建立连接时保存的那个BitTube:
//file:android_view_DisplayEventReceiver.cpp status_t NativeDisplayEventReceiver::initialize() {status_t result = mReceiver.initCheck();f (result) {ALOGW("Failed to initialize display event receiver, status=%d", result);return result;}int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, ALOOPER_EVENT_INPUT, // 监听BitTube的fd,有数据时,调用handlerthis, NULL);if (rc < 0) {return UNKNOWN_ERROR;}return OK; }
所以app接受vsync信号是通过监听BitTube的fd, BitTube底层是通过socket实现。
(2) sf与EventThread
SurfaceFlinger::init()中调用mEventQueue.setEventThread(mSFEventThread);
void MessageQueue::setEventThread(const sp<EventThread>& eventThread) {mEventThread = eventThread;mEvents = eventThread->createEventConnection();mEventTube = mEvents->getDataChannel();mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT,MessageQueue::cb_eventReceiver, this); }
在sf进程中直接监听BitTube的fd,当有vsync过来时, 直接由SF的MessageQueue处理
Android SurfaceFlinger vsync信号产生与分发相关推荐
- vsync信号产生与分发
以下分析基于android 4.4代码 vsync信号的产生.分发涉及到以下几个类,先主要了解下他们各自的功能: HWComposer:产生hardware vsync,post fb VSyncTh ...
- Android SurfaceFlinger SW Vsync模型
Android SurfaceFlinger Vsync这块比较复杂,最初在看这块的时候,迟迟不知道从何入手,网上看了各种SurfaceFlinger Vsync相关的博客,个人感觉紧紧是把代码流程给 ...
- Android12 SurfaceFlinger Vsync
Vsync可以控制系统绘图/合成的频率周期,是内容能够在正确的时机完整地显示在屏幕上 在Surfaceflinger中有一套SW-Vsync的机制,能够更灵活的控制app绘图与surfacefling ...
- android vsync信号间隔,Android SurfaceFlinger服务(五) ----- VSync信号的产生
Android为了增强界面流畅度引入了VSync机制.VSync信号一般由硬件产生,为了兼容一些老的机器,也可以软件产生.因些,就可以分为硬件VSync和软件VSync.VSync的生成逻辑主要在HW ...
- Android SurfaceFlinger 学习之路(五)----VSync 工作原理
原址 VSync信号的科普我们上一篇已经介绍过了,这篇我们要分析在SurfaceFlinger中的作用.(愈发觉得做笔记对自己记忆模块巩固有很多帮助,整理文章不一定是用来给别人看的,但一定是为加强自己 ...
- Android SurfaceFlinger
Android 系统启动过程 Activity 创建过程 Activity 与 Window 与 View 之间的关系 Android 系统从按下开机键到桌面,从桌面点击 App 图标到 Activi ...
- Android SurfaceFlinger学习
重学系列 1.Android 重学系列 SurfaceFlinger的概述 2.Android 重学系列 Ashmem匿名共享内存 3.Android 重学系列 SurfaceFlinger 的初始化 ...
- android surfaceflinger 代码,Android P 图形显示系统(七) SurfaceFlinger合...
SurfaceFlinger合成流程(二) SurfaceFlinger合成流程 MessageQueue中分发两个消息,一个INVALIDATE,一个REFRESH,SurfaceFlinger对这 ...
- app应用分发平台|苹果ios超级签名|APP封装打包|应用内测托管平台|iOS应用企业签名|Android应用上传内测-虾分发
CDN分发平台-注册免审核-虾分发 https://xiafenfa.com/ app应用分发平台|苹果ios超级签名|APP封装打包|应用内测托管平台|iOS应用企业签名|Android应用上传内测 ...
最新文章
- c++判断双击间隔_录井工常见故障判断处理
- linux系统学习之Linux打印文件和发送邮件
- (c语言)和与积的运算第一篇
- 如何让光标处于EditText的末尾
- Boost:bind绑定的测试自定义占位符
- django-celery
- 《是碰巧还是执着?python所阅读的每一场知识点,唯一的共同点就是——参赛选手中,有详解Python的装饰器!》
- log4j2+ELK
- Nagios+zabbix+ganglia的相关参数分析和优缺点介绍
- opencv-api morphologyEx
- ubuntu 自动加载ko_Ubuntu启动后自动加载ext4分区
- python安装不了怎么办_python安装运行时提示不是内部或外部命令怎么办
- python画条形图-python使用Matplotlib画条形图
- elementUI中table中自定义修改时间格式2020-10-26T10:00:00
- 鸿蒙面向开发者语言,华为正式发布鸿蒙OS 面向全球开发者开源!
- javascript中for循环里面套定时器,始终打印结束值原因
- C#实现模糊PID算法的代码
- 吴军《信息论40讲》课程目录
- php7版本号,discuz的php7版本号
- 你被选中了——晚会上的随机点名
热门文章
- [操作系统] 线程和进程的简单解释
- [Android Samples视频系列之ApiDemos] App-Activity-Recreate
- 生成BAPI的ALE接口
- HTTP请求字符限制和HTTP状态码
- 概率中的独立和不相关
- 配置 SQL Server 2005 以允许远程连接(服务器端)
- 【ROS】ros入门21讲(上)
- 服务器重启宝塔面板打不开了【已完美解决】
- i3处理器能运行python吗_老cpu(10年前的core i3 不支持avx指令集)安装tensorflow2.0...
- php设计模式-责任链模式