代码位置位于: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。