1. InputDispatcher 的簡(jiǎn)介
在 input 輸入事件番外4 中講到事件經(jīng)過(guò)獲取、初步處理后最終發(fā)送給 InputtDispatcher 進(jìn)行分發(fā),那么 InputtDispatcher 是怎么進(jìn)行分發(fā)的呢,首先從 InputtDispatcher 的設(shè)計(jì)思路出發(fā),然后再進(jìn)行一步步分析;
InputDispatcher 既然是要分發(fā)事件,就要搞清兩個(gè)問(wèn)題,發(fā)送的是什么?發(fā)送給誰(shuí)?也就是下面將要展開(kāi)分析的兩點(diǎn):
獲取發(fā)送事件;
獲取目標(biāo)app,并將事件交由其處理;
獲取發(fā)送事件:
第一步:獲取事件;
第二步:放入隊(duì)列前的簡(jiǎn)單處理;例如是否處于鎖屏狀態(tài)、有沒(méi)有被 InputFilter 消費(fèi)掉等;
第三步:放入隊(duì)列 Queue<EventEntry> mInboundQueue;
發(fā)送事件給目標(biāo)app:
第一步:找到目標(biāo) app;
第二步:放入隊(duì)列 Queue<DispatchEntry> outboundQueue;
第三步:從 outboundQueue 取出事件,通過(guò) Connection 發(fā)送給目標(biāo) app;
2. 獲取發(fā)送事件:
2.1 事件從 InputReader 到 InputDispatcher:上一節(jié)中講到 getListener()->notifyMotion(&args) 后事件就傳遞到 InputDispatcher 交給分發(fā)線程處理了,而且還提到 getListener() 其實(shí)就是在初始化 InputReader 時(shí)傳入的參數(shù) mDispatcher,這里就來(lái)分析一下:
(1)getListener():
// frameworks\native\services\inputflinger\InputManager.cpp
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
// InputReader 的構(gòu)造函數(shù) frameworks\native\services\inputflinger\InputReader.cpp
InputReader::InputReader(const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener) :
mContext(this), mEventHub(eventHub), mPolicy(policy),
mGlobalMetaState(0), mGeneration(1),
mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
mQueuedListener = new QueuedInputListener(listener); // 就在這里,初始化了 mQueuedListener
{ // acquire lock
AutoMutex _l(mLock);
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
} // release lock
}
InputListenerInterface* InputReader::ContextImpl::getListener() {
return mReader->mQueuedListener.get(); // 通過(guò) get() 函數(shù)獲得原生指針
}
(2)InputReader 傳遞事件到 InputDispatcher:
// 事件獲取線程中 獲取事件到事件傳遞 循環(huán)調(diào)用的方法:loopOnce()
void InputReader::loopOnce() {
// ...
// 1. 讀取事件
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
if (count) {
// 2. 事件的簡(jiǎn)單處理;
processEventsLocked(mEventBuffer, count);
}
// ...
} // release lock
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {
mPolicy->notifyInputDevicesChanged(inputDevices);
}
// 3. 把事件傳給 InputDispatcher 處理(也可以理解為交給分發(fā)線程處理)
mQueuedListener->flush(); // 這個(gè) mQueuedListener 其實(shí)就是 InputDispatcher
}
上面的代碼是上一節(jié)內(nèi)容的代碼,還是以 SingleTouch 為例,事件簡(jiǎn)單處理最終調(diào)用 getListener()->notifyMotion(&args),然后再調(diào)用 mQueuedListener->flush();
void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
// push() 方法:STL中常見(jiàn)的方法,向數(shù)據(jù)結(jié)構(gòu)中添加元素
mArgsQueue.push(new NotifyMotionArgs(*args));
}
void QueuedInputListener::flush() {
size_t count = mArgsQueue.size();
for (size_t i = 0; i < count; i++) {
NotifyArgs* args = mArgsQueue[i];
// mInnerListener 是 QueuedInputListener 構(gòu)造函數(shù)中傳入的 InputDispatcher
args->notify(mInnerListener);
delete args;
}
mArgsQueue.clear();
}
// 還是以上一節(jié)中為例 所以這里調(diào)用的時(shí) NotifyMotionArgs 的 notify() 方法;
void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const {
listener->notifyMotion(this); // 終于到 InputDispatcher 中了;
}
2.2 InputDispatcher::notifyMotion():從事件獲取到簡(jiǎn)單處理 mPolicy->interceptMotionBeforeQueueing(),最終通過(guò) needWake = true 喚醒分發(fā)線程;
在 InputReader 中通過(guò) listener->notifyMotion(this) 將事件封裝成 NotifyMotionArgs 傳遞到 InputDispatcher;
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
//(1)獲取發(fā)送事件:即封裝的 NotifyMotionArgs* args (上面講到的內(nèi)容)
// ... 省略一些打印信息的代碼
// 判斷是否是有效的事件
if (!validateMotionEvent(args->action, args->pointerCount, args->pointerProperties)) {
return;
}
uint32_t policyFlags = args->policyFlags;
policyFlags |= POLICY_FLAG_TRUSTED;
//(2)放入隊(duì)列前的簡(jiǎn)單處理
// 注釋 /*byref*/ 表示 "引用類型的變量",說(shuō)明這個(gè)方法的處理結(jié)果會(huì)保存在 policyFlags 中;并且最后根據(jù)
// 這個(gè) policyFlags 構(gòu)造出 newEntry;
mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);
bool needWake;
{ // acquire lock
mLock.lock();
if (shouldSendMotionToInputFilterLocked(args)) {
mLock.unlock();
MotionEvent event;
event.initialize(args->deviceId, args->source, args->action, args->flags,
args->edgeFlags, args->metaState, args->buttonState, 0, 0,
args->xPrecision, args->yPrecision,
args->downTime, args->eventTime,
args->pointerCount, args->pointerProperties, args->pointerCoords);
policyFlags |= POLICY_FLAG_FILTERED;
/* IMS.filterInputEvent:可攔截事件,當(dāng)返回值為 false 的事件都直接攔截,沒(méi)有機(jī)會(huì)加入mInboundQueue隊(duì)列 */
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
return; // event 被 InputFilter 消費(fèi)掉,直接返回
}
mLock.lock();
}
// Just enqueue a new motion event.
MotionEntry* newEntry = new MotionEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
args->action, args->flags, args->metaState, args->buttonState,
args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
args->displayId,
args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
//(3)放入隊(duì)列 Queue<EventEntry> mInboundQueue
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
} // release lock
if (needWake) {
mLooper->wake(); // 如果需要喚醒 InputDispatcher 線程, 則調(diào)用 Looper 的 wake() 方法
}
}
(1)獲取發(fā)送事件:notifyMotion() 方法中的參數(shù),即封裝的 NotifyMotionArgs* args;
(2)放入隊(duì)列前的簡(jiǎn)單處理: mPolicy->interceptMotionBeforeQueueing()
要想搞明白進(jìn)行了什么處理,首先得先搞明白這個(gè) mPolicy 是什么。
// mPolicy 定義:在 InputDispatcher.h 中
class Connection : public RefBase {
public:
sp<InputDispatcherPolicyInterface> mPolicy;
}
// mPolicy 的初始化:InputDispatcher 的構(gòu)造函數(shù)中
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
mPolicy(policy),/* mPolicy 的初始化,傳入的參數(shù) */
mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
mNextUnblockedEvent(NULL),
mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
mLooper = new Looper(false);
mKeyRepeatState.lastKeyEntry = NULL;
policy->getDispatcherConfiguration(&mConfig);
}
跟蹤代碼,結(jié)果發(fā)現(xiàn)是在 frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp 中初始化 InputManager(eventHub, this, this) 中傳入的 this (第三個(gè)參數(shù)),那就很容易找到 interceptMotionBeforeQueueing() 這個(gè)方法的代碼了:
void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
if (mInteractive) {
policyFlags |= POLICY_FLAG_INTERACTIVE;
}
if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {
if (policyFlags & POLICY_FLAG_INTERACTIVE) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
} else {
JNIEnv* env = jniEnv();
// 這是 JNI 回調(diào) Java 中的代碼:interceptMotionBeforeQueueingNonInteractive 的同名函數(shù) */
// 在這里直接說(shuō)明這個(gè)同名函數(shù) PhoneWindowManger.java 中,后續(xù)單獨(dú)一節(jié)來(lái)講 JNI 系統(tǒng)
jint wmActions = env->CallIntMethod(mServiceObj,
gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive,
when, policyFlags);
if (checkAndClearExceptionFromCallback(env,
"interceptMotionBeforeQueueingNonInteractive")) {
wmActions = 0;
}
// 根據(jù)回調(diào) Java 中的方法得到的結(jié)果 wmActions 來(lái)設(shè)置 policyFlags
handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
}
} else {
if (mInteractive) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
}
PhoneWindowManger.java 中:interceptMotionBeforeQueueingNonInteractive()
@Override
public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
if ((policyFlags & FLAG_WAKE) != 0) {
mPowerManager.wakeUp(whenNanos / 1000000);
return 0;
}
if (shouldDispatchInputWhenNonInteractive()) { // 有沒(méi)有鎖屏之類的
return ACTION_PASS_TO_USER; // 發(fā)送給 USER
}
return 0;
}
private boolean shouldDispatchInputWhenNonInteractive() {
return keyguardIsShowingTq() && mDisplay != null &&
mDisplay.getState() != Display.STATE_OFF; // 屏幕不是熄屏狀態(tài)
}
(3)將事件放入隊(duì)列 Queue<EventEntry> mInboundQueue:enqueueInboundEventLocked()
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
bool needWake = mInboundQueue.isEmpty(); // 如果隊(duì)列為空 , 則需要喚醒
mInboundQueue.enqueueAtTail(entry); // 插入到mInboundQueue隊(duì)列尾部
traceInboundQueueLengthLocked();
switch (entry->type) {
// 這里會(huì)優(yōu)化App切換的事件,如果上一個(gè)App還有事件沒(méi)處理完,也沒(méi)反饋事件處理完畢消息
// 則清空之前的事件,切換下一個(gè)應(yīng)用
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
if (isAppSwitchKeyEventLocked(keyEntry)) {
if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
mAppSwitchSawKeyDown = true;
} else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
if (mAppSwitchSawKeyDown) {
mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
mAppSwitchSawKeyDown = false;
needWake = true;
}
}
}
break;
}
// 當(dāng)一個(gè)非當(dāng)前激活app的點(diǎn)擊事件發(fā)生,會(huì)清空之前的事件
// 從這個(gè)新的點(diǎn)擊事件開(kāi)始
case EventEntry::TYPE_MOTION: {
MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
&& (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
&& mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
&& mInputTargetWaitApplicationHandle != NULL) {
int32_t displayId = motionEntry->displayId;
int32_t x = int32_t(motionEntry->pointerCoords[0].
getAxisValue(AMOTION_EVENT_AXIS_X));
int32_t y = int32_t(motionEntry->pointerCoords[0].
getAxisValue(AMOTION_EVENT_AXIS_Y));
sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y);
if (touchedWindowHandle != NULL
&& touchedWindowHandle->inputApplicationHandle
!= mInputTargetWaitApplicationHandle) {
mNextUnblockedEvent = motionEntry;
needWake = true;
}
}
break;
}
return needWake;
}
/*
這里做了兩種優(yōu)化,主要是在當(dāng)前App窗口處理事件過(guò)慢,同時(shí)你又觸發(fā)其他App的事件時(shí),Dispatcher就會(huì)
丟棄先前的事件,從這個(gè)開(kāi)始喚醒Dispatcher。這樣做很合情合理,用戶在使用時(shí),會(huì)遇到App由于開(kāi)發(fā)者水
平有限導(dǎo)致處理事件過(guò)慢情況,這時(shí)用戶等的不耐煩,則應(yīng)該讓用戶輕松的切換到其它 App,而不是阻塞在
那。所以,事件無(wú)法響應(yīng)只會(huì)發(fā)生在App內(nèi)部,而不會(huì)影響應(yīng)用的切換,從而提升用戶體驗(yàn)。App的質(zhì)量問(wèn)題
不會(huì)影響系統(tǒng)的運(yùn)轉(zhuǎn)。
*/
在這里 needWake 置為 true 后,結(jié)合上面的內(nèi)容,喚醒了事件分發(fā)線程,接下來(lái)就分析一下這個(gè)事件分發(fā)線程。
3. 發(fā)送事件給目標(biāo)app
InputDispatcherThread 與 前一節(jié)的中的 InputReader 線程一樣,直接進(jìn)入它的 threadLoop() 方法:
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce(); //調(diào)用了 InputDispatcher 的 dispatchOnce()
return true;
}
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
mDispatcherIsAliveCondition.broadcast();
// 第一次進(jìn)來(lái)時(shí) mCommandQueue 為空,能進(jìn)入此分支;
// 然后在 dispatchOnceInnerLocked() 方法中 return;
// 最終在 mLooper->pollOnce(timeoutMillis) 休眠等待;
if (!haveCommandsLocked()) { // 為空則開(kāi)始處理事件
// 會(huì)創(chuàng)建一個(gè) commandEntry,并 mCommandQueue.enqueueAtTail(commandEntry)
dispatchOnceInnerLocked(&nextWakeupTime);
}
// Run all pending commands if there are any.
// If any commands were run then force the next poll to wake up immediately.
// 如果 mCommandQueue 不為空,消費(fèi)掉隊(duì)列中的 commandEntry,直到為空
if (runCommandsLockedInterruptible()) { // mCommandQueue.isEmpty() 時(shí)返回 false
nextWakeupTime = LONG_LONG_MIN; // 如果有命令時(shí)立刻喚醒分發(fā)線程;
}
} // release lock
// Wait for callback or timeout or wake. (make sure we round up, not down)
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
// looper進(jìn)入休眠等待,wake() 方法喚醒(向fd中寫(xiě)入數(shù)據(jù)就會(huì)喚醒)
mLooper->pollOnce(timeoutMillis);
}
dispatchOnceInnerLocked() -> pokeUserActivityLocked() -> postCommandLocked(),在此過(guò)程中從事件隊(duì)列中取出事件,調(diào)用 pokeUserActivityLocked() 最終連接 PowerMangerService 保持屏幕喚醒;
// 傳遞流程 這個(gè)分支紀(jì)錄一下,暫時(shí)不跟進(jìn);
// 向 mCommandQueue 中添加 commandEntry:postCommandLocked() 方法中
(1)CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doPokeUserActivityLockedInterruptible)
(2)InputDispatcher.doPokeUserActivityLockedInterruptible ->
(3)com_android_server_input_InputManagerService.pokeUserActivit ->
(4)com_android_server_power_PowerManagerService.android_server_PowerManagerService_userActivity ->
(5)PowerManagerService.userActivityFromNative ->
(6)PowerManagerService.userActivityInternal ->
(7)PowerManagerService.userActivityNoUpdateLocked{ updatePowerStateLocked(); }
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
nsecs_t currentTime = now();
// 判斷事件分發(fā)是否允許,也就是在 IMS 未成功啟動(dòng)、非交互狀態(tài)下等是不可用的,默認(rèn)值是 false
if (!mDispatchEnabled) {
resetKeyRepeatLocked();
}
//判斷分發(fā)線程是否被凍結(jié),是否可以配發(fā),默認(rèn)值是false
if (mDispatchFrozen) {
return;
}
// 當(dāng)事件分發(fā)的事件點(diǎn)距離該事件加入 mInboundQueue 的時(shí)間超過(guò)500ms時(shí),則判定 app 切換過(guò)期;
// isAppSwitchDue 為 true;
bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
if (mAppSwitchDueTime < *nextWakeupTime) {
*nextWakeupTime = mAppSwitchDueTime;
}
//mPendingEvent是即將要被配發(fā)的事件,派發(fā)完成置為null,此處是判斷是否正在配發(fā)事件
if (! mPendingEvent) {
if (mInboundQueue.isEmpty()) { // 如果Event隊(duì)列為空的話
if (isAppSwitchDue) {
// The inbound queue is empty so the app switch key we were waiting
// for will never arrive. Stop waiting for it.
resetPendingAppSwitchLocked(false);
isAppSwitchDue = false;
}
// Synthesize a key repeat if appropriate.
if (mKeyRepeatState.lastKeyEntry) {
if (currentTime >= mKeyRepeatState.nextRepeatTime) {
mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
} else {
if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
*nextWakeupTime = mKeyRepeatState.nextRepeatTime;
}
}
}
// Nothing to do if there is no pending event.
if (!mPendingEvent) { // 如果沒(méi)有要處理的事件 , 則返回
return;
}
} else {// 有Event時(shí),取出第一個(gè)Event;
// Inbound queue has at least one entry.
mPendingEvent = mInboundQueue.dequeueAtHead();
traceInboundQueueLengthLocked();
}
// Poke user activity for this event.
if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
pokeUserActivityLocked(mPendingEvent);
}
// Get ready to dispatch the event.
// 重置此次事件分發(fā)的ANR超時(shí)時(shí)間,如果超過(guò)5秒,就會(huì)產(chǎn)生ANR
resetANRTimeoutsLocked();
}
// Now we have an event to dispatch.
// All events are eventually dequeued and processed this way, even if we intend to drop them.
ALOG_ASSERT(mPendingEvent != NULL);
bool done = false;
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;
}
if (mNextUnblockedEvent == mPendingEvent) {
mNextUnblockedEvent = NULL;
}
switch (mPendingEvent->type) {
// 處理 Configuration Change消息 , 即屏幕旋轉(zhuǎn)等等
case EventEntry::TYPE_CONFIGURATION_CHANGED: {
ConfigurationChangedEntry* typedEntry =
static_cast<ConfigurationChangedEntry*>(mPendingEvent);
done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
break;
}
// 處理設(shè)備重置消息
case EventEntry::TYPE_DEVICE_RESET: {
DeviceResetEntry* typedEntry =
static_cast<DeviceResetEntry*>(mPendingEvent);
done = dispatchDeviceResetLocked(currentTime, typedEntry);
dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
break;
}
// 處理Key按鍵消息
case EventEntry::TYPE_KEY: {
KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
if (isAppSwitchDue) {
if (isAppSwitchKeyEventLocked(typedEntry)) {
resetPendingAppSwitchLocked(true);
isAppSwitchDue = false;
} else if (dropReason == DROP_REASON_NOT_DROPPED) {
dropReason = DROP_REASON_APP_SWITCH;
}
}
if (dropReason == DROP_REASON_NOT_DROPPED
&& isStaleEventLocked(currentTime, typedEntry)) {
dropReason = DROP_REASON_STALE;
}
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
// 判斷時(shí)觸屏事件時(shí):
case EventEntry::TYPE_MOTION: {
MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
dropReason = DROP_REASON_APP_SWITCH;
}
if (dropReason == DROP_REASON_NOT_DROPPED
&& isStaleEventLocked(currentTime, typedEntry)) {
dropReason = DROP_REASON_STALE;
}
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
done = dispatchMotionLocked(currentTime, typedEntry,
&dropReason, nextWakeupTime); // 分發(fā)事件
break;
}
default:
ALOG_ASSERT(false);
break;
}
if (done) {
if (dropReason != DROP_REASON_NOT_DROPPED) {
dropInboundEventLocked(mPendingEvent, dropReason); // 從配發(fā)隊(duì)列里面丟棄事件
}
releasePendingEventLocked();
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
(關(guān)鍵代碼1)分發(fā)事件:done = dispatchMotionLocked();
bool InputDispatcher::dispatchMotionLocked(
nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
//...
bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
// 定義 targets(存儲(chǔ)窗口的集合) 找到目標(biāo)窗口
Vector<InputTarget> inputTargets;
bool conflictingPointerActions = false;
int32_t injectionResult;
if (isPointerEvent) {
// Pointer event. (eg. touchscreen)
// 如果是手指事件的話 ,則找到 Touch 窗口:關(guān)鍵代碼1
injectionResult = findTouchedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
} else {
// Non touch event. (eg. trackball)
// 如果不是手指觸摸事件 , 比如軌跡球事件的話 , 則找到Focus窗口;這個(gè)分支不是重點(diǎn)
injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime);
}
// 如果找到窗口失敗, 返回
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}
setInjectionResultLocked(entry, injectionResult);
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
return true;
}
// TODO: support sending secondary display events to input monitors
if (isMainDisplay(entry->displayId)) {
addMonitoringTargetsLocked(inputTargets);
}
// Dispatch the motion.
if (conflictingPointerActions) {
CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
"conflicting pointer actions");
synthesizeCancelationEventsForAllConnectionsLocked(options);
}
// 開(kāi)始向窗口分發(fā)事件:關(guān)鍵代碼2
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
3.1 找到目標(biāo) app (也就是找到目標(biāo)窗口):findTouchedWindowTargetsLocked(),也是這個(gè)方法限制了不同app在不同窗口層級(jí)時(shí),上面的app不能把觸屏事件分發(fā)給下面的app;先挖一個(gè)坑吧,后續(xù)寫(xiě)一章節(jié)來(lái)講這里的目標(biāo)窗口和 app 的綁定。
int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
const MotionEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
bool* outConflictingPointerActions) {
// ...
if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
//從 MotionEntry 中獲取坐標(biāo)點(diǎn)
int32_t pointerIndex = getMotionEventActionPointerIndex(action);
int32_t x = int32_t(entry->pointerCoords[pointerIndex].
getAxisValue(AMOTION_EVENT_AXIS_X));
int32_t y = int32_t(entry->pointerCoords[pointerIndex].
getAxisValue(AMOTION_EVENT_AXIS_Y));
sp<InputWindowHandle> newTouchedWindowHandle;
bool isTouchModal = false;
size_t numWindows = mWindowHandles.size();//1
// 遍歷窗口,找到觸摸過(guò)的窗口和窗口之外的外部目標(biāo)
for (size_t i = 0; i < numWindows; i++) {//2
//獲取InputDispatcher中代表窗口的windowHandle
sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
//得到窗口信息windowInfo
const InputWindowInfo* windowInfo = windowHandle->getInfo();
if (windowInfo->displayId != displayId) {
//如果displayId不匹配,開(kāi)始下一次循環(huán)
continue;
}
//獲取窗口的 flag
int32_t flags = windowInfo->layoutParamsFlags;
//如果窗口時(shí)可見(jiàn)的
if (windowInfo->visible) {
//如果窗口的 flag 不為FLAG_NOT_TOUCHABLE(窗口是 touchable)
if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
// 如果窗口是 focusable 或者 flag 不為FLAG_NOT_FOCUSABLE,則說(shuō)明該窗口是"可觸摸模式"
isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
| InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;//3
//如果窗口是可觸摸模式或者坐標(biāo)點(diǎn)落在窗口之上(找到目標(biāo)窗口)
if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
newTouchedWindowHandle = windowHandle;//4
break; // found touched window, exit window loop
}
}
if (maskedAction == AMOTION_EVENT_ACTION_DOWN
&& (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) {
//將符合條件的窗口放入TempTouchState中,以便后續(xù)處理。
mTempTouchState.addOrUpdateWindow(
windowHandle, InputTarget::FLAG_DISPATCH_AS_OUTSIDE, BitSet32(0));//5
}
}
// ...
}
} else{
// ...
}
// ...
// 把臨時(shí)存放窗口的 TempTouchState 加入到全局的 inputTargets 中
for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
touchedWindow.pointerIds, inputTargets);
}
// ...
}
(關(guān)鍵代碼2)開(kāi)始向窗口分發(fā)事件:dispatchEventLocked(currentTime, entry, inputTargets)
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
pokeUserActivityLocked(eventEntry);
for (size_t i = 0; i < inputTargets.size(); i++) { // 遍歷 inputTargets
const InputTarget& inputTarget = inputTargets.itemAt(i);
ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
if (connectionIndex >= 0) {
// 獲取跨進(jìn)程通訊的連接;
sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
// 通過(guò)拿到的連接進(jìn)行分發(fā);
prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
} else {
// ...
}
}
}
調(diào)用流程:
prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget) ->
enqueueDispatchEntriesLocked(currentTime, connection, splitMotionEntry, inputTarget) ->
startDispatchCycleLocked(currentTime, connection)
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
// ...
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
bool wasEmpty = connection->outboundQueue.isEmpty();
// Enqueue dispatch entries for the requested modes.
// 以下方法會(huì)調(diào)用 connection->outboundQueue.enqueueAtTail(dispatchEntry),
// 將事件放入隊(duì)列 Queue<DispatchEntry> outboundQueue;
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_IS);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
// If the outbound queue was previously empty, start the dispatch cycle going.
if (wasEmpty && !connection->outboundQueue.isEmpty()) {
// 從 outboundQueue 取出事件,通過(guò) Connection 發(fā)送給目標(biāo) app;
startDispatchCycleLocked(currentTime, connection);
}
}
3.2 將事件放入隊(duì)列 Queue<DispatchEntry> outboundQueue:
void InputDispatcher::enqueueDispatchEntryLocked(
const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
int32_t dispatchMode) {
int32_t inputTargetFlags = inputTarget->flags;
if (!(inputTargetFlags & dispatchMode)) {
return;
}
inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;
// This is a new event.
// Enqueue a new dispatch entry onto the outbound queue for this connection.
DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref
inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
inputTarget->scaleFactor);
// Apply target flags and update the connection's input state.
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
dispatchEntry->resolvedAction = keyEntry->action;
dispatchEntry->resolvedFlags = keyEntry->flags;
if (!connection->inputState.trackKey(keyEntry,
dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
delete dispatchEntry;
return; // skip the inconsistent event
}
break;
}
case EventEntry::TYPE_MOTION: {
MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
} else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
} else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
} else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
} else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
} else {
dispatchEntry->resolvedAction = motionEntry->action;
}
if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
&& !connection->inputState.isHovering(
motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) {
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
}
dispatchEntry->resolvedFlags = motionEntry->flags;
if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
}
if (!connection->inputState.trackMotion(motionEntry,
dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
delete dispatchEntry;
return; // skip the inconsistent event
}
break;
}
}
// Remember that we are waiting for this dispatch to complete.
if (dispatchEntry->hasForegroundTarget()) {
incrementPendingForegroundDispatchesLocked(eventEntry);
}
// Enqueue the dispatch entry.
connection->outboundQueue.enqueueAtTail(dispatchEntry);
traceOutboundQueueLengthLocked(connection);
}
3.3 從 outboundQueue 取出事件,通過(guò) Connection 發(fā)送給目標(biāo) app:
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection) {
while (connection->status == Connection::STATUS_NORMAL&& !connection->outboundQueue.isEmpty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.head;
dispatchEntry->deliveryTime = currentTime;
// Publish the event.
status_t status;
EventEntry* eventEntry = dispatchEntry->eventEntry;
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
// ... key 事件
break;
}
case EventEntry::TYPE_MOTION: {
MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
PointerCoords scaledCoords[MAX_POINTERS];
const PointerCoords* usingCoords = motionEntry->pointerCoords;
// Set the X and Y offset depending on the input source.
float xOffset, yOffset, scaleFactor;
if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
&& !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
scaleFactor = dispatchEntry->scaleFactor;
xOffset = dispatchEntry->xOffset * scaleFactor;
yOffset = dispatchEntry->yOffset * scaleFactor;
if (scaleFactor != 1.0f) {
for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
scaledCoords[i] = motionEntry->pointerCoords[i];
scaledCoords[i].scale(scaleFactor);
}
usingCoords = scaledCoords;
}
} else {
xOffset = 0.0f;
yOffset = 0.0f;
scaleFactor = 1.0f;
// We don't want the dispatch target to know.
if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
scaledCoords[i].clear();
}
usingCoords = scaledCoords;
}
}
// Publish the motion event.
// 通過(guò)連接分發(fā)給遠(yuǎn)程端;
status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
motionEntry->deviceId, motionEntry->source,
dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState,
xOffset, yOffset,
motionEntry->xPrecision, motionEntry->yPrecision,
motionEntry->downTime, motionEntry->eventTime,
motionEntry->pointerCount, motionEntry->pointerProperties,
usingCoords);
break;
}
// Check the result.
if (status) {
// ...
return;
}
// Re-enqueue the event on the wait queue.
connection->outboundQueue.dequeue(dispatchEntry);
traceOutboundQueueLengthLocked(connection);
connection->waitQueue.enqueueAtTail(dispatchEntry);
traceWaitQueueLengthLocked(connection);
}
}
從 outboundQueue 中取出需要處理的事件,交給 connection 的 inputPublisher 去分發(fā),將事件加入到 connection 的 waitQueue 中。到這里,事件就從 InputDispatcher 中分發(fā)出去了。
4. 最后的補(bǔ)充
過(guò)調(diào)用 inputPublisher.publishMotionEvent(),將事件從 InputDispatcher 分發(fā)出去,那這個(gè)方法里到底做了些什么呢?
(1)inputPublisher.publishMotionEvent():封裝 InputMessage,并通過(guò) InputChannel 的 sendMessage() 發(fā)送出去;
status_t InputPublisher::publishMotionEvent( // ... 一系列參數(shù) ) {
if (!seq) {
ALOGE("Attempted to publish a motion event with sequence number 0.");
return BAD_VALUE;
}
if (pointerCount > MAX_POINTERS || pointerCount < 1) {
ALOGE("channel '%s' publisher ~ Invalid number of pointers provided: %" PRIu32 ".",
mChannel->getName().string(), pointerCount);
return BAD_VALUE;
}
InputMessage msg;
msg.header.type = InputMessage::TYPE_MOTION;
msg.body.motion.seq = seq;
msg.body.motion.deviceId = deviceId;
msg.body.motion.source = source;
msg.body.motion.action = action;
// ... msg.body.motion 一系列賦值
for (uint32_t i = 0; i < pointerCount; i++) {
msg.body.motion.pointers[i].properties.copyFrom(pointerProperties[i]);
msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]);
}
return mChannel->sendMessage(&msg); // 調(diào)用了 InputChannel 的 sendMessage() 方法;
}
(2)sendMessage():通過(guò)系統(tǒng)的 send() 函數(shù)向 fd 中寫(xiě)入上面封裝的 InputMessage
status_t InputChannel::sendMessage(const InputMessage* msg) {
size_t msgLength = msg->size();
ssize_t nWrite;
do {
// send:是一個(gè)系統(tǒng)調(diào)用函數(shù),用來(lái)發(fā)送消息到一個(gè)套接字中
// end()函數(shù)只能在套接字處于連接狀態(tài)的時(shí)候才能使用。(只有這樣才知道接受者是誰(shuí))
nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
if (nWrite < 0) {
int error = errno;
if (error == EAGAIN || error == EWOULDBLOCK) {
return WOULD_BLOCK;
}
if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED || error == ECONNRESET) {
return DEAD_OBJECT;
}
return -error;
}
if (size_t(nWrite) != msgLength) {
return DEAD_OBJECT;
}
return OK;
}