Android輸入事件流程中的EventHub分析及源碼示範

來源:互聯網
上載者:User
 

Android2.3的輸入事件流程與以前版本有了較大的不同,這裡做一下詳細的分析,最後我把自己分析時用的示範代碼放在了這裡:

http://code.google.com/p/flying-on-android/

下面的分析都是基於這些源碼的,大家可以下載下來一邊看源碼一邊看文檔。源碼裡只要關注FlyingEvent這個類就可以了。如果只想看一下示範結果,可以直接把包裡的flying放到機器的/system/bin目錄執行,開啟logcat後就可以看到示範輸出。運行程式時,機器螢幕會有異象產生,很正常,因為這個程式原本是用於顯示SurfaceFlinger的,這次為了示範EventHub稍微改了一下。大家只要關注FlyingEvent.cpp這個檔案就好了。

大家也可以用源碼自己編譯出示範程式,只要把解壓後的flying檔案夾放到/frameworks/base/cmds/目錄下,然後切換到flying目錄下使用mm編譯。

 

先大致介紹一下整個流程,再做重點分析。輸入事件流程一共涉及到下面這幾個檔案:

/frameworks/base/services/java/com/android/server/WindowManagerService.java

/frameworks/base/services/java/com/android/server/InputManager.java

/frameworks/base/services/jni/com_android_server_InputManager.cpp

/frameworks/base/libs/ui/InputReader.cpp

/frameworks/base/libs/ui/InputDispatcher.cpp

/frameworks/base/libs/ui/EventHub.cpp

其中,WindowManagerService.java和InputManager.java主要向Android為視窗系統提供服務,EventHub.cpp主要用來讀取裝置檔案中的RawEvent,而InputReader.cpp和InputDispatcher.cpp算是它們之間的對接層。

 

它們的關係是:WindowManagerService通過InputManager提供的介面開啟一個線程驅動InputReader不斷地從/dev/input/目錄下面的裝置檔案讀取事件,然後通過InputDispatcher分發給串連到WindowManagerService服務的用戶端。

InputReader從裝置檔案中讀取的是RawEvent,在交給InputDispatcher進行分發之前,它需要先把RawEvent進行轉化分類,拆分成KeyEvent、MotionEvent、TrackEvent各種類型等。這篇文章主要關注的就是這個RawEvent的拆分過程,所以我們的重點在EventHub.cpp中。並且,為了簡單化分析過程,在這裡我的分析只關注觸控螢幕事件。看它是如何從RawEvent被拆分成應用程式層使用者事件MotionEvent的。

 

看下面的分析之前,最好先去上面提到的地址把源碼下載下來,參照裡面的FlyingEvent.cpp。

 

整個過程大致分成這麼幾步:

一、初始化。

先new一個EventHub的執行個體:mEventHub(new EventHub),

接下來,開啟一個線程通過mEventHub不停地從裝置檔案中讀取RawEvent並處理:

while (1) {

    RawEvent event;

    mEventHub->getEvent(&event);

    process(event);

}

EventHub在初始化的時候做一些事情,

1、搜尋當前的輸入裝置每搜尋到一個就會產生一個類型為DEVICE_ADDED的事件,當讀取這種RawEvent時,InputReader會把搜尋到的這個裝置記錄下來。

2、如果搜尋到了鍵盤時,就會載入鍵盤配置檔案。載入完成後產生一個類型為FINISHED_DEVICE_SCAN的事件。這樣,後邊從驅動讀取使用者按鍵時,就會去載入的鍵盤配置檔案中尋找映射的索引值封裝成KeyEvent返回給使用者。

 

二、EventHub初始化完畢後,就開始等待使用者輸入。線程一直阻塞在mEventHub->getEvent(&event),直到有使用者事件產生才會返回。

當有一個事件產生時,傳遞給process進行處理。

 

三、事件拆分

FlyingEvent.process裡面主要調用了FlyingEvent.consume方法來處理使用者事件。這裡只分析touch事件。touch事件可以分為三種:down,move,up。

down類型的touch事件需要四個RawEvent來完成,第一個是X座標(ABS_X),第二個是Y座標(ABS_Y),第三個代表方向(ABS_PRESSURE)(0的時候是up,1的時候是down,所以這裡應該是1),第四個是結束標誌(SYN_REPORT)。

move類型的touch事件需要三個RawEvent來完成,第一個是X座標,第二個是Y座標,第三個是結束標誌。

up類型的touch事件需要兩個RawEvent來完成,第一個代表方向(0的時候是up,1的時候是down,所以這裡應該是0),第四個是結束標誌。

可能你已經注意到了up事件是沒有座標資訊的,它的座標資訊與down(沒有move時)或最後一個move(down和up之間有move事件產生)事件的座標相同。

 

從FlyingEvent.consume方法中,每一個事件最終都會產生一個TouchEvent,然後調用printTouchEvent進行列印,最後把它儲存到eventBuffer中。

 

 

參考文章

李先靜的“Android輸入事件流程“,不過使用的Android版本比較老了。

http://blog.csdn.net/absurd/archive/2009/05/17/4195363.aspx

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.