女人被狂躁到高潮视频免费无遮挡,内射人妻骚骚骚,免费人成小说在线观看网站,九九影院午夜理论片少妇,免费av永久免费网址

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

? ? 接著上一篇文章Android消息機制不完全解析(上),接著看C++部分的實現(xiàn)。


? ? 首先,看看在/frameworks/base/core/jni/android_os_MessageQueue.cpp文件中看看android.os.MessageQueue類中的四個原生函數(shù)的實現(xiàn):


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(ptr);//指針強制轉換
????nativeMessageQueue->pollOnce(env,?timeoutMillis);//調用nativeMessageQueue的pollonce函數(shù)
}

static?void?android_os_MessageQueue_nativeWake(JNIEnv*?env,?jobject?obj,?jint?ptr)?{
????NativeMessageQueue*?nativeMessageQueue?=?reinterpret_cast(ptr);
????return?nativeMessageQueue->wake();//調用nativeMessageQueue的wake函數(shù)
}


? ? 從代碼中,可以看到這四個函數(shù)的實現(xiàn)都是依賴于NativeMessageQueue類。不過,在開始解析NativeMessageQueue之前,我們再看一些有意思的代碼:


static?void?android_os_MessageQueue_setNativeMessageQueue(JNIEnv*?env,?jobject?messageQueueObj,
????????NativeMessageQueue*?nativeMessageQueue)?{
????env->SetIntField(messageQueueObj,?gMessageQueueClassInfo.mPtr,
?????????????reinterpret_cast(nativeMessageQueue));//把nativeMessageQueue的實例地址強轉為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);
//這個函數(shù)在Android啟動的時候,會被系統(tǒng)調用
int?register_android_os_MessageQueue(JNIEnv*?env)?{
????int?res?=?jniRegisterNativeMethods(env,?"android/os/MessageQueue",
????????????gMessageQueueMethods,?NELEM(gMessageQueueMethods));//關聯(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ù)實際上把android.os.MessageQueue實例的mPtr值設置為nativeMessageQueue實例的地址。雖然Java語言沒有指針的說法,但是,這里的mPtr卻的的確確是作為一個指針使用的。現(xiàn)在,我們也就理解了,為什么mPtr可以被強制轉換為nativeMessageQueue了。


? ? 小結:


android_os_MessageQueue_nativeInit和android_os_MessageQueue_nativeDestory兩個函數(shù)做了些什么:


android_os_MessageQueue_nativeInit:構造NativeMessageQueue實例android_os_MessageQueue_nativeDestory:銷毀NativeMessageQeue實例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哦),關于MessageQueue我們只需要了解,它包含了一個成員mLooper即可(有興趣的同學可以查看/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);//實例化mLooper
????????Looper::setForThread(mLooper);
????}
}

? ? NativeMessageQueue構造實例的時候,會實例化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();
}

? ? 小結:


NativeMessageQueue的函數(shù)pollonce和wake實現(xià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();
};

? ? 因為代碼有點多,所以上面的聲明,已經(jīng)被我精簡了大部分,現(xiàn)在我們只關注我們關心的:pollonce和wake函數(shù)。


? ? 還是從構造函數(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);//設置為非阻塞模式
????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,實現(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)聽隊列中
????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的構造函數(shù)中,出現(xiàn)了命名管道和epoll相關的代碼,這是為什么呢?別急,接著看下去就知道了:

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等數(shù)據(jù)給調用者處理
????????????????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);//這一行才是重點!
????}
}

? ? 接著往下看,代碼有些長,但請仔細看:

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();//讀取命名管道內的數(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);//調用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);//調用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;
}

? ? 代碼比較長,所以分段分析:

????//?設置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相關的代碼:

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
}

? ? 是不是覺得上面的代碼似曾相識?和Java層的MessageQueue很像似有木有?和java層一樣,C++層存在消息隊列和消息處理機制,消息被保存到成員mMessageEvelopes中,并在pollInner函數(shù)中處理消息(調用MesageHandler的handleMesage函數(shù)處理)。

? ? 現(xiàn)在回到Looper::pollonceh函數(shù),我們就應該能夠理解,pollOnce函數(shù)到timeOutMillis參數(shù)僅僅代表了Java層下一個Message的觸發(fā)延遲,所以,我們還需要考慮C++層下一個Message的觸發(fā)延遲,所以,代碼設置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();

? ? 調用epoll函數(shù),等待event發(fā)生,epoll_wait函數(shù)的返回值有三種可能:失敗出錯、沒有event、有一個或多個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();//讀取命名管道內的數(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的時候,需要分為兩類:fd==mWakeReadPipeFd和fd!=mWakeReadPipeFd

fd==mWakeReadPipeFd:說明C++層,或者java層有新的Message出現(xiàn),需要處理。這種情況下,只需要讀mWakeReadPipeFd內的數(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)?{//僅當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函數(shù),可以向Looper的mEpollFd添加指定的Fd,當Fd觸發(fā)指定的event .e.i ?EPOLLIN or EPOLLOUT時,指定的相應的自定義callback就會得到執(zhí)行。

? ?另外,當Looper支持noncallback時,還可以向Looper添加callback為null的Fd,因為沒有callback,所以Fd添加者需要調用int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) 通過outFd、outEvent、outData參數(shù)獲取數(shù)據(jù)并進行處理。

? ? 所以當Fd觸發(fā)消息時,需要生成對應到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ù)返回的三種結果的不同處理已經(jīng)解析完畢,接下來代碼進入共同的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);//調用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);//調用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中寫入一個字符,所以mWakeReadPipeFd就會觸發(fā)EPOLLIN?event
????}?while?(nWrite?==?-1?&&?errno?==?EINTR);

????if?(nWrite?!=?1)?{
????????if?(errno?!=?EAGAIN)?{
????????????ALOGW("Could?not?write?wake?signal,?errno=%d",?errno);
????????}
????}
}

? ? 小結: Looper通過epoll函數(shù)組實現(xiàn)了一個可以支持隨時喚醒的阻塞機制Looper支持兩種不同的方式處理消息:Message + MessageHandler 和 LooperCallback。Looper的阻塞在如下四種條件下會被喚醒: 發(fā)生錯誤等待超時出現(xiàn)需要處理的新Message(包括C++層和Java層)由addFd函數(shù)添加的Fd觸發(fā)event


?

總結:



在哪個線程調用JAVA層的Looper.loop(),Mesage和callback(包括Java層和C++層)就在哪個線程被處理,上圖為Looper.loop函數(shù)的時序圖。C++層的NativeMesasgeQueue不應該是Java層的MesageQueue的內部實現(xiàn),而更接近于“欒生兄弟”的關系。MessageQueue負責處理java層上到消息,NativeMessageQueue負責處理C++層上的消息。其中Java層是在android.os.Looper.looper函數(shù)中調用android.os.Handler.dispatchMessage處理,而C++層是在android::Looper::pollInner函數(shù)中調用android::MessageHandler::handleMessage & android:LooperCallback::handleEvent函數(shù)處理。NativeMessageQueue利用Looper類實現(xiàn)了一個基于epoll函數(shù)和文件描述符(Fd)的可喚醒的阻塞機制。

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

LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅動性能的關鍵。

關鍵字: 工業(yè)電機 驅動電源

LED 驅動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅動電源 照明系統(tǒng) 散熱

根據(jù)LED驅動電源的公式,電感內電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質量和效率直接關系到城市的公共安全、居民生活質量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅動電源 功率因數(shù)校正

在LED照明技術日益普及的今天,LED驅動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅動電源

關鍵字: LED 驅動電源 開關電源

LED驅動電源是把電源供應轉換為特定的電壓電流以驅動LED發(fā)光的電壓轉換器,通常情況下:LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅動電源
關閉