QueuedInputListener#flush方法
該方法在InputReader#loopOnce最后觸發(fā)。flush刷新將遍歷QueuedInputListener中mArgsQueue的數(shù)組元素,觸發(fā)每一個元素NotifyArgs的notify方法,交給內(nèi)部InputDispatcher,清空數(shù)組。
void QueuedInputListener::flush() {
size_t count = mArgsQueue.size();
for (size_t i = 0; i < count; i++) {
NotifyArgs* args = mArgsQueue[i];
args->notify(mInnerListener);
delete args;
}
刷新完畢清空數(shù)組
mArgsQueue.clear();
}
NotifyMotionArgs#notify方法,調(diào)用派發(fā)者InputDispatcher的通知notifyMotion,將自己交給派發(fā)者。
void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const {
listener->notifyMotion(this);
}
InputDispatcher實現(xiàn)了通知各類事件的方法notifyXXX(XXX)。
這樣,從數(shù)組取出每一個事件,調(diào)用一次InputDispatcher的notifyMotion方法處理,事件交給InputDispatcher。
InputDispatcher#notifyMotion方法
這時仍然是讀取線程InputReaderThread在處理事務(wù),notifyMotion方法之后會喚醒分發(fā)線程,接下來的任務(wù)就由分發(fā)線程處理了。
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
...
//將NotifyMotionArgs的數(shù)據(jù)封裝為MotionEntry
MotionEntry* newEntry = new MotionEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
args->action, args->actionButton, args->flags,
args->metaState, args->buttonState,
args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
args->displayId,
args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
插入InputDispatcher的mInboundQueue隊列中
needWake = enqueueInboundEventLocked(newEntry);
...
//需要喚醒分發(fā)線程
if (needWake) {
mLooper->wake();
}
}
數(shù)據(jù)封裝成MotionEntry,封裝的觸屏信息MotionEntry插入InputDispatcher的mInboundQueue隊列。
InputDispatcher#enqueueInboundEventLocked方法
Queue<EventEntry> mInboundQueue;
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
bool needWake = mInboundQueue.isEmpty();//隊列為空時,喚醒
mInboundQueue.enqueueAtTail(entry);//插入到尾部
...
}
注意:mLooper屬于InputDispatcher,InputManager創(chuàng)建InputDispatcher時,在其構(gòu)造方法同時創(chuàng)建mLooper,創(chuàng)建的線程是服務(wù)線程,并非讀取或分發(fā)線程
這里只是借用了Looper提供的epoll喚醒與休眠機(jī)制,在分發(fā)線程中InputDispatcherThread中使用mLooper休眠,讀取線程負(fù)責(zé)喚醒。
InputDispatcherThread分發(fā)線程被喚醒
在InputDispatcherThread線程threadLoop循環(huán)中,觸發(fā)InputDispatcher的dispatchOnce方法。
InputDispatcher#dispatchOnce方法
void InputDispatcher::dispatchOnce() {
//下次喚醒事件,設(shè)置無限大
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
...
//mCommandQueue為空時,觸發(fā)dispatchOnceInnerLocked
if (!haveCommandsLocked()) {
dispatchOnceInnerLocked(&nextWakeupTime);
}
if (runCommandsLockedInterruptible()) {//mCommandQueue為空時是false
nextWakeupTime = LONG_LONG_MIN;
}
} // release lock
nsecs_t currentTime = now();
//計算下一次喚醒時間,比當(dāng)前時間大。
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
mLooper->pollOnce(timeoutMillis);
}
利用Looper在epoll_wait處進(jìn)入休眠,休眠timeoutMillis時間仍無事件,threadLoop會一直循環(huán),繼續(xù)dispatchOnce。
當(dāng)被喚醒時,執(zhí)行循環(huán)進(jìn)入dispatchOnceInnerLocked取出隊列中的事件。
mPendingEvent = mInboundQueue.dequeueAtHead();
//判斷事件類型
switch (mPendingEvent->type) {
...
case EventEntry::TYPE_MOTION: {
MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
...
done = dispatchMotionLocked(currentTime, typedEntry,
&dropReason, nextWakeupTime);
break;
}
...
}
wake喚醒
Looper借助epoll機(jī)制實現(xiàn)線程休眠,它本身內(nèi)部有套接字mWakeEventFd,在rebuildEpollLocked建立時,注冊到epoll_ctl監(jiān)聽。因此wake方法就是向mWakeEventFd套接字發(fā)送一段字符,促使epoll_wait處的線程能監(jiān)聽到,從而InputDispatcherThread線程被喚醒。
綜上,InputDispatcherThread線程負(fù)責(zé)事件的具體分發(fā)。InputDispatcher#dispatchMotionLocked處理MotionEntry。
下一步是將事件交給具體的進(jìn)程。
Happy
End
^ ^