input事件处理流程(四)

4.inputdispatcher的功能

既然事件已经从硬件上读取出来了,那么现在其实需要的就是将这个事件发送给对应的接收者处理。那先来看看inputdispatcher吧。

202InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
203    mPolicy(policy),
204    mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED),
205    mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
206    mNextUnblockedEvent(NULL),
207    mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
208    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
209    mLooper = new Looper(false);//注意此处是一个新的looper
210
211    mKeyRepeatState.lastKeyEntry = NULL;
212
213    policy->getDispatcherConfiguration(&mConfig);
214}

那我们接着上篇的inputreader将事件封装后,传递了过来,调用了notifykey

2388void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
//重新封装初始化key
2442    KeyEvent event;
2443    event.initialize(args->deviceId, args->source, args->action,
2444            flags, keyCode, args->scanCode, metaState, 0,
2445            args->downTime, args->eventTime);
2446
2447    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
2448
//查看是否需要wake这个looper
2474    if (needWake) {
2475        mLooper->wake();
2476    }
2477}

这里可以看到,事件传递上来后,需要先进行policy的一次过滤,这个policy就是当时我们传进去的nativeinputmanager

985void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
986        uint32_t& policyFlags) {
987    ATRACE_CALL();
988    // Policy:
989    // - Ignore untrusted events and pass them along.
990    // - Ask the window manager what to do with normal events and trusted injected events.
991    // - For normal events wake and brighten the screen if currently off or dim.
//备注解释的特别清楚了
1001        if (keyEventObj) {
    //通过jni的方式回调java层
1002            wmActions = env->CallIntMethod(mServiceObj,
1003                    gServiceClassInfo.interceptKeyBeforeQueueing,
1004                    keyEventObj, policyFlags);
1005            if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
1006                wmActions = 0;
1007            }
1008            android_view_KeyEvent_recycle(env, keyEventObj);
1009            env->DeleteLocalRef(keyEventObj);
1010        } else {
1011            ALOGE("Failed to obtain key event object for interceptKeyBeforeQueueing.");
1012            wmActions = 0;
1013        }
1021}

回调java层的函数,这时候回到java层

1970    private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
1971        return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
1972    }

可以看到,这里其实是掉了当时设置的callback的interceptkeybeforequeue。那当时的callback是啥呢。

当时设置的wm.getinputmonitor,这个inputmonitor是新建出来的,那么

446    @Override
447    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
448        if(mService.mTestFlag){
449            return 0x00000001;
450        }else {
451            return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
452        }
453    }

可以看到又回传到了policy,于是再次回到wms,此处的policy是在新建的时候传入的,查看新建的时候。

896            wm = WindowManagerService.main(context, inputManager,
897                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
898                    !mFirstBoot, mOnlyCore, new PhoneWindowManager());

所以也就是新建的phonewindowmanager。此处也就解释了,为什么有些点击事件是不会传给应用的,而是在phonewindowmanager那里就已经被拦截了。phonewindowmanager里面的一系列策略就不说了,只是会回传结果是是否需要发送给用户。此时回到inputdispatcher,

408bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
409    bool needWake = mInboundQueue.isEmpty();
410    mInboundQueue.enqueueAtTail(entry);
//此处可以看到,一开始就已经把这个事件放进了队列中
464
465    return needWake;
466}

在确认了是否需要wake后,如果需要wake,那么就wake了当前的looper。会调用dispatchonce。

230void InputDispatcher::dispatchOnce() {
231    nsecs_t nextWakeupTime = LONG_LONG_MAX;
232    { // acquire lock
233        AutoMutex _l(mLock);
234        mDispatcherIsAliveCondition.broadcast();
235
236        // Run a dispatch loop if there are no pending commands.
237        // The dispatch loop might enqueue commands to run afterwards.
238        if (!haveCommandsLocked()) {
239            dispatchOnceInnerLocked(&nextWakeupTime);//在此处进行了dispatch操作
240        }
241
242        // Run all pending commands if there are any.
243        // If any commands were run then force the next poll to wake up immediately.
244        if (runCommandsLockedInterruptible()) {
245            nextWakeupTime = LONG_LONG_MIN;
246        }
247    } // release lock
248
249    // Wait for callback or timeout or wake.  (make sure we round up, not down)
250    nsecs_t currentTime = now();
251    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
252    mLooper->pollOnce(timeoutMillis);
253}

看到这里,应该就知道中间的dispatchoneceinner方法就是dispatch的方法了

255void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
280
281    // Ready to start a new event.
282    // If we don't already have a pending event, go grab one.
283    if (! mPendingEvent) {
284        if (mInboundQueue.isEmpty()) {
285            if (isAppSwitchDue) {
286                // The inbound queue is empty so the app switch key we were waiting
287                // for will never arrive.  Stop waiting for it.
288                resetPendingAppSwitchLocked(false);
289                isAppSwitchDue = false;
290            }
291
292            // Synthesize a key repeat if appropriate.
293            if (mKeyRepeatState.lastKeyEntry) {
294                if (currentTime >= mKeyRepeatState.nextRepeatTime) {
    //如果当前没有事件的话,就从queue中取出一个
295                    mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
296                } else {
297                    if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
298                        *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
299                    }
300                }
301            }
302
303            // Nothing to do if there is no pending event.
304            if (!mPendingEvent) {
305                return;
306            }
307        } else {
    //如果有的话就直接取出来
308            // Inbound queue has at least one entry.
309            mPendingEvent = mInboundQueue.dequeueAtHead();
310            traceInboundQueueLengthLocked();
311        }
322    // Now we have an event to dispatch.
323    // All events are eventually dequeued and processed this way, even if we intend to drop them.
324    ALOG_ASSERT(mPendingEvent != NULL);
325    bool done = false;
326    DropReason dropReason = DROP_REASON_NOT_DROPPED;
327    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
328        dropReason = DROP_REASON_POLICY;
329    } else if (!mDispatchEnabled) {
330        dropReason = DROP_REASON_DISABLED;
331    }
332
333    if (mNextUnblockedEvent == mPendingEvent) {
334        mNextUnblockedEvent = NULL;
335    }
336
    //对不同事件的处理
337    switch (mPendingEvent->type) {
338    case EventEntry::TYPE_CONFIGURATION_CHANGED: {
339        ConfigurationChangedEntry* typedEntry =
340                static_cast<ConfigurationChangedEntry*>(mPendingEvent);
341        done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
342        dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
343        break;
344    }
345
346    case EventEntry::TYPE_DEVICE_RESET: {
347        DeviceResetEntry* typedEntry =
348                static_cast<DeviceResetEntry*>(mPendingEvent);
349        done = dispatchDeviceResetLocked(currentTime, typedEntry);
350        dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
351        break;
352    }
353
354    case EventEntry::TYPE_KEY: {
355        KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
356        if (isAppSwitchDue) {
357            if (isAppSwitchKeyEventLocked(typedEntry)) {
358                resetPendingAppSwitchLocked(true);
359                isAppSwitchDue = false;
360            } else if (dropReason == DROP_REASON_NOT_DROPPED) {
361                dropReason = DROP_REASON_APP_SWITCH;
362            }
363        }
364        if (dropReason == DROP_REASON_NOT_DROPPED
365                && isStaleEventLocked(currentTime, typedEntry)) {
366            dropReason = DROP_REASON_STALE;
367        }
368        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
369            dropReason = DROP_REASON_BLOCKED;
370        }
    //将事件传递出去
371        done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
372        break;
373    }
374
375    case EventEntry::TYPE_MOTION: {
376        MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
377        if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
378            dropReason = DROP_REASON_APP_SWITCH;
379        }
380        if (dropReason == DROP_REASON_NOT_DROPPED
381                && isStaleEventLocked(currentTime, typedEntry)) {
382            dropReason = DROP_REASON_STALE;
383        }
384        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
385            dropReason = DROP_REASON_BLOCKED;
386        }
387        done = dispatchMotionLocked(currentTime, typedEntry,
388                &dropReason, nextWakeupTime);
389        break;
390    }

406}

从上面的代码可以看出,可以取出刚刚放进queue中的事件进行处理,那么究竟是怎么处理的呢。

714bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
715        DropReason* dropReason, nsecs_t* nextWakeupTime) {
807    // Dispatch the key.
808    dispatchEventLocked(currentTime, entry, inputTargets);
809    return true;
810}

然后,经过了一系列的逻辑之后,重重判断,这时候终于可以将key dispatch出去了

918void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
919        EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
920#if DEBUG_DISPATCH_CYCLE
921    ALOGD("dispatchEventToCurrentInputTargets");
922#endif
923
924    ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
925
926    pokeUserActivityLocked(eventEntry);
927
928    for (size_t i = 0; i < inputTargets.size(); i++) {
929        const InputTarget& inputTarget = inputTargets.itemAt(i);
930
931        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
932        if (connectionIndex >= 0) {
933            sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
934            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
935        } else {
936#if DEBUG_FOCUS
937            ALOGD("Dropping event delivery to target with channel '%s' because it "
938                    "is no longer registered with the input dispatcher.",
939                    inputTarget.inputChannel->getName().string());
940#endif
941        }
942    }
943}

得到inputtarget的inputchannel,然后发送给对应的channel。

到此为止,input事件的读取和传递就已经告一段落了。

简单梳理下就是ims创建native的ims,nativeims创建inputreader和inputdispatcher,inputreader从eventhub中读取事件,同时将事件传递给inputdispatcher,inputdispatcher再将时间分发出去。

UML时序图如图

inputdispatcher事件分发流程