Android应用开发之Android源码之SurfaceFlinger的启动(三)
白羽 2018-08-10 来源 :网络 阅读 1134 评论 0

摘要:本文将带你了解Android应用开发之Android源码之SurfaceFlinger的启动(三),希望本文对大家学Android有所帮助

        本文将带你了解Android应用开发之Android源码之SurfaceFlinger的启动(三),希望本文对大家学Android有所帮助


page11
    我们来看一下SurfaceFlinger的onFirstRef函数的定义:
    1void EventThread::onFirstRef() {
    2    run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
    3}
    我靠, 又调用run函数, 这会导致又启动了一个线程.
    同样的, 这也会导致readyToRun和threadLoop函数的.
    EventThread的readyToRun函数是从Thread类继承而来的, 是个空函数.
    而EventThread的threadLoop函数的定义如下:
    1 bool EventThread::threadLoop() {
    2     DisplayEventReceiver::Event event;
    3     Vector< sp<EventThread::Connection> > signalConnections;
    4     signalConnections = waitForEvent(&event);
    5
    6     // dispatch events to listeners...
    7     const size_t count = signalConnections.size();
    8     for (size_t i=0 ; i<count ; i++) {
    9         const sp<Connection>& conn(signalConnections[i]);
    10         // now see if we still need to report this event
    11         status_t err = conn->postEvent(event);
    12         if (err == -EAGAIN || err == -EWOULDBLOCK) {
    13             // The destination doesn't accept events anymore, it's probably
    14             // full. For now, we just drop the events on the floor.
    15             // FIXME: Note that some events cannot be dropped and would have
    16             // to be re-sent later.
    17             // Right-now we don't have the ability to do this.
    18             ALOGW("EventThread: dropping event (%08x) for connection %p",
    19                     event.header.type, conn.get());
    20         } else if (err < 0) {
    21             // handle any other error on the pipe as fatal. the only
    22             // reasonable thing to do is to clean-up this connection.
    23             // The most common error we'll get here is -EPIPE.
    24             removeDisplayEventConnection(signalConnections[i]);
    25         }
    26     }
    27     return true;
    28 }
    EventThread的threadLoop函数的主要逻辑就是不停地等待事件, 然后交给Connection去处理.
page12
 我们来分析一下MessageQueue的setEventThread函数的逻辑实现, setEventThread函数的定义如下所示:
 1 void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
 2 {
 3     mEventThread = eventThread;
 4     mEvents = eventThread->createEventConnection();
 5     mEventTube = mEvents->getDataChannel();
 6     mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT, MessageQueue::cb_eventReceiver, this);
 7 }
 第4行(MessageQueue->setEventThread)会调用EventThread的createEventConnection函数, 关于createEventConnection函数的详细分析可以参考page13文件.
 第5行(MessageQueue->setEventThread)会调用Connection的getDataChannel来得到一个BitTube对象并初始化, getDataChannel函数的定义如下所示:
    sp<BitTube> EventThread::Connection::getDataChannel() const {
        return mChannel;
    }
    第6行(MessageQueue->setEventThread)会首先调用BitTube的getFd函数来得到一个文件操作符, 并加入到MessageQueue的Looper里.
    我们先看一下BitTube的getFd函数的定义, 如下所示:
    int BitTube::getFd() const
    {
        return mReceiveFd;
    }
    BitTube的getFd函数会返回用于接受的文件操作符, 这样当有数据写入该文件操作符的时候就会唤醒这个Looper处理该消息, 也就是说EventThread线程收到事件会交给SurfaceFlinger的Main线程取处理了, 这样就把EventThread线程和Main线程绑定到一起了.
    EventThread发过来的消息的处理函数是调用的MessageQueue的cb_eventReceiver函数, 关于cb_eventReceiver函数的详细分析可以参考page14文件.
page13
 在这里, 我们看一下EventThread的createEventConnection函数的具体实现, createEventConnection函数的定义如下:
 sp<EventThread::Connection> EventThread::createEventConnection() const {
        return new Connection(const_cast<EventThread*>(this));
    }
    createEventConnection函数只是返回了一个Connection对象.
    Connection类的构造函数的定义如下:
    EventThread::Connection::Connection(
            const sp<EventThread>& eventThread)
        : count(-1), mEventThread(eventThread), mChannel(new BitTube())
    {
    }
    可以看到, Connection的mChannel会用一个BitTube来初始化, BitTube的类的声明如下:
    class BitTube : public RefBase
    BitTube类的构造函数的定义如下:
    1 BitTube::BitTube()
    2     : mSendFd(-1), mReceiveFd(-1)
    3 {
    4     int sockets[2];
    5     if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
    6         int size = SOCKET_BUFFER_SIZE;
    7         setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
    8         setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
    9         setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
    10         setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
    11         fcntl(sockets[0], F_SETFL, O_NONBLOCK);
    12         fcntl(sockets[1], F_SETFL, O_NONBLOCK);
    13         mReceiveFd = sockets[0];
    14         mSendFd = sockets[1];
    15     } else {
    16         mReceiveFd = -errno;
    17         ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
    18     }
    19 }
    可以看出, BitTube构造函数只是创建了两个文件操作符, 一个用户读, 一个用于写.
page14
    在这篇文章里, 我们分析一下MessageQueue的cb_eventReceiver函数的实现:
    int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
        MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);
        return queue->eventReceiver(fd, events);
    }
    cb_eventReceiver函数又会调用eventReceiver函数, MessageQueue的eventReceiver函数的定义如下:
    1 int MessageQueue::eventReceiver(int fd, int events) {
    2     ssize_t n;
    3     DisplayEventReceiver::Event buffer[8];
    4     while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer,) > 0) {
    5         for (int i=0 ; i<n ; i++) {
    6             if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
    7 #if INVALIDATE_ON_VSYNC
    8                 mHandler->dispatchInvalidate();
    9 #else
    10                 mHandler->dispatchRefresh();
    11 #endif
    12                 break;
    13             }
    14         }
    15     }
    16     return 1;
    17 }
    第4行(MessageQueue->eventReceiver)会在mEventTube上调用DisplayEventReceiver的getEvents函数, 关于DisplayEventReceiver的getEvents函数的详细分析可以参考page15文件.
page15
 在这篇文章里, 我们分析一下DisplayEventReceiver的getEvents函数的实现:
 1ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events, size_t count) {
 2    return DisplayEventReceiver::getEvents(mDataChannel, events, count);
 3}
 两个参数的getEvents又会调用三个参数的重载版本, 该函数的定义如下:
    1ssize_t DisplayEventReceiver::getEvents(const sp<BitTube>& dataChannel, Event* events, size_t count)
    2{
    3    return BitTube::recvObjects(dataChannel, events, count);
    4}
    getEvents函数最终会调用BitTube的recvObjects函数, 而传入的文件操作符正是成员变量mEventTube.
    BitTube的recvObjects函数的定义如下:
    1 ssize_t BitTube::recvObjects(const sp<BitTube>& tube, void* events, size_t count, size_t objSize)
    2 {
    3     ssize_t numObjects = 0;
    4     for (size_t i=0 ; i<count ; i++) {
    5         char* vaddr = reinterpret_cast<char*>(events) + objSize * i;
    6         ssize_t size = tube->read(vaddr, objSize);
    7         if (size < 0) {
    8             // error occurred
    9             return size;
    10         } else if (size == 0) {
    11             // no more messages
    12             break;
    13         }
    14         numObjects++;
    15     }
    16     return numObjects;
    17 }
    第6行(BitTube->recvObjects)会在该BitTube上调用read函数来接受数据, BitTube的read函数的定义如下所示:
    1 ssize_t BitTube::read(void* vaddr, size_t size)
    2 {
    3     ssize_t err, len;
    4     do {
    5         len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT);
    6         err = len < 0 ? errno : 0;
    7     } while (err == EINTR);
    8     if (err == EAGAIN || err == EWOULDBLOCK) {
    9         // EAGAIN means that we have non-blocking I/O but there was
    10         // no data to be read. Nothing the client should care about.
    11         return 0;
    12     }
    13     return err == 0 ? len : -err;
    14 }
    第5行(BitTube->read)会在mReceiveFd文件操作符上读取size大小的数据, 并保存到地址vaddr里去.    

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!

本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程