Android訊息機制不完全解析(下) .

yangxi_001發表於2016-03-04

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


首先,看看在/frameworks/base/core/jni/android_os_MessageQueue.cpp檔案中看看android.os.MessageQueue類中的四個原生函式的實現:

  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. }  
static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) {
    NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();//構造NativeMessageQueue例項
    if (!nativeMessageQueue) {
        jniThrowRuntimeException(env, "Unable to allocate native queue");
        return;
    }
    nativeMessageQueue->incStrong(env);//強引用+1
    android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);
}

static void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jobject obj) {
    NativeMessageQueue* nativeMessageQueue =
            android_os_MessageQueue_getNativeMessageQueue(env, obj);
    if (nativeMessageQueue) {
        android_os_MessageQueue_setNativeMessageQueue(env, obj, NULL);
        nativeMessageQueue->decStrong(env);//強引用-1,實際上會導致釋放NativeMessageQueue例項
    }
}

static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
        jint ptr, jint timeoutMillis) {
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);//指標強制轉換
    nativeMessageQueue->pollOnce(env, timeoutMillis);//呼叫nativeMessageQueue的pollonce函式
}

static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) {
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
    return nativeMessageQueue->wake();//呼叫nativeMessageQueue的wake函式
}


    從程式碼中,可以看到這四個函式的實現都是依賴於NativeMessageQueue類。不過,在開始解析NativeMessageQueue之前,我們再看一些有意思的程式碼:

  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. }  
static void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject messageQueueObj,
        NativeMessageQueue* nativeMessageQueue) {
    env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr,
             reinterpret_cast<jint>(nativeMessageQueue));//把nativeMessageQueue的例項地址強轉為java的int型別並儲存到gMessageQueueClassInfo.mPtr中
}

    那麼gMessageQueueClassInfo.mPtr是什麼呢?

  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. }  
static JNINativeMethod gMessageQueueMethods[] = {
    /* name, signature, funcPtr */
    { "nativeInit", "()V", (void*)android_os_MessageQueue_nativeInit },
    { "nativeDestroy", "()V", (void*)android_os_MessageQueue_nativeDestroy },
    { "nativePollOnce", "(II)V", (void*)android_os_MessageQueue_nativePollOnce },
    { "nativeWake", "(I)V", (void*)android_os_MessageQueue_nativeWake }
};

#define FIND_CLASS(var, className) \
        var = env->FindClass(className); \
        LOG_FATAL_IF(! var, "Unable to find class " className);

#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
//這個函式在Android啟動的時候,會被系統呼叫
int register_android_os_MessageQueue(JNIEnv* env) {
    int res = jniRegisterNativeMethods(env, "android/os/MessageQueue",
            gMessageQueueMethods, NELEM(gMessageQueueMethods));//關聯MessageQueueQueue的原生函式
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    jclass clazz;
    FIND_CLASS(clazz, "android/os/MessageQueue");//獲取MessageQueue的class

    GET_FIELD_ID(gMessageQueueClassInfo.mPtr, clazz,
            "mPtr", "I");//獲取MessageQueue class的mPtr field的Id
    
    return 0;
}
    上面的程式碼很像java的反射有木有?

  1. Class cls = Class.forName("android.os.MessageQueue");  
  2. Field feild = cls.getField("mPtr");  
    Class cls = Class.forName("android.os.MessageQueue");
    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的宣告:

  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. };  
class NativeMessageQueue : public MessageQueue {
public:
    NativeMessageQueue();
    virtual ~NativeMessageQueue();

    virtual void raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj);

    void pollOnce(JNIEnv* env, int timeoutMillis);

    void wake();

private:
    bool mInCallback;
    jthrowable mExceptionObj;
};
    NativeMessageQueue繼承自MessageQueue(不是java中的android.os.MessageQueue哦),關於MessageQueue我們只需要瞭解,它包含了一個成員mLooper即可(有興趣的同學可以檢視/frameworks/base/core/jni/android_os_MessageQueue.h)    

  1. class MessageQueue  {  
  2.   
  3.     ......  
  4.   
  5. protected:  
  6.     sp<Looper> mLooper;  
  7. };  
class MessageQueue  {

    ......

protected:
    sp<Looper> mLooper;
};

    繼續看NativeMessageQueue的程式碼:

  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::NativeMessageQueue() : mInCallback(false), mExceptionObj(NULL) {
    mLooper = Looper::getForThread();
    if (mLooper == NULL) {
        mLooper = new Looper(false);//例項化mLooper
        Looper::setForThread(mLooper);
    }
}
    NativeMessageQueue構造例項的時候,會例項化mLooper。
  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. }  
void NativeMessageQueue::pollOnce(JNIEnv* env, int timeoutMillis) {
    mInCallback = true;
    mLooper->pollOnce(timeoutMillis);
    mInCallback = false;
    if (mExceptionObj) {
        env->Throw(mExceptionObj);
        env->DeleteLocalRef(mExceptionObj);
        mExceptionObj = NULL;
    }
}

void NativeMessageQueue::wake() {
    mLooper->wake();
}

    小結:

  1. NativeMessageQueue的函式pollonce和wake實現相當簡單,交給mLooper的同名函式。

Looper


    先來看看Looper的宣告/frameworks/native/include/utils/Looper.h:

  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. };  
class Looper : public ALooper, public RefBase {
protected:
    virtual ~Looper();

public:
    Looper(bool allowNonCallbacks);

    bool getAllowNonCallbacks() const;

    int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
    inline int pollOnce(int timeoutMillis) {
        return pollOnce(timeoutMillis, NULL, NULL, NULL);
    }

    void wake();

private:

    const bool mAllowNonCallbacks; // immutable

    int mWakeReadPipeFd;  // immutable
    int mWakeWritePipeFd; // immutable
    Mutex mLock;

    int mEpollFd; // immutable

    int pollInner(int timeoutMillis);
    void awoken();
};
    因為程式碼有點多,所以上面的宣告,已經被我精簡了大部分,現在我們只關注我們關心的:pollonce和wake函式。

    還是從建構函式開始(frameworks/native/utils/Looper.cpp):

  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::Looper(bool allowNonCallbacks) :
        mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
        mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
    int wakeFds[2];
    int result = pipe(wakeFds);//建立命名管道
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
    // 儲存命名管道
    mWakeReadPipeFd = wakeFds[0];
    mWakeWritePipeFd = wakeFds[1];

    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);//設定為非阻塞模式
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
            errno);

    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);//設定為非阻塞模式
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
            errno);
    // 開始使用epoll API,實現輪詢
    // Allocate the epoll instance and register the wake pipe.
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);//建立epoll檔案描述符
    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);

    struct epoll_event eventItem;
    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
    eventItem.events = EPOLLIN;
    eventItem.data.fd = mWakeReadPipeFd;
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); // 把剛才建立的命名管道的讀端加入的到epoll的監聽佇列中
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
            errno);
}

Looper::~Looper() {
    close(mWakeReadPipeFd);//釋放命名管道
    close(mWakeWritePipeFd);
    close(mEpollFd);//釋放epoll檔案描述符
}
    Looper的建構函式中,出現了命名管道和epoll相關的程式碼,這是為什麼呢?別急,接著看下去就知道了:
  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. }  
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) {//ident > 0, 即此response為noncallback,需要返回event,data等資料給呼叫者處理
                int fd = response.request.fd;
                int events = response.events;
                void* data = response.request.data;
#if DEBUG_POLL_AND_WAKE
                ALOGD("%p ~ pollOnce - returning signalled identifier %d: "
                        "fd=%d, events=0x%x, data=%p",
                        this, ident, fd, events, data);
#endif
                if (outFd != NULL) *outFd = fd;
                if (outEvents != NULL) *outEvents = events;
                if (outData != NULL) *outData = data;
                return ident;
            }
        }

        if (result != 0) {
#if DEBUG_POLL_AND_WAKE
            ALOGD("%p ~ pollOnce - returning result %d", this, result);
#endif
            if (outFd != NULL) *outFd = 0;
            if (outEvents != NULL) *outEvents = 0;
            if (outData != NULL) *outData = NULL;
            return result;
        }

        result = pollInner(timeoutMillis);//這一行才是重點!
    }
}
    接著往下看,程式碼有些長,但請仔細看:
  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. }  
int Looper::pollInner(int timeoutMillis) {
    
#if DEBUG_POLL_AND_WAKE
    ALOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
#endif

    // 設定timeoutMillis的值為Math.min(timeoutMills, mNextMessageUptime)
    // Adjust the timeout based on when the next message is due.
    if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
        if (messageTimeoutMillis >= 0
                && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
            timeoutMillis = messageTimeoutMillis;
        }
#if DEBUG_POLL_AND_WAKE
        ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
                this, mNextMessageUptime - now, timeoutMillis);
#endif
    }


    // Poll.
    int result = ALOOPER_POLL_WAKE;
    mResponses.clear();
    mResponseIndex = 0;

    // 開始輪詢
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

    // Acquire lock.
    mLock.lock();

    // Check for poll error.
    if (eventCount < 0) { //處理error
        if (errno == EINTR) {
            goto Done;
        }
        ALOGW("Poll failed with an unexpected error, errno=%d", errno);
        result = ALOOPER_POLL_ERROR;
        goto Done;
    }

    // Check for poll timeout.
    if (eventCount == 0) { // 未能等到event,故timeout
#if DEBUG_POLL_AND_WAKE
        ALOGD("%p ~ pollOnce - timeout", this);
#endif
        result = ALOOPER_POLL_TIMEOUT;
        goto Done;
    }

    // Handle all events.
#if DEBUG_POLL_AND_WAKE
    ALOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
#endif

    for (int i = 0; i < eventCount; i++) {//有event,則處理
        int fd = eventItems[i].data.fd;
        uint32_t epollEvents = eventItems[i].events;
        if (fd == mWakeReadPipeFd) {
            if (epollEvents & EPOLLIN) {
                awoken();//讀取命名管道內的資料
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
            }
        } else {
            ssize_t requestIndex = mRequests.indexOfKey(fd);
            if (requestIndex >= 0) {
                int events = 0;
                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;
                pushResponse(events, mRequests.valueAt(requestIndex));//把event新增到<span style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses中,等待後續處理</span>
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
                        "no longer registered.", epollEvents, fd);
            }
        }
    }
Done: ;
    // 處理C++層的Message
    // 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) {
            // Remove the envelope from the list.
            // We keep a strong reference to the handler until the call to handleMessage
            // finishes.  Then we drop it so that the handler can be deleted *before*
            // we reacquire our lock.
            { // obtain handler
                sp<MessageHandler> handler = messageEnvelope.handler;
                Message message = messageEnvelope.message;
                mMessageEnvelopes.removeAt(0);
                mSendingMessage = true;
                mLock.unlock();

#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
                ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
                        this, handler.get(), message.what);
#endif
                handler->handleMessage(message);//呼叫handler-><span style="FONT-FAMILY: Arial, Helvetica, sans-serif">handleMessage</span>
            } // release handler

            mLock.lock();
            mSendingMessage = false;
            result = ALOOPER_POLL_CALLBACK;
        } else {
            // The last message left at the head of the queue determines the next wakeup time.
            mNextMessageUptime = messageEnvelope.uptime;//更新<span style="FONT-FAMILY: Arial, Helvetica, sans-serif">mNextMessageUptime</span>
            break;
        }
    }

    // Release lock.
    mLock.unlock();
    // 處理<span style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses</span>
    // Invoke all response callbacks.
    for (size_t i = 0; i < mResponses.size(); i++) {
        Response& response = mResponses.editItemAt(i);
        if (response.request.ident == ALOOPER_POLL_CALLBACK) {
            int fd = response.request.fd;
            int events = response.events;
            void* data = response.request.data;
#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
            ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
                    this, response.request.callback.get(), fd, events, data);
#endif
            int callbackResult = response.request.callback->handleEvent(fd, events, data);//呼叫callback->handleEvent
            if (callbackResult == 0) {
                removeFd(fd);
            }
            // 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 = ALOOPER_POLL_CALLBACK;
        }
    }
    return result;
}

    程式碼比較長,所以分段分析:

  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. }  
    // 設定timeoutMillis的值為Math.min(timeoutMillis, mNextMessageUptime)
    // Adjust the timeout based on when the next message is due.
    if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
        if (messageTimeoutMillis >= 0
                && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
            timeoutMillis = messageTimeoutMillis;
        }#if DEBUG_POLL_AND_WAKE
        ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
                this, mNextMessageUptime - now, timeoutMillis);
#endif
    }

    為了解析這段程式碼,需要先補充一些C++層的Message相關的程式碼:

  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. }  
struct Message {
    Message() : what(0) { }
    Message(int what) : what(what) { }

    /* The message type. (interpretation is left up to the handler) */
    int what;
};


class MessageHandler : public virtual RefBase {
    protected:
        virtual ~MessageHandler() { }

    public:
        /**
         * Handles a message.
         */
        virtual void handleMessage(const Message& message) = 0;
}

struct MessageEnvelope {
    MessageEnvelope() : uptime(0) { }
    MessageEnvelope(nsecs_t uptime, const sp<MessageHandler> handler,const Message& message) : uptime(uptime), handler(handler), message(message) {}

    nsecs_t uptime;
    MessageHandler> handler;
    Message message;
};

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

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

void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
        const Message& message) {
#if DEBUG_CALLBACKS
    ALOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d",
            this, uptime, handler.get(), message.what);
#endif

    size_t i = 0;
    { // acquire lock
        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);

        // 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();
    }
}

void Looper::removeMessages(const sp<MessageHandler>& handler) {
#if DEBUG_CALLBACKS
    ALOGD("%p ~ removeMessages - handler=%p", this, handler.get());
#endif

    { // acquire lock
        AutoMutex _l(mLock);

        for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
            const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
            if (messageEnvelope.handler == handler) {
                mMessageEnvelopes.removeAt(i);
            }
        }
    } // release lock
}

void Looper::removeMessages(const sp<MessageHandler>& handler, int what) {
#if DEBUG_CALLBACKS
    ALOGD("%p ~ removeMessages - handler=%p, what=%d", this, handler.get(), what);
#endif

    { // acquire lock
        AutoMutex _l(mLock);

        for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
            const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
            if (messageEnvelope.handler == handler
                    && messageEnvelope.message.what == what) {
                mMessageEnvelopes.removeAt(i);
            }
        }
    } // release lock
}
    是不是覺得上面的程式碼似曾相識?和Java層的MessageQueue很像似有木有?和java層一樣,C++層存在訊息佇列和訊息處理機制,訊息被儲存到成員mMessageEvelopes中,並在pollInner函式中處理訊息(呼叫MesageHandler的handleMesage函式處理)。

    現在回到Looper::pollonceh函式,我們就應該能夠理解,pollOnce函式到timeOutMillis引數僅僅代表了Java層下一個Message的觸發延遲,所以,我們還需要考慮C++層下一個Message的觸發延遲,所以,程式碼設定timeoutMillis為timeoutMillis和mNextMessageUpTime中的較小值。


    繼續下一段程式碼:

  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();  
    int result = ALOOPER_POLL_WAKE;
    mResponses.clear();
    mResponseIndex = 0;
    // 開始輪詢
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

    // Acquire lock.
    mLock.lock();
    呼叫epoll函式,等待event發生,epoll_wait函式的返回值有三種可能:失敗出錯、沒有event、有一個或多個event。

1. 失敗的處理:

  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. }  
    // Check for poll error.
    if (eventCount < 0) { //處理error
        if (errno == EINTR) {
            goto Done;
        }
        ALOGW("Poll failed with an unexpected error, errno=%d", errno);
        result = ALOOPER_POLL_ERROR;
        goto Done;
    }
2. 沒有event發生:
  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.     }  
    // Check for poll timeout.
    if (eventCount == 0) { // 未能等到event,故timeout
#if DEBUG_POLL_AND_WAKE
        ALOGD("%p ~ pollOnce - timeout", this);
#endif
        result = ALOOPER_POLL_TIMEOUT;
        goto Done;
    }
3. 有event發生:
  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. }  
    // Handle all events.
#if DEBUG_POLL_AND_WAKE
    ALOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
#endif

    for (int i = 0; i < eventCount; i++) {//有event,則處理
        int fd = eventItems[i].data.fd;
        uint32_t epollEvents = eventItems[i].events;
        if (fd == mWakeReadPipeFd) {//說明java層或者C++層有新的Message
            if (epollEvents & EPOLLIN) {
                awoken();//讀取命名管道內的資料
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
            }
        } else {
            ssize_t requestIndex = mRequests.indexOfKey(fd);
            if (requestIndex >= 0) {
                int events = 0;
                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;
                pushResponse(events, mRequests.valueAt(requestIndex));//把event新增到<span style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses中,等待後續處理</span>
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
                        "no longer registered.", epollEvents, fd);
            }
        }
    }

    處理event的時候,需要分為兩類:fd==mWakeReadPipeFd和fd!=mWakeReadPipeFd

fd==mWakeReadPipeFd:說明C++層,或者java層有新的Message出現,需要處理。這種情況下,只需要讀mWakeReadPipeFd內的資料即可

  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. }  
void Looper::awoken() {
#if DEBUG_POLL_AND_WAKE
    ALOGD("%p ~ awoken", this);
#endif

    char buffer[16];
    ssize_t nRead;
    do {
        nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
    } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
}
fd!=mWakeReadPipeFd:首先需要搞明白fd是哪來的:

  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.     };  
    struct Request {
        int fd;
        int ident;
        sp<LooperCallback> callback;
        void* data;
    };


    struct Response {
        int events;
        Request request;
    };
  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. };  
/**
 * A looper callback.
 */
class LooperCallback : public virtual RefBase {
protected:
    virtual ~LooperCallback() { }


public:
    /**
     * Handles a poll event for the given file descriptor.
     * It is given the file descriptor it is associated with,
     * a bitmask of the poll events that were triggered (typically ALOOPER_EVENT_INPUT),
     * and the data pointer that was originally supplied.
     *
     * Implementations should return 1 to continue receiving callbacks, or 0
     * to have this file descriptor and callback unregistered from the looper.
     */
    virtual int handleEvent(int fd, int events, void* data) = 0;
};
  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. }  
int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
#if DEBUG_CALLBACKS
    ALOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,
            events, callback.get(), data);
#endif

    if (!callback.get()) {
        if (! mAllowNonCallbacks) {
            ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
            return -1;
        }

        if (ident < 0) {//僅當Looper支援NonCallbacks,並且ident大於0時,允許新增callback為null的Fd
            ALOGE("Invalid attempt to set NULL callback with ident < 0.");
            return -1;
        }
    } else {
        ident = ALOOPER_POLL_CALLBACK;
    }

    int epollEvents = 0;
    if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
    if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;

    { // acquire lock
        AutoMutex _l(mLock);

        Request request;
        request.fd = fd;
        request.ident = ident;
        request.callback = callback;
        request.data = data;

        struct epoll_event eventItem;
        memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
        eventItem.events = epollEvents;
        eventItem.data.fd = fd;

        ssize_t requestIndex = mRequests.indexOfKey(fd);
        if (requestIndex < 0) {
            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
            if (epollResult < 0) {
                ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
                return -1;
            }
            mRequests.add(fd, request);
        } else {//存在則替換
            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
            if (epollResult < 0) {
                ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
                return -1;
            }
            mRequests.replaceValueAt(requestIndex, request);
        }
    } // release lock
    return 1;
}

    從上面的程式碼,我們可知,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中,等待後續的處理。

  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. }  
void Looper::pushResponse(int events, const Request& request) {
    Response response;
    response.events = events;
    response.request = request;
    mResponses.push(response);
}

    到這裡為止,epoll_wait函式返回的三種結果的不同處理已經解析完畢,接下來程式碼進入共同的Done環節。

處理C++層的Message:

  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.     }  
Done: ;
    // 處理C++層的Message
    // 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) {
            // Remove the envelope from the list.
            // We keep a strong reference to the handler until the call to handleMessage
            // finishes.  Then we drop it so that the handler can be deleted *before*
            // we reacquire our lock.
            { // obtain handler
                sp<MessageHandler> handler = messageEnvelope.handler;
                Message message = messageEnvelope.message;
                mMessageEnvelopes.removeAt(0);
                mSendingMessage = true;
                mLock.unlock();

#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
                ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
                        this, handler.get(), message.what);
#endif
                handler->handleMessage(message);//呼叫handler-><span style="FONT-FAMILY: Arial, Helvetica, sans-serif">handleMessage</span>
            } // release handler

            mLock.lock();
            mSendingMessage = false;
            result = ALOOPER_POLL_CALLBACK;
        } else {
            // The last message left at the head of the queue determines the next wakeup time.
            mNextMessageUptime = messageEnvelope.uptime;//更新<span style="FONT-FAMILY: Arial, Helvetica, sans-serif">mNextMessageUptime</span>
            break;
        }
    }

處理Response:

  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.     }  
    // 處理<span style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses</span>
    // Invoke all response callbacks.
    for (size_t i = 0; i < mResponses.size(); i++) {
        Response& response = mResponses.editItemAt(i);
        if (response.request.ident == ALOOPER_POLL_CALLBACK) {
            int fd = response.request.fd;
            int events = response.events;
            void* data = response.request.data;
#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
            ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
                    this, response.request.callback.get(), fd, events, data);
#endif
            int callbackResult = response.request.callback->handleEvent(fd, events, data);//呼叫callback->handleEvent
            if (callbackResult == 0) {
                removeFd(fd);
            }
            // 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 = ALOOPER_POLL_CALLBACK;
        }
    }

    搞懂了上面的程式碼,我們就很容易明白wake函式做了些什麼:

  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. }  
void Looper::wake() {
#if DEBUG_POLL_AND_WAKE
    ALOGD("%p ~ wake", this);
#endif

    ssize_t nWrite;
    do {
        nWrite = write(mWakeWritePipeFd, "W", 1);//向<span style="font-family: Arial, Helvetica, sans-serif;">mWakeWritePipeFd</span><span style="font-family: Arial, Helvetica, sans-serif;">中寫入一個字元,所以mWakeReadPipeFd就會觸發</span><span style="font-family: Arial, Helvetica, sans-serif;">EPOLLIN event</span><span style="font-family: Arial, Helvetica, sans-serif;">
</span>    } while (nWrite == -1 && errno == EINTR);

    if (nWrite != 1) {
        if (errno != EAGAIN) {
            ALOGW("Could not write wake signal, errno=%d", errno);
        }
    }
}
    小結:
  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)的可喚醒的阻塞機制。    

相關文章