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系統中,還有很多地方都使用了這個機制。