1. 回顧
我們知道Android輸入系統(tǒng)是Reader線程通過驅(qū)動(dòng)程序得到上報(bào)的輸入事件,還要經(jīng)過處理,才可以將輸入事件發(fā)送給應(yīng)用程序,現(xiàn)在回顧一下是具體做哪些處理。
首先Reader線程會(huì)將輸入事件放入mInboundQueue隊(duì)列當(dāng)中,但是放入隊(duì)列之前需要進(jìn)行稍加處理。
1.1 處理類型
- 緊急事件,馬上處理(來電振鈴時(shí),按下音量鍵,會(huì)馬上靜音)
- 對(duì)輸入事件添加Flag,決定輸入事件是否傳給用戶Dispatch線程從mInboundQueue中取出事件,稍加處理之后,查找到目標(biāo)的應(yīng)用程序后,便會(huì)放入某個(gè)應(yīng)用程序的輸出隊(duì)列(mOutBoundQueue)
從輸出隊(duì)列中將事件取出,發(fā)送給應(yīng)用程序
2. Dispatch前處理總體分析
2.1 命令隊(duì)列為空時(shí)時(shí)候
從mIboundQueue取出事件
用它來生成一個(gè)命令,放入命令隊(duì)列或者直接丟棄(對(duì)于!Pass_To_User的事件)
對(duì)于經(jīng)過處理的事件,dispatch它
對(duì)于Global Key丟棄
System Key 丟棄
User Key 找到target,dispatch
InputDispatch.cpp
if (!haveCommandsLocked()) { dispatchOnceInnerLocked(&nextWakeupTime); }
2.2 命令隊(duì)列有數(shù)據(jù),執(zhí)行命令
Global Key 發(fā)廣播
System Key 直接處理
User Key 不做處理
InputDispatch.cpp
if (runCommandsLockedInterruptible()) { nextWakeupTime = LONG_LONG_MIN; }
3. dispatch前處理情景分析
3.1 !Pass_To_User
當(dāng)policyFlags = !Pass_To_User,則會(huì)執(zhí)行dispatchOnceInnerLocked函數(shù),設(shè)置dropreason
DropReason dropReason = DROP_REASON_NOT_DROPPED;if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) { dropReason = DROP_REASON_POLICY; } else if (!mDispatchEnabled) { dropReason = DROP_REASON_DISABLED; }
假設(shè)是一個(gè)按鍵類型的輸入事件,便會(huì)調(diào)用dispatchKeyLocked處理
// Clean up if dropping the event.if (*dropReason != DROP_REASON_NOT_DROPPED) { setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED); return true; }
3.2 Pass_To_User
需要分為Global Key/System Key/User Key三種情況,但是都是首先放入命令隊(duì)列中,并執(zhí)行命令,執(zhí)行的命令根據(jù)各個(gè)按鍵的返回值決定。
放入命令隊(duì)列
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) { CommandEntry* commandEntry = postCommandLocked( & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible); if (mFocusedWindowHandle != NULL) { commandEntry->inputWindowHandle = mFocusedWindowHandle; } commandEntry->keyEntry = entry; entry->refCount += 1;return false; // wait for the command to run
執(zhí)行命令
if (runCommandsLockedInterruptible()) { nextWakeupTime = LONG_LONG_MIN; }
CommandEntry* commandEntry = mCommandQueue.dequeueAtHead(); Command command = commandEntry->command; (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'//command執(zhí)行doInterceptKeyBeforeDispatchingLockedInterruptible函數(shù)
//最終調(diào)用PhoneWindowManager.java里面的同名函數(shù)nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle, &event, entry->policyFlags); mLock.lock();if (delay < 0) { entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP; //忽略按鍵不會(huì)再次上傳給用戶} else if (!delay) { entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE; } else { entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER; entry->interceptKeyWakeupTime = now() + delay; }
處理全局按鍵(Global Key)的代碼,返回-1,根據(jù)Global_Key.xml發(fā)送廣播給某個(gè)主鍵
if (mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {return -1; }
System Key:直接處理,return -1,意味著不會(huì)上傳給APP
User Key:return 0,事件解析結(jié)果是continue,讓APP來處理。再次執(zhí)行dispatchOnceInnerLocked,最終會(huì)找到目標(biāo)應(yīng)用程序,然后將該事件發(fā)給應(yīng)用程序
// Identify targets.Vector<InputTarget> inputTargets;int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime, entry, inputTargets, nextWakeupTime);
// Dispatch the key.dispatchEventLocked(currentTime, entry, inputTargets);
4. 總結(jié)
本篇博文主要分析dispatc前的處理過程,如下圖所示:
對(duì)于Reader線程讀到的輸入事件,會(huì)先進(jìn)行解析,解析之后進(jìn)行過濾,如果可以過濾就釋放,就不會(huì)放入mInBoundQueue隊(duì)列當(dāng)中,不可以過濾的話,無論是否Pass_To_User,都會(huì)放入mInBoundQueue隊(duì)列當(dāng)中
從mInBoundQueue隊(duì)列當(dāng)中取出輸入事件,判斷是否Pass_To_User,如果不是Pass_To_User則釋放掉,否則放入mCommandQueue當(dāng)中
再?gòu)膍CommandQueue隊(duì)列當(dāng)中,再次做解析,解析之后如果決定可以把他丟棄掉的話就直接release掉,否則則是放在mOutBoundQueue隊(duì)列中去,APP取出使用。下篇博文會(huì)具體分析這一步。
http://www.cnblogs.com/lkq1220/p/7170107.html