Native Looper
从 Native Looper 的角度逐行拆解核心源码,最终彻底搞清楚 Android 消息机制在 Native 层是如何构建出一个“消息循环 + 事件驱动”的系统的。
一、先看 Native Looper 的结构:
Looper.cpp
路径:system/core/libutils/Looper.cpp
class Looper : public RefBase {
public:
static sp<Looper> getForThread();
static void setForThread(const sp<Looper>& looper);
static sp<Looper> prepare(int opts);
int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
void wake();
...
private:
int mWakeEventFd; // eventfd
int mEpollFd; // epoll 句柄
Vector<RequestedEvent> mRequestedEvents; // 所监听的所有 fd
...
};
小结:
Looper 本质上是 epoll 的封装。它有两个关键 fd:
- mEpollFd:管理所有监听的 fd
- mWakeEventFd:用于被动唤醒 epoll_wait
二、创建 Looper:
Looper::prepare()
sp<Looper> Looper::prepare(int opts) {
sp<Looper> looper = new Looper(opts);
setForThread(looper);
return looper;
}
构造函数中做了关键的 epoll 和 eventfd 初始化:
Looper::Looper(int opts)
: mEpollFd(epoll_create(EPOLL_SIZE_HINT)),
mWakeEventFd(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC)),
...
{
// 添加 eventfd 到 epoll 监听
struct epoll_event eventItem;
memset(&eventItem, 0, sizeof(epoll_event));
eventItem.events = EPOLLIN;
eventItem.data.fd = mWakeEventFd;
epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, &eventItem);
}
小结:
这个时候,Looper 就具备了“阻塞等待事件 + 可以被 eventfd 唤醒”的能力了。
三、pollOnce:执行阻塞/唤醒轮询
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
return pollInner(timeoutMillis, outFd, outEvents, outData);
}
核心逻辑在 pollInner():
int Looper::pollInner(...) {
int eventCount = epoll_wait(mEpollFd, eventItems, capacity, timeoutMillis);
for (int i = 0; i < eventCount; i++) {
int fd = eventItems[i].data.fd;
if (fd == mWakeEventFd) {
// 被唤醒:eventfd 可读
uint64_t counter;
read(mWakeEventFd, &counter, sizeof(uint64_t)); // 清除事件
} else {
// 其他 fd 有事件触发,如 socket、pipe、binder 等
processEvent(fd);
}
}
...
}
四、wake():从 Java 层触发唤醒
void Looper::wake() {
uint64_t inc = 1;
write(mWakeEventFd, &inc, sizeof(uint64_t)); // 写入让 eventfd 可读
}
这个函数就是 MessageQueue.nativeWake() 的最终实现,Java 调用了它,epoll_wait() 就从阻塞中醒来。
五、消息传递链梳理图(Native 层)
Java Handler.sendMessage()
↓
MessageQueue.enqueueMessage()
↓
nativeWake(mPtr)
↓
NativeMessageQueue.wake()
↓
write(mWakeEventFd)
↓
【epoll_wait 醒来】
↓
Looper.pollInner()
→ 发现 mWakeEventFd 可读
→ read(mWakeEventFd) 清除唤醒
→ 继续处理 MessageQueue 的 Java 消息
六、Native Looper 还能监听谁?
除了 mWakeEventFd,还可以监听其他 fd,如 socket、pipe、binder:
int Looper::addFd(int fd, int ident, int events, ...) {
struct epoll_event eventItem;
eventItem.events = events; // EPOLLIN / EPOLLOUT 等
eventItem.data.fd = fd;
epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem);
}
比如:
- 系统服务监听 binder 事件
- ALooper(NDK)监听 sensor fd
- SurfaceFlinger 监听 buffer queue fd
Looper是Android Native 层的统一事件源
七、总结:Native 层消息循环核心逻辑
组件 | 功能 |
---|---|
epoll | 等待 fd 上的事件(阻塞) |
eventfd | 触发一个可读事件(唤醒 epoll) |
Looper | 封装 epoll 管理、执行消息循环 |
NativeMessageQueue | Java MessageQueue 的 C++ 支撑层 |
nativePollOnce() | Java 阻塞入口,内部调用 epoll_wait |
nativeWake() | Java 唤醒入口,内部 write eventfd |