Looper源代码解析<一>

代码位置位于:aosp\system\core\libutils\Looper.cpp
这个类在handler机制,SurfaceFlinger中消息调度机制都起到了关键作用。先来看下这个类的构造方法。

Looper::Looper(bool allowNonCallbacks) :
        mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
        mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
        mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
    mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    rebuildEpollLocked();
}

先看下几个内部变量。
mAllowNonCallbacks:true 代表file descriptors(文件描述符)可以被注册,并且没有返回。这个意味着调用者调用pollOnce()的时候,将要处理没有任何回调的消息。
mSendingMessage:是否正在发送消息
mPolling:我们目前是否在等待工作
mEpollFd:关键变量。注册Epoll返回的文件描述符。(Epoll机制是一种多进程通信的机制,现在可以类别socket机制来学习,实质还是不一样的)
mEpollRebuildRequired:是否需要重建Epoll
mNextRequestSeq:下个请求的序号
mResponseIndex:获取到回复的索引
mNextMessageUptime:下一个消息的可用时间(一般设置最大值就行,LLONG_MAX)
接下来进行。构造方法的分析。
mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
//先来普及一下基础知识。
eventfd的创建是通过eventfd函数实现的,返回值即是该eventfd所对应的文件描述符,函数的原型如下所示:

在这里插入图片描述
initval:创建eventfd时它所对应的64位计数器的初始值;
flags:eventfd文件描述符的标志,可由三种选项组成:EFD_CLOEXEC、EFD_NONBLOCK和EFD_SEMAPHORE。
EFD_CLOEXEC表示返回的eventfd文件描述符在fork后exec其他程序时会自动关闭这个文件描述符;
EFD_NONBLOCK设置返回的eventfd非阻塞;
EFD_SEMAPHORE表示将eventfd作为一个信号量来使用。
所以mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); 就是创建了一个eventfd文件描述符(为了线程间通信用的)。
接下来: rebuildEpollLocked();
epoll机制是一个能够管理FD的(如上文的eventfd,socket,普通file)的一种机制。
再来个Request的结构信息。

  struct Request {
        int fd;
        int ident;
        int events;
        int seq;
        sp<LooperCallback> callback;
        void* data;

        void initEventItem(struct epoll_event* eventItem) const;
    };

Repose的结构信息

  struct Response {
        int events;
        Request request;
    };
void Looper::rebuildEpollLocked() {
    //创建了一个epoll类型的fd。
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
    struct epoll_event eventItem;
    //先将eventItem的内存区域置0
    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
    //事件类型为EPOLLIN,当有事件来到的时候会触发,或者理解为上述mWakeEventFd如果有数据写入,epoll机制就能够立即返回并且读到此epoll_event.
    eventItem.events = EPOLLIN;
    //上一个方法创建的eventfd。
    eventItem.data.fd = mWakeEventFd;
    //将epoll_event 数据注册进入内核。这样同样的mEpollFd中如果有事件来临将会触发epoll_event.
    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
    //mRequests 是一个map,key为fd,value为上述Request 结构。是在Looper.addFd中加入的。此时遍历此结构。并且把mRequests中的所有fd加入到新创建的。epoll里面。
    for (size_t i = 0; i < mRequests.size(); i++) {
        const Request& request = mRequests.valueAt(i);
        struct epoll_event eventItem;
        request.initEventItem(&eventItem);
        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem);
        if (epollResult < 0) {
            ALOGE("Error adding epoll events for fd %d while rebuilding epoll set: %s",
                  request.fd, strerror(errno));
        }
    }
}

构造函数讲完了,也知道了构造函数主要做了两个事情。一个是创建了一个eventfd,一个是创建了mEpollFd,并且把epoll_event 加入了到了eventfd,后续等到fd中有了事件读入就会触发epoll机制的回调。
现在来讲讲Looper是怎么用的。再牛逼的代码,再精巧的结构也得在实际业务场景中才能体会其价值。
我们还是以SurfaceFlinger的初始化构造开始讲吧。SF 构造方法走完会调用

 void SurfaceFlinger::onFirstRef()
{
    mEventQueue.init(this);
}

mEventQueue实际就是MessageQueue(难道取名叫做mMessageQueue不好么)

void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
{
    mFlinger = flinger;
    mLooper = new Looper(true);
    mHandler = new Handler(*this);
}

我们看到了这里面初始化了Looper和Handler。Looper刚刚已经构造完毕,现在讲讲Handler的初始化。
Handler实际类似一个大管家,只是起到一个中转通知的作用,具体的业务功能它是一个也不做,是不是有点类似我们的leader

  class Handler : public MessageHandler {
        enum {
            eventMaskInvalidate     = 0x1,
            eventMaskRefresh        = 0x2,
            eventMaskTransaction    = 0x4
        };
        MessageQueue& mQueue;
        int32_t mEventMask;
    public:
        explicit Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) { }
        virtual void handleMessage(const Message& message);
        void dispatchRefresh();
        void dispatchInvalidate();
    };

注意handleMessage和dispatchRefresh、dispatchInvalidate都在MessageQueue里面实现。
基本逻辑就是SF 需要刷新的时候首先调用MessageQueue的dispatchRefresh,然后MQ调用handler的dispatchRefresh,然后调用到Looper的sendMessage。实际最终干活的还是我们的Looper。我们以刷新为例子,来分析下Looper的epoll机制。

void MessageQueue::Handler::dispatchRefresh() {
 mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
}

void MessageQueue::Handler::dispatchInvalidate() {
 mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
}

void MessageQueue::Handler::handleMessage(const Message& message) {
    switch (message.what) {
        case INVALIDATE:
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
        case REFRESH:
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
    }
}

来看看Looper干了啥。
mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));

void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
    sendMessageAtTime(now, handler, message);
}

continue…实际调用的是sendMessageAtTime。

void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
        const Message& message) {
    size_t i = 0;
    { 
        size_t messageCount = mMessageEnvelopes.size();
        //寻找消息队列中,根据时间排序,找到比要插入的消息小的那个消息。
        while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {
            i += 1;
        }
        //创造MessageEnvelope 
        MessageEnvelope messageEnvelope(uptime, handler, message);
        //插入其中。现在我们send的消息已经到了消息队列中。等待Loop来poll。
        mMessageEnvelopes.insertAt(messageEnvelope, i, 1);
        // Optimization: If the Looper is currently sending a message, then we can skip
        // the call to wake() because the next thing the Looper will do after processing
        // messages is to decide when the next wakeup time should be.  In fact, it does
        // not even matter whether this code is running on the Looper thread.
        if (mSendingMessage) {
            return;
        }
    } // release lock
    // Wake the poll loop only when we enqueue a new message at the head.
    if (i == 0) {
        wake();
    }
}

现在我们send的消息已经到了消息队列中。等待Loop中fd监听到相关事件,再去处理这个消息队列。这个相关事件可能是Vysnc信号。
当SF 运行起来的时候,会调用下面这个方法。

void SurfaceFlinger::waitForEvent() {
    mEventQueue.waitMessage();
}

继续。

void MessageQueue::waitMessage() {
    do {
        IPCThreadState::self()->flushCommands();
        //这句话主要作用就是epoll_wait 等待epoll_event 事件到来,然后从消息队列去拿到消息去执行。实际handler机制拿消息核心也是这句话。
        int32_t ret = mLooper->pollOnce(-1);
        switch (ret) {
            case Looper::POLL_WAKE:
            case Looper::POLL_CALLBACK:
                continue;
            case Looper::POLL_ERROR:
                ALOGE("Looper::POLL_ERROR");
                continue;
            case Looper::POLL_TIMEOUT:
                // timeout (should not happen)
                continue;
            default:
                // should not happen
                ALOGE("Looper::pollOnce() returned unknown status %d", ret);
                continue;
        }
    } while (true);
}

此段代码属于死循环,跳不出来的,这也是消息机制得以生效得根本原因。
先看第一句话。 IPCThreadState::self()->flushCommands();
IPCThreadState.cpp 位于 frameworks/native/libs/binder中,属于binder机制交互得核心类。

void IPCThreadState::flushCommands()
{
    talkWithDriver(false);
}

talkWithDriver(false); 属于跟binder驱动交互。

可以看出来 talkWithDriver(false)实际上完成了与binder驱动的一次读写交互。接下来可以Looper里面的
int32_t ret = mLooper->pollOnce(-1); 这句话了,代码如下。传入timeoutMills代表没有延迟。

int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    int result = 0;
    for (;;) {
        while (mResponseIndex < mResponses.size()) {
            const Response& response = mResponses.itemAt(mResponseIndex++);
            int ident = response.request.ident;
            if (ident >= 0) {
                int fd = response.request.fd;
                int events = response.events;
                void* data = response.request.data;
                if (outFd != NULL) *outFd = fd;
                if (outEvents != NULL) *outEvents = events;
                if (outData != NULL) *outData = data;
                return ident;
            }
        }
            if (outFd != NULL) *outFd = 0;
            if (outEvents != NULL) *outEvents = 0;
            if (outData != NULL) *outData = NULL;
            return result;
        }

        result = pollInner(timeoutMillis);
    }
int Looper::pollInner(int timeoutMillis) {
    // Poll.
    int result = POLL_WAKE;
    //清空回复队列
    mResponses.clear();
    mResponseIndex = 0;
    // We are about to idle.
    mPolling = true;
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    //等待是否有消息到来,这里是线程通信,一旦有消息就会返回,否则会阻塞。
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
    // No longer idling.
    mPolling = false;
    // Acquire lock.
    mLock.lock();
    //有消息到来处理消息。
    // Handle all events.
    for (int i = 0; i < eventCount; i++) {
        int fd = eventItems[i].data.fd;
        uint32_t epollEvents = eventItems[i].events;
        //此处主要利用了epollEvents的events属性,分为事件EVENT_INPUT,EVENT_OUTPUT,EVENT_ERROR,EVENT_HANGUP
        //唤醒,其实就是MQ中调用了阻塞方法,这里如果有消息到来就要唤醒了。
        if (fd == mWakeEventFd) {
            if (epollEvents & EPOLLIN) {
                awoken();
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents);
            }
        } else {
            ssize_t requestIndex = mRequests.indexOfKey(fd);
            if (requestIndex >= 0) {
                int events = 0;
                if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
                if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
                if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
                if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;
                //将消息压入到mReponse里面。
                pushResponse(events, mRequests.valueAt(requestIndex));
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
                        "no longer registered.", epollEvents, fd);
            }
        }
    }
    // Invoke pending message callbacks.
    mNextMessageUptime = LLONG_MAX;
    while (mMessageEnvelopes.size() != 0) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
        if (messageEnvelope.uptime <= now) {
            { // obtain handler
                sp<MessageHandler> handler = messageEnvelope.handler;
                Message message = messageEnvelope.message;
                mMessageEnvelopes.removeAt(0);
                mSendingMessage = true;
                mLock.unlock();
                handler->handleMessage(message);
            } // release handler

            mLock.lock();
            mSendingMessage = false;
            result = POLL_CALLBACK;
        } else {
            // The last message left at the head of the queue determines the next wakeup time.
            mNextMessageUptime = messageEnvelope.uptime;
            break;
        }
    }

    // Release lock.
    mLock.unlock();
     //消息回调。  
    // Invoke all response callbacks.
    for (size_t i = 0; i < mResponses.size(); i++) {
        Response& response = mResponses.editItemAt(i);
        if (response.request.ident == POLL_CALLBACK) {
            int fd = response.request.fd;
            int events = response.events;
            void* data = response.request.data;
            int callbackResult = response.request.callback->handleEvent(fd, events, data);
            if (callbackResult == 0) {
                removeFd(fd, response.request.seq);
            }
            // Clear the callback reference in the response structure promptly because we
            // will not clear the response vector itself until the next poll.
            response.request.callback.clear();
            result = POLL_CALLBACK;
        }
    }
    return result;
}

看到这儿,就等epoll_wait 回调整个sf就能够收到消息,进而传递给app。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值