標籤:inputdispatcher
在InputReader從EventHub中擷取輸入事件,包含觸控螢幕事件、物理按鍵事件等,然後轉交給InputDispatcher線程,InputDispatcher經過篩選,過濾輸入事件。對於觸摸事件通過調用findTouchedWindowTargetsLocked()函數找到合適的InputTarget,然後通過dispatchEventLocked()->prepareDispatchCycleLocked()->enqueueDispatchEntriesLocked()->enqueueDispatchEntryLocked()-> connection->outboundQueue.enqueueAtTail(dispatchEntry)添加到與InputTarget一一對應的connection中的一個隊列中。如果之前該隊列無資料,並且當前觸摸事件已成功加入該隊列,則繼續調用startDispatchCycleLocked()函數進行分發處理。在startDispatchCycleLocked()中,有一個while迴圈,該迴圈從connection->outboundQueue隊列中取出輸入事件,如果該輸入事件是按鍵(key)事件,則調用connection->inputPublisher.publishKeyEvent()函數,如果是觸摸事件則調用connection->inputPublisher.publishMotionEvent()。publishKeyEvent()和publishMotionEvent()都是調用mChannel->sendMessage()將輸入事件發送出去。mChannel是一個C++層InputChannel對象,該對象的賦值過程如下:registerInputChannel()->new Connection->Connection()建構函式->InputPublisher()建構函式。事實上,在registerInputChannel()被調用之前,ViewRootImple在增加一個視窗時調用ViewRootImpl.setView()->mWindowSession.addToDisplay()-WindowManagerService.addWindow(),在addWindow()中會建立一對InputChannel(Nativie層),實際上是建立一對Socket,服務端InputChanel被WMS註冊到InputDispatcher中,用戶端InputChannel被返回給ViewRootImpl,ViewRootImpl將用戶端InputChannel作為參數new一個InputEventReceiver對象,在InputEventReceiver()建構函式中繼續調用nativeInit()函數來建立一個native層的NativeInputEventReceiver對象,前面建立的用戶端InputChannel會儲存在該對象中。
總結:WMS會調用native層介面建立一對通訊端,服務端儲存在InputDispatcher中,用戶端儲存在NativeInputEventReceiver中(android_view_inputEventReceiver.cpp)。
很容易想到輸入事件是從InputDispatcher流向NativeInputEventReceiver中。在建立一個native層的NativeInputEventReceiver對象後會立即調用NativeInputEventReceiver->initialize(),該函數調用mMessageQueue->getLooper()->addFd(fd,0, events, this, NULL)將用戶端socket控制代碼添加到Looper的輪詢隊列中,參數this指向NativeInputEventReceiver本身,意味著只要服務端InputDispatcher發送輸入事件,用戶端收到這個事件,就調用NativeInputEventReceiver的某個函數,具體調用哪個函數,自然是NativeInputEventReceiver實現了LooperCallback的介面函數handleEvent()。但此時收到的事件只是代表socket用戶端有事件來,並沒有把具體的事件讀取出來,這點需要注意。
總結:用戶端收到輸入事件,即調用NativeInputEventReceiver->handleEvent()函數。
在handleEvent()函數中,繼續調用consumeEvents()->mInputConsumer.consume()->mChannel->receiveMessage(&mMsg)將具體輸入事件讀取出來,然後調用env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.dispatchInputEvent,seq, inputEventObj),可以知道native層讀取輸入事件後,然後會回調java層InputEventReceiver.java中的dispatchInputEvent()函數。事實上,
dispatchInputEvent繼續調用onInputEvent(event);此時可能並不調用InputEventReceiver類中的onInputEvent()方法,而是調用子類onInputEvent()方法。在ViewRootImpl中存在WindowInputEventReceiver類型變數mInputEventReceiver,WindowInputEventReceiver類繼承InputEventReceiver,並實現onInputEvent()方法由此可得出結論:native層socket用戶端讀取輸入事件,最終調用InputEventReceiver類子類的onInputEvent()方法,ViewRootImpl繼承InputEventReceiver,因此ViewRootImpl.onInputEvent()將被調用。
總結:對於一般的觸控螢幕事件最終處理者是ViewRootImpl類,對於IME則處理者是IInputMethodSessionWrapper類,當然WMS是不會處理這些輸入事件的。
繼續研究ViewRootImpl.onInputEvent()函數,onInputEvent()->doProcessInputEvents()->deliverInputEvent(),