輸入事件的源頭位于/dev/input/下的設(shè)備節(jié)點救军,輸入事件的終點是WMS管理的某個窗口。所以輸入系統(tǒng)的主要工作是讀取設(shè)備節(jié)點中的原始事件倘零,接著進行加工封裝唱遭,然后派發(fā)給一個特定的窗口或者窗口中的控件。整個流程由InputManagerService系統(tǒng)服務(wù)為核心的多個參與者共同完成呈驶,如下圖所示拷泽。
流程大致為:
- 內(nèi)核將原始事件寫入設(shè)備節(jié)點
- InputReader不斷地通過EventHub將原始事件取出來并翻譯加工成Android輸入事件,然后交給InputDispather
- InputDispather根據(jù)WMS提供的窗口信息將事件交給合適的窗口
- 窗口的ViewRootImpl對象再沿著控件樹將事件派發(fā)給感興趣的控件
- 控件對齊收到的事件做出響應(yīng)袖瞻,更新自己的畫面司致、執(zhí)行特定的動作
下面介紹下參與者:
- Linux內(nèi)核:
接收輸入設(shè)備的中斷,將原始事件的數(shù)據(jù)寫入設(shè)備節(jié)點中聋迎。 - 設(shè)備節(jié)點:
內(nèi)核與IMS的橋梁脂矫,它將原始事件暴露給用戶空間,以便IMS可以從中讀取事件霉晕。 - InputManagerService:
一個Android的系統(tǒng)服務(wù)庭再,分為Java層和Native層。
Java層負責(zé)與WMS通信牺堰。
Native層則是InputReader和InputDispatcher兩個輸入系統(tǒng)關(guān)鍵組件的運行容器拄轻。 - EventHub:
通過getevents訪問設(shè)備節(jié)點,并把訪問到的原始輸入事件以及設(shè)備節(jié)點的增刪返回給使用者伟葫。 - InputReader:
運行在一個獨立的線程中哺眯。通過線程循環(huán)不斷的從EventHub中讀取原始事件,然后進行加工處理封裝為包含更多信息扒俯、更具可讀性的輸入事件奶卓,然后交給InputDispatcher進行派發(fā)。
當設(shè)備節(jié)點有增刪時撼玄,更新輸入設(shè)備列表和配置夺姑。 - InputReaderPolicy:
為InputReader加工處理原始事件,提供策略配置信息掌猛。例如:鍵盤布局盏浙。 - InputDispatcher:
運行在一個獨立的線程中眉睹。保管來自WMS的所有窗口的信息,其收到來自InputReader的輸入事件后废膘,會在其保管的窗口中尋找合適的窗口竹海,并將事件派發(fā)給此窗口。 - InputDispatcherPolicy:
為InputDispatcher派發(fā)過程提供策略丐黄。例如截取某些特定的輸入事件用作特殊用途斋配,或者阻止將某些事件派發(fā)給目標窗口。
示例:截取HOME鍵到PhoneWindowManager中進行處理灌闺,阻止窗口收到HOME鍵按下的事件艰争。 - WMS:
當新建窗口時,WMS為新窗口和IMS創(chuàng)建了事件傳遞所用的通道桂对。
WMS實時更新窗口的可點擊區(qū)域甩卓、焦點窗口等信息給IMS的InputDispatcher。 - ViewRootImpl:
對某些窗口蕉斜,如壁紙窗口逾柿、SurfaceView的窗口來說,窗口就是輸入事件派發(fā)的終點宅此。而其他的机错,比如說Activity、對話框等使用了Android控件系統(tǒng)的窗口來說诽凌,輸入事件的終點是控件(View)毡熏。ViewRootImpl將窗口所接收的輸入事件沿著控件樹將事件派發(fā)給感興趣的控件。