www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 芯聞號(hào) > 充電吧
[導(dǎo)讀]? ? 接著上一篇文章Android消息機(jī)制不完全解析(上),接著看C++部分的實(shí)現(xiàn)。? ? 首先,看看在/frameworks/base/core/jni/android_os_MessageQue

? ? 接著上一篇文章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ī)制。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉