EventThread 分析
Posted Achillisjack
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EventThread 分析相关的知识,希望对你有一定的参考价值。
在SurfaceFlinger的init方法中,构造了2个EventThread类型的线程,
mEventThread = new EventThread(vsyncSrc, *this, false);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
mEventQueue.setEventThread(mSFEventThread);
EventThread也是一个线程类,继承于Thread,定义如下,
class EventThread : public Thread, private VSyncSource::Callback
EventThread的构造方法没什么可论述的, onFirstRef方法如下,
void EventThread::onFirstRef()
run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
和一般C/C++ 线程一样,调用线程的run方法之后,会调用到threadLoop方法,该方法主要逻辑如下,
1,调用waitForEvent方法进入等待,
DisplayEventReceiver::Event event;
Vector< sp<EventThread::Connection> > signalConnections;
signalConnections = waitForEvent(&event);
2,调用Connection的postEvent方法,将vsync信号分发给监听者,
const size_t count = signalConnections.size();
for (size_t i=0 ; i<count ; i++)
const sp<Connection>& conn(signalConnections[i]);
// now see if we still need to report this event
status_t err = conn->postEvent(event);
3,最后返回true,系统会再次调用这个线程的threadloop,从而形成一个循环,
return true;
在论述其他方法之前,先看下内部类Connection,其定义如下,
class Connection : public BnDisplayEventConnection
听名字可知, Connection代表了SurfaceFlinger 进程和客户端的通道,主要用于SurfaceFlinger 进程 向 客户端分发vsync信号。也就是说,客户端注册一个监听器,就会创建一个Connection对象。例如, SurfaceFlinger。在SurfaceFlinger的init方法中,
mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
mEventQueue.setEventThread(mSFEventThread);
创建vsync线程之后,就调用MessageQueue的setEventThread方法开始创建Connection对象。调用流程图如下,
MessageQueue的setEventThread方法如下,
mEventThread = eventThread;
mEvents = eventThread->createEventConnection();
mEvents->stealReceiveChannel(&mEventTube);
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
MessageQueue::cb_eventReceiver, this);
首先调用EventThread的createEventConnection方法创建Connection对象;
EventThread的createEventConnection方法如下,
sp<EventThread::Connection> EventThread::createEventConnection() const
return new Connection(const_cast<EventThread*>(this));
Connection构造方法如下,
EventThread::Connection::Connection(
const sp<EventThread>& eventThread)
: count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize)
构造了一个BitTube对象来初始化Connection对象的成员变量mChannel,BitTube类只是对Socket通信方式的封装。一般的socket可以用于服务端和客户端的双向通信,但是一般情况下,BitTube仅用于服务端向客户端发送数据,是单向的。与此同时,在构造函数之后,会调用onFirstRef方法,该方法如下,
mEventThread->registerDisplayEventConnection(this);
调用EventThread的registerDisplayEventConnection方法,该方法如下,
Mutex::Autolock _l(mLock);
mDisplayEventConnections.add(connection);
mCondition.broadcast();
return NO_ERROR;
将创建的Connection对象 保存在 mDisplayEventConnections 变量中,该变量是一个简单的集合,在EventThread.h中的定义如下,
SortedVector< wp<Connection> > mDisplayEventConnections;
也就是说,调用MessageQueue的setEventThread方法之后,会自动创建一个Connection对象,并且保存在mDisplayEventConnections变量中,当分发vsync消息时,会从mDisplayEventConnections 变量中取出Connection对象。回头看EventThread的threadLoop方法,首先调用waitForEvent方法获取Connection对象,然后调用Connection对象的postEvent发送消息。waitForEvent方法调用流程图如下,
waitForEvent方法主要逻辑如下,
1,从mDisplayEventConnections 变量中取出Connection对象
for (size_t i=0 ; i<count ; i++)
sp<Connection> connection(mDisplayEventConnections[i].promote());
2,如果不需要vsync信号,则调用disableVSyncLocked方法;
否则调用enableVSyncLocked方法.
if (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();
3,最后阻塞线程,
mCondition.wait(mLock);
disableVSyncLocked方法如下,
mVsyncEnabled = false; //当前的状态值赋值为false
mVSyncSource->setVSyncEnabled(false);
mDebugVsyncEnabled = false;
调用DispSyncSource的setVSyncEnabled方法。
mVsyncEnabled = true;
mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this));
mVSyncSource->setVSyncEnabled(true);
调用DispSyncSource的setCallback方法设置回调,因此回调对象为DispSyncSource。和disableVSyncLocked方法一样,也会调用VsyncSource的setVSyncEnabled方法,只是参数不同。DispSyncSource也是SurfaceFlinger_hwc1.cpp中的一个内部类,定义如下,
class DispSyncSource : public VSyncSource, private DispSync::Callback
setVSyncEnabled方法主要逻辑如下,
1,如果设置vsync信号可用,则调用DispSync的addEventListener方法注册监听者,
status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this));
2,否则调用则调用DispSync的removeEventListener方法取消注册监听者,
status_t err = mDispSync->removeEventListener(
static_cast<DispSync::Callback*>(this));
DispSync的addEventListener方法如下,
Mutex::Autolock lock(mMutex);
return mThread->addEventListener(name, phase, callback);
调用内部类DispSyncThread的addEventListener方法,该方法主要逻辑如下,
1,遍历mEventListeners,查看是否包含回调对象,
for (size_t i = 0; i < mEventListeners.size(); i++)
if (mEventListeners[i].mCallback == callback)
return BAD_VALUE;
2,为EventListener对象赋值,
EventListener listener;
listener.mName = name;
listener.mPhase = phase;
listener.mCallback = callback;
3,最后将EventListener对象塞入mEventListeners集合中,
mEventListeners.push(listener);
mCond.signal();
并且,线程也休眠了,等待唤醒。最后终于将DispSyncSource关联的EventListener对象塞入mEventListeners 集合中, DispSync.cpp 中的定义如下,
Vector<EventListener> mEventListeners;
EventListener是DispSyncThread 内部的一个结构体,定义如下,
struct EventListener
const char* mName;
nsecs_t mPhase;
nsecs_t mLastEventTime;
sp<DispSync::Callback> mCallback;
;
因此,在DispSync 章节中DispSyncThread的threadLoop方法最后会调用的是DispSyncSource的onDispSyncEvent方法。removeEventListener方法和addEventListener调用流程完全相同,只是将DispSyncSource关联的EventListener对象从mEventListeners 集合中删除。EventThread线程在threadloop调用waitForEvent方法会休眠,在vsync信号到来也EventThread的onVSyncEvent方法中会唤醒,唤醒之后, threadloop中的代码才继续往下执行,分发vsync信号。调用所有客户端的Connection的postEvent方法,将vsync信号分发给监听者,
for (size_t i=0 ; i<count ; i++)
const sp<Connection>& conn(signalConnections[i]);
// now see if we still need to report this event
status_t err = conn->postEvent(event);
Connection的postEvent方法调用流程图如下,
postEvent方法如下,
ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
return size < 0 ? status_t(size) : status_t(NO_ERROR);
mChannel就是前面说的BitTube对象,调用DisplayEventReceiver的sendEvents方法将event数据写入。
这样,vsync信号数据就从服务端传输到了客户端。
那么,哪些客户端创建了Connection对象并且收到vsync信号呢?
有2类,一类是surfaceflinger(前面已经论述创建Connection对象), 它负责UI数据的合成,肯定要受vsync信号,当然这是进程内的通信;另外一类是应用进程。
在论述SurfaceFlinger处理vsync信号之前,首先论述一下Looper 监听文件描述符机制。
以上是关于EventThread 分析的主要内容,如果未能解决你的问题,请参考以下文章