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

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器