Android消息機(jī)制不完全解析(下)
? ? 接著上一篇文章Android消息機(jī)制不完全解析(上),接著看C++部分的實(shí)現(xiàn)。
? ? 首先,看看在/frameworks/base/core/jni/android_os_MessageQueue.cpp文件中看看android.os.MessageQueue類中的四個(gè)原生函數(shù)的實(shí)現(xiàn):
static?void?android_os_MessageQueue_nativeInit(JNIEnv*?env,?jobject?obj)?{ ????NativeMessageQueue*?nativeMessageQueue?=?new?NativeMessageQueue();//構(gòu)造NativeMessageQueue實(shí)例 ????if?(!nativeMessageQueue)?{ ????????jniThrowRuntimeException(env,?"Unable?to?allocate?native?queue"); ????????return; ????} ????nativeMessageQueue->incStrong(env);//強(qiáng)引用+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);//強(qiáng)引用-1,實(shí)際上會(huì)導(dǎo)致釋放NativeMessageQueue實(shí)例 ????} } static?void?android_os_MessageQueue_nativePollOnce(JNIEnv*?env,?jobject?obj, ????????jint?ptr,?jint?timeoutMillis)?{ ????NativeMessageQueue*?nativeMessageQueue?=?reinterpret_cast(ptr);//指針強(qiáng)制轉(zhuǎn)換 ????nativeMessageQueue->pollOnce(env,?timeoutMillis);//調(diào)用nativeMessageQueue的pollonce函數(shù) } static?void?android_os_MessageQueue_nativeWake(JNIEnv*?env,?jobject?obj,?jint?ptr)?{ ????NativeMessageQueue*?nativeMessageQueue?=?reinterpret_cast(ptr); ????return?nativeMessageQueue->wake();//調(diào)用nativeMessageQueue的wake函數(shù) }
? ? 從代碼中,可以看到這四個(gè)函數(shù)的實(shí)現(xiàn)都是依賴于NativeMessageQueue類。不過,在開始解析NativeMessageQueue之前,我們?cè)倏匆恍┯幸馑嫉拇a:
static?void?android_os_MessageQueue_setNativeMessageQueue(JNIEnv*?env,?jobject?messageQueueObj, ????????NativeMessageQueue*?nativeMessageQueue)?{ ????env->SetIntField(messageQueueObj,?gMessageQueueClassInfo.mPtr, ?????????????reinterpret_cast(nativeMessageQueue));//把nativeMessageQueue的實(shí)例地址強(qiáng)轉(zhuǎn)為java的int類型并保存到gMessageQueueClassInfo.mPtr中 }
? ? 那么gMessageQueueClassInfo.mPtr是什么呢?
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); //這個(gè)函數(shù)在Android啟動(dòng)的時(shí)候,會(huì)被系統(tǒng)調(diào)用 int?register_android_os_MessageQueue(JNIEnv*?env)?{ ????int?res?=?jniRegisterNativeMethods(env,?"android/os/MessageQueue", ????????????gMessageQueueMethods,?NELEM(gMessageQueueMethods));//關(guān)聯(lián)MessageQueueQueue的原生函數(shù) ????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的反射有木有?
????Class?cls?=?Class.forName("android.os.MessageQueue"); ????Field?feild?=?cls.getField("mPtr");
? ? 到這里,我們就明白了android_os_MessageQueue_setNativeMessageQueue函數(shù)實(shí)際上把a(bǔ)ndroid.os.MessageQueue實(shí)例的mPtr值設(shè)置為nativeMessageQueue實(shí)例的地址。雖然Java語言沒有指針的說法,但是,這里的mPtr卻的的確確是作為一個(gè)指針使用的?,F(xiàn)在,我們也就理解了,為什么mPtr可以被強(qiáng)制轉(zhuǎn)換為nativeMessageQueue了。
? ? 小結(jié):
android_os_MessageQueue_nativeInit和android_os_MessageQueue_nativeDestory兩個(gè)函數(shù)做了些什么:
android_os_MessageQueue_nativeInit:構(gòu)造NativeMessageQueue實(shí)例android_os_MessageQueue_nativeDestory:銷毀NativeMessageQeue實(shí)例NativeMessageQueue
? ? 先來看看NativeMessageQueue的聲明:
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哦),關(guān)于MessageQueue我們只需要了解,它包含了一個(gè)成員mLooper即可(有興趣的同學(xué)可以查看/frameworks/base/core/jni/android_os_MessageQueue.h) ? ?
class?MessageQueue??{ ????...... protected: ????spmLooper; };
? ? 繼續(xù)看NativeMessageQueue的代碼:
NativeMessageQueue::NativeMessageQueue()?:?mInCallback(false),?mExceptionObj(NULL)?{ ????mLooper?=?Looper::getForThread(); ????if?(mLooper?==?NULL)?{ ????????mLooper?=?new?Looper(false);//實(shí)例化mLooper ????????Looper::setForThread(mLooper); ????} }
? ? NativeMessageQueue構(gòu)造實(shí)例的時(shí)候,會(huì)實(shí)例化mLooper。
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(); }
? ? 小結(jié):
NativeMessageQueue的函數(shù)pollonce和wake實(shí)現(xiàn)相當(dāng)簡(jiǎn)單,交給mLooper的同名函數(shù)。
Looper
? ? 先來看看Looper的聲明/frameworks/native/include/utils/Looper.h:
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(); };
? ? 因?yàn)榇a有點(diǎn)多,所以上面的聲明,已經(jīng)被我精簡(jiǎn)了大部分,現(xiàn)在我們只關(guān)注我們關(guān)心的:pollonce和wake函數(shù)。
? ? 還是從構(gòu)造函數(shù)開始(frameworks/native/utils/Looper.cpp):
Looper::Looper(bool?allowNonCallbacks)?: ????????mAllowNonCallbacks(allowNonCallbacks),?mSendingMessage(false), ????????mResponseIndex(0),?mNextMessageUptime(LLONG_MAX)?{ ????int?wakeFds[2]; ????int?result?=?pipe(wakeFds);//創(chuàng)建命名管道 ????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);//設(shè)置為非阻塞模式 ????LOG_ALWAYS_FATAL_IF(result?!=?0,?"Could?not?make?wake?read?pipe?non-blocking.??errno=%d", ????????????errno); ????result?=?fcntl(mWakeWritePipeFd,?F_SETFL,?O_NONBLOCK);//設(shè)置為非阻塞模式 ????LOG_ALWAYS_FATAL_IF(result?!=?0,?"Could?not?make?wake?write?pipe?non-blocking.??errno=%d", ????????????errno); ????//?開始使用epoll?API,實(shí)現(xiàn)輪詢 ????//?Allocate?the?epoll?instance?and?register?the?wake?pipe. ????mEpollFd?=?epoll_create(EPOLL_SIZE_HINT);//創(chuàng)建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);?//?把剛才創(chuàng)建的命名管道的讀端加入的到epoll的監(jiān)聽隊(duì)列中 ????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的構(gòu)造函數(shù)中,出現(xiàn)了命名管道和epoll相關(guān)的代碼,這是為什么呢?別急,接著看下去就知道了:
int?Looper::pollOnce(int?timeoutMillis,?int*?outFd,?int*?outEvents,?void**?outData)?{ ????int?result?=?0; ????for?(;;)?{ ???????//?這段代碼暫時(shí)無視 ???????while?(mResponseIndex?<?mResponses.size())?{ ????????????const?Response&?response?=?mResponses.itemAt(mResponseIndex++); ????????????int?ident?=?response.request.ident; ????????????if?(ident?>=?0)?{//ident?>?0,?即此response為noncallback,需要返回event,data等數(shù)據(jù)給調(diào)用者處理 ????????????????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);//這一行才是重點(diǎn)! ????} }
? ? 接著往下看,代碼有些長,但請(qǐng)仔細(xì)看:
int?Looper::pollInner(int?timeoutMillis)?{ ???? #if?DEBUG_POLL_AND_WAKE ????ALOGD("%p?~?pollOnce?-?waiting:?timeoutMillis=%d",?this,?timeoutMillis); #endif ????//?設(shè)置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();//讀取命名管道內(nèi)的數(shù)據(jù) ????????????}?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添加到mResponses中,等待后續(xù)處理 ????????????}?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 ????????????????sphandler?=?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);//調(diào)用handler->handleMessage ????????????}?//?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;//更新mNextMessageUptime ????????????break; ????????} ????} ????//?Release?lock. ????mLock.unlock(); ????//?處理mResponses ????//?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);//調(diào)用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; }
? ? 代碼比較長,所以分段分析:
????//?設(shè)置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 ????}
? ? 為了解析這段代碼,需要先補(bǔ)充一些C++層的Message相關(guān)的代碼:
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?sphandler,const?Message&?message)?:?uptime(uptime),?handler(handler),?message(message)?{} ????nsecs_t?uptime; ????MessageHandler>?handler; ????Message?message; }; void?Looper::sendMessage(const?sp&?handler,?const?Message&?message)?{ ????nsecs_t?now?=?systemTime(SYSTEM_TIME_MONOTONIC); ????sendMessageAtTime(now,?handler,?message); } void?Looper::sendMessageDelayed(nsecs_t?uptimeDelay,?const?sp&?handler, ????????const?Message&?message)?{ ????nsecs_t?now?=?systemTime(SYSTEM_TIME_MONOTONIC); ????sendMessageAtTime(now?+?uptimeDelay,?handler,?message); } void?Looper::sendMessageAtTime(nsecs_t?uptime,?const?sp&?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&?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&?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 }
? ? 是不是覺得上面的代碼似曾相識(shí)?和Java層的MessageQueue很像似有木有?和java層一樣,C++層存在消息隊(duì)列和消息處理機(jī)制,消息被保存到成員mMessageEvelopes中,并在pollInner函數(shù)中處理消息(調(diào)用MesageHandler的handleMesage函數(shù)處理)。
? ? 現(xiàn)在回到Looper::pollonceh函數(shù),我們就應(yīng)該能夠理解,pollOnce函數(shù)到timeOutMillis參數(shù)僅僅代表了Java層下一個(gè)Message的觸發(fā)延遲,所以,我們還需要考慮C++層下一個(gè)Message的觸發(fā)延遲,所以,代碼設(shè)置timeoutMillis為timeoutMillis和mNextMessageUpTime中的較小值。
? ? 繼續(xù)下一段代碼:
????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();
? ? 調(diào)用epoll函數(shù),等待event發(fā)生,epoll_wait函數(shù)的返回值有三種可能:失敗出錯(cuò)、沒有event、有一個(gè)或多個(gè)event。
1. 失敗的處理:
????//?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發(fā)生:
????//?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發(fā)生:
????//?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();//讀取命名管道內(nèi)的數(shù)據(jù) ????????????}?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添加到mResponses中,等待后續(xù)處理 ????????????}?else?{ ????????????????ALOGW("Ignoring?unexpected?epoll?events?0x%x?on?fd?%d?that?is?" ????????????????????????"no?longer?registered.",?epollEvents,?fd); ????????????} ????????} ????}
? ? 處理event的時(shí)候,需要分為兩類:fd==mWakeReadPipeFd和fd!=mWakeReadPipeFd
fd==mWakeReadPipeFd:說明C++層,或者java層有新的Message出現(xiàn),需要處理。這種情況下,只需要讀mWakeReadPipeFd內(nèi)的數(shù)據(jù)即可
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是哪來的:
????struct?Request?{ ????????int?fd; ????????int?ident; ????????spcallback; ????????void*?data; ????}; ????struct?Response?{ ????????int?events; ????????Request?request; ????};
/** ?*?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; };
int?Looper::addFd(int?fd,?int?ident,?int?events,?const?sp&?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)?{//僅當(dāng)Looper支持NonCallbacks,并且ident大于0時(shí),允許添加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函數(shù),可以向Looper的mEpollFd添加指定的Fd,當(dāng)Fd觸發(fā)指定的event .e.i ?EPOLLIN or EPOLLOUT時(shí),指定的相應(yīng)的自定義callback就會(huì)得到執(zhí)行。
? ?另外,當(dāng)Looper支持noncallback時(shí),還可以向Looper添加callback為null的Fd,因?yàn)闆]有callback,所以Fd添加者需要調(diào)用int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) 通過outFd、outEvent、outData參數(shù)獲取數(shù)據(jù)并進(jìn)行處理。
? ? 所以當(dāng)Fd觸發(fā)消息時(shí),需要生成對(duì)應(yīng)到reponse并添加到meResponses中,等待后續(xù)的處理。
void?Looper::pushResponse(int?events,?const?Request&?request)?{ ????Response?response; ????response.events?=?events; ????response.request?=?request; ????mResponses.push(response); }
? ? 到這里為止,epoll_wait函數(shù)返回的三種結(jié)果的不同處理已經(jīng)解析完畢,接下來代碼進(jìn)入共同的Done環(huán)節(jié)。
處理C++層的Message:
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 ????????????????sphandler?=?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);//調(diào)用handler->handleMessage ????????????}?//?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;//更新mNextMessageUptime ????????????break; ????????} ????}
處理Response:
????//?處理mResponses ????//?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);//調(diào)用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函數(shù)做了些什么:
void?Looper::wake()?{ #if?DEBUG_POLL_AND_WAKE ????ALOGD("%p?~?wake",?this); #endif ????ssize_t?nWrite; ????do?{ ????????nWrite?=?write(mWakeWritePipeFd,?"W",?1);//向mWakeWritePipeFd中寫入一個(gè)字符,所以mWakeReadPipeFd就會(huì)觸發(fā)EPOLLIN?event ????}?while?(nWrite?==?-1?&&?errno?==?EINTR); ????if?(nWrite?!=?1)?{ ????????if?(errno?!=?EAGAIN)?{ ????????????ALOGW("Could?not?write?wake?signal,?errno=%d",?errno); ????????} ????} }
? ? 小結(jié): Looper通過epoll函數(shù)組實(shí)現(xiàn)了一個(gè)可以支持隨時(shí)喚醒的阻塞機(jī)制Looper支持兩種不同的方式處理消息:Message + MessageHandler 和 LooperCallback。Looper的阻塞在如下四種條件下會(huì)被喚醒: 發(fā)生錯(cuò)誤等待超時(shí)出現(xiàn)需要處理的新Message(包括C++層和Java層)由addFd函數(shù)添加的Fd觸發(fā)event
?
總結(jié):
在哪個(gè)線程調(diào)用JAVA層的Looper.loop(),Mesage和callback(包括Java層和C++層)就在哪個(gè)線程被處理,上圖為Looper.loop函數(shù)的時(shí)序圖。C++層的NativeMesasgeQueue不應(yīng)該是Java層的MesageQueue的內(nèi)部實(shí)現(xiàn),而更接近于“欒生兄弟”的關(guān)系。MessageQueue負(fù)責(zé)處理java層上到消息,NativeMessageQueue負(fù)責(zé)處理C++層上的消息。其中Java層是在android.os.Looper.looper函數(shù)中調(diào)用android.os.Handler.dispatchMessage處理,而C++層是在android::Looper::pollInner函數(shù)中調(diào)用android::MessageHandler::handleMessage & android:LooperCallback::handleEvent函數(shù)處理。NativeMessageQueue利用Looper類實(shí)現(xiàn)了一個(gè)基于epoll函數(shù)和文件描述符(Fd)的可喚醒的阻塞機(jī)制。