Android Input事件獲取與分發(fā)簡單總結(jié)

一旗芬、整體流程

系統(tǒng)Input事件傳遞主要經(jīng)過如下幾個部分:

1.1輸入系統(tǒng)部分

輸入子系統(tǒng)

手機(jī)的輸入設(shè)備(包括屏幕疮丛、鍵盤、鼠標(biāo)等)履恩,當(dāng)前可用暇屋,會在文件系統(tǒng)/dev/input中創(chuàng)建對應(yīng)的設(shè)備節(jié)點咐刨,用戶操作輸入設(shè)備會產(chǎn)生輸入事件(按鍵事件、觸摸事件定鸟、鼠標(biāo)事件)等联予。

/dev/input/event0
/dev/input/event1
/dev/input/event2
...

InputManagerService
IMS初始化過程主要構(gòu)造了如下結(jié)構(gòu):

從結(jié)構(gòu)看材原,IMS核心功能實現(xiàn)在Native層:

  • IMS由SystemServer創(chuàng)建余蟹。

  • 在system_server進(jìn)程中包含兩個重要的線程InputReaderThread和InputDispatcherThread子刮,其內(nèi)部分別對應(yīng)InputReader和InputDispatcher兩個工作類。

  • InputReader負(fù)責(zé)讀取底層收集的input事件:從EventHub讀InputEvent并且傳給InputDispatcher來進(jìn)行分發(fā)葵孤。

  • InputDispatcher負(fù)責(zé)分發(fā)input事件到應(yīng)用層橱赠。WindowManagerService在app端setView的時候就創(chuàng)建了一對Socket連接狭姨,InputDispatcher利用這個Socket連接和app端通信。

1.2 WMS處理部分

WMS的職責(zé)之一就是輸入系統(tǒng)的中轉(zhuǎn)站绑莺,WMS作為Window的管理者惕耕,會配合IMS將輸入事件交由合適的Window來處理诫肠。

1.3 View處理部分

app端的ViewRootImpl里面的InputEventReceiver會接到從Socket得到的InputEvent栋豫。最終走APP的事件傳遞,消費事件蛤铜。

二丛肢、InputManagerService初始化過程

通過流程圖可以看出,這部分主要是做了一系列的初始化工作:

  • startOtherServices中穆刻,創(chuàng)建了IMS以及WMS杠步,并將WMS中的monitor傳給了IMS,作為回調(diào)朵锣,最后啟動IMS诚些。

  • IMS的初始化中執(zhí)行了nativeInit,該方法中創(chuàng)建了一個NativeInputManager實例助析,并且和java層使用的是同一個looper椅您。

  • 在NativeInputManager的初始化中創(chuàng)建了一個Eventhub,同時將這個Eventhub傳給新建的Inputmanager雪隧,Eventhub就是將數(shù)據(jù)從硬件驅(qū)動上讀出來然后傳遞上來的通道员舵。

  • InputManager初始化時創(chuàng)建了兩個重要線程:InputReaderThread和InputDispatcherThread马僻。

  • InputManager的start方法,讓兩個線程開啟了循環(huán)執(zhí)行操作措近。

三女淑、InputReader處理InputEvent流程

簡單總結(jié):

  • InputReader啟動后執(zhí)行l(wèi)oopOnce鸭你,它是一個可阻塞循環(huán)。

  • loopOnce循環(huán)中會通過Eventhub調(diào)用getEvents阁谆,來獲取底層input事件瓣窄,getEvents其實分成了三部分,首先是進(jìn)行device的讀取和處理裳凸,掃描/dev/input/目錄來生成device數(shù)據(jù)。二是看有沒有需要處理的時間逗宁,如果有那么就處理了返回梦湘。最后是進(jìn)行等待,等待對應(yīng)事件的發(fā)生哼拔。

  • 讀到了事件就會調(diào)用processEventsLocked處理事件:循環(huán)獲取EventHub給過來的事件瓣颅,這里事件包括來自Kernel的input事件和對Input事件的插入和刪除操作(這個不管)宫补,針對Kernel的input事件,交給processEventsForDeviceLocked處理健民。

  • processEventsForDeviceLocked 調(diào)用對應(yīng)的InputDevice處理Input事件贫贝,而InputDevice又會去匹配上對應(yīng)的InputMapper來處理對應(yīng)事件。(在InputDevice中凤优,存儲著許多InputMapper蜈彼,每種InputMapper對應(yīng)一類Device幸逆,例如:Touch暮现、Keyboard、Vibrator等等……)而調(diào)用InputDevice的process函數(shù)拍顷,就是將Input事件傳遞給每一個InputMapper塘幅,匹配的InputMapper就會對Input事件進(jìn)行處理,不匹配的則會忽略踏揣。

  • InputMapper將數(shù)據(jù)綜合打包成三種數(shù)據(jù)封裝:NotifyKeyArgs捞稿、NotifyMotionArgs和NotifySwichArgs,分別對應(yīng)key彰亥、Motion和Swich事件衰齐。

  • 最后調(diào)用mQueuedListener->flush(),將事件隊列中的所有事件交給在InputReader中注冊過的InputDispatcher仁卷。InputDispatcher先于InputReader被創(chuàng)建犬第,InputDispatcher沒有輸入事件處理時會進(jìn)入睡眠狀態(tài)歉嗓,等待InputReader通知喚醒。InputDispatcher的notifyKey函數(shù)中會根據(jù)按鍵數(shù)據(jù)來判斷InputDispatcher是否要被喚醒哮幢,InputDispatcher被喚醒后志珍,會重新調(diào)用dispatchOnceInnerLocked函數(shù)將輸入事件分發(fā)給合適的Window。

InputReader從EventHub獲取input event,將input event打包成Args放到InputDispacher的mInboundQueue敛纲,然后通過notifyKey喚醒InputDispacher淤翔。

四、InputDispatch分發(fā)流程

簡單總結(jié):

上節(jié)InputReader把input event放入了mInboundQueue(NotifyMotionArgs轉(zhuǎn)換為MotionEntry监嗜,添加到隊尾)。InputDispatcherThread被喚醒后稚补,通過InputDispatcher主要任務(wù)是找到對應(yīng)的window框喳,并建立進(jìn)程間通信五垮,把input event 傳遞過去。

  • InputDispatcher中润绎,由dispatchOnceInnerLocked處理input event:

1)從mInboundQueue取出事件
2)通過EventEntry的類型诞挨,對不同事件進(jìn)行不同處理惶傻,下面以TYPE_KEY為例
3)TYPE_KEY對應(yīng)會執(zhí)行dispatchKeyLocked,將事件分發(fā)出去

  • dispatchKeyLocked中做三件事情:

1)postCommandLocked 讓policy處理Home涂佃、Menu等系統(tǒng)按鍵蜈敢,policy對應(yīng)的是NativeInputManager
2)findFocusedWindowTargetsLocked 判斷發(fā)生按鍵事件的Window并得到對應(yīng)的inputTargets
3)dispatchEventLocked 通過InputTarget獲取對應(yīng)的Connection抓狭,每個焦點窗口在InputDispacher里都有一個對應(yīng)的Connection,通過這個Connection可以跟InputDispacher通信辐宾。然后發(fā)送事件EventEntry,先是將eventEntry放入Connection的outboundQueue,再通過InputPublisher將Entry發(fā)送給窗口叠纹,再將Entry從outboundQueue移到waitQueue里,最后由InputPublisher調(diào)用InputChanel的SendMessage()敞葛,SendMessage()再動用socket的send()函數(shù)惹谐,將打包好的Message發(fā)送給窗口驼卖。

  • InputChannel封裝了窗口與InputDispatcher間的跨進(jìn)程通信

應(yīng)用在ViewRootImpl的setView()酌畜,最終會調(diào)用IWindowSession的addToDisplay()函數(shù)卿叽,該函數(shù)帶上了mInputChannel參數(shù),向WMS注冊Channel贩虾。

五缎罢、App端處理流程

簡單總結(jié):

  • WindowInputEventReceiver中的onInputEvent回調(diào)執(zhí)行enqueueInputEvent策精,從隊列中獲取一個QueuedInputEvent崇棠,判斷是立刻執(zhí)行還是延遲執(zhí)行,但是最終都會走doProcessInputEvents酬蹋。

  • doProcessInputEvents中主要通過deliverInputEvent進(jìn)行事件分發(fā)抽莱。這里核心是InputStage體系食铐,責(zé)任鏈模式。最終會匹配上對應(yīng)Stage來進(jìn)行事件分發(fā)處理象泵。

  • 以Activity偶惠,View的按鍵分發(fā)流程相關(guān)的InputStage:ViewPostImeInputStage為例朗涩,執(zhí)行ProcessKeyEvent

第一步是調(diào)用PhoneWindow.DecorView的dispatchKeyEvent函數(shù),DecorView是View層次結(jié)構(gòu)的根節(jié)點兄一,按鍵從根節(jié)點開始按View的事件傳遞流程走出革。

第二步是判斷按鍵是否是四向鍵,或者是TAB鍵骂束,如果是則需要移動焦點栖雾。

本文只是參考了網(wǎng)上的文章析藕,針對input系統(tǒng)總結(jié)了一個模糊的流程,input總體來看還是比較復(fù)雜的竞慢,想要深入學(xué)習(xí)還是需要針對源碼進(jìn)行詳細(xì)分析治泥。

參考
https://zhuanlan.zhihu.com/p/29152319
https://blog.csdn.net/urdfmqcul2/article/details/78146424
https://blog.csdn.net/xingchenxuanfeng/article/details/79208005
https://blog.csdn.net/chenweiaiyanyan/article/details/72884141

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載居夹,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末劫扒,一起剝皮案震驚了整個濱河市狸膏,隨后出現(xiàn)的幾起案子沟饥,更是在濱河造成了極大的恐慌,老刑警劉巖湾戳,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贤旷,死亡現(xiàn)場離奇詭異,居然都是意外死亡砾脑,警方通過查閱死者的電腦和手機(jī)幼驶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拦止,“玉大人县遣,你說我怎么就攤上這事汹族∠羟螅” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵顶瞒,是天一觀的道長夸政。 經(jīng)常有香客問我,道長榴徐,這世上最難降的妖魔是什么守问? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮坑资,結(jié)果婚禮上耗帕,老公的妹妹穿的比我還像新娘。我一直安慰自己袱贮,他們只是感情好仿便,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著攒巍,像睡著了一般嗽仪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上柒莉,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天闻坚,我揣著相機(jī)與錄音,去河邊找鬼兢孝。 笑死窿凤,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的跨蟹。 我是一名探鬼主播雳殊,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼喷市!你這毒婦竟也來了相种?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤品姓,失蹤者是張志新(化名)和其女友劉穎寝并,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腹备,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡衬潦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了植酥。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镀岛。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡弦牡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出漂羊,到底是詐尸還是另有隱情驾锰,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布走越,位于F島的核電站椭豫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏旨指。R本人自食惡果不足惜赏酥,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谆构。 院中可真熱鬧裸扶,春花似錦、人聲如沸搬素。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蔗蹋。三九已至何荚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間猪杭,已是汗流浹背餐塘。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留皂吮,地道東北人戒傻。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像蜂筹,于是被迫代替她去往敵國和親需纳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容