天天看點

上報和分發消息的流程

概論

        Android系統中,大體上分為三個層次kernel、framework、app層。對于kernel層,我們主要關心的是驅動,驅動層上報的事件都是原始資料。這些原始資料通過相應的機制上傳到framework層的frameworks\base\service\input檔案夾下的EventHub檔案中對裝置進行掃描區分具體的裝置,并交由InputReader.cpp進行對資料的讀取和分類。到達MotionEvent或者KeyEvent進行處理。此處這樣說明總感覺到奇怪。        (2012-5-14 update)        在android中我們采用了一種從下而上,又從上而下的過程。在這個過程中我們首先是通過對輸入裝置的操作,進而使得硬體上報資料,而運作在系統中的線程等待接收資料,進而形成一種服務的關系。而從上而下的過程就是一種管理的過程,在這個過程中,我們上報的事件會得到合理的處理。         實際在代碼中WindowManagerService中對InputManager進行了初始化,并且調用了start函數進行了啟動。        此時大家一定想找到InputManager問個究竟,但是定睛一看,赫然顯示兩個InputManager。這可叫人如何是好?        本人猜想,應該此處的調用應該是InputManager.java。因為通常的調用都是從Java開始的。可能此處說法不嚴謹,但是鄙人認為科學都是“大膽假設、小心驗證”。當然就從程式閱讀本身也能找到根據。 因為此處的構造函數是有參數的。java中有而cpp中沒有。(2012年5月7日修訂)此處我們往下看的時候,發現在C++裡面有函數的重載,而重載的構造函數中就有帶有參數的構造函數。那到底此處我們是調用的哪個構造函數呢?當我們開始了解java和其他程式設計語言的互相調用之後我們發現在Android中我們都會通過JNI機制将本地的函數通過函數指針的形式提供給JAVA層進行調用。是以在命名上一般都以native開頭。這樣看來我們似乎對這一問題有了更深入的了解。         接着往下走發現在java中有回調函數和nativeInit,相信大家也是對這個函數比較感興趣。但是此處還是要簡單的說明下此回調函數。該函數則會利用windowManagerService,調用windowManagerService内部的其他方法。我們接着往下走,在nativeInit函數中将會建立一個此處會建立一個EventHub對象,以及InputManager對象。InputManager對象建立InputReaderThread以及InputDispatcherThread線程。在InputManager的構造函數中初始化了EventHub對象,通過傳遞參數給InptReader的構造函數。此處調用InputListener對事件進行監聽,并且将消息放到消息隊列中。自此WindowManagerService中對InputManager的初始化過程完成。        我們在通過EventHub擷取資料之後,在inputreader函數中對原始的資料進行cook處理,處理之後形成應用程式能夠識别的資料。這時候通過copyfrom函數将資料放到input中。最終通過inputlistener的flush函數進行監聽,此過程就是調用notifyMotionevent函數此函數即通過inputdiapatcher進行分發。在資料分發的過程中,是通過flag對資料要進行分發還是攔截進行判斷,并進行相應的處理。