1.回顾

我们在上一篇文章《Handler机制》中详细叙述了Handler运行机制的java层实现,每当分析到jni,就只简要说明了下底层做了什么,因此,我们在这篇文章中详细来分析一下Handler的底层代码,看看底层是如何实现的。首先列出底层有那些方法。先分析简单的。

1
2
3
4
5
6
7
// frameworks/base/core/java/android/os/MessageQueue.java
private native static long nativeInit();
private native static void nativeDestroy(long ptr);
private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
private native static void nativeWake(long ptr);
private native static boolean nativeIsPolling(long ptr);
private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);

2.nativeInit()分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// frameworks\base\core\jni\android_os_MessageQueue.cpp
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
// 实例化一个NativeMessageQueue对象
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
if (!nativeMessageQueue) {
jniThrowRuntimeException(env, "Unable to allocate native queue");
return 0;
}

// 强引用计数+1
nativeMessageQueue->incStrong(env);
// 将对象地址转化成jlong型,赋值给java层的mPtr参数,以后访问native中的messagequeue对象就通过该指针找到他。
return reinterpret_cast<jlong>(nativeMessageQueue);
}

3.nativeDestroy()分析

1
2
3
4
5
6
static void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
// 通过ptr找到messagequeue对象
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
// 引用计数减一
nativeMessageQueue->decStrong(env);
}

4.nativeIsPolling()分析

1
2
3
4
5
6
static jboolean android_os_MessageQueue_nativeIsPolling(JNIEnv* env, jclass clazz, jlong ptr) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
// 返回当前poll是否空闲,true为空闲,正在等待监听事件产生
// mPolling在pollInner中被赋值
return nativeMessageQueue->getLooper()->isPolling();
}

5.nativeSetFileDescriptorEvents()分析

nativeSetFileDescriptorEvents()给java层提供了一个接口,上层可以自己选择要监听的事件,事件分为:

  • EVENT_INPUT
  • EVENT_OUTPUT
  • EVENT_ERROR
1
2
3
4
5
static void android_os_MessageQueue_nativeSetFileDescriptorEvents(JNIEnv* env, jclass clazz,
jlong ptr, jint fd, jint events) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeMessageQueue->setFileDescriptorEvents(fd, events);
}

6.nativePollOnce()分析

下面开始分析重头戏,开始分析nativePollOnce()和nativeWake()两个方法

1
2
3
4
5
6
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
jlong ptr, jint timeoutMillis) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
// 调用到messagequeue的pollonce方法中去。
nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
mPollEnv = env;
mPollObj = pollObj;
// 调用到Looper的pollOnce方法,并且传入超时时间
mLooper->pollOnce(timeoutMillis);
mPollObj = NULL;
mPollEnv = NULL;

if (mExceptionObj) {
env->Throw(mExceptionObj);
env->DeleteLocalRef(mExceptionObj);
mExceptionObj = NULL;
}
}
1
2
3
4
// system\core\libutils\Looper.cpp
inline int pollOnce(int timeoutMillis) {
return pollOnce(timeoutMillis, NULL, NULL, NULL);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
int result = 0;
for (;;) {
......
// 判断pollInner处理的结果
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);
}
}

result代表pollinner中epoll处理事件的状态

  • POLL_WAKE:调用wate()说明正在等待事件发生
  • POLL_CALLBACK:将结果返回给回调
  • POLL_TIMEOUT:epoll_wait()超时
  • POLL_ERROR:内部错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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;
}
}

// Poll.
int result = POLL_WAKE;
mResponses.clear();
mResponseIndex = 0;

// We are about to idle.
mPolling = true;

struct epoll_event eventItems[EPOLL_MAX_EVENTS];
//阻塞整个线程,等待监听的事件发送,eventCount是epoll_wait的返回,返回需要处理的事件数目
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

......

// Check for poll timeout.
// 如果过了超时事件,还没事件发生,就直接返回,通知超时
if (eventCount == 0) {
result = POLL_TIMEOUT;
goto Done;
}

// Handle all events.
// 开始处理监听的事件
for (int i = 0; i < eventCount; i++) {
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
if (fd == mWakeEventFd) {
if (epollEvents & EPOLLIN) {
// 如果有事件发送,并且是我们监听的fd并且是输入事件,线程则被唤醒,开始执行被阻塞下面的代码
awoken();
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents);
}
} else {
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex >= 0) {
int events = 0;
if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;
pushResponse(events, mRequests.valueAt(requestIndex));
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
"no longer registered.", epollEvents, fd);
}
}
}
Done: ;

.....
return result;
}

看到这里,继续回顾java如何取message的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 Message next() {
// Return here if the message loop has already quit and been disposed.
// This can happen if the application tries to restart a looper after quit
// which is not supported.
final long ptr = mPtr;
if (ptr == 0) {
return null;
}

int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}

// 调用nativePollOnce()线程就阻塞在这里,不继续执行下面代码
nativePollOnce(ptr, nextPollTimeoutMillis);
// 唤醒或者阻塞超时就开始执行下面代码

synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
// 下面就是加锁取一个msg返回的逻辑
......
}

6.nativeWake()分析

上面我们分析了调用nativePollOnce(),线程会被阻塞,不会继续执行下面的代码,要么是被唤醒,要么超时才开始执行下面的代码。下面我们就来看一下线程是如何被唤醒的。

1
2
3
4
5
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
// 调用messagequeue的wake()方法
nativeMessageQueue->wake();
}
1
2
3
4
void NativeMessageQueue::wake() {
// 继续往下掉用
mLooper->wake();
}
1
2
3
4
5
6
void Looper::wake() {
// 写了一个1到mWakeEventFd中,激活epoll事件,然后线程就被唤醒了
uint64_t inc = 1;
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
// 处理错误
}

因此唤醒就特别简单,直接向监听的fd中写一个字符即可唤醒线程处理事件。

未完待续,顺势推舟,下面一篇叙述一下epoll是如何使用的方法

HandlerThread、JobIntentService和JobService的使用方法。参考《Handler扩展使用