Android訊息機制不完全解析(下) .
轉自:http://blog.csdn.net/a220315410/article/details/10444171
首先,看看在/frameworks/base/core/jni/android_os_MessageQueue.cpp檔案中看看android.os.MessageQueue類中的四個原生函式的實現:
- static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) {
- NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();//構造NativeMessageQueue例項
- if (!nativeMessageQueue) {
- jniThrowRuntimeException(env, "Unable to allocate native queue");
- return;
- }
- nativeMessageQueue->incStrong(env);//強引用+1
- android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);
- }
- static void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jobject obj) {
- NativeMessageQueue* nativeMessageQueue =
- android_os_MessageQueue_getNativeMessageQueue(env, obj);
- if (nativeMessageQueue) {
- android_os_MessageQueue_setNativeMessageQueue(env, obj, NULL);
- nativeMessageQueue->decStrong(env);//強引用-1,實際上會導致釋放NativeMessageQueue例項
- }
- }
- static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
- jint ptr, jint timeoutMillis) {
- NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);//指標強制轉換
- nativeMessageQueue->pollOnce(env, timeoutMillis);//呼叫nativeMessageQueue的pollonce函式
- }
- static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) {
- NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
- return nativeMessageQueue->wake();//呼叫nativeMessageQueue的wake函式
- }
static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) {
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();//構造NativeMessageQueue例項
if (!nativeMessageQueue) {
jniThrowRuntimeException(env, "Unable to allocate native queue");
return;
}
nativeMessageQueue->incStrong(env);//強引用+1
android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);
}
static void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jobject obj) {
NativeMessageQueue* nativeMessageQueue =
android_os_MessageQueue_getNativeMessageQueue(env, obj);
if (nativeMessageQueue) {
android_os_MessageQueue_setNativeMessageQueue(env, obj, NULL);
nativeMessageQueue->decStrong(env);//強引用-1,實際上會導致釋放NativeMessageQueue例項
}
}
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
jint ptr, jint timeoutMillis) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);//指標強制轉換
nativeMessageQueue->pollOnce(env, timeoutMillis);//呼叫nativeMessageQueue的pollonce函式
}
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
return nativeMessageQueue->wake();//呼叫nativeMessageQueue的wake函式
}
從程式碼中,可以看到這四個函式的實現都是依賴於NativeMessageQueue類。不過,在開始解析NativeMessageQueue之前,我們再看一些有意思的程式碼:
- static void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject messageQueueObj,
- NativeMessageQueue* nativeMessageQueue) {
- env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr,
- reinterpret_cast<jint>(nativeMessageQueue));//把nativeMessageQueue的例項地址強轉為java的int型別並儲存到gMessageQueueClassInfo.mPtr中
- }
static void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject messageQueueObj,
NativeMessageQueue* nativeMessageQueue) {
env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr,
reinterpret_cast<jint>(nativeMessageQueue));//把nativeMessageQueue的例項地址強轉為java的int型別並儲存到gMessageQueueClassInfo.mPtr中
}
那麼gMessageQueueClassInfo.mPtr是什麼呢?
- static JNINativeMethod gMessageQueueMethods[] = {
- /* name, signature, funcPtr */
- { "nativeInit", "()V", (void*)android_os_MessageQueue_nativeInit },
- { "nativeDestroy", "()V", (void*)android_os_MessageQueue_nativeDestroy },
- { "nativePollOnce", "(II)V", (void*)android_os_MessageQueue_nativePollOnce },
- { "nativeWake", "(I)V", (void*)android_os_MessageQueue_nativeWake }
- };
- #define FIND_CLASS(var, className) \
- var = env->FindClass(className); \
- LOG_FATAL_IF(! var, "Unable to find class " className);
- #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
- var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
- LOG_FATAL_IF(! var, "Unable to find field " fieldName);
- //這個函式在Android啟動的時候,會被系統呼叫
- int register_android_os_MessageQueue(JNIEnv* env) {
- int res = jniRegisterNativeMethods(env, "android/os/MessageQueue",
- gMessageQueueMethods, NELEM(gMessageQueueMethods));//關聯MessageQueueQueue的原生函式
- LOG_FATAL_IF(res < 0, "Unable to register native methods.");
- jclass clazz;
- FIND_CLASS(clazz, "android/os/MessageQueue");//獲取MessageQueue的class
- GET_FIELD_ID(gMessageQueueClassInfo.mPtr, clazz,
- "mPtr", "I");//獲取MessageQueue class的mPtr field的Id
- return 0;
- }
static JNINativeMethod gMessageQueueMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit", "()V", (void*)android_os_MessageQueue_nativeInit },
{ "nativeDestroy", "()V", (void*)android_os_MessageQueue_nativeDestroy },
{ "nativePollOnce", "(II)V", (void*)android_os_MessageQueue_nativePollOnce },
{ "nativeWake", "(I)V", (void*)android_os_MessageQueue_nativeWake }
};
#define FIND_CLASS(var, className) \
var = env->FindClass(className); \
LOG_FATAL_IF(! var, "Unable to find class " className);
#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
LOG_FATAL_IF(! var, "Unable to find field " fieldName);
//這個函式在Android啟動的時候,會被系統呼叫
int register_android_os_MessageQueue(JNIEnv* env) {
int res = jniRegisterNativeMethods(env, "android/os/MessageQueue",
gMessageQueueMethods, NELEM(gMessageQueueMethods));//關聯MessageQueueQueue的原生函式
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
jclass clazz;
FIND_CLASS(clazz, "android/os/MessageQueue");//獲取MessageQueue的class
GET_FIELD_ID(gMessageQueueClassInfo.mPtr, clazz,
"mPtr", "I");//獲取MessageQueue class的mPtr field的Id
return 0;
}
上面的程式碼很像java的反射有木有?
- Class cls = Class.forName("android.os.MessageQueue");
- Field feild = cls.getField("mPtr");
Class cls = Class.forName("android.os.MessageQueue");
Field feild = cls.getField("mPtr");
到這裡,我們就明白了android_os_MessageQueue_setNativeMessageQueue函式實際上把android.os.MessageQueue例項的mPtr值設定為nativeMessageQueue例項的地址。雖然Java語言沒有指標的說法,但是,這裡的mPtr卻的的確確是作為一個指標使用的。現在,我們也就理解了,為什麼mPtr可以被強制轉換為nativeMessageQueue了。
小結:
- android_os_MessageQueue_nativeInit和android_os_MessageQueue_nativeDestory兩個函式做了些什麼:
- android_os_MessageQueue_nativeInit:構造NativeMessageQueue例項
- android_os_MessageQueue_nativeDestory:銷燬NativeMessageQeue例項
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;
- };
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:
- sp<Looper> mLooper;
- };
class MessageQueue {
......
protected:
sp<Looper> mLooper;
};
繼續看NativeMessageQueue的程式碼:
- NativeMessageQueue::NativeMessageQueue() : mInCallback(false), mExceptionObj(NULL) {
- mLooper = Looper::getForThread();
- if (mLooper == NULL) {
- mLooper = new Looper(false);//例項化mLooper
- Looper::setForThread(mLooper);
- }
- }
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();
- }
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的函式pollonce和wake實現相當簡單,交給mLooper的同名函式。
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();
- };
class Looper : public ALooper, public RefBase {
protected:
virtual ~Looper();
public:
Looper(bool allowNonCallbacks);
bool getAllowNonCallbacks() const;
int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
inline int pollOnce(int timeoutMillis) {
return pollOnce(timeoutMillis, NULL, NULL, NULL);
}
void wake();
private:
const bool mAllowNonCallbacks; // immutable
int mWakeReadPipeFd; // immutable
int mWakeWritePipeFd; // immutable
Mutex mLock;
int mEpollFd; // immutable
int pollInner(int timeoutMillis);
void awoken();
};
因為程式碼有點多,所以上面的宣告,已經被我精簡了大部分,現在我們只關注我們關心的:pollonce和wake函式。
還是從建構函式開始(frameworks/native/utils/Looper.cpp):
- Looper::Looper(bool allowNonCallbacks) :
- mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
- mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
- int wakeFds[2];
- int result = pipe(wakeFds);//建立命名管道
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
- // 儲存命名管道
- mWakeReadPipeFd = wakeFds[0];
- mWakeWritePipeFd = wakeFds[1];
- result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);//設定為非阻塞模式
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
- errno);
- result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);//設定為非阻塞模式
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
- errno);
- // 開始使用epoll API,實現輪詢
- // Allocate the epoll instance and register the wake pipe.
- mEpollFd = epoll_create(EPOLL_SIZE_HINT);//建立epoll檔案描述符
- LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
- struct epoll_event eventItem;
- memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
- eventItem.events = EPOLLIN;
- eventItem.data.fd = mWakeReadPipeFd;
- result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); // 把剛才建立的命名管道的讀端加入的到epoll的監聽佇列中
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",
- errno);
- }
- Looper::~Looper() {
- close(mWakeReadPipeFd);//釋放命名管道
- close(mWakeWritePipeFd);
- close(mEpollFd);//釋放epoll檔案描述符
- }
Looper::Looper(bool allowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
int wakeFds[2];
int result = pipe(wakeFds);//建立命名管道
LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
// 儲存命名管道
mWakeReadPipeFd = wakeFds[0];
mWakeWritePipeFd = wakeFds[1];
result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);//設定為非阻塞模式
LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
errno);
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);//設定為非阻塞模式
LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
errno);
// 開始使用epoll API,實現輪詢
// Allocate the epoll instance and register the wake pipe.
mEpollFd = epoll_create(EPOLL_SIZE_HINT);//建立epoll檔案描述符
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
struct epoll_event eventItem;
memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
eventItem.events = EPOLLIN;
eventItem.data.fd = mWakeReadPipeFd;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); // 把剛才建立的命名管道的讀端加入的到epoll的監聽佇列中
LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",
errno);
}
Looper::~Looper() {
close(mWakeReadPipeFd);//釋放命名管道
close(mWakeWritePipeFd);
close(mEpollFd);//釋放epoll檔案描述符
}
Looper的建構函式中,出現了命名管道和epoll相關的程式碼,這是為什麼呢?別急,接著看下去就知道了:
- int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
- int result = 0;
- for (;;) {
- // 這段程式碼暫時無視
- while (mResponseIndex < mResponses.size()) {
- const Response& response = mResponses.itemAt(mResponseIndex++);
- int ident = response.request.ident;
- if (ident >= 0) {//ident > 0, 即此response為noncallback,需要返回event,data等資料給呼叫者處理
- int fd = response.request.fd;
- int events = response.events;
- void* data = response.request.data;
- #if DEBUG_POLL_AND_WAKE
- ALOGD("%p ~ pollOnce - returning signalled identifier %d: "
- "fd=%d, events=0x%x, data=%p",
- this, ident, fd, events, data);
- #endif
- if (outFd != NULL) *outFd = fd;
- if (outEvents != NULL) *outEvents = events;
- if (outData != NULL) *outData = data;
- return ident;
- }
- }
- if (result != 0) {
- #if DEBUG_POLL_AND_WAKE
- ALOGD("%p ~ pollOnce - returning result %d", this, result);
- #endif
- if (outFd != NULL) *outFd = 0;
- if (outEvents != NULL) *outEvents = 0;
- if (outData != NULL) *outData = NULL;
- return result;
- }
- result = pollInner(timeoutMillis);//這一行才是重點!
- }
- }
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
int result = 0;
for (;;) {
// 這段程式碼暫時無視
while (mResponseIndex < mResponses.size()) {
const Response& response = mResponses.itemAt(mResponseIndex++);
int ident = response.request.ident;
if (ident >= 0) {//ident > 0, 即此response為noncallback,需要返回event,data等資料給呼叫者處理
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ pollOnce - returning signalled identifier %d: "
"fd=%d, events=0x%x, data=%p",
this, ident, fd, events, data);
#endif
if (outFd != NULL) *outFd = fd;
if (outEvents != NULL) *outEvents = events;
if (outData != NULL) *outData = data;
return ident;
}
}
if (result != 0) {
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ pollOnce - returning result %d", this, result);
#endif
if (outFd != NULL) *outFd = 0;
if (outEvents != NULL) *outEvents = 0;
if (outData != NULL) *outData = NULL;
return result;
}
result = pollInner(timeoutMillis);//這一行才是重點!
}
}
接著往下看,程式碼有些長,但請仔細看:
- int Looper::pollInner(int timeoutMillis) {
- #if DEBUG_POLL_AND_WAKE
- ALOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
- #endif
- // 設定timeoutMillis的值為Math.min(timeoutMills, mNextMessageUptime)
- // Adjust the timeout based on when the next message is due.
- if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
- if (messageTimeoutMillis >= 0
- && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
- timeoutMillis = messageTimeoutMillis;
- }
- #if DEBUG_POLL_AND_WAKE
- ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
- this, mNextMessageUptime - now, timeoutMillis);
- #endif
- }
- // Poll.
- int result = ALOOPER_POLL_WAKE;
- mResponses.clear();
- mResponseIndex = 0;
- // 開始輪詢
- struct epoll_event eventItems[EPOLL_MAX_EVENTS];
- int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
- // Acquire lock.
- mLock.lock();
- // Check for poll error.
- if (eventCount < 0) { //處理error
- if (errno == EINTR) {
- goto Done;
- }
- ALOGW("Poll failed with an unexpected error, errno=%d", errno);
- result = ALOOPER_POLL_ERROR;
- goto Done;
- }
- // Check for poll timeout.
- if (eventCount == 0) { // 未能等到event,故timeout
- #if DEBUG_POLL_AND_WAKE
- ALOGD("%p ~ pollOnce - timeout", this);
- #endif
- result = ALOOPER_POLL_TIMEOUT;
- goto Done;
- }
- // Handle all events.
- #if DEBUG_POLL_AND_WAKE
- ALOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
- #endif
- for (int i = 0; i < eventCount; i++) {//有event,則處理
- int fd = eventItems[i].data.fd;
- uint32_t epollEvents = eventItems[i].events;
- if (fd == mWakeReadPipeFd) {
- if (epollEvents & EPOLLIN) {
- awoken();//讀取命名管道內的資料
- } else {
- ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
- }
- } else {
- ssize_t requestIndex = mRequests.indexOfKey(fd);
- if (requestIndex >= 0) {
- int events = 0;
- if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
- if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
- if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
- if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
- pushResponse(events, mRequests.valueAt(requestIndex));//把event新增到<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses中,等待後續處理</SPAN>
- } else {
- ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
- "no longer registered.", epollEvents, fd);
- }
- }
- }
- Done: ;
- // 處理C++層的Message
- // Invoke pending message callbacks.
- mNextMessageUptime = LLONG_MAX;
- while (mMessageEnvelopes.size() != 0) {
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
- if (messageEnvelope.uptime <= now) {
- // Remove the envelope from the list.
- // We keep a strong reference to the handler until the call to handleMessage
- // finishes. Then we drop it so that the handler can be deleted *before*
- // we reacquire our lock.
- { // obtain handler
- sp<MessageHandler> handler = messageEnvelope.handler;
- Message message = messageEnvelope.message;
- mMessageEnvelopes.removeAt(0);
- mSendingMessage = true;
- mLock.unlock();
- #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
- ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
- this, handler.get(), message.what);
- #endif
- handler->handleMessage(message);//呼叫handler-><SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">handleMessage</SPAN>
- } // release handler
- mLock.lock();
- mSendingMessage = false;
- result = ALOOPER_POLL_CALLBACK;
- } else {
- // The last message left at the head of the queue determines the next wakeup time.
- mNextMessageUptime = messageEnvelope.uptime;//更新<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">mNextMessageUptime</SPAN>
- break;
- }
- }
- // Release lock.
- mLock.unlock();
- // 處理<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses</SPAN>
- // Invoke all response callbacks.
- for (size_t i = 0; i < mResponses.size(); i++) {
- Response& response = mResponses.editItemAt(i);
- if (response.request.ident == ALOOPER_POLL_CALLBACK) {
- int fd = response.request.fd;
- int events = response.events;
- void* data = response.request.data;
- #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
- ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
- this, response.request.callback.get(), fd, events, data);
- #endif
- int callbackResult = response.request.callback->handleEvent(fd, events, data);//呼叫callback->handleEvent
- if (callbackResult == 0) {
- removeFd(fd);
- }
- // Clear the callback reference in the response structure promptly because we
- // will not clear the response vector itself until the next poll.
- response.request.callback.clear();
- result = ALOOPER_POLL_CALLBACK;
- }
- }
- return result;
- }
int Looper::pollInner(int timeoutMillis) {
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
#endif
// 設定timeoutMillis的值為Math.min(timeoutMills, mNextMessageUptime)
// Adjust the timeout based on when the next message is due.
if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
if (messageTimeoutMillis >= 0
&& (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
timeoutMillis = messageTimeoutMillis;
}
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
this, mNextMessageUptime - now, timeoutMillis);
#endif
}
// Poll.
int result = ALOOPER_POLL_WAKE;
mResponses.clear();
mResponseIndex = 0;
// 開始輪詢
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
// Acquire lock.
mLock.lock();
// Check for poll error.
if (eventCount < 0) { //處理error
if (errno == EINTR) {
goto Done;
}
ALOGW("Poll failed with an unexpected error, errno=%d", errno);
result = ALOOPER_POLL_ERROR;
goto Done;
}
// Check for poll timeout.
if (eventCount == 0) { // 未能等到event,故timeout
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ pollOnce - timeout", this);
#endif
result = ALOOPER_POLL_TIMEOUT;
goto Done;
}
// Handle all events.
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
#endif
for (int i = 0; i < eventCount; i++) {//有event,則處理
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
if (fd == mWakeReadPipeFd) {
if (epollEvents & EPOLLIN) {
awoken();//讀取命名管道內的資料
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
}
} else {
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex >= 0) {
int events = 0;
if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
pushResponse(events, mRequests.valueAt(requestIndex));//把event新增到<span style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses中,等待後續處理</span>
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
"no longer registered.", epollEvents, fd);
}
}
}
Done: ;
// 處理C++層的Message
// Invoke pending message callbacks.
mNextMessageUptime = LLONG_MAX;
while (mMessageEnvelopes.size() != 0) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
if (messageEnvelope.uptime <= now) {
// Remove the envelope from the list.
// We keep a strong reference to the handler until the call to handleMessage
// finishes. Then we drop it so that the handler can be deleted *before*
// we reacquire our lock.
{ // obtain handler
sp<MessageHandler> handler = messageEnvelope.handler;
Message message = messageEnvelope.message;
mMessageEnvelopes.removeAt(0);
mSendingMessage = true;
mLock.unlock();
#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
this, handler.get(), message.what);
#endif
handler->handleMessage(message);//呼叫handler-><span style="FONT-FAMILY: Arial, Helvetica, sans-serif">handleMessage</span>
} // release handler
mLock.lock();
mSendingMessage = false;
result = ALOOPER_POLL_CALLBACK;
} else {
// The last message left at the head of the queue determines the next wakeup time.
mNextMessageUptime = messageEnvelope.uptime;//更新<span style="FONT-FAMILY: Arial, Helvetica, sans-serif">mNextMessageUptime</span>
break;
}
}
// Release lock.
mLock.unlock();
// 處理<span style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses</span>
// Invoke all response callbacks.
for (size_t i = 0; i < mResponses.size(); i++) {
Response& response = mResponses.editItemAt(i);
if (response.request.ident == ALOOPER_POLL_CALLBACK) {
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
this, response.request.callback.get(), fd, events, data);
#endif
int callbackResult = response.request.callback->handleEvent(fd, events, data);//呼叫callback->handleEvent
if (callbackResult == 0) {
removeFd(fd);
}
// Clear the callback reference in the response structure promptly because we
// will not clear the response vector itself until the next poll.
response.request.callback.clear();
result = ALOOPER_POLL_CALLBACK;
}
}
return result;
}
程式碼比較長,所以分段分析:
- // 設定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);
- if
- }
// 設定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 sp<MessageHandler> handler,const Message& message) : uptime(uptime), handler(handler), message(message) {}
- nsecs_t uptime;
- MessageHandler> handler;
- Message message;
- };
- void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- sendMessageAtTime(now, handler, message);
- }
- void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
- const Message& message) {
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- sendMessageAtTime(now + uptimeDelay, handler, message);
- }
- void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
- const Message& message) {
- #if DEBUG_CALLBACKS
- ALOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d",
- this, uptime, handler.get(), message.what);
- #endif
- size_t i = 0;
- { // acquire lock
- AutoMutex _l(mLock);
- size_t messageCount = mMessageEnvelopes.size();
- while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {
- i += 1;
- }
- MessageEnvelope messageEnvelope(uptime, handler, message);
- mMessageEnvelopes.insertAt(messageEnvelope, i, 1);
- // Optimization: If the Looper is currently sending a message, then we can skip
- // the call to wake() because the next thing the Looper will do after processing
- // messages is to decide when the next wakeup time should be. In fact, it does
- // not even matter whether this code is running on the Looper thread.
- if (mSendingMessage) {
- return;
- }
- } // release lock
- // Wake the poll loop only when we enqueue a new message at the head.
- if (i == 0) {
- wake();
- }
- }
- void Looper::removeMessages(const sp<MessageHandler>& handler) {
- #if DEBUG_CALLBACKS
- ALOGD("%p ~ removeMessages - handler=%p", this, handler.get());
- #endif
- { // acquire lock
- AutoMutex _l(mLock);
- for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
- const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
- if (messageEnvelope.handler == handler) {
- mMessageEnvelopes.removeAt(i);
- }
- }
- } // release lock
- }
- void Looper::removeMessages(const sp<MessageHandler>& handler, int what) {
- #if DEBUG_CALLBACKS
- ALOGD("%p ~ removeMessages - handler=%p, what=%d", this, handler.get(), what);
- #endif
- { // acquire lock
- AutoMutex _l(mLock);
- for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
- const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
- if (messageEnvelope.handler == handler
- && messageEnvelope.message.what == what) {
- mMessageEnvelopes.removeAt(i);
- }
- }
- } // release lock
- }
struct Message {
Message() : what(0) { }
Message(int what) : what(what) { }
/* The message type. (interpretation is left up to the handler) */
int what;
};
class MessageHandler : public virtual RefBase {
protected:
virtual ~MessageHandler() { }
public:
/**
* Handles a message.
*/
virtual void handleMessage(const Message& message) = 0;
}
struct MessageEnvelope {
MessageEnvelope() : uptime(0) { }
MessageEnvelope(nsecs_t uptime, const sp<MessageHandler> handler,const Message& message) : uptime(uptime), handler(handler), message(message) {}
nsecs_t uptime;
MessageHandler> handler;
Message message;
};
void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
sendMessageAtTime(now, handler, message);
}
void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
const Message& message) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
sendMessageAtTime(now + uptimeDelay, handler, message);
}
void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
const Message& message) {
#if DEBUG_CALLBACKS
ALOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d",
this, uptime, handler.get(), message.what);
#endif
size_t i = 0;
{ // acquire lock
AutoMutex _l(mLock);
size_t messageCount = mMessageEnvelopes.size();
while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {
i += 1;
}
MessageEnvelope messageEnvelope(uptime, handler, message);
mMessageEnvelopes.insertAt(messageEnvelope, i, 1);
// Optimization: If the Looper is currently sending a message, then we can skip
// the call to wake() because the next thing the Looper will do after processing
// messages is to decide when the next wakeup time should be. In fact, it does
// not even matter whether this code is running on the Looper thread.
if (mSendingMessage) {
return;
}
} // release lock
// Wake the poll loop only when we enqueue a new message at the head.
if (i == 0) {
wake();
}
}
void Looper::removeMessages(const sp<MessageHandler>& handler) {
#if DEBUG_CALLBACKS
ALOGD("%p ~ removeMessages - handler=%p", this, handler.get());
#endif
{ // acquire lock
AutoMutex _l(mLock);
for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
if (messageEnvelope.handler == handler) {
mMessageEnvelopes.removeAt(i);
}
}
} // release lock
}
void Looper::removeMessages(const sp<MessageHandler>& handler, int what) {
#if DEBUG_CALLBACKS
ALOGD("%p ~ removeMessages - handler=%p, what=%d", this, handler.get(), what);
#endif
{ // acquire lock
AutoMutex _l(mLock);
for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
if (messageEnvelope.handler == handler
&& messageEnvelope.message.what == what) {
mMessageEnvelopes.removeAt(i);
}
}
} // release lock
}
是不是覺得上面的程式碼似曾相識?和Java層的MessageQueue很像似有木有?和java層一樣,C++層存在訊息佇列和訊息處理機制,訊息被儲存到成員mMessageEvelopes中,並在pollInner函式中處理訊息(呼叫MesageHandler的handleMesage函式處理)。
現在回到Looper::pollonceh函式,我們就應該能夠理解,pollOnce函式到timeOutMillis引數僅僅代表了Java層下一個Message的觸發延遲,所以,我們還需要考慮C++層下一個Message的觸發延遲,所以,程式碼設定timeoutMillis為timeoutMillis和mNextMessageUpTime中的較小值。
繼續下一段程式碼:
- 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();
int result = ALOOPER_POLL_WAKE;
mResponses.clear();
mResponseIndex = 0;
// 開始輪詢
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
// Acquire lock.
mLock.lock();
呼叫epoll函式,等待event發生,epoll_wait函式的返回值有三種可能:失敗出錯、沒有event、有一個或多個event。
1. 失敗的處理:
- // 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 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發生:
- // 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;
- }
// 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發生:
- // Handle all events.
- DEBUG_POLL_AND_WAKE
- ALOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
- if
- for (int i = 0; i < eventCount; i++) {//有event,則處理
- int fd = eventItems[i].data.fd;
- uint32_t epollEvents = eventItems[i].events;
- if (fd == mWakeReadPipeFd) {//說明java層或者C++層有新的Message
- if (epollEvents & EPOLLIN) {
- awoken();//讀取命名管道內的資料
- } else {
- ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
- }
- } else {
- ssize_t requestIndex = mRequests.indexOfKey(fd);
- if (requestIndex >= 0) {
- int events = 0;
- if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
- if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
- if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
- if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
- pushResponse(events, mRequests.valueAt(requestIndex));//把event新增到<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses中,等待後續處理</SPAN>
- } else {
- ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
- "no longer registered.", epollEvents, fd);
- }
- }
- }
// Handle all events.
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
#endif
for (int i = 0; i < eventCount; i++) {//有event,則處理
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
if (fd == mWakeReadPipeFd) {//說明java層或者C++層有新的Message
if (epollEvents & EPOLLIN) {
awoken();//讀取命名管道內的資料
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
}
} else {
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex >= 0) {
int events = 0;
if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
pushResponse(events, mRequests.valueAt(requestIndex));//把event新增到<span style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses中,等待後續處理</span>
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
"no longer registered.", epollEvents, fd);
}
}
}
處理event的時候,需要分為兩類:fd==mWakeReadPipeFd和fd!=mWakeReadPipeFd
fd==mWakeReadPipeFd:說明C++層,或者java層有新的Message出現,需要處理。這種情況下,只需要讀mWakeReadPipeFd內的資料即可
- 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));
- }
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;
- sp<LooperCallback> callback;
- void* data;
- };
- struct Response {
- int events;
- Request request;
- };
struct Request {
int fd;
int ident;
sp<LooperCallback> callback;
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;
- };
/**
* 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<LooperCallback>& callback, void* data) {
- #if DEBUG_CALLBACKS
- ALOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,
- events, callback.get(), data);
- #endif
- if (!callback.get()) {
- if (! mAllowNonCallbacks) {
- ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
- return -1;
- }
- if (ident < 0) {//僅當Looper支援NonCallbacks,並且ident大於0時,允許新增callback為null的Fd
- ALOGE("Invalid attempt to set NULL callback with ident < 0.");
- return -1;
- }
- } else {
- ident = ALOOPER_POLL_CALLBACK;
- }
- int epollEvents = 0;
- if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
- if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;
- { // acquire lock
- AutoMutex _l(mLock);
- Request request;
- request.fd = fd;
- request.ident = ident;
- request.callback = callback;
- request.data = data;
- struct epoll_event eventItem;
- memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
- eventItem.events = epollEvents;
- eventItem.data.fd = fd;
- ssize_t requestIndex = mRequests.indexOfKey(fd);
- if (requestIndex < 0) {
- int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
- if (epollResult < 0) {
- ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
- return -1;
- }
- mRequests.add(fd, request);
- } else {//存在則替換
- int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
- if (epollResult < 0) {
- ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
- return -1;
- }
- mRequests.replaceValueAt(requestIndex, request);
- }
- } // release lock
- return 1;
- }
int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
#if DEBUG_CALLBACKS
ALOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,
events, callback.get(), data);
#endif
if (!callback.get()) {
if (! mAllowNonCallbacks) {
ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
return -1;
}
if (ident < 0) {//僅當Looper支援NonCallbacks,並且ident大於0時,允許新增callback為null的Fd
ALOGE("Invalid attempt to set NULL callback with ident < 0.");
return -1;
}
} else {
ident = ALOOPER_POLL_CALLBACK;
}
int epollEvents = 0;
if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;
{ // acquire lock
AutoMutex _l(mLock);
Request request;
request.fd = fd;
request.ident = ident;
request.callback = callback;
request.data = data;
struct epoll_event eventItem;
memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
eventItem.events = epollEvents;
eventItem.data.fd = fd;
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex < 0) {
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
if (epollResult < 0) {
ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
return -1;
}
mRequests.add(fd, request);
} else {//存在則替換
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
if (epollResult < 0) {
ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
return -1;
}
mRequests.replaceValueAt(requestIndex, request);
}
} // release lock
return 1;
}
從上面的程式碼,我們可知,Looper還支援新增Fd和自定義的callback,類似java層的Message.callback。
通過addFd函式,可以向Looper的mEpollFd新增指定的Fd,當Fd觸發指定的event .e.i EPOLLIN or EPOLLOUT時,指定的相應的自定義callback就會得到執行。
另外,當Looper支援noncallback時,還可以向Looper新增callback為null的Fd,因為沒有callback,所以Fd新增者需要呼叫int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) 通過outFd、outEvent、outData引數獲取資料並進行處理。
所以當Fd觸發訊息時,需要生成對應到reponse並新增到meResponses中,等待後續的處理。
- void Looper::pushResponse(int events, const Request& request) {
- Response response;
- response.events = events;
- response.request = request;
- mResponses.push(response);
- }
void Looper::pushResponse(int events, const Request& request) {
Response response;
response.events = events;
response.request = request;
mResponses.push(response);
}
到這裡為止,epoll_wait函式返回的三種結果的不同處理已經解析完畢,接下來程式碼進入共同的Done環節。
處理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
- sp<MessageHandler> handler = messageEnvelope.handler;
- Message message = messageEnvelope.message;
- mMessageEnvelopes.removeAt(0);
- mSendingMessage = true;
- mLock.unlock();
- #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
- ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
- this, handler.get(), message.what);
- #endif
- handler->handleMessage(message);//呼叫handler-><SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">handleMessage</SPAN>
- } // release handler
- mLock.lock();
- mSendingMessage = false;
- result = ALOOPER_POLL_CALLBACK;
- } else {
- // The last message left at the head of the queue determines the next wakeup time.
- mNextMessageUptime = messageEnvelope.uptime;//更新<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">mNextMessageUptime</SPAN>
- break;
- }
- }
Done: ;
// 處理C++層的Message
// Invoke pending message callbacks.
mNextMessageUptime = LLONG_MAX;
while (mMessageEnvelopes.size() != 0) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
if (messageEnvelope.uptime <= now) {
// Remove the envelope from the list.
// We keep a strong reference to the handler until the call to handleMessage
// finishes. Then we drop it so that the handler can be deleted *before*
// we reacquire our lock.
{ // obtain handler
sp<MessageHandler> handler = messageEnvelope.handler;
Message message = messageEnvelope.message;
mMessageEnvelopes.removeAt(0);
mSendingMessage = true;
mLock.unlock();
#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
this, handler.get(), message.what);
#endif
handler->handleMessage(message);//呼叫handler-><span style="FONT-FAMILY: Arial, Helvetica, sans-serif">handleMessage</span>
} // release handler
mLock.lock();
mSendingMessage = false;
result = ALOOPER_POLL_CALLBACK;
} else {
// The last message left at the head of the queue determines the next wakeup time.
mNextMessageUptime = messageEnvelope.uptime;//更新<span style="FONT-FAMILY: Arial, Helvetica, sans-serif">mNextMessageUptime</span>
break;
}
}
處理Response:
- // 處理<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses</SPAN>
- // Invoke all response callbacks.
- for (size_t i = 0; i < mResponses.size(); i++) {
- Response& response = mResponses.editItemAt(i);
- if (response.request.ident == ALOOPER_POLL_CALLBACK) {
- int fd = response.request.fd;
- int events = response.events;
- void* data = response.request.data;
- #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
- ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
- this, response.request.callback.get(), fd, events, data);
- #endif
- int callbackResult = response.request.callback->handleEvent(fd, events, data);//呼叫callback->handleEvent
- if (callbackResult == 0) {
- removeFd(fd);
- }
- // Clear the callback reference in the response structure promptly because we
- // will not clear the response vector itself until the next poll.
- response.request.callback.clear();
- result = ALOOPER_POLL_CALLBACK;
- }
- }
// 處理<span style="FONT-FAMILY: Arial, Helvetica, sans-serif">mResponses</span>
// Invoke all response callbacks.
for (size_t i = 0; i < mResponses.size(); i++) {
Response& response = mResponses.editItemAt(i);
if (response.request.ident == ALOOPER_POLL_CALLBACK) {
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
this, response.request.callback.get(), fd, events, data);
#endif
int callbackResult = response.request.callback->handleEvent(fd, events, data);//呼叫callback->handleEvent
if (callbackResult == 0) {
removeFd(fd);
}
// Clear the callback reference in the response structure promptly because we
// will not clear the response vector itself until the next poll.
response.request.callback.clear();
result = ALOOPER_POLL_CALLBACK;
}
}
搞懂了上面的程式碼,我們就很容易明白wake函式做了些什麼:
- void Looper::wake() {
- #if DEBUG_POLL_AND_WAKE
- ALOGD("%p ~ wake", this);
- #endif
- ssize_t nWrite;
- do {
- nWrite = write(mWakeWritePipeFd, "W", 1);//向<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif; FONT-SIZE: 12px">mWakeWritePipeFd</SPAN><SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif; FONT-SIZE: 12px">中寫入一個字元,所以mWakeReadPipeFd就會觸發</SPAN><SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif; FONT-SIZE: 12px">EPOLLIN event</SPAN><SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif; FONT-SIZE: 12px">
- </SPAN> } while (nWrite == -1 && errno == EINTR);
- if (nWrite != 1) {
- if (errno != EAGAIN) {
- ALOGW("Could not write wake signal, errno=%d", errno);
- }
- }
- }
void Looper::wake() {
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ wake", this);
#endif
ssize_t nWrite;
do {
nWrite = write(mWakeWritePipeFd, "W", 1);//向<span style="font-family: Arial, Helvetica, sans-serif;">mWakeWritePipeFd</span><span style="font-family: Arial, Helvetica, sans-serif;">中寫入一個字元,所以mWakeReadPipeFd就會觸發</span><span style="font-family: Arial, Helvetica, sans-serif;">EPOLLIN event</span><span style="font-family: Arial, Helvetica, sans-serif;">
</span> } while (nWrite == -1 && errno == EINTR);
if (nWrite != 1) {
if (errno != EAGAIN) {
ALOGW("Could not write wake signal, errno=%d", errno);
}
}
}
小結:
- Looper通過epoll函式組實現了一個可以支援隨時喚醒的阻塞機制
- Looper支援兩種不同的方式處理訊息:Message + MessageHandler 和 LooperCallback。
- Looper的阻塞在如下四種條件下會被喚醒:
- 發生錯誤
- 等待超時
- 出現需要處理的新Message(包括C++層和Java層)
- 由addFd函式新增的Fd觸發event
總結:
- 在哪個執行緒呼叫JAVA層的Looper.loop(),Mesage和callback(包括Java層和C++層)就在哪個執行緒被處理,上圖為Looper.loop函式的時序圖。
- C++層的NativeMesasgeQueue不應該是Java層的MesageQueue的內部實現,而更接近於“欒生兄弟”的關係。MessageQueue負責處理java層上到訊息,NativeMessageQueue負責處理C++層上的訊息。其中Java層是在android.os.Looper.looper函式中呼叫android.os.Handler.dispatchMessage處理,而C++層是在android::Looper::pollInner函式中呼叫android::MessageHandler::handleMessage & android:LooperCallback::handleEvent函式處理。
- NativeMessageQueue利用Looper類實現了一個基於epoll函式和檔案描述符(Fd)的可喚醒的阻塞機制。
相關文章
- Android訊息機制不完全解析(上) .Android
- Android的Handler訊息機制 解析Android
- Handler訊息機制完全解析Handler解析
- Android訊息機制Message訊息池Android
- android訊息機制—HandlerAndroid
- 理解 Android 訊息機制Android
- Android訊息機制HandlerAndroid
- Android 之訊息機制Android
- Android的訊息機制Android
- 深度解析VC中的訊息傳遞機制(下)
- Android原始碼解析之一 非同步訊息機制Android原始碼非同步
- android之 Android訊息機制Android
- Android訊息傳遞之Handler訊息機制Android
- Android非同步訊息機制Android非同步
- Android訊息機制Handler用法Android
- Android 訊息機制詳解Android
- Android訊息機制(七) RxjavaAndroidRxJava
- Android Handler訊息傳遞機制:圖文解析工作原理Android
- Android訊息機制全面解析(Handler,MessageQueue,Looper,Threadlocal)AndroidOOPthread
- Android全面解析之由淺及深Handler訊息機制Android
- Android訊息機制-ThreadLocal原理解析:資料存取Androidthread
- OC訊息機制,訊息轉發機制
- iOS 訊息轉發機制Demo解析iOS
- [Android進階]Android訊息機制Android
- Android Handler 訊息機制詳述Android
- 深入理解Android訊息機制Android
- Android訊息機制原始碼分析Android原始碼
- 訊息機制
- Android 訊息機制詳解(Android P)Android
- 全面剖析Android訊息機制原始碼Android原始碼
- 深入理解 Android 訊息機制原理Android
- 深入探索Android訊息機制之HandlerAndroid
- 淺析Android中的訊息機制Android
- Android程式間通訊–訊息機制及IPC機制實現薦Android
- Handler訊息處理機制原始碼解析 上原始碼
- iOS訊息機制iOS
- SAP訊息機制
- Android 訊息機制:Handler、MessageQueue 和 LooperAndroidOOP