分析到pollInner方法,epoll_wait睡眠timeoutMillis时间,或者其他线程往消息队列中添加消息因为添加消息会往mWakeEventFd写入数据,会唤醒epoll。 这次我们来分析一下其他线程往消息队列中添加消息的过程,handler的sendxxx()方法都会走到enqueueMessage,加入消息队列
framework/base/core/java/android/os/Handler.java
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
// target设置为handler
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
framework/base/core/java/android/os/MessageQueue.java
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
synchronized (this) {
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
// 设置msg的信息
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
// 新的头节点,队列是空的或者when=0立即执行 或者when小于队列头部的when,
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
// 这种情况要唤醒,mBlocked记录了native是否阻塞,只有阻塞的时候才唤醒
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
// 插到队列中间,及时性不高,除非遇到了消息屏障,不然不用唤醒
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
// 底层唤醒
nativeWake(mPtr);
}
}
return true;
}
mBlocked记录了当前的native层的是否睡眠阻塞,如果新消息插入到了队列头部,那么要唤醒处理;如果是插入到队列非头部位置,这时候不用唤醒native层。
framework/base/core/jni/android_os_MessageQueue.cpp
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
// NativeMessageQueue#wake
nativeMessageQueue->wake();
}
void NativeMessageQueue::wake() {
// 调用looper
mLooper->wake();
}
/system/core/libutils/Looper.cpp
void Looper::wake() {
uint64_t inc = 1;
// mWakeEventFd是之前消息体系刚建立时候注册到epoll的fd
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd.get(), &inc, sizeof(uint64_t)));
......
}
往mWakeEventFd中写入了一个1, 那么这时候epoll监听到文件有变化,会从pollInner的epoll_wait返回,那么java层的queue.next()就可以继续执行,next()的逻辑在上一篇中分析过,我们这边看消息的执行时间已经到了的情况 ,返回msg到Looper.loop()
framework/base/core/java/android/os/Looper.java
public static void loop() {
final Looper me = myLooper();
// 死循环
for (;;) {
// 获取消息对象
Message msg = queue.next(); // might block
......
try {
// 执行handler的dispatchMessage
msg.target.dispatchMessage(msg);
}
......
}
}
msg的target就是handler,这边执行handler的dispatchMessage framework/base/core/java/android/os/Handler.java
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
这边有优先级, msg.callback > handler#mCallback > handleMessage(msg)
到这边就分析了sendxxx方法的执行流程,包括插入队列过程 -> 唤醒native过程 -> msg处理过程。
后面分析android input系统,在学之前需要熟悉epoll,native层的looper。