Android消息机制不完全解析(下) .

来源:互联网 发布:温州慧网网络好不好 编辑:程序博客网 时间:2024/05/22 17:05

转自:http://blog.csdn.net/a220315410/article/details/10444171


首先,看看在/frameworks/base/core/jni/android_os_MessageQueue.cpp文件中看看android.os.MessageQueue类中的四个原生函数的实现:

[java] view plain copy print?
  1. static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) {  
  2.     NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();//构造NativeMessageQueue实例  
  3.     if (!nativeMessageQueue) {  
  4.         jniThrowRuntimeException(env, "Unable to allocate native queue");  
  5.         return;  
  6.     }  
  7.     nativeMessageQueue->incStrong(env);//强引用+1  
  8.     android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);  
  9. }  
  10.   
  11. static void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jobject obj) {  
  12.     NativeMessageQueue* nativeMessageQueue =  
  13.             android_os_MessageQueue_getNativeMessageQueue(env, obj);  
  14.     if (nativeMessageQueue) {  
  15.         android_os_MessageQueue_setNativeMessageQueue(env, obj, NULL);  
  16.         nativeMessageQueue->decStrong(env);//强引用-1,实际上会导致释放NativeMessageQueue实例  
  17.     }  
  18. }  
  19.   
  20. static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,  
  21.         jint ptr, jint timeoutMillis) {  
  22.     NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);//指针强制转换  
  23.     nativeMessageQueue->pollOnce(env, timeoutMillis);//调用nativeMessageQueue的pollonce函数  
  24. }  
  25.   
  26. static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) {  
  27.     NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);  
  28.     return nativeMessageQueue->wake();//调用nativeMessageQueue的wake函数  
  29. }  


    从代码中,可以看到这四个函数的实现都是依赖于NativeMessageQueue类。不过,在开始解析NativeMessageQueue之前,我们再看一些有意思的代码:

[cpp] view plain copy print?
  1. static void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject messageQueueObj,  
  2.         NativeMessageQueue* nativeMessageQueue) {  
  3.     env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr,  
  4.              reinterpret_cast<jint>(nativeMessageQueue));//把nativeMessageQueue的实例地址强转为java的int类型并保存到gMessageQueueClassInfo.mPtr中  
  5. }  

    那么gMessageQueueClassInfo.mPtr是什么呢?

[cpp] view plain copy print?
  1. static JNINativeMethod gMessageQueueMethods[] = {  
  2.     /* name, signature, funcPtr */  
  3.     { "nativeInit""()V", (void*)android_os_MessageQueue_nativeInit },  
  4.     { "nativeDestroy""()V", (void*)android_os_MessageQueue_nativeDestroy },  
  5.     { "nativePollOnce""(II)V", (void*)android_os_MessageQueue_nativePollOnce },  
  6.     { "nativeWake""(I)V", (void*)android_os_MessageQueue_nativeWake }  
  7. };  
  8.   
  9. #define FIND_CLASS(var, className) \   
  10.         var = env->FindClass(className); \  
  11.         LOG_FATAL_IF(! var, "Unable to find class " className);  
  12.   
  13. #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \  
  14.         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \  
  15.         LOG_FATAL_IF(! var, "Unable to find field " fieldName);  
  16. //这个函数在Android启动的时候,会被系统调用   
  17. int register_android_os_MessageQueue(JNIEnv* env) {  
  18.     int res = jniRegisterNativeMethods(env, "android/os/MessageQueue",  
  19.             gMessageQueueMethods, NELEM(gMessageQueueMethods));//关联MessageQueueQueue的原生函数  
  20.     LOG_FATAL_IF(res < 0, "Unable to register native methods.");  
  21.   
  22.     jclass clazz;  
  23.     FIND_CLASS(clazz, "android/os/MessageQueue");//获取MessageQueue的class  
  24.   
  25.     GET_FIELD_ID(gMessageQueueClassInfo.mPtr, clazz,  
  26.             "mPtr""I");//获取MessageQueue class的mPtr field的Id  
  27.       
  28.     return 0;  
  29. }  
    上面的代码很像java的反射有木有?

[java] view plain copy print?
  1. Class cls = Class.forName("android.os.MessageQueue");  
  2. Field feild = cls.getField("mPtr");  
    到这里,我们就明白了android_os_MessageQueue_setNativeMessageQueue函数实际上把android.os.MessageQueue实例的mPtr值设置为nativeMessageQueue实例的地址。虽然Java语言没有指针的说法,但是,这里的mPtr却的的确确是作为一个指针使用的。现在,我们也就理解了,为什么mPtr可以被强制转换为nativeMessageQueue了。

    小结:

  1. android_os_MessageQueue_nativeInit和android_os_MessageQueue_nativeDestory两个函数做了些什么:

  • android_os_MessageQueue_nativeInit:构造NativeMessageQueue实例
  • android_os_MessageQueue_nativeDestory:销毁NativeMessageQeue实例

NativeMessageQueue


    先来看看NativeMessageQueue的声明:

[cpp] view plain copy print?
  1. class NativeMessageQueue : public MessageQueue {  
  2. public:  
  3.     NativeMessageQueue();  
  4.     virtual ~NativeMessageQueue();  
  5.   
  6.     virtual void raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj);  
  7.   
  8.     void pollOnce(JNIEnv* env, int timeoutMillis);  
  9.   
  10.     void wake();  
  11.   
  12. private:  
  13.     bool mInCallback;  
  14.     jthrowable mExceptionObj;  
  15. };  
    NativeMessageQueue继承自MessageQueue(不是java中的android.os.MessageQueue哦),关于MessageQueue我们只需要了解,它包含了一个成员mLooper即可(有兴趣的同学可以查看/frameworks/base/core/jni/android_os_MessageQueue.h)    

[cpp] view plain copy print?
  1. class MessageQueue  {  
  2.   
  3.     ......  
  4.   
  5. protected:  
  6.     sp<Looper> mLooper;  
  7. };  

    继续看NativeMessageQueue的代码:

[cpp] view plain copy print?
  1. NativeMessageQueue::NativeMessageQueue() : mInCallback(false), mExceptionObj(NULL) {  
  2.     mLooper = Looper::getForThread();  
  3.     if (mLooper == NULL) {  
  4.         mLooper = new Looper(false);//实例化mLooper  
  5.         Looper::setForThread(mLooper);  
  6.     }  
  7. }  
    NativeMessageQueue构造实例的时候,会实例化mLooper。
[cpp] view plain copy print?
  1. void NativeMessageQueue::pollOnce(JNIEnv* env, int timeoutMillis) {  
  2.     mInCallback = true;  
  3.     mLooper->pollOnce(timeoutMillis);  
  4.     mInCallback = false;  
  5.     if (mExceptionObj) {  
  6.         env->Throw(mExceptionObj);  
  7.         env->DeleteLocalRef(mExceptionObj);  
  8.         mExceptionObj = NULL;  
  9.     }  
  10. }  
  11.   
  12. void NativeMessageQueue::wake() {  
  13.     mLooper->wake();  
  14. }  

    小结:

  1. NativeMessageQueue的函数pollonce和wake实现相当简单,交给mLooper的同名函数。

Looper


    先来看看Looper的声明/frameworks/native/include/utils/Looper.h:

[cpp] view plain copy print?
  1. class Looper : public ALooper, public RefBase {  
  2. protected:  
  3.     virtual ~Looper();  
  4.   
  5. public:  
  6.     Looper(bool allowNonCallbacks);  
  7.   
  8.     bool getAllowNonCallbacks() const;  
  9.   
  10.     int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);  
  11.     inline int pollOnce(int timeoutMillis) {  
  12.         return pollOnce(timeoutMillis, NULL, NULL, NULL);  
  13.     }  
  14.   
  15.     void wake();  
  16.   
  17. private:  
  18.   
  19.     const bool mAllowNonCallbacks; // immutable  
  20.   
  21.     int mWakeReadPipeFd;  // immutable  
  22.     int mWakeWritePipeFd; // immutable  
  23.     Mutex mLock;  
  24.   
  25.     int mEpollFd; // immutable  
  26.   
  27.     int pollInner(int timeoutMillis);  
  28.     void awoken();  
  29. };  
    因为代码有点多,所以上面的声明,已经被我精简了大部分,现在我们只关注我们关心的:pollonce和wake函数。

    还是从构造函数开始(frameworks/native/utils/Looper.cpp):

[cpp] view plain copy print?
  1. Looper::Looper(bool allowNonCallbacks) :  
  2.         mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),  
  3.         mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {  
  4.     int wakeFds[2];  
  5.     int result = pipe(wakeFds);//创建命名管道  
  6.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);  
  7.     // 保存命名管道   
  8.     mWakeReadPipeFd = wakeFds[0];  
  9.     mWakeWritePipeFd = wakeFds[1];  
  10.   
  11.     result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);//设置为非阻塞模式  
  12.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",  
  13.             errno);  
  14.   
  15.     result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);//设置为非阻塞模式  
  16.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",  
  17.             errno);  
  18.     // 开始使用epoll API,实现轮询   
  19.     // Allocate the epoll instance and register the wake pipe.  
  20.     mEpollFd = epoll_create(EPOLL_SIZE_HINT);//创建epoll文件描述符  
  21.     LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);  
  22.   
  23.     struct epoll_event eventItem;  
  24.     memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union  
  25.     eventItem.events = EPOLLIN;  
  26.     eventItem.data.fd = mWakeReadPipeFd;  
  27.     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); // 把刚才创建的命名管道的读端加入的到epoll的监听队列中  
  28.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",  
  29.             errno);  
  30. }  
  31.   
  32. Looper::~Looper() {  
  33.     close(mWakeReadPipeFd);//释放命名管道   
  34.     close(mWakeWritePipeFd);  
  35.     close(mEpollFd);//释放epoll文件描述符   
  36. }  
    Looper的构造函数中,出现了命名管道和epoll相关的代码,这是为什么呢?别急,接着看下去就知道了:
[cpp] view plain copy print?
  1. int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {  
  2.     int result = 0;  
  3.     for (;;) {  
  4.        // 这段代码暂时无视   
  5.        while (mResponseIndex < mResponses.size()) {  
  6.             const Response& response = mResponses.itemAt(mResponseIndex++);  
  7.             int ident = response.request.ident;  
  8.             if (ident >= 0) {//ident > 0, 即此response为noncallback,需要返回event,data等数据给调用者处理  
  9.                 int fd = response.request.fd;  
  10.                 int events = response.events;  
  11.                 void* data = response.request.data;  
  12. #if DEBUG_POLL_AND_WAKE   
  13.                 ALOGD("%p ~ pollOnce - returning signalled identifier %d: "  
  14.                         "fd=%d, events=0x%x, data=%p",  
  15.                         this, ident, fd, events, data);  
  16. #endif   
  17.                 if (outFd != NULL) *outFd = fd;  
  18.                 if (outEvents != NULL) *outEvents = events;  
  19.                 if (outData != NULL) *outData = data;  
  20.                 return ident;  
  21.             }  
  22.         }  
  23.   
  24.         if (result != 0) {  
  25. #if DEBUG_POLL_AND_WAKE   
  26.             ALOGD("%p ~ pollOnce - returning result %d"this, result);  
  27. #endif   
  28.             if (outFd != NULL) *outFd = 0;  
  29.             if (outEvents != NULL) *outEvents = 0;  
  30.             if (outData != NULL) *outData = NULL;  
  31.             return result;  
  32.         }  
  33.   
  34.         result = pollInner(timeoutMillis);//这一行才是重点!   
  35.     }  
  36. }  
    接着往下看,代码有些长,但请仔细看:
[cpp] view plain copy print?
  1. int Looper::pollInner(int timeoutMillis) {  
  2.       
  3. #if DEBUG_POLL_AND_WAKE   
  4.     ALOGD("%p ~ pollOnce - waiting: timeoutMillis=%d"this, timeoutMillis);  
  5. #endif   
  6.   
  7.     // 设置timeoutMillis的值为Math.min(timeoutMills, mNextMessageUptime)  
  8.     // Adjust the timeout based on when the next message is due.  
  9.     if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {  
  10.         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  11.         int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);  
  12.         if (messageTimeoutMillis >= 0  
  13.                 && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {  
  14.             timeoutMillis = messageTimeoutMillis;  
  15.         }  
  16. #if DEBUG_POLL_AND_WAKE   
  17.         ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",  
  18.                 this, mNextMessageUptime - now, timeoutMillis);  
  19. #endif   
  20.     }  
  21.   
  22.   
  23.     // Poll.   
  24.     int result = ALOOPER_POLL_WAKE;  
  25.     mResponses.clear();  
  26.     mResponseIndex = 0;  
  27.   
  28.     // 开始轮询   
  29.     struct epoll_event eventItems[EPOLL_MAX_EVENTS];  
  30.     int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);  
  31.   
  32.     // Acquire lock.   
  33.     mLock.lock();  
  34.   
  35.     // Check for poll error.   
  36.     if (eventCount < 0) { //处理error  
  37.         if (errno == EINTR) {  
  38.             goto Done;  
  39.         }  
  40.         ALOGW("Poll failed with an unexpected error, errno=%d", errno);  
  41.         result = ALOOPER_POLL_ERROR;  
  42.         goto Done;  
  43.     }  
  44.   
  45.     // Check for poll timeout.   
  46.     if (eventCount == 0) { // 未能等到event,故timeout  
  47. #if DEBUG_POLL_AND_WAKE   
  48.         ALOGD("%p ~ pollOnce - timeout"this);  
  49. #endif   
  50.         result = ALOOPER_POLL_TIMEOUT;  
  51.         goto Done;  
  52.     }  
  53.   
  54.     // Handle all events.   
  55. #if DEBUG_POLL_AND_WAKE   
  56.     ALOGD("%p ~ pollOnce - handling events from %d fds"this, eventCount);  
  57. #endif   
  58.   
  59.     for (int i = 0; i < eventCount; i++) {//有event,则处理  
  60.         int fd = eventItems[i].data.fd;  
  61.         uint32_t epollEvents = eventItems[i].events;  
  62.         if (fd == mWakeReadPipeFd) {  
  63.             if (epollEvents & EPOLLIN) {  
  64.                 awoken();//读取命名管道内的数据   
  65.             } else {  
  66.                 ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);  
  67.             }  
  68.         } else {  
  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));//把event添加到<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses中,等待后续处理</SPAN>  
  77.             } else {  
  78.                 ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "  
  79.                         "no longer registered.", epollEvents, fd);  
  80.             }  
  81.         }  
  82.     }  
  83. Done: ;  
  84.     // 处理C++层的Message   
  85.     // Invoke pending message callbacks.   
  86.     mNextMessageUptime = LLONG_MAX;  
  87.     while (mMessageEnvelopes.size() != 0) {  
  88.         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  89.         const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);  
  90.         if (messageEnvelope.uptime <= now) {  
  91.             // Remove the envelope from the list.  
  92.             // We keep a strong reference to the handler until the call to handleMessage  
  93.             // finishes.  Then we drop it so that the handler can be deleted *before*  
  94.             // we reacquire our lock.   
  95.             { // obtain handler   
  96.                 sp<MessageHandler> handler = messageEnvelope.handler;  
  97.                 Message message = messageEnvelope.message;  
  98.                 mMessageEnvelopes.removeAt(0);  
  99.                 mSendingMessage = true;  
  100.                 mLock.unlock();  
  101.   
  102. #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS   
  103.                 ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",  
  104.                         this, handler.get(), message.what);  
  105. #endif   
  106.                 handler->handleMessage(message);//调用handler-><SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">handleMessage</SPAN>  
  107.             } // release handler   
  108.   
  109.             mLock.lock();  
  110.             mSendingMessage = false;  
  111.             result = ALOOPER_POLL_CALLBACK;  
  112.         } else {  
  113.             // The last message left at the head of the queue determines the next wakeup time.  
  114.             mNextMessageUptime = messageEnvelope.uptime;//更新<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">mNextMessageUptime</SPAN>  
  115.             break;  
  116.         }  
  117.     }  
  118.   
  119.     // Release lock.   
  120.     mLock.unlock();  
  121.     // 处理<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses</SPAN>  
  122.     // Invoke all response callbacks.   
  123.     for (size_t i = 0; i < mResponses.size(); i++) {  
  124.         Response& response = mResponses.editItemAt(i);  
  125.         if (response.request.ident == ALOOPER_POLL_CALLBACK) {  
  126.             int fd = response.request.fd;  
  127.             int events = response.events;  
  128.             void* data = response.request.data;  
  129. #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS  
  130.             ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",  
  131.                     this, response.request.callback.get(), fd, events, data);  
  132. #endif   
  133.             int callbackResult = response.request.callback->handleEvent(fd, events, data);//调用callback->handleEvent  
  134.             if (callbackResult == 0) {  
  135.                 removeFd(fd);  
  136.             }  
  137.             // Clear the callback reference in the response structure promptly because we  
  138.             // will not clear the response vector itself until the next poll.  
  139.             response.request.callback.clear();  
  140.             result = ALOOPER_POLL_CALLBACK;  
  141.         }  
  142.     }  
  143.     return result;  
  144. }  

    代码比较长,所以分段分析:

[cpp] view plain copy print?
  1. // 设置timeoutMillis的值为Math.min(timeoutMillis, mNextMessageUptime)  
  2. // Adjust the timeout based on when the next message is due.  
  3. if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {  
  4.     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  5.     int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);  
  6.     if (messageTimeoutMillis >= 0  
  7.             && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {  
  8.         timeoutMillis = messageTimeoutMillis;  
  9.     }#if DEBUG_POLL_AND_WAKE  
  10.     ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",  
  11.             this, mNextMessageUptime - now, timeoutMillis);  
  12. if  
  13. }  

    为了解析这段代码,需要先补充一些C++层的Message相关的代码:

[cpp] view plain copy print?
  1. struct Message {  
  2.     Message() : what(0) { }  
  3.     Message(int what) : what(what) { }  
  4.   
  5.     /* The message type. (interpretation is left up to the handler) */  
  6.     int what;  
  7. };  
  8.   
  9.   
  10. class MessageHandler : public virtual RefBase {  
  11.     protected:  
  12.         virtual ~MessageHandler() { }  
  13.   
  14.     public:  
  15.         /** 
  16.          * Handles a message. 
  17.          */  
  18.         virtual void handleMessage(const Message& message) = 0;  
  19. }  
  20.   
  21. struct MessageEnvelope {  
  22.     MessageEnvelope() : uptime(0) { }  
  23.     MessageEnvelope(nsecs_t uptime, const sp<MessageHandler> handler,const Message& message) : uptime(uptime), handler(handler), message(message) {}  
  24.   
  25.     nsecs_t uptime;  
  26.     MessageHandler> handler;  
  27.     Message message;  
  28. };  
  29.   
  30. void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {  
  31.     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  32.     sendMessageAtTime(now, handler, message);  
  33. }  
  34.   
  35. void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,  
  36.         const Message& message) {  
  37.     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  38.     sendMessageAtTime(now + uptimeDelay, handler, message);  
  39. }  
  40.   
  41. void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,  
  42.         const Message& message) {  
  43. #if DEBUG_CALLBACKS   
  44.     ALOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d",  
  45.             this, uptime, handler.get(), message.what);  
  46. #endif   
  47.   
  48.     size_t i = 0;  
  49.     { // acquire lock   
  50.         AutoMutex _l(mLock);  
  51.   
  52.         size_t messageCount = mMessageEnvelopes.size();  
  53.         while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {  
  54.             i += 1;  
  55.         }  
  56.   
  57.         MessageEnvelope messageEnvelope(uptime, handler, message);  
  58.         mMessageEnvelopes.insertAt(messageEnvelope, i, 1);  
  59.   
  60.         // Optimization: If the Looper is currently sending a message, then we can skip  
  61.         // the call to wake() because the next thing the Looper will do after processing  
  62.         // messages is to decide when the next wakeup time should be.  In fact, it does  
  63.         // not even matter whether this code is running on the Looper thread.  
  64.         if (mSendingMessage) {  
  65.             return;  
  66.         }  
  67.     } // release lock   
  68.   
  69.     // Wake the poll loop only when we enqueue a new message at the head.  
  70.     if (i == 0) {  
  71.         wake();  
  72.     }  
  73. }  
  74.   
  75. void Looper::removeMessages(const sp<MessageHandler>& handler) {  
  76. #if DEBUG_CALLBACKS   
  77.     ALOGD("%p ~ removeMessages - handler=%p"this, handler.get());  
  78. #endif   
  79.   
  80.     { // acquire lock   
  81.         AutoMutex _l(mLock);  
  82.   
  83.         for (size_t i = mMessageEnvelopes.size(); i != 0; ) {  
  84.             const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);  
  85.             if (messageEnvelope.handler == handler) {  
  86.                 mMessageEnvelopes.removeAt(i);  
  87.             }  
  88.         }  
  89.     } // release lock   
  90. }  
  91.   
  92. void Looper::removeMessages(const sp<MessageHandler>& handler, int what) {  
  93. #if DEBUG_CALLBACKS   
  94.     ALOGD("%p ~ removeMessages - handler=%p, what=%d"this, handler.get(), what);  
  95. #endif   
  96.   
  97.     { // acquire lock   
  98.         AutoMutex _l(mLock);  
  99.   
  100.         for (size_t i = mMessageEnvelopes.size(); i != 0; ) {  
  101.             const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);  
  102.             if (messageEnvelope.handler == handler  
  103.                     && messageEnvelope.message.what == what) {  
  104.                 mMessageEnvelopes.removeAt(i);  
  105.             }  
  106.         }  
  107.     } // release lock   
  108. }  
    是不是觉得上面的代码似曾相识?和Java层的MessageQueue很像似有木有?和java层一样,C++层存在消息队列和消息处理机制,消息被保存到成员mMessageEvelopes中,并在pollInner函数中处理消息(调用MesageHandler的handleMesage函数处理)。

    现在回到Looper::pollonceh函数,我们就应该能够理解,pollOnce函数到timeOutMillis参数仅仅代表了Java层下一个Message的触发延迟,所以,我们还需要考虑C++层下一个Message的触发延迟,所以,代码设置timeoutMillis为timeoutMillis和mNextMessageUpTime中的较小值。


    继续下一段代码:

[cpp] view plain copy print?
  1. int result = ALOOPER_POLL_WAKE;  
  2. mResponses.clear();  
  3. mResponseIndex = 0;  
  4. // 开始轮询   
  5. struct epoll_event eventItems[EPOLL_MAX_EVENTS];  
  6. int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);  
  7.   
  8. // Acquire lock.   
  9. mLock.lock();  
    调用epoll函数,等待event发生,epoll_wait函数的返回值有三种可能:失败出错、没有event、有一个或多个event。

1. 失败的处理:

[cpp] view plain copy print?
  1. // Check for poll error.   
  2. if (eventCount < 0) { //处理error  
  3.     if (errno == EINTR) {  
  4.         goto Done;  
  5.     }  
  6.     ALOGW("Poll failed with an unexpected error, errno=%d", errno);  
  7.     result = ALOOPER_POLL_ERROR;  
  8.     goto Done;  
  9. }  
2. 没有event发生:
[cpp] view plain copy print?
  1.     // Check for poll timeout.   
  2.     if (eventCount == 0) { // 未能等到event,故timeout  
  3. #if DEBUG_POLL_AND_WAKE   
  4.         ALOGD("%p ~ pollOnce - timeout"this);  
  5. #endif   
  6.         result = ALOOPER_POLL_TIMEOUT;  
  7.         goto Done;  
  8.     }  
3. 有event发生:
[cpp] view plain copy print?
  1. // Handle all events.   
  2. DEBUG_POLL_AND_WAKE  
  3. ALOGD("%p ~ pollOnce - handling events from %d fds"this, eventCount);  
  4. if  
  5.   
  6. for (int i = 0; i < eventCount; i++) {//有event,则处理  
  7.     int fd = eventItems[i].data.fd;  
  8.     uint32_t epollEvents = eventItems[i].events;  
  9.     if (fd == mWakeReadPipeFd) {//说明java层或者C++层有新的Message  
  10.         if (epollEvents & EPOLLIN) {  
  11.             awoken();//读取命名管道内的数据   
  12.         } else {  
  13.             ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);  
  14.         }  
  15.     } else {  
  16.         ssize_t requestIndex = mRequests.indexOfKey(fd);  
  17.         if (requestIndex >= 0) {  
  18.             int events = 0;  
  19.             if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;  
  20.             if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;  
  21.             if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;  
  22.             if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;  
  23.             pushResponse(events, mRequests.valueAt(requestIndex));//把event添加到<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses中,等待后续处理</SPAN>  
  24.         } else {  
  25.             ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "  
  26.                     "no longer registered.", epollEvents, fd);  
  27.         }  
  28.     }  
  29. }  

    处理event的时候,需要分为两类:fd==mWakeReadPipeFd和fd!=mWakeReadPipeFd

fd==mWakeReadPipeFd:说明C++层,或者java层有新的Message出现,需要处理。这种情况下,只需要读mWakeReadPipeFd内的数据即可

[cpp] view plain copy print?
  1. void Looper::awoken() {  
  2. #if DEBUG_POLL_AND_WAKE   
  3.     ALOGD("%p ~ awoken"this);  
  4. #endif   
  5.   
  6.     char buffer[16];  
  7.     ssize_t nRead;  
  8.     do {  
  9.         nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));  
  10.     } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));  
  11. }  
fd!=mWakeReadPipeFd:首先需要搞明白fd是哪来的:

[cpp] view plain copy print?
  1.     struct Request {  
  2.         int fd;  
  3.         int ident;  
  4.         sp<LooperCallback> callback;  
  5.         void* data;  
  6.     };  
  7.   
  8.   
  9.     struct Response {  
  10.         int events;  
  11.         Request request;  
  12.     };  
[cpp] view plain copy print?
  1. /** 
  2.  * A looper callback. 
  3.  */  
  4. class LooperCallback : public virtual RefBase {  
  5. protected:  
  6.     virtual ~LooperCallback() { }  
  7.   
  8.   
  9. public:  
  10.     /** 
  11.      * Handles a poll event for the given file descriptor. 
  12.      * It is given the file descriptor it is associated with, 
  13.      * a bitmask of the poll events that were triggered (typically ALOOPER_EVENT_INPUT), 
  14.      * and the data pointer that was originally supplied. 
  15.      * 
  16.      * Implementations should return 1 to continue receiving callbacks, or 0 
  17.      * to have this file descriptor and callback unregistered from the looper. 
  18.      */  
  19.     virtual int handleEvent(int fd, int events, void* data) = 0;  
  20. };  
[cpp] view plain copy print?
  1. int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {  
  2. #if DEBUG_CALLBACKS   
  3.     ALOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p"this, fd, ident,  
  4.             events, callback.get(), data);  
  5. #endif   
  6.   
  7.     if (!callback.get()) {  
  8.         if (! mAllowNonCallbacks) {  
  9.             ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");  
  10.             return -1;  
  11.         }  
  12.   
  13.         if (ident < 0) {//仅当Looper支持NonCallbacks,并且ident大于0时,允许添加callback为null的Fd  
  14.             ALOGE("Invalid attempt to set NULL callback with ident < 0.");  
  15.             return -1;  
  16.         }  
  17.     } else {  
  18.         ident = ALOOPER_POLL_CALLBACK;  
  19.     }  
  20.   
  21.     int epollEvents = 0;  
  22.     if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;  
  23.     if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;  
  24.   
  25.     { // acquire lock   
  26.         AutoMutex _l(mLock);  
  27.   
  28.         Request request;  
  29.         request.fd = fd;  
  30.         request.ident = ident;  
  31.         request.callback = callback;  
  32.         request.data = data;  
  33.   
  34.         struct epoll_event eventItem;  
  35.         memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union  
  36.         eventItem.events = epollEvents;  
  37.         eventItem.data.fd = fd;  
  38.   
  39.         ssize_t requestIndex = mRequests.indexOfKey(fd);  
  40.         if (requestIndex < 0) {  
  41.             int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);  
  42.             if (epollResult < 0) {  
  43.                 ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);  
  44.                 return -1;  
  45.             }  
  46.             mRequests.add(fd, request);  
  47.         } else {//存在则替换  
  48.             int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);  
  49.             if (epollResult < 0) {  
  50.                 ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);  
  51.                 return -1;  
  52.             }  
  53.             mRequests.replaceValueAt(requestIndex, request);  
  54.         }  
  55.     } // release lock   
  56.     return 1;  
  57. }  

    从上面的代码,我们可知,Looper还支持添加Fd和自定义的callback,类似java层的Message.callback。 

   通过addFd函数,可以向Looper的mEpollFd添加指定的Fd,当Fd触发指定的event .e.i  EPOLLIN or EPOLLOUT时,指定的相应的自定义callback就会得到执行。

   另外,当Looper支持noncallback时,还可以向Looper添加callback为null的Fd,因为没有callback,所以Fd添加者需要调用int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) 通过outFd、outEvent、outData参数获取数据并进行处理。

    所以当Fd触发消息时,需要生成对应到reponse并添加到meResponses中,等待后续的处理。

[cpp] view plain copy print?
  1. void Looper::pushResponse(int events, const Request& request) {  
  2.     Response response;  
  3.     response.events = events;  
  4.     response.request = request;  
  5.     mResponses.push(response);  
  6. }  

    到这里为止,epoll_wait函数返回的三种结果的不同处理已经解析完毕,接下来代码进入共同的Done环节。

处理C++层的Message:

[cpp] view plain copy print?
  1. Done: ;  
  2.     // 处理C++层的Message   
  3.     // Invoke pending message callbacks.   
  4.     mNextMessageUptime = LLONG_MAX;  
  5.     while (mMessageEnvelopes.size() != 0) {  
  6.         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  7.         const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);  
  8.         if (messageEnvelope.uptime <= now) {  
  9.             // Remove the envelope from the list.  
  10.             // We keep a strong reference to the handler until the call to handleMessage  
  11.             // finishes.  Then we drop it so that the handler can be deleted *before*  
  12.             // we reacquire our lock.   
  13.             { // obtain handler   
  14.                 sp<MessageHandler> handler = messageEnvelope.handler;  
  15.                 Message message = messageEnvelope.message;  
  16.                 mMessageEnvelopes.removeAt(0);  
  17.                 mSendingMessage = true;  
  18.                 mLock.unlock();  
  19.   
  20. #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS   
  21.                 ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",  
  22.                         this, handler.get(), message.what);  
  23. #endif   
  24.                 handler->handleMessage(message);//调用handler-><SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">handleMessage</SPAN>  
  25.             } // release handler   
  26.   
  27.             mLock.lock();  
  28.             mSendingMessage = false;  
  29.             result = ALOOPER_POLL_CALLBACK;  
  30.         } else {  
  31.             // The last message left at the head of the queue determines the next wakeup time.  
  32.             mNextMessageUptime = messageEnvelope.uptime;//更新<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">mNextMessageUptime</SPAN>  
  33.             break;  
  34.         }  
  35.     }  

处理Response:

[cpp] view plain copy print?
  1.     // 处理<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses</SPAN>  
  2.     // Invoke all response callbacks.   
  3.     for (size_t i = 0; i < mResponses.size(); i++) {  
  4.         Response& response = mResponses.editItemAt(i);  
  5.         if (response.request.ident == ALOOPER_POLL_CALLBACK) {  
  6.             int fd = response.request.fd;  
  7.             int events = response.events;  
  8.             void* data = response.request.data;  
  9. #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS  
  10.             ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",  
  11.                     this, response.request.callback.get(), fd, events, data);  
  12. #endif   
  13.             int callbackResult = response.request.callback->handleEvent(fd, events, data);//调用callback->handleEvent  
  14.             if (callbackResult == 0) {  
  15.                 removeFd(fd);  
  16.             }  
  17.             // Clear the callback reference in the response structure promptly because we  
  18.             // will not clear the response vector itself until the next poll.  
  19.             response.request.callback.clear();  
  20.             result = ALOOPER_POLL_CALLBACK;  
  21.         }  
  22.     }  

    搞懂了上面的代码,我们就很容易明白wake函数做了些什么:

[cpp] view plain copy print?
  1. void Looper::wake() {  
  2. #if DEBUG_POLL_AND_WAKE   
  3.     ALOGD("%p ~ wake"this);  
  4. #endif   
  5.   
  6.     ssize_t nWrite;  
  7.     do {  
  8.         nWrite = write(mWakeWritePipeFd, "W", 1);//向<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif; FONT-SIZE: 12px">mWakeWritePipeFd</SPAN><SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif; FONT-SIZE: 12px">中写入一个字符,所以mWakeReadPipeFd就会触发</SPAN><SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif; FONT-SIZE: 12px">EPOLLIN event</SPAN><SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif; FONT-SIZE: 12px">  
  9. </SPAN>    } while (nWrite == -1 && errno == EINTR);  
  10.   
  11.     if (nWrite != 1) {  
  12.         if (errno != EAGAIN) {  
  13.             ALOGW("Could not write wake signal, errno=%d", errno);  
  14.         }  
  15.     }  
  16. }  
    小结:
  1. Looper通过epoll函数组实现了一个可以支持随时唤醒的阻塞机制
  2. Looper支持两种不同的方式处理消息:Message + MessageHandler 和 LooperCallback。
  3. Looper的阻塞在如下四种条件下会被唤醒:
    • 发生错误
    • 等待超时
    • 出现需要处理的新Message(包括C++层和Java层)
    • 由addFd函数添加的Fd触发event

 

总结:


  1. 在哪个线程调用JAVA层的Looper.loop(),Mesage和callback(包括Java层和C++层)就在哪个线程被处理,上图为Looper.loop函数的时序图。
  2. C++层的NativeMesasgeQueue不应该是Java层的MesageQueue的内部实现,而更接近于“栾生兄弟”的关系。MessageQueue负责处理java层上到消息,NativeMessageQueue负责处理C++层上的消息。其中Java层是在android.os.Looper.looper函数中调用android.os.Handler.dispatchMessage处理,而C++层是在android::Looper::pollInner函数中调用android::MessageHandler::handleMessage & android:LooperCallback::handleEvent函数处理。
  3. NativeMessageQueue利用Looper类实现了一个基于epoll函数和文件描述符(Fd)的可唤醒的阻塞机制。    
0 0
原创粉丝点击