原址

以下分析基于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信号产生与分发相关推荐

  1. vsync信号产生与分发

    以下分析基于android 4.4代码 vsync信号的产生.分发涉及到以下几个类,先主要了解下他们各自的功能: HWComposer:产生hardware vsync,post fb VSyncTh ...

  2. Android SurfaceFlinger SW Vsync模型

    Android SurfaceFlinger Vsync这块比较复杂,最初在看这块的时候,迟迟不知道从何入手,网上看了各种SurfaceFlinger Vsync相关的博客,个人感觉紧紧是把代码流程给 ...

  3. Android12 SurfaceFlinger Vsync

    Vsync可以控制系统绘图/合成的频率周期,是内容能够在正确的时机完整地显示在屏幕上 在Surfaceflinger中有一套SW-Vsync的机制,能够更灵活的控制app绘图与surfacefling ...

  4. android vsync信号间隔,Android SurfaceFlinger服务(五) ----- VSync信号的产生

    Android为了增强界面流畅度引入了VSync机制.VSync信号一般由硬件产生,为了兼容一些老的机器,也可以软件产生.因些,就可以分为硬件VSync和软件VSync.VSync的生成逻辑主要在HW ...

  5. Android SurfaceFlinger 学习之路(五)----VSync 工作原理

    原址 VSync信号的科普我们上一篇已经介绍过了,这篇我们要分析在SurfaceFlinger中的作用.(愈发觉得做笔记对自己记忆模块巩固有很多帮助,整理文章不一定是用来给别人看的,但一定是为加强自己 ...

  6. Android SurfaceFlinger

    Android 系统启动过程 Activity 创建过程 Activity 与 Window 与 View 之间的关系 Android 系统从按下开机键到桌面,从桌面点击 App 图标到 Activi ...

  7. Android SurfaceFlinger学习

    重学系列 1.Android 重学系列 SurfaceFlinger的概述 2.Android 重学系列 Ashmem匿名共享内存 3.Android 重学系列 SurfaceFlinger 的初始化 ...

  8. android surfaceflinger 代码,Android P 图形显示系统(七) SurfaceFlinger合...

    SurfaceFlinger合成流程(二) SurfaceFlinger合成流程 MessageQueue中分发两个消息,一个INVALIDATE,一个REFRESH,SurfaceFlinger对这 ...

  9. app应用分发平台|苹果ios超级签名|APP封装打包|应用内测托管平台|iOS应用企业签名|Android应用上传内测-虾分发

    CDN分发平台-注册免审核-虾分发 https://xiafenfa.com/ app应用分发平台|苹果ios超级签名|APP封装打包|应用内测托管平台|iOS应用企业签名|Android应用上传内测 ...

最新文章

  1. c++判断双击间隔_录井工常见故障判断处理
  2. linux系统学习之Linux打印文件和发送邮件
  3. (c语言)和与积的运算第一篇
  4. 如何让光标处于EditText的末尾
  5. Boost:bind绑定的测试自定义占位符
  6. django-celery
  7. 《是碰巧还是执着?python所阅读的每一场知识点,唯一的共同点就是——参赛选手中,有详解Python的装饰器!》
  8. log4j2+ELK
  9. Nagios+zabbix+ganglia的相关参数分析和优缺点介绍
  10. opencv-api morphologyEx
  11. ubuntu 自动加载ko_Ubuntu启动后自动加载ext4分区
  12. python安装不了怎么办_python安装运行时提示不是内部或外部命令怎么办
  13. python画条形图-python使用Matplotlib画条形图
  14. elementUI中table中自定义修改时间格式2020-10-26T10:00:00
  15. 鸿蒙面向开发者语言,华为正式发布鸿蒙OS 面向全球开发者开源!
  16. javascript中for循环里面套定时器,始终打印结束值原因
  17. C#实现模糊PID算法的代码
  18. 吴军《信息论40讲》课程目录
  19. php7版本号,discuz的php7版本号
  20. 你被选中了——晚会上的随机点名

热门文章

  1. [操作系统] 线程和进程的简单解释
  2. [Android Samples视频系列之ApiDemos] App-Activity-Recreate
  3. 生成BAPI的ALE接口
  4. HTTP请求字符限制和HTTP状态码
  5. 概率中的独立和不相关
  6. 配置 SQL Server 2005 以允许远程连接(服务器端)
  7. 【ROS】ros入门21讲(上)
  8. 服务器重启宝塔面板打不开了【已完美解决】
  9. i3处理器能运行python吗_老cpu(10年前的core i3 不支持avx指令集)安装tensorflow2.0...
  10. php设计模式-责任链模式