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;

也就是说,调用MessageQueuesetEventThread方法之后,会自动创建一个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);

调用DispSyncSourcesetCallback方法设置回调,因此回调对象为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 分析的主要内容,如果未能解决你的问题,请参考以下文章

EventThread 分析

Looper 监听文件描述符

Looper 监听文件描述符

有关软件工程专业的论述

论述性文本分类

Zookeeper之Zookeeper的Client的分析