InputDispatcher的線程循環由InputDispatchr::diapatchOnce()完成
InputDispatcher::diapatchOnce(){
1、通過dispatcherInnerOnceLocked()進行輸入事件的派發,其傳出參數nextWeakupTime決定下次派發線程的循還執行時間
2、執行命令隊列中的命令,可以通過InputDispatcher::postCommandLocked()函數將命令追加到命令列表中
3,如果有必要,將派發線程進入休眠狀態,並由nextWeakupTime確定具體的休眠時間,Looper的pollOnce的實質就是epoll_wait()
派發線程在三種情況下將被喚醒:
1、有事件注入派發列隊時,調用Looper::wake()主動喚醒
2、epol_wait()堅挺的fd有epoll_event發生時
3、到達nextWeakupTime的時間點時
}
//該函數體現了派發過程的整體流程
InputDispatcher::dispatcherInnerOnceLocked(nextWeakUpTime){
1、setInputDispatchMode()函數可以使InputDispatcher在禁用,凍結,和正常三種狀態下切換
2、從派發隊列中取出一事件進行派發
如果派發隊列爲空,則直接返回。nextWeakupTime保持LONG_LONG_MAX,派發隊列進入無限的休眠期
resetANRTimeoutsLocked(),爲事件重置ANR信息
3、檢查時間是否需要被丟棄,dropReason描述了時間是否需要被丟棄
4、執行dispatchMotionLocked()進行Motion事件的派發
}
DropReason枚舉完整的描述了是事件被丟棄的所有原因:
1、DROP_REASON_POLICY:
2、DROP_REASON_APP_SWITCH
3、DROP_REASON_BLOCKED
4、DROP_REASON_DISABLED
5、DROP_REASON_STALE
//專門爲Motion事件尋找合適的目標窗口
dispatchMotionLocked(){
1、根據Motion事件,尋找合適的窗口,injectionResult保存尋找結果,找到的合適的窗口將會被保存在inputTarget列表中
findTouchedWindowTargetsLocked(correntTime,entry,inputTargets,nextWakeupTime,&conflictPointerActions)
2、調用dispatchEventLocked()將事件派發給inputTargets中
}
InputDispatcher::findTouchedWindowTargetsLocked(){
1、遍歷mWindowsHandles列表中所有的WindowHandle,檢查事件座標點是否落在其上
2、檢查TempTouchState中所有的目標窗口是否已準備好接受新的輸入事件
3、若窗口查找成功,設置injectionResult爲SUCCEEDED,並將生成的InputTarget放入參數inputTargets中
}
InputDispatcher::dispatchEventLocked(){
//根據InputTarget中的InputChannel獲取對應的Connection對象的索引
1、getConnectionIndexLocked(inputTarget,inputChannel)
//調用prepareDispatchCycleLocked()針對當前的InputTarget啓動發送事件循環
}
prepareDispatchCycleLocked(){
//將事件添加到Connection的發送隊列中
enqueueDiapatchEntriesLocked(curentTime,connection,eventEntry,inputTarget)
}
enqueueDiapatchEntriesLocked(curentTime,connection,eventEntry,inputTarget){
//將事件信息封裝成DispatchEntry,然後注入Connection的發送隊列中
enqueueDiapatchEntryLocked(connection,eventEntry,inputTarget,InputTarget::FLAG_DISPATCH_AS_IS)
//啓動發送循環
startDispatchCycleLocked(currentTime,connection)
}
FLAG_DISPATCH_AS_IS表示不修改事件的action類型
startDispatchCycleLocked(currentTime,connection){
//不斷的從發送隊列中獲取DispatchEntry,並將事件發送到InputChannel中
//根據不同的事件類型,選擇InputPublisher不同的發送函數
//將DispatchEntry轉存到waitQueue中
}
//派發按鍵事件
dispatchKeyLocked(){
}
//將事件注入派發列隊
InputDispatcher::notifyKey(){
1、根據policyF了該修改事件的mateState
2、詢問按鍵事件上的派發策略
interceptKeyBeforeQueueing()
3、構建KeyEntry
}
Command命令執行doInterceptKeyBeforeDispatcher()函數想DispatcherPolicy查詢派發策略,將結果保存在interceptKeyResult中
InputDispatcher::doInterceptKeyBeforeDispatcher(){
//創建KeyEvent對象
//調用interceptKeyBeforeDiapatching()從DispatcherPolicy中獲取派發策略,返回延遲派發的時間delay
}
delay的三種取值:
1、INTERCEPT_KEY_RESULT_SKIP:表示DispatcherPolicy自己處理按鍵事件,不希望派發給用戶
2、INTERCEPT_KEY_RESULT_CONTINUE:表示可以正常的派發給用戶
3、INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER:表示DispatcherPolicy尚未決定好如何處理這個按鍵事件,暫停派發工作,時間又delay決定
DispatcherPolicy是一個實現了DispatcherPolicyInterface的對象,保存在InputDispatcher的mPolicy成員變量中
interceptMotionBeforeQueueing()的調用發生在Reader線程中,其主要作用是返回policyFlags派發策略,PhoneWindowManager可以根據設備的狀態返回如下策略:
POLICY_FLAG_WOKE_HERE:
POLICY_FLAG_BRIGHT_HERE
POLICY_FLAG_PASS_TO_USER
InputManagerService::InputManagerService.filterInputEvent(InputEvent event,int policyFlags){
}
輸入事件的發送,接收與反饋
InputChannel的本質是一對SocketPair(非網絡套接字),用來實現在本機內進行進程的通信
InputChannel::openInputChannelPair(){
}
public int addWindow(......,InputChannel outInputChannel){
//openInputChannelPair()調用Native層的openInputChannelPair()函數,並將兩個Native層的InputChannel對象封裝爲Java對象返回
//其中一個InputChannel端交給WindowState保存
1、win.setInputChannel(inputChannels[0])
//另一個InputChannel則通過transferTo函數傳遞給調用者
2、inputChannels[1].transferTo(outInputChannel)
//將WindowState所保存的InputChannel向IMS進行註冊
3、registerInputChannel(win.mInputChannel,win.mInputWindowHandle)
//將所有的窗口信息更新到InputManagerService
mInputMonitor.updateInputWindowsLw(false)
}
registerInputChannel(InputChannel inputChannel,INputWindowHandle inputWindowHandle){
//直接調用nativeRegisterInputChannel,由Native層完成註冊工作
nativeRegisterInputChannel(mPtr,inputChannel,inputWindowHandle,false)
}
實際的註冊過程在InputDispatcher的同名函數完成
InputChannel(const sp<InputChannel>& inputChannel,const sp<InputWindowHandle>& inputWindowHandle,bool monitor){
1、爲傳入的InputChannel創建一個Connection對象並進行封裝
new Connection(inpputChannel,inputWindowHandle,monitor)
2、監聽InputChannel的可讀性。Looper對象具有監聽文件描述符可讀性時間的能力
}
InputMonitor.updateInputWindowsLw(boolean force){
//獲取用於遍歷所有WMS窗口的枚舉器,其參數表示採用反向遍歷
//將窗口的佈局信息轉存到inputWindowHandle中,然後將inputWindowHandle保存到mInputWindowHandles列表中
addInputWindowHandleLw();
//mInputWindowHandles列表提交給InputManagerService
mServic.mInputManager.setInputWindows(mInputWindowHandles)
//清空mInputWindowHandles列表
clearInputWindowHandleLw()
}
setInputWindows(mInputWindowHandles){
1使用傳入的InputWindowHandle列表替換現有的列表
2、調用updateInfo()函數,將JAVA層的佈局信息搬運到其InputWindowInfo
3、將焦點窗口保存到mInputWindowHandle中
}
窗口端連接的建立
窗口端通過addWindow()函數獲得InputChannel後,便會使用它創建一個InputEventReceiver對象,該對象可以接收來自InputChannel的輸入事件
InputHandler是SampleWindow實現的一個繼承自InputEventReceiver的類
事件的接收
InputPublisher將事件以InputMessage的形式寫入InputChannel之後,Looper會被喚醒,執行InputEventReceiver的handle-Event(),該方法直
接調用了consumeEvent()。
consumeEvent(){
1、通過consume()函數從InputChannel中讀取一條InputMessage,解析爲InputEvent,作爲參數傳出
2、根據事件的類型分別創建KeyEvent與MotionEvent的Java對象
3、通過JNI回調Java層的InputEventReceiver的dispatchInputEvent()函數
}
InputEventReceiver.dispatchInputEvent(){
//保存來自InputDispatcher的序列號
//調用onInputEvent(event)函數
}
事件的反饋與發送循環
事件的反饋由InputEventReceiver.finishInputEvent()發起
InputEventReceiver.finishInputEvent(){
//從字典中將事件對應的序列號取出
IndexOfKey();
//由nativeFinishInputEvent完成反饋動作
nativeFinishInputEvent(mReceiverPtr,seq,handled)
}
發送過程由NativeInputEventReceiver完成
NativeInputEventReceiver::finishInputEvent(){
//由mInputConsumer將handle兩個信息以InputMessage的形式寫入InputChannel中
mInputConsumer.sendFinishedSignal(seq,handled)
}
當InputChannel被寫入數據時,會觸發服務端的InputChannel可讀性事件,InputDispatcher的被喚醒,執行handleReceiverCallback()
handleReceiverCallback(){
//1、獲取對應的Connection對象
//2、循環讀取竟可能多的反饋信息
//3、調用finishDispatchCycleLocked()函數完成對反饋的處理
}
finishDispatchCycleLocked()函數將向InputDispatcher發送一個命令,處理反饋的函數是doDispatcherCycleFinishLockedInterruptible()
doDispatcherCycleFinishLockedInterruptible(){
}
焦點窗口:即當前操作的窗口,尋找焦點窗口的基本原則是沿着ZOrder的順序從上到下遍歷窗口
Android輸入系統筆記
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章
去掉Activity跳轉動畫
sengeiou
2020-02-24 07:14:12
Android-Framework層理解(1)
AFull-GF
2020-02-23 04:43:45
去掉Activity跳轉動畫
sengeiou
2020-02-24 07:14:12
Android-Framework層理解(1)
AFull-GF
2020-02-23 04:43:45
Android Sensor 使能流程
sengeiou
2018-09-04 14:24:35
VSCode 常用設置
sengeiou
2018-09-04 14:24:34
Android Binder IPC
yhcelebrite
2018-09-03 14:21:23
zygote
yhcelebrite
2018-09-03 14:21:23
SystemUI PoweUI筆記
漆黑迷夜
2018-09-03 10:05:14
zygote啓動流程
漆黑迷夜
2018-09-03 10:05:13
SystemUI筆記 SystemBars
漆黑迷夜
2018-09-03 10:05:13
SystemUI VolumeService
漆黑迷夜
2018-09-03 10:05:13
Android筆記 SystemServer
漆黑迷夜
2018-09-03 10:05:12
Androidframework LocationManager筆記
漆黑迷夜
2018-09-03 10:05:12
SystemUI RingtonePlayer
漆黑迷夜
2018-09-03 10:05:12