欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Looper 监听文件描述符

程序员文章站 2022-03-29 16:15:02
...

还是以SurfaceFlinger为例论述。SurfaceFlinger的init方法会调用MessageQueue的setEventThread方法创建Connection对象,并且还会调用Looper的addFd方法将BitTube对象的文件描述符添加到Looper中进行监听,

mEventThread = eventThread;
mEvents = eventThread->createEventConnection();
mEvents->stealReceiveChannel(&mEventTube);
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
    MessageQueue::cb_eventReceiver, this);

也就是说,一旦BitTube对象的文件描述符发生变化,就会回调MessageQueuecb_eventReceiver方法。

Looper的addFd方法调用流程图如下,

Looper 监听文件描述符

Looper中有2个addFd方法,

return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data);

如果callback不为空,就构造SimpleLooperCallback对象, SimpleLooperCallback 是Looper.cpp中的一个类,其构造方法如下,

SimpleLooperCallback::SimpleLooperCallback(Looper_callbackFunc callback) :
        mCallback(callback) {
}

将回调方法赋值给mCallback变量, Looper.h中的mCallback声明如下,

Looper_callbackFunc mCallback;

addFd方法逻辑如下,

1,为结构体Request 赋值,主要保存文件描述符,回调方法等,

Request request;
request.fd = fd;
request.ident = ident;
request.events = events;
request.seq = mNextRequestSeq++;
request.callback = callback;
request.data = data;

Request 结构体定义在Looper.h中。

2,调用系统的epoll_ctl 方法添加到epoll监控中,并且将request结构体对象添加到mRequests列表中。

int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
•••
mRequests.add(fd, request);

根据Looper机制,消息处理最后会调用Looper的pollOnce方法,该方法处理回调流程图如下,

Looper 监听文件描述符

pollInner方法主要逻辑如下,

1,调用系统的epoll_wait方法等待epoll事件的到来,也就是BitTube 对应文件值发生变化,

int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

2,调用SimpleLooperCallback的handleEvent方法进行回调处理,

int callbackResult = response.request.callback->handleEvent(fd, events, data);

SimpleLooperCallback的handleEvent方法如下,

int SimpleLooperCallback::handleEvent(int fd, int events, void* data) {
    return mCallback(fd, events, data);
}

直接调用回调方法。此回调方法就是通过addFd方法设置的回调方法。

在此,需要记住的是,通过调用Looper的addFd方法设置方法的回调,如果文件描述符发生变化,就会调用回调方法。

在SurfaceFlinger中,

mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
    MessageQueue::cb_eventReceiver, this);

一旦BitTube对应文件值发生变化,就会回调MessageQueue的cb_eventReceiver方法。

除了SurfaceFlinger 使用了这种机制之外,在android系统中,还有很多地方都使用了这个机制。

例如,按键/消息 事件从从驱动到HAL到JNI最后到APP就是通过这种方法监听的,详细请见http://blog.csdn.net/u012439416/article/details/54605324