Android4.4之Input模組筆記

來源:互聯網
上載者:User

標籤: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(),


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.