【从源码看Android】03Android MessageQueue消息循环处理机制(epoll实现)

1 enqueueMessage


handler发送一条消息

[java]  view plain copy
  1. mHandler.sendEmptyMessage(1);  
经过层层调用,进入到sendMessageAtTime函数块,最后调用到enqueueMessage

Handler.java

[java]  view plain copy
  1. public boolean sendMessageAtTime(Message msg, long uptimeMillis) {  
  2.         MessageQueue queue = mQueue;  
  3.         if (queue == null) {  
  4.             RuntimeException e = new RuntimeException(  
  5.                     this + " sendMessageAtTime() called with no mQueue");  
  6.             Log.w("Looper", e.getMessage(), e);  
  7.             return false;  
  8.         }  
  9.         return enqueueMessage(queue, msg, uptimeMillis);  
  10.     }  


最后调用到Handler私有的函数enqueueMessage,把handler对象赋值给msg.target,调用queue.enqueueMessage

Handler.java
[java]  view plain copy
  1. private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {  
  2.         msg.target = this;  
  3.         if (mAsynchronous) {  
  4.             msg.setAsynchronous(true);  
  5.         }  
  6.         return queue.enqueueMessage(msg, uptimeMillis);  
  7.     }  


下面是核心代码,首先是获得同步锁,

MessageQueue.java

[java]  view plain copy
  1. boolean enqueueMessage(Message msg, long when) {  
  2.         if (msg.isInUse()) {  
  3.             throw new AndroidRuntimeException(msg + " This message is already in use.");  
  4.         }  
  5.         if (msg.target == null) {  
  6.             throw new AndroidRuntimeException("Message must have a target.");  
  7.         }  
  8.   
  9.         synchronized (this) {  
  10.             if (mQuitting) {  
  11.                 RuntimeException e = new RuntimeException(  
  12.                         msg.target + " sending message to a Handler on a dead thread");  
  13.                 Log.w("MessageQueue", e.getMessage(), e);  
  14.                 return false;  
  15.             }  
  16.   
  17.             msg.when = when;  
  18.             Message p = mMessages;  
  19.             boolean needWake;  
  20.             if (p == null || when == 0 || when < p.when) {  
  21.                 // New head, wake up the event queue if blocked.  
  22.                 msg.next = p;  
  23.                 mMessages = msg;  
  24.                 needWake = mBlocked;  
  25.             } else {  
  26.                 // Inserted within the middle of the queue.  Usually we don't have to wake  
  27.                 // up the event queue unless there is a barrier at the head of the queue  
  28.                 // and the message is the earliest asynchronous message in the queue.  
  29.                 needWake = mBlocked && p.target == null && msg.isAsynchronous();  
  30.                 Message prev;  
  31.                 for (;;) {  
  32.                     prev = p;  
  33.                     p = p.next;  
  34.                     if (p == null || when < p.when) {  
  35.                         break;  
  36.                     }  
  37.                     if (needWake && p.isAsynchronous()) {  
  38.                         needWake = false;  
  39.                     }  
  40.                 }  
  41.                 msg.next = p; // invariant: p == prev.next  
  42.                 prev.next = msg;  
  43.             }  
  44.   
  45.             // We can assume mPtr != 0 because mQuitting is false.  
  46.             if (needWake) {  
  47.                 nativeWake(mPtr);  
  48.             }  
  49.         }  
  50.         return true;  
  51.     }  

首先是获得自身的同步锁synchronized (this),接着这个msg跟MessageQueue实例的头结点Message进行触发时间先后的比较,

如果触发时间比现有的头结点Message前,则这个新的Message作为整个MessageQueue的头结点,如果阻塞着,则立即唤醒线程处理

如果触发时间比头结点晚,则按照触发时间先后,在消息队列中间插入这个结点

接着如果需要唤醒,则调用nativeWake函数


在android_os_MessageQueue.cpp里定义了nativeWake函数

[cpp]  view plain copy
  1. static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) {  
  2.     NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);  
  3.     return nativeMessageQueue->wake();  
  4. }  

实际调用到mLooper->wake();

android_os_MessageQueue.cpp

[cpp]  view plain copy
  1. void NativeMessageQueue::wake() {  
  2.     mLooper->wake();  
  3. }  
而mLooper是cpp层的Looper对象,

framework/base/libs/utils/Looper.cpp

[cpp]  view plain copy
  1. void Looper::wake() {  
  2. #if DEBUG_POLL_AND_WAKE  
  3.     LOGD("%p ~ wake"this);  
  4. #endif  
  5.   
  6. #ifdef LOOPER_STATISTICS  
  7.     // FIXME: Possible race with awoken() but this code is for testing only and is rarely enabled.  
  8.     if (mPendingWakeCount++ == 0) {  
  9.         mPendingWakeTime = systemTime(SYSTEM_TIME_MONOTONIC);  
  10.     }  
  11. #endif  
  12.   
  13.     ssize_t nWrite;  
  14.     do {  
  15.         nWrite = write(mWakeWritePipeFd, "W", 1);  
  16.     } while (nWrite == -1 && errno == EINTR);  
  17.   
  18.     if (nWrite != 1) {  
  19.         if (errno != EAGAIN) {  
  20.             LOGW("Could not write wake signal, errno=%d", errno);  
  21.         }  
  22.     }  
  23. }  

是不是很熟悉?基本就是上一讲epoll原型的唤醒函数,向mWakeWritePipeFD写入1字节,唤醒监听block在mWakeReadPipeFD端口的epoll_wait



2 dequeueMessage


首先dequeueMessage只是我取的一个叫法,当java层的Looper进行loop的时候,就已经在不停地读取MessageQueue里的Message了

Looper.java

[java]  view plain copy
  1. public static void loop() {  
  2.         final Looper me = myLooper();  
  3.         if (me == null) {  
  4.             throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");  
  5.         }  
  6.         final MessageQueue queue = me.mQueue;  
  7.   
  8.         // Make sure the identity of this thread is that of the local process,  
  9.         // and keep track of what that identity token actually is.  
  10.         Binder.clearCallingIdentity();  
  11.         final long ident = Binder.clearCallingIdentity();  
  12.   
  13.         for (;;) {  
  14.             Message msg = queue.next(); // might block  
  15.             if (msg == null) {  
  16.                 // No message indicates that the message queue is quitting.  
  17.                 return;  
  18.             }  
  19.   
  20.             // This must be in a local variable, in case a UI event sets the logger  
  21.             Printer logging = me.mLogging;  
  22.             if (logging != null) {  
  23.                 logging.println(">>>>> Dispatching to " + msg.target + " " +  
  24.                         msg.callback + ": " + msg.what);  
  25.             }  
  26.   
  27.             msg.target.dispatchMessage(msg);  
  28.   
  29.             if (logging != null) {  
  30.                 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);  
  31.             }  
  32.   
  33.             // Make sure that during the course of dispatching the  
  34.             // identity of the thread wasn't corrupted.  
  35.             final long newIdent = Binder.clearCallingIdentity();  
  36.             if (ident != newIdent) {  
  37.                 Log.wtf(TAG, "Thread identity changed from 0x"  
  38.                         + Long.toHexString(ident) + " to 0x"  
  39.                         + Long.toHexString(newIdent) + " while dispatching to "  
  40.                         + msg.target.getClass().getName() + " "  
  41.                         + msg.callback + " what=" + msg.what);  
  42.             }  
  43.   
  44.             msg.recycle();  
  45.         }  
  46.     }  

调用queue.next()读取下一条消息(在loop调用的线程中),如果读取到了就msg,target.dispatchMessage,

下面来看看queue.next()如何实现


MessageQueue.java

[java]  view plain copy
  1. Message next() {  
  2.         int pendingIdleHandlerCount = -1// -1 only during first iteration  
  3.         int nextPollTimeoutMillis = 0;  
  4.         for (;;) {  
  5.             if (nextPollTimeoutMillis != 0) {  
  6.                 Binder.flushPendingCommands();  
  7.             }  
  8.   
  9.             // We can assume mPtr != 0 because the loop is obviously still running.  
  10.             // The looper will not call this method after the loop quits.  
  11.             nativePollOnce(mPtr, nextPollTimeoutMillis);  
  12.   
  13.             synchronized (this) {  
  14.                 // Try to retrieve the next message.  Return if found.  
  15.                 final long now = SystemClock.uptimeMillis();  
  16.                 Message prevMsg = null;  
  17.                 Message msg = mMessages;  
  18.                 if (msg != null && msg.target == null) {  
  19.                     // Stalled by a barrier.  Find the next asynchronous message in the queue.  
  20.                     do {  
  21.                         prevMsg = msg;  
  22.                         msg = msg.next;  
  23.                     } while (msg != null && !msg.isAsynchronous());  
  24.                 }  
  25.                 if (msg != null) {  
  26.                     if (now < msg.when) {  
  27.                         // Next message is not ready.  Set a timeout to wake up when it is ready.  
  28.                         nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);  
  29.                     } else {  
  30.                         // Got a message.  
  31.                         mBlocked = false;  
  32.                         if (prevMsg != null) {  
  33.                             prevMsg.next = msg.next;  
  34.                         } else {  
  35.                             mMessages = msg.next;  
  36.                         }  
  37.                         msg.next = null;  
  38.                         if (false) Log.v("MessageQueue""Returning message: " + msg);  
  39.                         msg.markInUse();  
  40.                         return msg;  
  41.                     }  
  42.                 } else {  
  43.                     // No more messages.  
  44.                     nextPollTimeoutMillis = -1;  
  45.                 }  
  46.   
  47.                 // Process the quit message now that all pending messages have been handled.  
  48.                 if (mQuitting) {  
  49.                     dispose();  
  50.                     return null;  
  51.                 }  
  52.   
  53.                 // If first time idle, then get the number of idlers to run.  
  54.                 // Idle handles only run if the queue is empty or if the first message  
  55.                 // in the queue (possibly a barrier) is due to be handled in the future.  
  56.                 if (pendingIdleHandlerCount < 0  
  57.                         && (mMessages == null || now < mMessages.when)) {  
  58.                     pendingIdleHandlerCount = mIdleHandlers.size();  
  59.                 }  
  60.                 if (pendingIdleHandlerCount <= 0) {  
  61.                     // No idle handlers to run.  Loop and wait some more.  
  62.                     mBlocked = true;  
  63.                     continue;  
  64.                 }  
  65.   
  66.                 if (mPendingIdleHandlers == null) {  
  67.                     mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];  
  68.                 }  
  69.                 mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);  
  70.             }  
  71.   
  72.             // Run the idle handlers.  
  73.             // We only ever reach this code block during the first iteration.  
  74.             for (int i = 0; i < pendingIdleHandlerCount; i++) {  
  75.                 final IdleHandler idler = mPendingIdleHandlers[i];  
  76.                 mPendingIdleHandlers[i] = null// release the reference to the handler  
  77.   
  78.                 boolean keep = false;  
  79.                 try {  
  80.                     keep = idler.queueIdle();  
  81.                 } catch (Throwable t) {  
  82.                     Log.wtf("MessageQueue""IdleHandler threw exception", t);  
  83.                 }  
  84.   
  85.                 if (!keep) {  
  86.                     synchronized (this) {  
  87.                         mIdleHandlers.remove(idler);  
  88.                     }  
  89.                 }  
  90.             }  
  91.   
  92.             // Reset the idle handler count to 0 so we do not run them again.  
  93.             pendingIdleHandlerCount = 0;  
  94.   
  95.             // While calling an idle handler, a new message could have been delivered  
  96.             // so go back and look again for a pending message without waiting.  
  97.             nextPollTimeoutMillis = 0;  
  98.         }  
  99.     }  

首先是个包内函数,所以在同一个包中(android.os)的Looper对象能调用到

nativePollOnce(mPtr, nextPollTimeoutMillis);函数待会展开,功能是调用上一讲的epoll_wait,

nextPollTimeoutMillis超时时间为下一条Message的触发时间,如果没有消息则会一直阻塞到超过超时时间

被唤醒后,我们暂时先忽略barrier类型的Message(这是android4.1后加入的一个特性Choreographer,http://blog.csdn.net/innost/article/details/8272867),

如果头结点msg不为null,就判断现在到了这条msg触发时间没有,

如果没到,则nextPollTimeoutMillis设置为这个条消息需要执行的时间和现在的时间差,给for循环下一次调用nativePollOnce时使用

如果到了甚至超过了,则取出这条msg,退出for循环返回这条msg,给上面上的handler进行dispatch


那么nativePollOnce具体是如何实现的呢?

android_os_MessageQueue.cpp

[cpp]  view plain copy
  1. static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,  
  2.         jint ptr, jint timeoutMillis) {  
  3.     NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);  
  4.     nativeMessageQueue->pollOnce(timeoutMillis);  
  5. }  


调用到了nativeMessageQueue->pollOnce

android_os_MessageQueue.cpp

[cpp]  view plain copy
  1. void NativeMessageQueue::pollOnce(int timeoutMillis) {  
  2.     mLooper->pollOnce(timeoutMillis);  
  3. }  


调用到了mLooper->pollOnce

同样,在framework/base/libs/utils/Looper.cpp中

[cpp]  view plain copy
  1. int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {  
  2.     int result = 0;  
  3.     for (;;) {  
  4.         while (mResponseIndex < mResponses.size()) {  
  5.             const Response& response = mResponses.itemAt(mResponseIndex++);  
  6.             if (! response.request.callback) {  
  7. #if DEBUG_POLL_AND_WAKE  
  8.                 LOGD("%p ~ pollOnce - returning signalled identifier %d: "  
  9.                         "fd=%d, events=0x%x, data=%p"this,  
  10.                         response.request.ident, response.request.fd,  
  11.                         response.events, response.request.data);  
  12. #endif  
  13.                 if (outFd != NULL) *outFd = response.request.fd;  
  14.                 if (outEvents != NULL) *outEvents = response.events;  
  15.                 if (outData != NULL) *outData = response.request.data;  
  16.                 return response.request.ident;  
  17.             }  
  18.         }  
  19.   
  20.         if (result != 0) {  
  21. #if DEBUG_POLL_AND_WAKE  
  22.             LOGD("%p ~ pollOnce - returning result %d"this, result);  
  23. #endif  
  24.             if (outFd != NULL) *outFd = 0;  
  25.             if (outEvents != NULL) *outEvents = NULL;  
  26.             if (outData != NULL) *outData = NULL;  
  27.             return result;  
  28.         }  
  29.   
  30.         result = pollInner(timeoutMillis);  
  31.     }  
  32. }  
因为这个流程和mResponses无关,先忽略这部分,

调用到pollInner

framework/base/libs/utils/Looper.cpp

[cpp]  view plain copy
  1. nt Looper::pollInner(int timeoutMillis) {  
  2. #if DEBUG_POLL_AND_WAKE  
  3.     LOGD("%p ~ pollOnce - waiting: timeoutMillis=%d"this, timeoutMillis);  
  4. #endif  
  5.   
  6.     int result = ALOOPER_POLL_WAKE;  
  7.     mResponses.clear();  
  8.     mResponseIndex = 0;  
  9.   
  10. #ifdef LOOPER_STATISTICS  
  11.     nsecs_t pollStartTime = systemTime(SYSTEM_TIME_MONOTONIC);  
  12. #endif  
  13.   
  14. #ifdef LOOPER_USES_EPOLL  
  15.     struct epoll_event eventItems[EPOLL_MAX_EVENTS];  
  16.     int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);  
  17.     bool acquiredLock = false;  
  18. #else  
  19.     // Wait for wakeAndLock() waiters to run then set mPolling to true.  
  20.     mLock.lock();  
  21.     while (mWaiters != 0) {  
  22.         mResume.wait(mLock);  
  23.     }  
  24.     mPolling = true;  
  25.     mLock.unlock();  
  26.   
  27.     size_t requestedCount = mRequestedFds.size();  
  28.     int eventCount = poll(mRequestedFds.editArray(), requestedCount, timeoutMillis);  
  29. #endif  
  30.   
  31.     if (eventCount < 0) {  
  32.         if (errno == EINTR) {  
  33.             goto Done;  
  34.         }  
  35.   
  36.         LOGW("Poll failed with an unexpected error, errno=%d", errno);  
  37.         result = ALOOPER_POLL_ERROR;  
  38.         goto Done;  
  39.     }  
  40.   
  41.     if (eventCount == 0) {  
  42. #if DEBUG_POLL_AND_WAKE  
  43.         LOGD("%p ~ pollOnce - timeout"this);  
  44. #endif  
  45.         result = ALOOPER_POLL_TIMEOUT;  
  46.         goto Done;  
  47.     }  
  48.   
  49. #if DEBUG_POLL_AND_WAKE  
  50.     LOGD("%p ~ pollOnce - handling events from %d fds"this, eventCount);  
  51. #endif  
  52.   
  53. #ifdef LOOPER_USES_EPOLL  
  54.     for (int i = 0; i < eventCount; i++) {  
  55.         int fd = eventItems[i].data.fd;  
  56.         uint32_t epollEvents = eventItems[i].events;  
  57.         if (fd == mWakeReadPipeFd) {  
  58.             if (epollEvents & EPOLLIN) {  
  59.                 awoken();  
  60.             } else {  
  61.                 LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);  
  62.             }  
  63.         } else {  
  64.             if (! acquiredLock) {  
  65.                 mLock.lock();  
  66.                 acquiredLock = true;  
  67.             }  
  68.   
  69.             ssize_t requestIndex = mRequests.indexOfKey(fd);  
  70.             if (requestIndex >= 0) {  
  71.                 int events = 0;  
  72.                 if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;  
  73.                 if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;  
  74.                 if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;  
  75.                 if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;  
  76.                 pushResponse(events, mRequests.valueAt(requestIndex));  
  77.             } else {  
  78.                 LOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "  
  79.                         "no longer registered.", epollEvents, fd);  
  80.             }  
  81.         }  
  82.     }  
  83.     if (acquiredLock) {  
  84.         mLock.unlock();  
  85.     }  
  86. Done: ;  
  87. #else  
  88.     for (size_t i = 0; i < requestedCount; i++) {  
  89.         const struct pollfd& requestedFd = mRequestedFds.itemAt(i);  
  90.   
  91.         short pollEvents = requestedFd.revents;  
  92.         if (pollEvents) {  
  93.             if (requestedFd.fd == mWakeReadPipeFd) {  
  94.                 if (pollEvents & POLLIN) {  
  95.                     awoken();  
  96.                 } else {  
  97.                     LOGW("Ignoring unexpected poll events 0x%x on wake read pipe.", pollEvents);  
  98.                 }  
  99.             } else {  
  100.                 int events = 0;  
  101.                 if (pollEvents & POLLIN) events |= ALOOPER_EVENT_INPUT;  
  102.                 if (pollEvents & POLLOUT) events |= ALOOPER_EVENT_OUTPUT;  
  103.                 if (pollEvents & POLLERR) events |= ALOOPER_EVENT_ERROR;  
  104.                 if (pollEvents & POLLHUP) events |= ALOOPER_EVENT_HANGUP;  
  105.                 if (pollEvents & POLLNVAL) events |= ALOOPER_EVENT_INVALID;  
  106.                 pushResponse(events, mRequests.itemAt(i));  
  107.             }  
  108.             if (--eventCount == 0) {  
  109.                 break;  
  110.             }  
  111.         }  
  112.     }  
  113.   
  114. Done:  
  115.     // Set mPolling to false and wake up the wakeAndLock() waiters.  
  116.     mLock.lock();  
  117.     mPolling = false;  
  118.     if (mWaiters != 0) {  
  119.         mAwake.broadcast();  
  120.     }  
  121.     mLock.unlock();  
  122. #endif  
  123.   
  124. #ifdef LOOPER_STATISTICS  
  125.     nsecs_t pollEndTime = systemTime(SYSTEM_TIME_MONOTONIC);  
  126.     mSampledPolls += 1;  
  127.     if (timeoutMillis == 0) {  
  128.         mSampledZeroPollCount += 1;  
  129.         mSampledZeroPollLatencySum += pollEndTime - pollStartTime;  
  130.     } else if (timeoutMillis > 0 && result == ALOOPER_POLL_TIMEOUT) {  
  131.         mSampledTimeoutPollCount += 1;  
  132.         mSampledTimeoutPollLatencySum += pollEndTime - pollStartTime  
  133.                 - milliseconds_to_nanoseconds(timeoutMillis);  
  134.     }  
  135.     if (mSampledPolls == SAMPLED_POLLS_TO_AGGREGATE) {  
  136.         LOGD("%p ~ poll latency statistics: %0.3fms zero timeout, %0.3fms non-zero timeout"this,  
  137.                 0.000001f * float(mSampledZeroPollLatencySum) / mSampledZeroPollCount,  
  138.                 0.000001f * float(mSampledTimeoutPollLatencySum) / mSampledTimeoutPollCount);  
  139.         mSampledPolls = 0;  
  140.         mSampledZeroPollCount = 0;  
  141.         mSampledZeroPollLatencySum = 0;  
  142.         mSampledTimeoutPollCount = 0;  
  143.         mSampledTimeoutPollLatencySum = 0;  
  144.     }  
  145. #endif  
  146.   
  147.     for (size_t i = 0; i < mResponses.size(); i++) {  
  148.         const Response& response = mResponses.itemAt(i);  
  149.         if (response.request.callback) {  
  150. #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS  
  151.             LOGD("%p ~ pollOnce - invoking callback: fd=%d, events=0x%x, data=%p"this,  
  152.                     response.request.fd, response.events, response.request.data);  
  153. #endif  
  154.             int callbackResult = response.request.callback(  
  155.                     response.request.fd, response.events, response.request.data);  
  156.             if (callbackResult == 0) {  
  157.                 removeFd(response.request.fd);  
  158.             }  
  159.   
  160.             result = ALOOPER_POLL_CALLBACK;  
  161.         }  
  162.     }  
  163.     return result;  
  164. }  

主要看#ifdef  LOOPER_USES_EPOLL部分

int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

等待所有attach到mEpollFd上的事件,如果收到唤醒信号继续执行,否则阻塞等待

之后的#ifdef  LOOPER_USES_EPOLL部分

[cpp]  view plain copy
  1. #ifdef LOOPER_USES_EPOLL  
  2.     for (int i = 0; i < eventCount; i++) {  
  3.         int fd = eventItems[i].data.fd;  
  4.         uint32_t epollEvents = eventItems[i].events;  
  5.         if (fd == mWakeReadPipeFd) {  
  6.             if (epollEvents & EPOLLIN) {  
  7.                 awoken();  
  8.             } else {  
  9.                 LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);  
  10.             }  
  11.         } else {  
  12.             if (! acquiredLock) {  
  13.                 mLock.lock();  
  14.                 acquiredLock = true;  
  15.             }  
  16.   
  17.             ssize_t requestIndex = mRequests.indexOfKey(fd);  
  18.             if (requestIndex >= 0) {  
  19.                 int events = 0;  
  20.                 if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;  
  21.                 if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;  
  22.                 if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;  
  23.                 if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;  
  24.                 pushResponse(events, mRequests.valueAt(requestIndex));  
  25.             } else {  
  26.                 LOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "  
  27.                         "no longer registered.", epollEvents, fd);  
  28.             }  
  29.         }  
  30.     }  
  31.     if (acquiredLock) {  
  32.         mLock.unlock();  
  33.     }  
  34. Done: ;  

对所有attach在mEpollFd上的事件进行遍历,如果对象文件描述符有mWakeReadPipeFd,则awoken()

framework/base/libs/utils/Looper.cpp

[cpp]  view plain copy
  1. void Looper::awoken() {  
  2. #if DEBUG_POLL_AND_WAKE  
  3.     LOGD("%p ~ awoken"this);  
  4. #endif  
  5.   
  6. #ifdef LOOPER_STATISTICS  
  7.     if (mPendingWakeCount == 0) {  
  8.         LOGD("%p ~ awoken: spurious!"this);  
  9.     } else {  
  10.         mSampledWakeCycles += 1;  
  11.         mSampledWakeCountSum += mPendingWakeCount;  
  12.         mSampledWakeLatencySum += systemTime(SYSTEM_TIME_MONOTONIC) - mPendingWakeTime;  
  13.         mPendingWakeCount = 0;  
  14.         mPendingWakeTime = -1;  
  15.         if (mSampledWakeCycles == SAMPLED_WAKE_CYCLES_TO_AGGREGATE) {  
  16.             LOGD("%p ~ wake statistics: %0.3fms wake latency, %0.3f wakes per cycle"this,  
  17.                     0.000001f * float(mSampledWakeLatencySum) / mSampledWakeCycles,  
  18.                     float(mSampledWakeCountSum) / mSampledWakeCycles);  
  19.             mSampledWakeCycles = 0;  
  20.             mSampledWakeCountSum = 0;  
  21.             mSampledWakeLatencySum = 0;  
  22.         }  
  23.     }  
  24. #endif  
  25.   
  26.     char buffer[16];  
  27.     ssize_t nRead;  
  28.     do {  
  29.         nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));  
  30.     } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));  
  31. }  

awoken()即上一讲中得awoken()函数,用于把mWakeReadPipeFd上的数据读取干净,因为mWakeWriteReadPipeFd可能写入多次

读取干净后下一次epoll_wait时就会等待mWakeWriteReadPipeFd写入,如果没有读取干净,即通知epoll内核和mWakeReadPipeFd这个事件相关的处理完毕了,

否则epoll_wait就一直会触发对应的事件了(不等待新的写入,一直不阻塞)


3 总结

那么至此,enqueueMessage和定义dequeueMessage都解释清楚,感觉豁然开朗了有木有!!!!

下一讲讲nativeapp的线程消息循环处理过程(主要解读android_native_app_glue.c)

欢迎各位指正!!


4 reference

android sdk sourcecode

android framework sourcecode

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值