日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

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

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

??Step 11.?InputDispatcher.dispatchOnceInnerLocked

?? ? ? ?這個(gè)函數(shù)定義在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;??
  • ???????????????????????????????}??
  • ??
  • ????......??
  • ????}??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?我們忽略了這個(gè)函數(shù)的次要邏輯,主要關(guān)注鍵盤事件的主要處理流程。首先,如果前面發(fā)生的鍵盤事件都已經(jīng)處理完畢,那么這里的mPendingEvent就為NULL,又因?yàn)榍懊嫖覀儼褎倓偘l(fā)生的鍵盤事件加入了mInboundQueue隊(duì)列,因此,這里mInboundQueue不為NULL,于是,這里就把mInboundQueue隊(duì)列中的鍵盤事件取出來,放在mPendingEvent變量中:

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

    ?

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

    ?? ? ? ?這個(gè)函數(shù)定義在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是否已經(jīng)標(biāo)志出誰是當(dāng)前激活的Activity窗口,如果沒有,就需要通過findFocusedWindowTargetsLocked函數(shù)來把它找出來。當(dāng)把當(dāng)前激活的Activity窗口找出來以后,接下來就調(diào)用dispatchEventToCurrentInputTargetsLocked函數(shù)把鍵盤事件分發(fā)給它了。

    ?

    ?? ? ? ?我們先來看一InputDispatcher是如何找到當(dāng)前激活的Activity窗口的,然后再分析它把鍵盤事件分發(fā)給當(dāng)前激活A(yù)ctivity窗口的過程。

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

    ?? ? ? ?這個(gè)函數(shù)定義在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;??
  • }??
  • ?? ? ? ?回憶前面我們分析應(yīng)用程序注冊(cè)鍵盤消息接收通道的過程時(shí),在Step 9中,當(dāng)前處于激活狀態(tài)的應(yīng)用程序會(huì)通過調(diào)用InputDispatcher類setInputWindows函數(shù)把把當(dāng)前獲得焦點(diǎn)的Activity窗口設(shè)置到mFocusedWindow中去,因此,這里的mFocusedWindow不為NULL,于是,就通過了第一個(gè)if語句的檢查。

    ?

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

    ?? ? ? ?第三個(gè)if語句檢查當(dāng)前激活的Activity窗口是否是處于paused狀態(tài),如果是的話,也不用進(jìn)一步處理了。一般情況下,當(dāng)前激活的Activity窗口都是處于resumed狀態(tài)的,于是,這個(gè)if語句的檢查也通過了。

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

    ?? ? ? ?最后,就調(diào)用addWindowTargetLocked函數(shù)把當(dāng)前激活的Activity窗口添加到InputDispatcher類的mCurrentInputTargets成員變量中去。

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

    ?? ? ? ?這個(gè)函數(shù)定義在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;??
  • }??
  • ?? ? ? ?這個(gè)函數(shù)簡(jiǎn)單,就是把傳進(jìn)來的參數(shù)window添加到mCurrentInputTargets中去就完事了,后面InputDispatcher就會(huì)從mCurrentInputTargets中取出恰當(dāng)?shù)腁ctivity窗口,然后把鍵盤事件分發(fā)給它。

    ?? ? ? ?回到Step 12中的dispatchKeyLocked函數(shù),它接下來就調(diào)用dispatchEventToCurrentInputTargetsLocked來進(jìn)一步處理了。

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

    ?? ? ? ?這個(gè)函數(shù)定義在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?{??
  • ???????????......??
  • ???}??
  • }??
  • ?? ? ? ?這個(gè)函數(shù)的實(shí)現(xiàn)也比較簡(jiǎn)單,前面我們已經(jīng)把當(dāng)前需要接受鍵盤事件的Activity窗口添加到mCurrentInputTargets中去了,因此,這里就分別把它們?nèi)〕鰜?#xff0c;然后調(diào)用prepareDispatchCycleLocked函數(shù)把鍵盤事件分發(fā)給它們處理。

    ?

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

    轉(zhuǎn)載于:https://blog.51cto.com/shyluo/966635

    總結(jié)

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

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。