Looper 监听文件描述符
还是以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对象的文件描述符发生变化,就会回调MessageQueue的cb_eventReceiver方法。
Looper的addFd方法调用流程图如下,
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方法,该方法处理回调流程图如下,
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