日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android应用程序键盘(Keyboard)消息处理机制分析(17)

發布時間:2025/7/14 Android 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android应用程序键盘(Keyboard)消息处理机制分析(17) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??Step 11.?InputDispatcher.dispatchOnceInnerLocked

?? ? ? ?這個函數定義在frameworks/base/libs/ui/InputDispatcher.cpp文件中:

  • void?InputDispatcher::dispatchOnceInnerLocked(nsecs_t?keyRepeatTimeout,??
  • ????nsecs_t?keyRepeatDelay,?nsecs_t*?nextWakeupTime)?{??
  • ????......??
  • ??
  • ????//?Ready?to?start?a?new?event.??
  • ????//?If?we?don't?already?have?a?pending?event,?go?grab?one.??
  • ????if?(!?mPendingEvent)?{??
  • ????????if?(mInboundQueue.isEmpty())?{??
  • ????????????......??
  • ????????}?else?{??
  • ????????????//?Inbound?queue?has?at?least?one?entry.??
  • ????????????EventEntry*?entry?=?mInboundQueue.headSentinel.next;??
  • ??
  • ????????????......??
  • ??
  • ????????????mInboundQueue.dequeue(entry);??
  • ????????????mPendingEvent?=?entry;??
  • ????????}??
  • ??
  • ????????......??
  • ????}??
  • ??
  • ????......??
  • ??
  • ????switch?(mPendingEvent->type)?{??
  • ????......??
  • ??
  • ????case?EventEntry::TYPE_KEY:?{??
  • ????????KeyEntry*?typedEntry?=?static_cast<KeyEntry*>(mPendingEvent);??
  • ????????......??
  • ????????done?=?dispatchKeyLocked(currentTime,?typedEntry,?keyRepeatTimeout,??
  • ????????????&dropReason,?nextWakeupTime);??
  • ????????break;??
  • ???????????????????????????????}??
  • ??
  • ????......??
  • ????}??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?我們忽略了這個函數的次要邏輯,主要關注鍵盤事件的主要處理流程。首先,如果前面發生的鍵盤事件都已經處理完畢,那么這里的mPendingEvent就為NULL,又因為前面我們把剛剛發生的鍵盤事件加入了mInboundQueue隊列,因此,這里mInboundQueue不為NULL,于是,這里就把mInboundQueue隊列中的鍵盤事件取出來,放在mPendingEvent變量中:

  • mInboundQueue.dequeue(entry);??
  • mPendingEvent?=?entry;??
  • ?? ? ? ?由于這里發生的是鍵盤事件,即mPendingEvent->type的值為EventEntry::TYPE_KEY,于是,在接下來的switch語句中就會執行dispatchKeyLocked函數來分發鍵盤消息。

    ?

    ?? ? ? ?Step 12.?InputDispatcher.dispatchKeyLocked

    ?? ? ? ?這個函數定義在frameworks/base/libs/ui/InputDispatcher.cpp文件中:

  • bool?InputDispatcher::dispatchKeyLocked(??
  • ????????nsecs_t?currentTime,?KeyEntry*?entry,?nsecs_t?keyRepeatTimeout,??
  • ????????DropReason*?dropReason,?nsecs_t*?nextWakeupTime)?{??
  • ????......??
  • ??
  • ????//?Identify?targets.??
  • ????if?(!?mCurrentInputTargetsValid)?{??
  • ????????int32_t?injectionResult?=?findFocusedWindowTargetsLocked(currentTime,??
  • ????????????entry,?nextWakeupTime);??
  • ??
  • ????????......??
  • ????}??
  • ??
  • ????//?Dispatch?the?key.??
  • ????dispatchEventToCurrentInputTargetsLocked(currentTime,?entry,?false);??
  • ????return?true;??
  • }??
  • ?? ? ? ? InputDispatcher類中的mCurrentInputTargetsValid成員變量表示InputDispatcher是否已經標志出誰是當前激活的Activity窗口,如果沒有,就需要通過findFocusedWindowTargetsLocked函數來把它找出來。當把當前激活的Activity窗口找出來以后,接下來就調用dispatchEventToCurrentInputTargetsLocked函數把鍵盤事件分發給它了。

    ?

    ?? ? ? ?我們先來看一InputDispatcher是如何找到當前激活的Activity窗口的,然后再分析它把鍵盤事件分發給當前激活Activity窗口的過程。

    ?? ? ? ?Step 13.?InputDispatcher.findFocusedWindowTargetsLocked

    ?? ? ? ?這個函數定義在frameworks/base/libs/ui/InputDispatcher.cpp文件中:

  • int32_t?InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t?currentTime,??
  • ????????const?EventEntry*?entry,?nsecs_t*?nextWakeupTime)?{??
  • ????mCurrentInputTargets.clear();??
  • ??
  • ????int32_t?injectionResult;??
  • ??
  • ????//?If?there?is?no?currently?focused?window?and?no?focused?application??
  • ????//?then?drop?the?event.??
  • ????if?(!?mFocusedWindow)?{??
  • ????????if?(mFocusedApplication)?{??
  • ????????????......??
  • ????????????injectionResult?=?handleTargetsNotReadyLocked(currentTime,?entry,??
  • ????????????????mFocusedApplication,?NULL,?nextWakeupTime);??
  • ????????????goto?Unresponsive;??
  • ????????}??
  • ??
  • ????????......??
  • ????????injectionResult?=?INPUT_EVENT_INJECTION_FAILED;??
  • ????????goto?Failed;??
  • ????}??
  • ??
  • ????//?Check?permissions.??
  • ????if?(!?checkInjectionPermission(mFocusedWindow,?entry->injectionState))?{??
  • ????????injectionResult?=?INPUT_EVENT_INJECTION_PERMISSION_DENIED;??
  • ????????goto?Failed;??
  • ????}??
  • ??
  • ????//?If?the?currently?focused?window?is?paused?then?keep?waiting.??
  • ????if?(mFocusedWindow->paused)?{??
  • ????????......??
  • ????????injectionResult?=?handleTargetsNotReadyLocked(currentTime,?entry,??
  • ????????????mFocusedApplication,?mFocusedWindow,?nextWakeupTime);??
  • ????????goto?Unresponsive;??
  • ????}??
  • ??
  • ????//?If?the?currently?focused?window?is?still?working?on?previous?events?then?keep?waiting.??
  • ????if?(!?isWindowFinishedWithPreviousInputLocked(mFocusedWindow))?{??
  • ????????......??
  • ????????injectionResult?=?handleTargetsNotReadyLocked(currentTime,?entry,??
  • ????????????mFocusedApplication,?mFocusedWindow,?nextWakeupTime);??
  • ????????goto?Unresponsive;??
  • ????}??
  • ??
  • ????//?Success!??Output?targets.??
  • ????injectionResult?=?INPUT_EVENT_INJECTION_SUCCEEDED;??
  • ????addWindowTargetLocked(mFocusedWindow,?InputTarget::FLAG_FOREGROUND,?BitSet32(0));??
  • ??
  • ????......??
  • ??
  • ????return?injectionResult;??
  • }??
  • ?? ? ? ?回憶前面我們分析應用程序注冊鍵盤消息接收通道的過程時,在Step 9中,當前處于激活狀態的應用程序會通過調用InputDispatcher類setInputWindows函數把把當前獲得焦點的Activity窗口設置到mFocusedWindow中去,因此,這里的mFocusedWindow不為NULL,于是,就通過了第一個if語句的檢查。

    ?

    ?? ? ? ?第二個if語句檢查權限問題,原來,這個鍵盤事件除了是由硬件觸發的外,也可以由其它進程注入進來的,如果這個鍵盤事件是由其它進程注入進來的,那么entry->injectState就不為NULL,它里面包含了事件注冊者的進程ID和用戶ID,于是,這里就會調用checkInjectionPermission來檢查這個事件注入者的進程ID和用戶ID,看看它是否具有這個權限。這里我們不考慮這種情況,因此,這里的entry->injectState為NULL,于是,這個if語句的檢查也通過了。

    ?? ? ? ?第三個if語句檢查當前激活的Activity窗口是否是處于paused狀態,如果是的話,也不用進一步處理了。一般情況下,當前激活的Activity窗口都是處于resumed狀態的,于是,這個if語句的檢查也通過了。

    ?? ? ? ?第四個if語句檢查當前激活的Activity窗口是否還正在處理前一個鍵盤事件,如果是的話,那就要等待它處理完前一個鍵盤事件后再來處理新的鍵盤事件了。這里我們也假設當前激活的Activity窗口不是正在處理前面的鍵盤事件,因此,這個if語句的檢查也通過了。

    ?? ? ? ?最后,就調用addWindowTargetLocked函數把當前激活的Activity窗口添加到InputDispatcher類的mCurrentInputTargets成員變量中去。

    ?? ? ? ?Step 14.?InputDispatcher.addWindowTargetLocked

    ?? ? ? ?這個函數定義在frameworks/base/libs/ui/InputDispatcher.cpp文件中:

  • void?InputDispatcher::addWindowTargetLocked(const?InputWindow*?window,?int32_t?targetFlags,??
  • ????????BitSet32?pointerIds)?{??
  • ????mCurrentInputTargets.push();??
  • ??
  • ????InputTarget&?target?=?mCurrentInputTargets.editTop();??
  • ????target.inputChannel?=?window->inputChannel;??
  • ????target.flags?=?targetFlags;??
  • ????target.xOffset?=?-?window->frameLeft;??
  • ????target.yOffset?=?-?window->frameTop;??
  • ????target.pointerIds?=?pointerIds;??
  • }??
  • ?? ? ? ?這個函數簡單,就是把傳進來的參數window添加到mCurrentInputTargets中去就完事了,后面InputDispatcher就會從mCurrentInputTargets中取出恰當的Activity窗口,然后把鍵盤事件分發給它。

    ?? ? ? ?回到Step 12中的dispatchKeyLocked函數,它接下來就調用dispatchEventToCurrentInputTargetsLocked來進一步處理了。

    ?? ? ? ?Step 15.?InputDispatcher.dispatchEventToCurrentInputTargetsLocked

    ?? ? ? ?這個函數定義在frameworks/base/libs/ui/InputDispatcher.cpp文件中:

  • void?InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t?currentTime,??
  • ????????EventEntry*?eventEntry,?bool?resumeWithAppendedMotionSample)?{??
  • ???......??
  • ??
  • ???for?(size_t?i?=?0;?i?<?mCurrentInputTargets.size();?i++)?{??
  • ???????const?InputTarget&?inputTarget?=?mCurrentInputTargets.itemAt(i);??
  • ??
  • ???????ssize_t?connectionIndex?=?getConnectionIndexLocked(inputTarget.inputChannel);??
  • ???????if?(connectionIndex?>=?0)?{??
  • ???????????sp<Connection>?connection?=?mConnectionsByReceiveFd.valueAt(connectionIndex);??
  • ???????????prepareDispatchCycleLocked(currentTime,?connection,?eventEntry,?&?inputTarget,??
  • ???????????????resumeWithAppendedMotionSample);??
  • ???????}?else?{??
  • ???????????......??
  • ???}??
  • }??
  • ?? ? ? ?這個函數的實現也比較簡單,前面我們已經把當前需要接受鍵盤事件的Activity窗口添加到mCurrentInputTargets中去了,因此,這里就分別把它們取出來,然后調用prepareDispatchCycleLocked函數把鍵盤事件分發給它們處理。

    ?

    ?? ? ? ?前面我們在分析應用程序注冊鍵盤消息接收通道的過程時,在Step 18中(InputDispatcher.registerInputChannel),把Server端的InputChannel封裝成了一個Connection,然后以這個InputChannel中的Receive Pipe Fd作為鍵值把這個Connection對象保存在mConnectionsByReceiveFd中。這里,既然我們已經通過mCurrentInputTargets得到了表示當前需要接收鍵盤事件的Activity窗口的InputTarget對象,而且這個InputTarget對象的inputChannel就表示當初在InputDispatcher中注冊的Server端InputChannel,因此,這里就可以把這個Connection對象取出來,最后調用prepareDispatchCycleLocked函數來進一步處理。

    轉載于:https://blog.51cto.com/shyluo/966635

    總結

    以上是生活随笔為你收集整理的Android应用程序键盘(Keyboard)消息处理机制分析(17)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。