在上一篇文章Android VSync信号产生过程源码分析中分别介绍了VSync的两种产生方式,无论是通过硬件中断产生还是通过软件模拟产生,VSync事件最终都会交给EventThread线程来分发给所有VSync事件接收者。VSync事件接收者有很多,SurfaceFlinger就是其中一个重要的VSync事件接收者。那么EventThread线程是如何知道该将VSync分发给谁呢?EventThread线程有是如何将VSync事件分发给所有VSync事件接收者的呢?本文就针对这两个问题展开分析。我们知道VSync事件是由EventThread线程分发,而VSync事件接收者可能与EventThread线程同属一个进程,也可能分属不同的进程,这里就设计跨进程通信了,Android对VSync事件的分发采用Socket通信方式。
EventThread线程分发VSync事件
对VSYNC等事件感兴趣的对象,比如MessageQueue,首先要通过EventThread::createEventConnection()来建立一个连接,实际上就是生成了一个EventThread::Connection对象,Connection只是双方业务上连接,而BitTube则是数据传输通道。
sp<EventThread::Connection> EventThread::createEventConnection() const { return new Connection(const_cast<EventThread*>(this)); }这里只是简单地构造一个Connection对象,Connection对象的构造过程如下:
EventThread::Connection::Connection(const sp<EventThread>& eventThread) : count(-1), mEventThread(eventThread), mChannel(new BitTube()) { }在构造Connection对象时,构造了一个BitTube对象来初始化Connection对象的成员变量mChannel,从上图可以看出,BitTube类只是对Socket通信方式的封装,BitTube对象的构造过程如下:
BitTube::BitTube(): mSendFd(-1), mReceiveFd(-1) { int sockets[2]; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) { int size = SOCKET_BUFFER_SIZE; setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); fcntl(sockets[0], F_SETFL, O_NONBLOCK); fcntl(sockets[1], F_SETFL, O_NONBLOCK); mReceiveFd = sockets[0]; mSendFd = sockets[1]; } else { mReceiveFd = -errno; ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd)); } }
当Connection对象第一次被强引用时,自动调用onFirstRef()函数来初始化该对象。
void EventThread::Connection::onFirstRef() { mEventThread->registerDisplayEventConnection(this); }在onFirstRef()函数里主动调用EventThread::registerDisplayEventConnection()把自己加入到EventThread的成员变量mDisplayEventConnections中,mDisplayEventConnections是一个向量类型,保存所有需要接收VSync信号的连接Connection,这样EventThread线程在分发VSync事件时,就知道将VSync事件分发给谁了。对VSYNC信号感兴趣的人,通过registerDisplayEventConnection()函数将连接Connection注册到EventThread中。
status_t EventThread::registerDisplayEventConnection( const sp<EventThread::Connection>& connection) { Mutex::Autolock _l(mLock); //仅仅将注册的Connection添加到EventThread的成员变量mDisplayEventConnections中 mDisplayEventConnections.add(connection); mCondition.broadcast(); return NO_ERROR; }EventThread的成员变量mDisplayEventConnections用于记录所有注册的Connection连接。
bool EventThread::threadLoop() { nsecs_t timestamp; DisplayEventReceiver::Event vsync; //定义displayEventConnections向量,用于保存所有需要接收VSync事件的连接 Vector< wp<EventThread::Connection> > displayEventConnections; do { Mutex::Autolock _l(mLock); //判断是否上报VSync do { // latch VSYNC event if any timestamp = mVSyncTimestamp; mVSyncTimestamp = 0; //标示是否有客户端在等待VSync事件 bool waitForNextVsync = false; size_t count = mDisplayEventConnections.size(); for (size_t i=0 ; i<count ; i++) { sp<Connection> connection = mDisplayEventConnections.itemAt(i).promote(); // count >= 1 : continuous event. count is the vsync rate // count == 0 : one-shot event that has not fired // count ==-1 : one-shot event that fired this round / disabled // count ==-2 : one-shot event that fired the round before if (connection!=0 && connection->count >= 0) { // at least one continuous mode or active one-shot event waitForNextVsync = true; break; } } if (timestamp) { if (!waitForNextVsync) { //接收到VSync事件,但当前没有客户端需要接收VSync事件,所以关闭VSync事件源 disableVSyncLocked(); } else { //如果有客户需要接收VSync事件,则跳出此循环,进入VSync事件分发阶段 break; } } else { //等待接收VSync事件,并重新评估是否需要分发该事件或者是否需要关闭VSync事件源 if (waitForNextVsync) { //如果有客户端需要接收VSync事件,则打开VSync事件源 enableVSyncLocked(); } } //等待VSync事件 if (mUseSoftwareVSync && waitForNextVsync) { // h/w vsync cannot be used (screen is off), so we use // a timeout instead. it doesn't matter how imprecise this // is, we just need to make sure to serve the clients if (mCondition.waitRelative(mLock, ms2ns(16)) == TIMED_OUT) { mVSyncTimestamp = systemTime(SYSTEM_TIME_MONOTONIC); } } else { mCondition.wait(mLock); } } while(true); //当需要分发VSync时,跳出上面的while循环, mDeliveredEvents++; mLastVSyncTimestamp = timestamp; // now see if we still need to report this VSYNC event const size_t count = mDisplayEventConnections.size(); //遍历已注册的所有Connection,将需要接收VSync的Connection添加到displayEventConnections向量中 for (size_t i=0 ; i<count ; i++) { bool reportVsync = false; sp<Connection> connection = mDisplayEventConnections.itemAt(i).promote(); //如果当前Connection已经死亡,则遍历下一个注册的Connection if (connection == 0) continue; const int32_t count = connection->count; if (count >= 1) { if (count==1 || (mDeliveredEvents % count) == 0) { // continuous event, and time to report it reportVsync = true; } } else if (count >= -1) { if (count == 0) { // fired this time around reportVsync = true; } connection->count--; } if (reportVsync) { displayEventConnections.add(connection); } } } while (!displayEventConnections.size()); //如果向量displayEventConnections的大小大于0,则将VSync信号分发给displayEventConnections中的Connection //定义即将分发的VSync事件 vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; vsync.header.timestamp = timestamp; vsync.vsync.count = mDeliveredEvents; const size_t count = displayEventConnections.size(); //遍历displayEventConnections中的所有Connection for (size_t i=0 ; i<count ; i++) { sp<Connection> conn(displayEventConnections[i].promote()); // make sure the connection didn't die if (conn != NULL) { //发送VSync事件 status_t err = conn->postEvent(vsync); if (err == -EAGAIN || err == -EWOULDBLOCK) { //这两个错误是指对方当前不接受事件,有可能是事件已满,放弃这次操作,不作处理 } else if (err < 0) { //事件发送错误,则从Connection注册列表mDisplayEventConnections中移除该Connection removeDisplayEventConnection(displayEventConnections[i]); } } else { //Connection为空,则从Connection注册列表mDisplayEventConnections中移除该Connection removeDisplayEventConnection(displayEventConnections[i]); } } //VSync事件分发完毕,清空displayEventConnections向量 displayEventConnections.clear(); return true; }在EventThread线程中,通过遍历连接注册列表mDisplayEventConnections,将VSync事件分发给已注册,并且需要接收VSync事件的Connection。调用各个Connection的postEvent()函数来发送一个VSync事件:
status_t EventThread::Connection::postEvent(const DisplayEventReceiver::Event& event) { ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1); return size < 0 ? status_t(size) : status_t(NO_ERROR); }参数event描述的是一个VSync事件,Connection的成员变量mChannel指向BitTube对象,通过已创建的BitTube传输通道来发送VSync事件Event信息。
ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel,Event const* events, size_t count) { return BitTube::sendObjects(dataChannel, events, count); }调用BitTube类的sendObjects()函数来发送一个VSync事件信息
ssize_t BitTube::sendObjects(const sp<BitTube>& tube,void const* events, size_t count, size_t objSize) { ssize_t numObjects = 0; for (size_t i=0 ; i<count ; i++) { const char* vaddr = reinterpret_cast<const char*>(events) + objSize * i; ssize_t size = tube->write(vaddr, objSize); if (size < 0) { // error occurred return size; } else if (size == 0) { // no more space break; } numObjects++; } return numObjects; }该函数可以发送多个事件对象,对于每一个事件对象的发送使用BitTube类的write()函数来完成。
ssize_t BitTube::write(void const* vaddr, size_t size) { ssize_t err, len; do { len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL); err = len < 0 ? errno : 0; } while (err == EINTR); return err == 0 ? len : -err; }这里就采用BitTube对象中创建的Socket来发送一个事件信息。因此EventThread线程分发VSync事件是通过在Socket发送端mSendFd写入一个Event事件信息,这样对于监听在Socket接收端的VSync接收者就可以收到VSync事件信息Event了。