本文基于Android9.0源码
引言
通过上一篇Handler(一)源码解析,我们对Handler已经有了一定的了解,我们再深入分析一下Handler Native实现。
frameworks/base/core/jni/android_os_MessageQueue.cpp
frameworks/base/core/jni/android_os_MessageQueue.h
system/core/libutils/Looper.cpp
system/core/include/utils/Looper.h
初始化流程
1、通过MessageQueue的构造方法,调用nativeInit(),调用到android_os_MessageQueue_nativeInit()方法,生成NativeMessageQueue对象。
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
if (!nativeMessageQueue) {
jniThrowRuntimeException(env, "Unable to allocate native queue");
return 0;
}
nativeMessageQueue->incStrong(env);
return reinterpret_cast<jlong>(nativeMessageQueue);
}
2、NativeMessageQueue()获取Looper对象,首次创建Looper为null,调用构造方法。
NativeMessageQueue::NativeMessageQueue() :
mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
mLooper = Looper::getForThread();
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
3、调用系统函数eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC)获取文件描述符,并触发调用rebuildEpollLocked()。
Looper::Looper(bool allowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd: %s",
strerror(errno));
AutoMutex _l(mLock);
rebuildEpollLocked();
}
4、调用epoll_create(EPOLL_SIZE_HINT),创建epoll对象;
通过epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem)添加监听。
void Looper::rebuildEpollLocked() {
········
// Allocate the new epoll instance and register the wake pipe.
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(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 = mWakeEventFd;
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
········
}
处理消息流程
1、Looper.loop()阻塞
(1)通过android_os_MessageQueue_nativePollOnce()调用到自己的pollOnce();然后调用mLooper.pollOnce().
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
jlong ptr, jint timeoutMillis) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
mPollEnv = env;
mPollObj = pollObj;
mLooper->pollOnce(timeoutMillis);
}
(2)在pollOnce()中调用pollInner()方法。
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
int result = 0;
········
for (;;) {
if (result != 0) {
if (outFd != NULL) *outFd = 0;
if (outEvents != NULL) *outEvents = 0;
if (outData != NULL) *outData = NULL;
return result;
}
result = pollInner(timeoutMillis);
}
}
(3)通过epoll_wait()开始阻塞
int Looper::pollInner(int timeoutMillis) {
········
// 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;
}
}
········
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
········
}
2、唤醒
(1)超时唤醒(延时消息)
当通过epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis)阻塞线程时,需要传入timeoutMillis。而这个timeoutMillis是根据下个消息计算出来的,当延时消息需要执行时,epoll_wait超时,解除阻塞。
(2)主动唤醒(新即时消息)
线程会在pollInner()中通过epoll机制阻塞,当向列表中添加消息时,会计算消息的更新时间,如果需要立即处理,则会调用nativeWake()方法唤醒阻塞。
通过系统函数write(mWakeEventFd, &inc, sizeof(uint64_t))向mWakeEventFd中写入数据,触发epoll的监听。
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeMessageQueue->wake();
}
void NativeMessageQueue::wake() {
mLooper->wake();
}
void Looper::wake() {
uint64_t inc = 1;
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
if (nWrite != sizeof(uint64_t)) {
if (errno != EAGAIN) {
LOG_ALWAYS_FATAL("Could not write wake signal to fd %d: %s",mWakeEventFd, strerror(errno));
}
}
}