[android_os_MessageQueue.cpp-->android_os_MessageQueue_nativePollOnce()] static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj, jint ptr, jint timeoutMillis) NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr); // 取出NativeMessageQueue对象,并调用它的pollOnce nativeMessageQueue->pollOnce(timeoutMillis); } 分析pollOnce函数: [android_os_MessageQueue.cpp-->NativeMessageQueue::pollOnece()] void NativeMessageQueue::pollOnce(int timeoutMillis) { mLooper->pollOnce(timeoutMillis); // pollOnce()操作被传递到Looper的pollOnce函数 } Looper的pollOnce函数如下: [Looper.cpp-->Looper::pollOnce()] inline int pollOnce(int timeoutMillis) { return pollOnce(timeoutMillis, NULL, NULL, NULL); }
/* ② 得到epoll句柄后,下一步就是通过epoll_ctl把需要监听的文件句柄加入epoll句柄中。除了 指定文件句柄本身的fd值外,同时还需要指定在该fd上等待什么事件。epoll支持4类事件,分别是 EPOLLIN(句柄可读)、EPOLLOUT(句柄可写)、EPOLLERR(句柄错误)和EPOLLHUP(句柄断)。 epoll定义了一个结构体struct epoll_event来表达监听句柄的诉求。假设现在有一个监听端的socket 句柄listener,要把它加入epoll句柄中 */ struct epoll_event listenEvent; //先定义一个event /* EPOLLIN表示可读事件,EPOLLOUT表示可写事件,另外还有EPOLLERR,EPOLLHUP表示系统默认会将 EPOLLERR加入事件集合中 */ listenEvent.events = EPOLLIN;// 指定该句柄的可读事件 // epoll_event中有一个联合体叫data,用来存储上下文数据,本例的上下文数据就是句柄自己listenEvent. data.fd = listenEvent; /* ③ EPOLL_CTL_ADD将监听fd和监听事件加入epoll句柄的等待队列中; EPOLL_CTL_DEL将监听fd从epoll句柄中移除; EPOLL_CTL_MOD修改监听fd的监听事件,例如本来只等待可读事件,现在需要同时等待可写事件,那么 修改listenEvent.events 为EPOLLIN|EPOLLOUT后,再传给epoll句柄 */ epoll_ctl(epollHandle,EPOLL_CTL_ADD, listener,&listenEvent); /* 当把所有感兴趣的fd都加入epoll句柄后,就可以开始坐等感兴趣的事情发生了。为了接收所发生的事 情,先定义一个epoll_event数组 */ struct epoll_event resultEvents[10]; int timeout = -1; while(1) { /* ④ 调用epoll_wait用于等待事件。其中timeout可以指定一个超时时间,resultEvents用于接收 发生的事件,10为该数组的大小。 epoll_wait函数的返回值有如下含义: nfds大于0表示所监听的句柄上有事件发生; nfds等于0表示等待超时; nfds小于0表示等待过程中发生了错误 */ int nfds = epoll_wait(epollHandle, resultEvents, 10, timeout); if(nfds == -1) { // epoll_wait发生了错误 } else if(nfds == 0) { //发生超时,期间没有发生任何事件 } else { // ⑤ resultEvents用于返回那些发生了事件的信息 for(int i = 0; i < nfds; i++) { struct epoll_event & event = resultEvents[i]; if(event & EPOLLIN) { /* ⑥ 收到可读事件。到底是哪个文件句柄发生该事件呢?可通过event.data这个联合体取 得之前传递给epoll的上下文数据,该上下文信息可用于判断到底是谁发生了事件 */ ...... } .......//其他处理 } } }
[Looper.cpp-->Looper::pollOnce()] int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) { int result = 0; for (;;) { // 一个无限循环 // mResponses是一个Vector,这里首先需要处理response while (mResponseIndex < mResponses.size()) { const Response& response = mResponses.itemAt(mResponseIndex++); ALooper_callbackFunc callback = response.request.callback; if (!callback) {// 首先处理那些没有callback的Response int ident = response.request.ident; // ident是这个Response的id 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; /* 实际上,对于没有callback的Response,pollOnce只是返回它的ident,实际 并没有做什么处理。因为没有callback,所以系统也不知道如何处理 */ return ident; } } if (result != 0) { if (outFd != NULL) *outFd = 0; if (outEvents != NULL) *outEvents = NULL; if (outData != NULL) *outData = NULL; return result; } // 调用pollInner函数。注意,它在for循环内部 result = pollInner(timeoutMillis); } }
[Looper.cpp-->Looper::pollInner()] int Looper::pollInner(int timeoutMillis) { if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); ......//根据Native Message的信息计算此次需要等待的时间 timeoutMillis = messageTimeoutMillis; } int result = ALOOPER_POLL_WAKE; mResponses.clear(); mResponseIndex = 0; #ifdef LOOPER_USES_EPOLL // 只讨论使用epoll进行I/O复用的方式 struct epoll_event eventItems[EPOLL_MAX_EVENTS]; // 调用epoll_wait,等待感兴趣的事件或超时发生 int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis); #else ......//使用别的方式进行I/O复用 #endif //从epoll_wait返回,这时候一定发生了什么事情 mLock.lock(); if (eventCount < 0) { //返回值小于零,表示发生错误 if (errno == EINTR) { goto Done; } //设置result为ALLOPER_POLL_ERROR,并跳转到Done result = ALOOPER_POLL_ERROR; goto Done; } //eventCount为零,表示发生超时,因此直接跳转到Done if (eventCount == 0) { result = ALOOPER_POLL_TIMEOUT; goto Done; } #ifdef LOOPER_USES_EPOLL // 根据epoll的用法,此时的eventCount表示发生事件的个数 for (int i = 0; i < eventCount; i++) { int fd = eventItems[i].data.fd; uint32_t epollEvents = eventItems[i].events; /* 之前通过pipe函数创建过两个fd,这里根据fd知道是管道读端有可读事件。 还记得对nativeWake函数的分析吗?在那里我们向管道写端写了一个“W”字符,这样就能触 发管道读端从epoll_wait函数返回了 */ if (fd == mWakeReadPipeFd) { if (epollEvents & EPOLLIN) { // awoken函数直接读取并清空管道数据,读者可自行研究该函数 awoken(); } ...... } else { /* mRequests和前面的mResponse相对应,它也是一个KeyedVector,其中存储了fd和 对应的Request结构体,该结构体封装了和监控文件句柄相关的一些上下文信息,例如 回调函数等。我们在后面的小节会再次介绍该结构体 */ ssize_t requestIndex = mRequests.indexOfKey(fd); if (requestIndex >= 0) { int events = 0; // 将epoll返回的事件转换成上层LOOPER使用的事件 if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT; if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT; if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR; if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP; // 每处理一个Request,就相应构造一个Response pushResponse(events, mRequests.valueAt(requestIndex)); } ...... } } Done: ; #else ...... #endif // 除了处理Request外,还处理Native的Message mNextMessageUptime = LLONG_MAX; while (mMessageEnvelopes.size() != 0) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0); if (messageEnvelope.uptime <= now) { { sp<MessageHandler> handler = messageEnvelope.handler; Message message = messageEnvelope.message; mMessageEnvelopes.removeAt(0); mSendingMessage = true; mLock.unlock(); /* 调用Native的handler处理Native的Message 从这里也可看出Native Message和Java层的Message没有什么关系 */ handler->handleMessage(message); } mLock.lock(); mSendingMessage = false; result = ALOOPER_POLL_CALLBACK; } else { mNextMessageUptime = messageEnvelope.uptime; break; } } mLock.unlock(); // 处理那些带回调函数的Response for (size_t i = 0; i < mResponses.size(); i++) { const Response& response = mResponses.itemAt(i); ALooper_callbackFunc callback = response.request.callback; if (callback) {// 有了回调函数,就能知道如何处理所发生的事情了 int fd = response.request.fd; int events = response.events; void* data = response.request.data; // 调用回调函数处理所发生的事件 int callbackResult = callback(fd, events, data); if (callbackResult == 0) { // callback函数的返回值很重要,如果为0,表明不需要再次监视该文件句柄 removeFd(fd); } result = ALOOPER_POLL_CALLBACK; } } return result; }
[android_app_NativeActivity.cpp-->loadNativeCode_native()] static jint loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,jobject messageQueue, jstring internalDataDir, jstring obbDir, jstring externalDataDir, int sdkVersion, jobject jAssetMgr, jbyteArray savedState) { ...... /* 调用Looper的addFd函数。第一个参数表示监听的fd;第二个参数0表示ident;第三个参数表示 需要监听的事件,这里为只监听可读事件;第四个参数为回调函数,当该fd发生指定事件时,looper 将回调该函数;第五个参数code为回调函数的参数 */ code->looper->addFd(code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code); ...... } Looper的addFd()代码如下所示: [Looper.cpp-->Looper::addFd()] int Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) { if (! callback) { /* 判断该Looper是否支持不带回调函数的文件句柄添加。一般不支持,因为没有回调函数, Looper也不知道如何处理该文件句柄上发生的事情 */ if (! mAllowNonCallbacks) { return -1; } ...... } #ifdef LOOPER_USES_EPOLL int epollEvents = 0; // 将用户的事件转换成epoll使用的值 if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN; if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT; { AutoMutex _l(mLock); Request request; // 创建一个Request对象 request.fd = fd; // 保存fd request.ident = ident; // 保存id request.callback = callback; //保存 callback request.data = data; // 保存用户自定义数据 struct epoll_event eventItem; memset(& eventItem, 0, sizeof(epoll_event)); eventItem.events = epollEvents; eventItem.data.fd = fd; // 判断该Request是否已经存在,mRequests以fd作为key值 ssize_t requestIndex = mRequests.indexOfKey(fd); if (requestIndex < 0) { // 如果是新的文件句柄,则需要为epoll增加该fd int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem); ...... // 保存Request到mRequests键值数组 mRequests.add(fd, request); } else { // 如果之前加过,那么修改该监听句柄的一些信息 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem); ...... mRequests.replaceValueAt(requestIndex, request); } } #else ...... #endif return 1; } 4. 处理监控请求 我们发现在pollInner()函数中,当某个监控fd上发生事件后,就会把对应的Request取出来调用。 pushResponse(events, mRequests.itemAt(i)); 此函数如下: [Looper.cpp-->Looper::pushResponse()] void Looper::pushResponse(int events, const Request& request) { Response response; response.events = events; response.request = request; //其实很简单,就是保存所发生的事情和对应的Request mResponses.push(response); //然后保存到mResponse数组 }
[Looper.cpp-->Looper::sendMessage()] void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) { //Native的sendMessage函数必须同时传递一个Handler nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); sendMessageAtTime(now, handler, message); //调用sendMessageAtTime } [Looper.java-->Looper::sendMessageAtTime()] void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler, const Message& message) { size_t i = 0; { AutoMutex _l(mLock); size_t messageCount = mMessageEnvelopes.size(); // 按时间排序,将消息插入正确的位置 while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) { i += 1; } MessageEnvelope messageEnvelope(uptime, handler, message); mMessageEnvelopes.insertAt(messageEnvelope, i, 1); // mSendingMessage和Java层中的那个mBlocked一样,是一个小小的优化措施 if (mSendingMessage) { return; } } // 唤醒epoll_wait,让它处理消息 if (i == 0) { wake(); } }