Android R input 之 InputDispatcher 工作流程

Posted pecuyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android R input 之 InputDispatcher 工作流程相关的知识,希望对你有一定的参考价值。

文章托管在gitee上 Android Notes , 同步csdn

InputDispatcher 的创建

如前所述,InputDispatcher 是在 InputManager 构造方法中通过工厂方法createInputDispatcher 创建.
此处的policy 实际上就是 NativeInputManager, 它是相关策略的实现类

sp<InputDispatcherInterface> createInputDispatcher(
        const sp<InputDispatcherPolicyInterface>& policy) 
    // 直接通过new创建
    return new android::inputdispatcher::InputDispatcher(policy);


创建 InputDispatcher

构造函数主要做一些初始化工作

/// @frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
      : mPolicy(policy), // 派发策略
        mPendingEvent(nullptr),  // 待分发的事件
        mLastDropReason(DropReason::NOT_DROPPED),  // 上次事件丢弃的原因
        mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
        mAppSwitchSawKeyDown(false),
        mAppSwitchDueTime(LONG_LONG_MAX), // app 切换的超时时间
        mNextUnblockedEvent(nullptr),
        mDispatchEnabled(false),
        mDispatchFrozen(false),
        mInputFilterEnabled(false),
        // mInTouchMode will be initialized by the WindowManager to the default device config.
        // To avoid leaking stack in case that call never comes, and for tests,
        // initialize it here anyways.
        mInTouchMode(true), // 默认touch mode
        // 设置focus DisplayId为默认id
        mFocusedDisplayId(ADISPLAY_ID_DEFAULT) 
    mLooper = new Looper(false); // 创建 Looper

    // The interface used by the InputDispatcher to report information about input events after
    // it is sent to the application, such as if a key is unhandled or dropped.
    // 上报unhandled or dropped key 的信息, 目前是空实现
    mReporter = createInputReporter();

    mKeyRepeatState.lastKeyEntry = nullptr;

    policy->getDispatcherConfiguration(&mConfig);

派发策略 InputDispatcherPolicyInterface

事件派发策略, 它的实现通常是在java层的PhoneWindowManager

class InputDispatcherPolicyInterface : public virtual RefBase 
protected:
    InputDispatcherPolicyInterface() 
    virtual ~InputDispatcherPolicyInterface() 

public:
    /* Notifies the system that a configuration change has occurred. */
    virtual void notifyConfigurationChanged(nsecs_t when) = 0;

    /* Notifies the system that an application is not responding.
     * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
    virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>& inputApplicationHandle,
                              const sp<IBinder>& token, const std::string& reason) = 0;  // 通知ANR

    /* Notifies the system that an input channel is unrecoverably broken. */
    virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
    virtual void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) = 0;  // 焦点改变

    /* Gets the input dispatcher configuration. */
    virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;

    /* Filters an input event.
     * Return true to dispatch the event unmodified, false to consume the event.
     * A filter can also transform and inject events later by passing POLICY_FLAG_FILTERED
     * to injectInputEvent.
     */
    virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) = 0;

    /* Intercepts a key event immediately before queueing it.
     * The policy can use this method as an opportunity to perform power management functions
     * and early event preprocessing such as updating policy flags.
     *
     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
     * should be dispatched to applications.
     */
    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0; // 入队之前的拦截操作

    /* Intercepts a touch, trackball or other motion event before queueing it.
     * The policy can use this method as an opportunity to perform power management functions
     * and early event preprocessing such as updating policy flags.
     *
     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
     * should be dispatched to applications.
     */
    virtual void interceptMotionBeforeQueueing(const int32_t displayId, nsecs_t when,
                                               uint32_t& policyFlags) = 0;

    /* Allows the policy a chance to intercept a key before dispatching. */   // 分发之前的拦截操作
    virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>& token,const KeyEvent* keyEvent,uint32_t policyFlags) = 0;

    /* Allows the policy a chance to perform default processing for an unhandled key.
     * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
    virtual bool dispatchUnhandledKey(const sp<IBinder>& token, const KeyEvent* keyEvent,uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;

    /* Notifies the policy about switch events.
     */
    virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
                              uint32_t policyFlags) = 0;

    /* Poke user activity for an event dispatched to a window. */
    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0;

    /* Checks whether a given application pid/uid has permission to inject input events into other applications.
     *
     * This method is special in that its implementation promises to be non-reentrant and
     * is safe to call while holding other locks.  (Most other methods make no such guarantees!)
     */
    virtual bool checkInjectEventsPermissionNonReentrant(int32_t injectorPid,
                                                         int32_t injectorUid) = 0;

    /* Notifies the policy that a pointer down event has occurred outside the current focused window.
     *
     * The touchedToken passed as an argument is the window that received the input event.
     */
    virtual void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) = 0;
;

NativeInputManager::getDispatcherConfiguration

InputDispatcher构造的最后,通过policy获取配置信息, 此处的policy实际上是NativeInputManager对象. 通过实现可知,是通过IMS的相关方法获取时间.

void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) 
    ATRACE_CALL();
    JNIEnv* env = jniEnv();

    jint keyRepeatTimeout = env->CallIntMethod(mServiceObj,
            gServiceClassInfo.getKeyRepeatTimeout); // 通过IMS 获取第一个按键重复事件的超时时间 默认500ms
    if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatTimeout")) 
        outConfig->keyRepeatTimeout = milliseconds_to_nanoseconds(keyRepeatTimeout);
    

    jint keyRepeatDelay = env->CallIntMethod(mServiceObj,
            gServiceClassInfo.getKeyRepeatDelay); // 获取连续重复按键之间的时间 50s
    if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatDelay")) 
        outConfig->keyRepeatDelay = milliseconds_to_nanoseconds(keyRepeatDelay);
    

InputDispatcher::start

IMS#start方法会调用nativeStart, 之后在native会进一步调用InputDispatcher::start. 在这个方法中,会创建其InputThread任务线程. 如前所述,InputThread构造方法内部会创建一个线程,并启动此线程.

status_t InputDispatcher::start() 
    if (mThread) 
        return ALREADY_EXISTS;
    
    mThread = std::make_unique<InputThread>(
            "InputDispatcher", [this]()  dispatchOnce(); , [this]()  mLooper->wake(); );
    return OK;

注意到创建InputThread时有三个参数,第一个是线程的名称,第二个是线程执行threadLoop时回调的函数,此处写法是C++11的lambda表达式,第三个参数是线程销毁前调用来唤醒线程的回调.
因此当线程运行时会不停的调用dispatchOnce, 来完成分发的操作

InputDispatcher::dispatchOnce

dispatchOnce 用于完成事件的派发,逻辑比较简洁:

  • 没有待处理的commands时, 执行派发操作, 派发是串行的处理
  • 处理 pending commands. Command通常是对dispatcher函数相关操作的封装,添加到mCommandQueue,等待dispatcher处理
  • 处理 ANR 事件
  • 计算下一次的唤醒时间, 若为LONG_LONG_MAX,则通知进入idle
  • 通过mLooper->pollOnce等待相关事件, 如 callback / timeout / wake
void InputDispatcher::dispatchOnce() 
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
     // acquire lock
        std::scoped_lock _l(mLock);
        mDispatcherIsAlive.notify_all();  // 通知dispatcher线程还活跃, 用于检测死锁

        // Run a dispatch loop if there are no pending commands.
        // The dispatch loop might enqueue commands to run afterwards.
        if (!haveCommandsLocked())  // 如果没有commands 则进行事件分发
            dispatchOnceInnerLocked(&nextWakeupTime);
        

        // Run all pending commands if there are any.
        // If any commands were run then force the next poll to wake up immediately.
        if (runCommandsLockedInterruptible())  // 执行commands
            nextWakeupTime = LONG_LONG_MIN; // 立即进行下一轮的派发
        

        // If we are still waiting for ack on some events,
        // we might have to wake up earlier to check if an app is anr'ing.
        const nsecs_t nextAnrCheck = processAnrsLocked(); // 处理anr
        nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);

        // We are about to enter an infinitely long sleep, because we have no commands or
        // pending or queued events
        if (nextWakeupTime == LONG_LONG_MAX) 
            mDispatcherEnteredIdle.notify_all();  // 通知进入idle
        
     // 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);
    mLooper->pollOnce(timeoutMillis);

InputDispatcher::dispatchOnceInnerLocked

这个函数完成一次事件的派发流程. 通常对于一个事件,调用一次就可以完成派发, 而某些事件比如key事件,当需要传递给user时,会先经过策略类进行处理,从而导致会调用多次.
这个函数的功能相对简单:

  • 取出pending事件, 当队列有事件时取出队列头, 当事件队列为空时,则尝试处理重复事件
  • 处理需要 drop 的事件
  • 针对type处理相关事件的派发
  • 结束事件派发
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) 
    nsecs_t currentTime = now();

    // Reset the key repeat timer whenever normal dispatch is suspended while the
    // device is in a non-interactive state.  This is to ensure that we abort a key
    // repeat if the device is just coming out of sleep.
    if (!mDispatchEnabled)   // 分发被禁止, 通常设备处于 non-interactive
        resetKeyRepeatLocked();
    

    // If dispatching is frozen, do not process timeouts or try to deliver any new events.
    if (mDispatchFrozen)  // 分发被冻结,直接返回
        if (DEBUG_FOCUS) 
            ALOGD("Dispatch frozen.  Waiting some more.");
        
        return;
    

    // Optimize latency of app switches.
    // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
    // been pressed.  When it expires, we preempt dispatch and drop all other pending events.
    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;  // app 切换时间到期
    if (mAppSwitchDueTime < *nextWakeupTime)  // 下次唤醒时间大于 app 切换时间到期时间,则更新唤醒时间为早的
        *nextWakeupTime = mAppSwitchDueTime;
    

    /// 下面进入派发流程
    // Ready to start a new event.
    // If we don't already have a pending event, go grab one.
    if (!mPendingEvent)  // 尝试获取新的Event来处理
        if (mInboundQueue.empty())  // 派发队列是空的
            if (isAppSwitchDue)  // 这种情况如果app切换超时, 需要重置
                // 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)  // 下次repeat时间较短,设置成wakeup时间
                        *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
                    
                
            

            // Nothing to do if there is no pending event.
            if (!mPendingEvent)  // 没有pending的直接返回
                return;
            
         else  // 不为空,则取出队列头的作为待分发事件
            // Inbound queue has at least one entry.
            mPendingEvent = mInboundQueue.front(); // 取出队列头元素
            mInboundQueue.pop_front();  // 出队
            traceInboundQueueLengthLocked();
        

        // Poke user activity for this event.
        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)  // 传给user, 则需要通知user活动
           // 此处会回调到PowerManagerService的userActivityFromNative
           // 下面调用会被封装成一个command,在下次派发循环中处理
            pokeUserActivityLocked(*mPendingEvent);
        
    

    // 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 != nullptr);
    bool done = false;
    // 判断事件是否被丢弃, 丢弃的事件不会进行分发
    DropReason dropReason = DropReason::NOT_DROPPED;
     // 如果不传递给user, 通常是在interceptKeyBeforeQueueing处理是否传递
     // 没有FLAG POLICY_FLAG_PASS_TO_USER , 则会因为DropReason::POLICY 而被丢弃
    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) 
        dropReason = DropReason::POLICY;
     else if (!mDispatchEnabled)  // 若分发被禁止
        dropReason = DropReason::DISABLED;
    

    if (mNextUnblockedEvent == mPendingEvent)  // 下一个不阻塞的事件
        mNextUnblockedEvent = nullptr;
    

    // 下面针对类型进行派发
    switch (mPendingEvent->type) 
        case EventEntry::Type::CONFIGURATION_CHANGED:  // input device configuration has changed
            ConfigurationChangedEntry* typedEntry =
                    static_cast<ConfigurationChangedEntry*>(mPendingEvent);
            done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
            dropReason = DropReason::NOT_DROPPED; // configuration changes are never dropped
            break;
        

        case EventEntry::Type::DEVICE_RESET:  //  device reset
            DeviceResetEntry* typedEntry = static_cast<DeviceResetEntry*>(mPendingEvent);
            done = dispatchDeviceResetLocked(currentTime, typedEntry);
            dropReason = DropReason::NOT_DROPPED; // device resets are never dropped
            break;
        

        case EventEntry::Type::FOCUS: 
            FocusEntry* typedEntry = static_cast<FocusEntry*>(mPendingEvent);
            dispatchFocusLocked(currentTime, typedEntry);
            done = true;
            dropReason = DropReason::NOT_DROPPED; // focus events are never dropped
            break;
        

        case EventEntry::Type::KEY:  // 派发 key 事件
            KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
            if (isAppSwitchDue)   // app切换的key事件到期, 需要丢弃此事件之前的所有事件
                if (isAppSwitchKeyEvent(*typedEntry))  // 当前事件是app切换的key事件,则重置到期时间
                    resetPendingAppSwitchLocked(true);
                    isAppSwitchDue = false;
                 else if (dropReason == DropReason::NOT_DROPPED)  // 否则此未丢弃的事件会因为APP_SWITCH而丢弃
                    dropReason = DropReason::APP_SWITCH;
                
            
            if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *typedEntry))  // 过期事件, 此时距离事件发生时间>=10sec
                dropReason = DropReason::STALE;
            
            if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent)  // 有非阻塞事件需要处理
                dropReason = DropReason::BLOCKED;
            
            done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);  // 处理key事件派发
            break;
        

        case EventEntry::Type::MOTION:   // 派发触摸事件
            MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
            if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue)  // app切换到期
                dropReason = DropReason::APP_SWITCH;
            
            if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *typedEntry))  // 过期事件
                dropReason = DropReason::STALE;
            
            if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent)  // 有非阻塞事件需要处理
                dropReason = DropReason::BLOCKED;
            
            done = dispatchMotionLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
            break;
        
    

    if (done)  // 完成派发?
        if (dropReason != DropReason::NOT_DROPPED)  // 如果被丢弃
            dropInboundEventLocked(*mPendingEvent, dropReason);
        
        mLastDropReason = dropReason;

        releasePendingEventLocked();
        *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
    

InputDispatcher::synthesizeKeyRepeatLocked

此函数用于合成一个重重复key事件, 注意repeatCount都递增了1

KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) 
    KeyEntry* entry = mKeyRepeatState.lastKeyEntry;

    // Reuse the repeated key entry if it is otherwise unreferenced.
    uint32_t policyFlags = entry->policyFlags &
            (POLICY_FLAG_RAW_MASK | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED); // 添加flag
    if (entry->refCount == 1)  // 没有其他引用时复用,防止冲突. entry->refCount默认是1
        entry->recycle();
        entry->id = mIdGenerator.nextId();
        entry->eventTime = currentTime;
        entry->policyFlags = policyFlags;
        entry->repeatCount += 1;
     else  // 已在其他地方被引用,需要创建新entry
        KeyEntry* newEntry =
                new KeyEntry(mIdGenerator.nextId(), currentTime, entry->deviceId, entry->source,
                             entry->displayId, policyFlags, entry->action, entry->flags,
                             entry->keyCode, entry->scanCode, entry->metaState,
                             entry->repeatCount + 1, entry->downTime);

        mKeyRepeatState.lastKeyEntry = newEntry;
        entry->release();

        entry = newEntry;
    
    entry->syntheticRepeat = true; // 设置事件是合成的

    // Increment reference count since we keep a reference to the event in
    // mKeyRepeatState.lastKeyEntry in addition to the one we return.
    entry->refCount += 1;

    mKeyRepeatState.nextRepeatTime = currentTime + mConfig.keyRepeatDelay; // 注意此处的nextRepeatTime,与当前间隔keyRepeatDelay 50ms
    return entry;

接下来以key事件的派发流程来分析事件派发的过程.

InputDispatcher::dispatchKeyLocked

bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
                                        DropReason* dropReason, nsecs_t* nextWakeupTime) 
    // Preprocessing.
    if (!entry->dispatchInProgress)  // 如果不是在派发过程中
        // 处理key事件的repeat
        // repeat条件: ①repeatCount为0 , ②是Down事件, ③是trusted事件 ④策略没有禁止repeat
        // 上面条件说明这是一个 initial Down事件(可能是设备驱动生成的repeat事件)
        if (entry->repeatCount == 0 && entry->action == AKEY_EVENT_ACTION_DOWN &&
            (entry->policyFlags & POLICY_FLAG_TRUSTED) &&
            (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) 
            // 根据下面的注释看,是设备驱动生成了repeat事件, 为什么此处不是之前合成的重复事件? 之前一直忽略了repeatCount成员
            // 如果是之前合成的重复事件,repeatCount则不为0(synthesizeKeyRepeatLocked函数对其进行过递增), 上面的repeat条件将不满足而无法进入  
            if (mKeyRepeatState.lastKeyEntry &&  // 既然设备驱动生成了repeat事件(也就是当前entry), 那么就不需要自己去合成一个了
                mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) // 存在lastKeyEntry, 且keyCode一致 说明此key之前触发过
                // We have seen two identical key downs in a row which indicates that the device
                // driver is automatically generating key repeats itself.  We take note of the
                // repeat here, but we disable our own next key repeat timer since it is clear that
                // we will not need to synthesize key repeats ourselves.
                entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1; // 递增repeatCount
                resetKeyRepeatLocked(); // 重置 mKeyRepeatState 为nullptr
                mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
             else 
                // Not a repeat.  Save key down state in case we do see a repeat later.
                resetKeyRepeatLocked();
                mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
            
            mKeyRepeatState.lastKeyEntry = entry; // 设置新的lastKeyEntry
            entry->refCount += 1;
         else if (!entry->syntheticRepeat)  // 不是合成的repeat事件
            resetKeyRepeatLocked(); // 重置 lastKeyEntry
        

        if (entry->repeatCount == 1)  // repeatCount 为1, 则添加长按事件的FLAG
            entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
         else 
            entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
        

        entry->dispatchInProgress = true; // 派发中..

        logOutboundKeyDetails("dispatchKey - ", *entry);
    

    // Handle case where the policy asked us to try again later last time.
    // 之前策略决定稍后重试,这个根据PhoneWindowManager#interceptKeyBeforeDispatching 返回值决定
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) 
        if (currentTime < entry->interceptKeyWakeupTime)  // 还未到时间继续 只更新唤醒时间
            if (entry->interceptKeyWakeupTime < *nextWakeupTime) 
                *nextWakeupTime = entry->interceptKeyWakeupTime;
            
            return false; // wait until next wakeup
        
        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;  // 重置, 让policy再次处理
        entry->interceptKeyWakeupTime = 0;
    

    // Give the policy a chance to intercept the key.
    // interceptKeyResult有三种情况 :
    // INTERCEPT_KEY_RESULT_SKIP(跳过派发)  INTERCEPT_KEY_RESULT_CONTINUE(继续派发) INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER(稍后重试派发)
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN)  // 为unknown,认为没有处理过
        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER)  // 如果需要传递给user, 则需要调用策略类进行处理
          // 将doInterceptKeyBeforeDispatchingLockedInterruptible操作封装成command,在执行dispatchOnceInnerLocked后处理command
            std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
                    &InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
            sp<InputWindowHandle> focusedWindowHandle =
                    getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(*entry));// 获取指定displayId对应的focusedWindowHandle
            if (focusedWindowHandle != nullptr) 
                commandEntry->inputChannel = getInputChannelLocked(focusedWindowHandle->getToken());
            
            commandEntry->keyEntry = entry;
            postCommandLocked(std::move(commandEntry)); // 投递command
            entry->refCount += 1;
            return false; // wait for the command to run  此处返回false会先执行command, 然后再继续进行此事件派发
         else   // 否则继续派发
            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
        
     else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP)  // 如果是skip则drop事件
        if (*dropReason == DropReason::NOT_DROPPED) 
            *dropReason = DropReason::POLICY;
        
    

    // Clean up if dropping the event.
    if (*dropReason != DropReason::NOT_DROPPED)  // 事件丢弃处理
        setInjectionResult(entry,
                           *dropReason == DropReason::POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED
                                                             : INPUT_EVENT_INJECTION_FAILED); // 设置事件注入的结果
        mReporter->reportDroppedKey(entry->id);
        return true;
    

    // Identify targets.
    std::vector<InputTarget> inputTargets;  // 目标窗口结果保存在此集合
    int32_t injectionResult =
            findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime); // 寻找到焦点窗口
    if (injectionResult == INPUT_EVENT_INJECTION_PENDING)  // pending表示需要等待
        return false;
    

    setInjectionResult(entry, injectionResult); // 设置事件注入的结果
    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED)  // 非success将不会被派发
        return true;
    

    // Add monitor channels from event's or focused display.
    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry)); // 将monitor列表的window也加入派发目标窗口列表

    // Dispatch the key.
    dispatchEventLocked(currentTime, entry, inputTargets);  // 开始派发事件到目标窗口
    return true;

下面看一些关键的方法的具体实现.

InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible

如上分析, 当key事件需要分发到user时,需要先通过策略处理. 将doInterceptKeyBeforeDispatchingLockedInterruptible方法的操作封装成了一个Command,然后投递到command队列.
在dispatchOnceInnerLocked完后,会执行runCommandsLockedInterruptible处理command, 因此会导致该方法被调用. 在执行完策略处理后,事件的interceptKeyResult有三种取值:

  • KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
  • KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
  • KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;
void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
        CommandEntry* commandEntry) 
    KeyEntry* entry = commandEntry->keyEntry;
    KeyEvent event = createKeyEvent(*entry);

    mLock.unlock();

    android::base::Timer t;
    // InputChannel对应的IBinder token
    sp<IBinder> token = commandEntry->inputChannel != nullptr
            ? commandEntry->inputChannel->getConnectionToken()
            : nullptr;
    // 调用路径 NativeInputManager -> InputManagerService -> InputManagerCallback -> PhoneWindowManager
    nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(token, &event, entry->policyFlags);
    if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) 
        ALOGW("Excessive delay in interceptKeyBeforeDispatching; took %s ms",
              std::to_string(t.duration().count()).c_str());
    

    mLock.lock();

    if (delay < 0)  // <0 , 事件将会跳过, 可能已经被policy处理了
        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
     else if (!delay)  // = 0 , 继续分发
        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
     else  // > 0 , 延时分发
        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;
        entry->interceptKeyWakeupTime = now() + delay;
    
    entry->release();

在处理此command后,会继续进行之前未派发完的事件派发任务, 然后根据interceptKeyResult判断是否需要继续还是丢弃事件.

InputDispatcher::findFocusedWindowTargetsLocked

再次回到dispatchKeyLocked分发, 当处理完interceptBeforeDispatch的策略后,若事件没有被丢弃,则会尝试寻找focusd window. 逻辑如下:

  • 获取指定displayId的焦点窗口和焦点应用,如果两者都不存在,则说明没有找到.如果有焦点应用,但是没有焦点窗口,则需要等待焦点窗口的出现, 默认等待5s
  • 如果找到焦点窗口,重置ANR相关信息
  • 如果是注入(inject)的事件,需要检查相关权限(android.permission.INJECT_EVENTS)
  • 如果焦点窗口处于paused状态,则需要等待
  • 如果是key事件, 则需要等待之前的事件全部处理完成才派发. 等待超时时间500ms
  • 添加当前目标窗口到inputTargets列表, 注意添加时的FLAG FLAG_FOREGROUND和FLAG_DISPATCH_AS_IS

返回值表示查找的状态:

  • INPUT_EVENT_INJECTION_FAILED 没有找到焦点窗口或等待焦点窗口出现超时
  • INPUT_EVENT_INJECTION_PENDING
    - 等待焦点窗口
    - 焦点窗口处于paused状态
    - 如果是key事件,等待之前的事件全部处理完成
  • INPUT_EVENT_INJECTION_PERMISSION_DENIED
    - 注册事件的应用uid 与目标窗口应用的uid不一致, 且没有权限 android.permission.INJECT_EVENTS
  • INPUT_EVENT_INJECTION_SUCCEEDED 找到焦点窗口
int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
                                                        const EventEntry& entry,
                                                        std::vector<InputTarget>& inputTargets,
                                                        nsecs_t* nextWakeupTime) 
    std::string reason;

    int32_t displayId = getTargetDisplayId(entry);
    sp<InputWindowHandle> focusedWindowHandle =
            getValueByKey(mFocusedWindowHandlesByDisplay, displayId); // 获取焦点窗口 handle
    sp<InputApplicationHandle> focusedApplicationHandle =
            getValueByKey(mFocusedApplicationHandlesByDisplay, displayId); // 获取焦点应用handle

    // If there is no currently focused window and no focused application
    // then drop the event.
    if (focusedWindowHandle == nullptr && focusedApplicationHandle == nullptr)  // 没有焦点应用且没有焦点窗口
        ALOGI("Dropping %s event because there is no focused window or focused application in "
              "display %" PRId32 ".",
              EventEntry::typeToString(entry.type), displayId);
        return INPUT_EVENT_INJECTION_FAILED;
    

    // Compatibility behavior: raise ANR if there is a focused application, but no focused window.
    // Only start counting when we have a focused event to dispatch. The ANR is canceled if we
    // start interacting with another application via touch (app switch). This code can be removed
    // if the "no focused window ANR" is moved to the policy. Input doesn't know whether
    // an app is expected to have a focused window.
    if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr)  // 有焦点应用但是没有焦点窗口
        if (!mNoFocusedWindowTimeoutTime.has_value())  // 新窗口可能在添加中, 等待添加完成
            // We just discovered that there's no focused window. Start the ANR timer
            const nsecs_t timeout = focusedApplicationHandle->getDispatchingTimeout(
                    DEFAULT_INPUT_DISPATCHING_TIMEOUT.count());
            mNoFocusedWindowTimeoutTime = currentTime + timeout;
            mAwaitedFocusedApplication = focusedApplicationHandle;
            ALOGW("Waiting because no window has focus but %s may eventually add a "
                  "window when it finishes starting up. Will wait for %" PRId64 "ms",
                  mAwaitedFocusedApplication->getName().c_str(), ns2ms(timeout));
            *nextWakeupTime = *mNoFocusedWindowTimeoutTime;
            return INPUT_EVENT_INJECTION_PENDING; // 返回 pending
         else if (currentTime > *mNoFocusedWindowTimeoutTime) 
            // Already raised ANR. Drop the event
            ALOGE("Dropping %s event because there is no focused window",
                  EventEntry::typeToString(entry.type));
            return INPUT_EVENT_INJECTION_FAILED; // 已经等待超时, 返回失败
         else 
            // Still waiting for the focused window
            return INPUT_EVENT_INJECTION_PENDING;  // 还未超时, 继续等待
        
    

    // we have a valid, non-null focused window
    resetNoFocusedWindowTimeoutLocked();  // 重置超时时间, Resetting ANR timeouts

    // Check permissions. 主要是通过IMS来检查权限 android.Manifest.permission.INJECT_EVENTS
    if (!checkInjectionPermission(focusedWindowHandle, entry.injectionState)) 
        return INPUT_EVENT_INJECTION_PERMISSION_DENIED;
    

    if (focusedWindowHandle->getInfo()->paused)  // 窗口paused状态,等待
        ALOGI("Waiting because %s is paused", focusedWindowHandle->getName().c_str());
        return INPUT_EVENT_INJECTION_PENDING;
    

    // If the event is a key event, then we must wait for all previous events to
    // complete before delivering it because previous events may have the
    // side-effect of transferring focus to a different window and we want to
    // ensure that the following keys are sent to the new window.
    //
    // Suppose the user touches a button in a window then immediately presses "A".
    // If the button causes a pop-up window to appear then we want to ensure that
    // the "A" key is delivered to the new pop-up window.  This is because users
    // often anticipate pending UI changes when typing on a keyboard.
    // To obtain this behavior, we must serialize key events with respect to all
    // prior input events.
    if (entry.type == EventEntry::Type::KEY)  // 如果是key事件, 则需要等待之前的事件全部处理完成才派发
        if (shouldWaitToSendKeyLocked(currentTime, focusedWindowHandle->getName().c_str())) 
            *nextWakeupTime = *mKeyIsWaitingForEventsTimeout; // 设置下次唤醒时间为等待超时时间
            return INPUT_EVENT_INJECTION_PENDING;
        
    

    // Success!  Output targets.
    addWindowTargetLocked(focusedWindowHandle,
                          InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,// 注意此处的FLAG, 在派发时生成对应的dispatchEntry
                          BitSet32(0), inputTargets);  // 保存到inputTargets

    // Done.
    return INPUT_EVENT_INJECTION_SUCCEEDED;

InputDispatcher::checkInjectionPermission

检查注入事件的权限,看是否能向当前窗口注入事件:

  • 注册事件的应用uid 与目标窗口应用的uid一致, 则可以直接注入
  • 若不一致, 则还需要权限 android.permission.INJECT_EVENTS
bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
                                               const InjectionState* injectionState) 
    if (injectionState &&
        (windowHandle == nullptr ||
          // 注册事件的应用uid 与目标窗口应用的uid不一致. 此处若相等,则整个if不成立
         windowHandle->getInfo()->ownerUid != injectionState->injectorUid) &&
         // 没有权限 android.permission.INJECT_EVENTS
        !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) 
        if (windowHandle != nullptr) 
            ALOGW("Permission denied: injecting event from pid %d uid %d to window %s "
                  "owned by uid %d",
                  injectionState->injectorPid, injectionState->injectorUid,
                  windowHandle->getName().c_str(), windowHandle->getInfo()->ownerUid);
         else 
            ALOGW("Permission denied: injecting event from pid %d uid %d",
                  injectionState->injectorPid, injectionState->injectorUid);
        
        return false;
    
    return true;

InputDispatcher::shouldWaitToSendKeyLocked

看key事件是否需要等待之前的事件派发完成

bool InputDispatcher::shouldWaitToSendKeyLocked(nsecs_t currentTime,
                                                const char* focusedWindowName) 
    // mAnrTracker为空,说明之前的事件都已经发送事件反馈,将相关anr记录从其中移除,即事件都已经派发完毕                                              
    if (mAnrTracker.empty()) 
        // already processed all events that we waited for
        mKeyIsWaitingForEventsTimeout = std::nullopt; // 清除等待超时
        return false;
    

    // 到此说明之前还有事件没有派发完, mKeyIsWaitingForEventsTimeout没有value则说明还没设置等待
    if (!mKeyIsWaitingForEventsTimeout.has_value()) 
        // Start the timer
        ALOGD("Waiting to send key to %s because there are unprocessed events that may cause "
              "focus to change",
              focusedWindowName);
        mKeyIsWaitingForEventsTimeout = currentTime + KEY_WAITING_FOR_EVENTS_TIMEOUT.count(); // 设置等待超时
        return true;
    

    // We still have pending events, and already started the timer
    if (currentTime < *mKeyIsWaitingForEventsTimeout)  // 判断等待超时事件是否还没有到
        return true; // Still waiting
    

    // Waited too long, and some connection still hasn't processed all motions
    // Just send the key to the focused window
    ALOGW("Dispatching key to %s even though there are other unprocessed events",
          focusedWindowName);
    mKeyIsWaitingForEventsTimeout = std::nullopt; // 清除等待超时
    return false;  // 已超时,不需要等待

InputDispatcher::addWindowTargetLocked
void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
                                            int32_t targetFlags, BitSet32 pointerIds,
                                            std::vector<InputTarget>& inputTargets) 
    // 查找 windowHandle 对应的 InputTarget                                        
    std::vector<InputTarget>::iterator it =
            std::find_if(inputTargets.begin(), inputTargets.end(),
                         [&windowHandle](const InputTarget& inputTarget) 
                             return inputTarget.inputChannel->getConnectionToken() ==
                                     windowHandle->getToken();  // 根据InputChannel的token判断是否存在
                         );

    const InputWindowInfo* windowInfo = windowHandle->getInfo();

    if (it == inputTargets.end())  // 不存在对应的InputTarget
        InputTarget inputTarget;
        sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken()); // 根据token查找InputChannel
        if (inputChannel == nullptr)  // 不存在InputChannel, 直接返回
            ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str());
            return;
        
        // 初始化 InputTarget
        inputTarget.inputChannel = inputChannel;
        inputTarget.flags = targetFlags;
        inputTarget.globalScaleFactor = windowInfo->globalScaleFactor; // ignored for KeyEvents
        inputTargets.push_back(inputTarget);
        it = inputTargets.end() - 1;
    

    ALOG_ASSERT(it->flags == targetFlags);
    ALOG_ASSERT(it->globalScaleFactor == windowInfo->globalScaleFactor);

    it->addPointers(pointerIds, -windowInfo->frameLeft, -windowInfo->frameTop,
                    windowInfo->windowXScale, windowInfo->windowYScale); // 设置Pointer信息

InputDispatcher::setInjectionResult

这个函数用于设置通过InputDispatcher::injectInputEvent 注入事件的结果. 后续再开篇分析事件注入.

void InputDispatcher::setInjectionResult(EventEntry* entry, int32_t injectionResult) 
    InjectionState* injectionState = entry->injectionState;
    if (injectionState)  // 不为nullptr, 则是通过injectInputEvent注入的事件
#if DEBUG_INJECTION
        ALOGD("Setting input event injection result to %d.  "
              "injectorPid=%d, injectorUid=%d",
              injectionResult, injectionState->injectorPid, injectionState->injectorUid);
#endif

        if (injectionState->injectionIsAsync && !(entry->policyFlags & POLICY_FLAG_FILTERED)) 
            // Log the outcome since the injector did not wait for the injection result.
            switch (injectionResult) 
                case INPUT_EVENT_INJECTION_SUCCEEDED:
                    ALOGV("Asynchronous input event injection succeeded.");
                    break;
                case INPUT_EVENT_INJECTION_FAILED:
                    ALOGW("Asynchronous input event injection failed.");
                    break;
                case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
                    ALOGW("Asynchronous input event injection permission denied.");
                    break;
                case INPUT_EVENT_INJECTION_TIMED_OUT:
                    ALOGW("Asynchronous input event injection timed out.");
                    break;
            
        

        injectionState->injectionResult = injectionResult;
        mInjectionResultAvailable.notify_all(); // 唤醒在injectInputEvent函数中的等待,处理结果
    

InputDispatcher::addGlobalMonitoringTargetsLocked

将全局监视器也添加到目标窗口. 通过InputManagerService#monitorInput可以注册事件监听器. PointerEventDispatcher的实现是基于此原理实现的.

void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
                                                       int32_t displayId, float xOffset,
                                                       float yOffset) 
    std::unordered_map<int32_t, std::vector<Monitor>>::const_iterator it =
            mGlobalMonitorsByDisplay.find(displayId);

    if (it != mGlobalMonitorsByDisplay.end()) 
        const std::vector<Monitor>& monitors = it->second;
        for (const Monitor& monitor : monitors) 
            addMonitoringTargetLocked(monitor, xOffset, yOffset, inputTargets);
        
    

addMonitoringTargetLocked方法如下

void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor, float xOffset,
                                                float yOffset,
                                                std::vector<InputTarget>& inputTargets) 
    InputTarget target;
    target.inputChannel = monitor.inputChannel;
    target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
    target.setDefaultPointerInfo(xOffset, yOffset, 1 /* windowXScale */, 1 /* windowYScale */);
    inputTargets.push_back(target);

InputDispatcher::dispatchEventLocked

再次回到dispatchKeyLocked, 当获取到目标窗口后, 就可以调用dispatchEventLocked来将事件派发到窗口.

void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* eventEntry,
                                          const std::vector<InputTarget>& inputTargets) 
    ATRACE_CALL();
#if DEBUG_DISPATCH_CYCLE
    ALOGD("dispatchEventToCurrentInputTargets");
#endif

    ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true

    pokeUserActivityLocked(*eventEntry); // 通知PMS user activity

    for (const InputTarget& inputTarget : inputTargets)  // 遍历目标窗口
        sp<Connection> connection =
                getConnectionLocked(inputTarget.inputChannel->getConnectionToken()); // 根据InputChannel的token获取窗口的connection
        if (connection != nullptr)  // 开始派发
            prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
         else 
            if (DEBUG_FOCUS) 
                ALOGD("Dropping event delivery to target with channel '%s' because it "
                      "is no longer registered with the input dispatcher.",
                      inputTarget.inputChannel->getName().c_str());
            
        
    

InputDispatcher::prepareDispatchCycleLocked

这个方法开启了事件派发循环. 当将事件派发到目标窗口,在目标窗口处理完毕后, 会发送一个事件处理的反馈到dispatcher, 这才算一个闭环.

void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
                                                 const sp<Connection>& connection,
                                                 EventEntry* eventEntry,
                                                 const InputTarget& inputTarget) 
    if (ATRACE_ENABLED())  /// trace
        std::string message =
                StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, id=0x%" PRIx32 ")",
                             connection->getInputChannelName().c_str(), eventEntry->id);
        ATRACE_NAME(message.c_str());
    
#if DEBUG_DISPATCH_CYCLE
    ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
          "globalScaleFactor=%f, pointerIds=0x%x %s",
          connection->getInputChannelName().c_str(), inputTarget.flags,
          inputTarget.globalScaleFactor, inputTarget.pointerIds.value,
          inputTarget.getPointerInfoString().c_str());
#endif

    // Skip this event if the connection status is not normal.
    // We don't want to enqueue additional outbound events if the connection is broken.
    if (connection->status != Connection::STATUS_NORMAL)  // connection状态不是Normal的,丢弃此事件
#if DEBUG_DISPATCH_CYCLE
        ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
              connection->getInputChannelName().c_str(), connection->getStatusLabel());
#endif
        return;
    

    // Split a motion event if needed.
    if (inputTarget.flags & InputTarget::FLAG_SPLIT)   / /针对触摸事件
        LOG_ALWAYS_FATAL_IF(eventEntry->type != EventEntry::Type::MOTION,
                            "Entry type %s should not have FLAG_SPLIT",
                            EventEntry::typeToString(eventEntry->type));

        const MotionEntry& originalMotionEntry = static_cast<const MotionEntry&>(*eventEntry);
        if (inputTarget.pointerIds.count() != originalMotionEntry.pointerCount) 
            MotionEntry* splitMotionEntry =
                    splitMotionEvent(originalMotionEntry, inputTarget.pointerIds);
            if (!splitMotionEntry) 
                return; // split event was dropped
            
            if (DEBUG_FOCUS) 
                ALOGD("channel '%s' ~ Split motion event.",
                      connection->getInputChannelName().c_str());
                logOutboundMotionDetails("  ", *splitMotionEntry);
            
            enqueueDispatchEntriesLocked(currentTime, connection, splitMotionEntry, inputTarget);
            splitMotionEntry->release();
            return;
        
    

    // Not splitting.  Enqueue dispatch entries for the event as is.
    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);

InputDispatcher::enqueueDispatchEntriesLocked

将事件添加到派发队列, 然后看是否启动派发循环

  • 原来有事件在处理, 需要等待之前的结束
  • 原来队列是空, 则需要启动派发循环
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
                                                   const sp<Connection>& connection,
                                                   EventEntry* eventEntry,
                                                   const InputTarget& inputTarget) 
    if (ATRACE_ENABLED()) 
        std::string message =
                StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, id=0x%" PRIx32 ")",
                             connection->getInputChannelName().c_str(), eventEntry->id);
        ATRACE_NAME(message.c_str());
    

    bool wasEmpty = connection->outboundQueue.empty();

    // 添加dispatchEntry, 根据inputTarget的flags过滤不必要的, 对于key事件,对应的FLAG是FLAG_DISPATCH_AS_IS
    // Enqueue dispatch entries for the requested modes.
    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); // key事件这个dispatchMode会添加
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
                               InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
                               InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);

    // connection的派发队列为空, 添加新元素,会启动connection的事件派发, 否则等待之前的事件派发完成
    // 即之前的事件派发循环的反馈收到后, 再继续下一个派发循环
    // If the outbound queue was previously empty, start the dispatch cycle going.
    if (wasEmpty && !connection->outboundQueue.empty())    
        startDispatchCycleLocked(currentTime, connection);
    

InputDispatcher::enqueueDispatchEntryLocked

对于key事件,对应的inputTarget.flags 只包含上面的FLAG_DISPATCH_AS_IS. 上面虽然加了很多dispatchMode, 但是大都被过滤掉了.

void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
                                                 EventEntry* eventEntry,
                                                 const InputTarget& inputTarget,
                                                 int32_t dispatchMode) 
    if (ATRACE_ENABLED()) 
        std::string message = StringPrintf("enqueueDispatchEntry(inputChannel=%s, dispatchMode=%s)",
                                           connection->getInputChannelName().c_str(),
                                           dispatchModeToString(dispatchMode).c_str());
        ATRACE_NAME(message.c_str());
    
    int32_t inputTargetFlags = inputTarget.flags;
    if (!(inputTargetFlags & dispatchMode))  // 过滤掉不包含的dispatchMode
        return;
    
    // 去掉除了dispatchMode的其他mode
    inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;

    // This is a new event.
    // Enqueue a new dispatch entry onto the outbound queue for this connection.
    std::unique_ptr<DispatchEntry> dispatchEntry =
            createDispatchEntry(inputTarget, eventEntry, inputTargetFlags); // 对要派发的事件创建一个 DispatchEntry

    // Use the eventEntry from dispatchEntry since the entry may have changed and can now be a
    // different EventEntry than what was passed in.
    EventEntry* newEntry = dispatchEntry->eventEntry;
    // Apply target flags and update the connection's input state.
    switch (newEntry->type) 
        case EventEntry::Type::KEY: 
            const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*newEntry);
            dispatchEntry->resolvedEventId = keyEntry.id;
            dispatchEntry->resolvedAction = keyEntry.action;
            dispatchEntry->resolvedFlags = keyEntry.flags;

            if (!connection->inputState.trackKey(keyEntry, dispatchEntry->resolvedAction,
                                                 dispatchEntry->resolvedFlags))  // 处理 inconsistent key event
#if DEBUG_DISPATCH_CYCLE
                ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
                      connection->getInputChannelName().c_str());
#endif
                return; // skip the inconsistent event
            
            break;
        

        case EventEntry::Type::MOTION: ...
        case EventEntry::Type::FOCUS: ...
        case EventEntry::Type::CONFIGURATION_CHANGED: ...
        case EventEntry::Type::DEVICE_RESET: ...
    

    // Remember that we are waiting for this dispatch to complete.
    if (dispatchEntry->hasForegroundTarget())  // 实际上就是判断 targetFlags & InputTarget::FLAG_FOREGROUND , 处理key事件添加了此FLAG
        incrementPendingForegroundDispatches(newEntry); // 尝试增加 injectionState->pendingForegroundDispatches
    

    // Enqueue the dispatch entry.
    connection->outboundQueue.push_back(dispatchEntry.release()); // 添加到connection->outboundQueue
    traceOutboundQueueLength(connection);


InputDispatcher::startDispatchCycleLocked

回到enqueueDispatchEntriesLocked的最后, 假设需要启动派发循环,将调用startDispatchCycleLocked

void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
                                               const sp<Connection>& connection) 

    while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.empty())  // 取出所有的事件进行派发
        DispatchEntry* dispatchEntry = connection->outboundQueue.front(); // 取出头部
        dispatchEntry->deliveryTime = currentTime;
        const nsecs_t timeout =  // 计算超时时间,优先取出window->getDispatchingTimeout, 默认5s
                getDispatchingTimeoutLocked(connection->inputChannel->getConnectionToken());
        dispatchEntry->timeoutTime = currentTime + timeout;

        // Publish the event.
        status_t status;
        EventEntry* eventEntry = dispatchEntry->eventEntry;
        switch (eventEntry->type) 
            case EventEntry::Type::KEY: 
                const KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
                std::array<uint8_t, 32> hmac = getSignature(*keyEntry, *dispatchEntry);

                // Publish the key event.
                status =    /// 派发key事件
                        connection->inputPublisher
                                .publishKeyEvent(dispatchEntry->seq, dispatchEntry->resolvedEventId,
                                                 keyEntry->deviceId, keyEntry->source,
                                                 keyEntry->displayId, std::move(hmac),
                                                 dispatchEntry->resolvedAction,
                                                 dispatchEntry->resolvedFlags, keyEntry->keyCode,
                                                 keyEntry->scanCode, keyEntry->metaState,
                                                 keyEntry->repeatCount, keyEntry->downTime,
                                                 keyEntry->eventTime);
                break;
            

            case EventEntry::Type::MOTION: ...
            case EventEntry::Type::FOCUS: ...
            case EventEntry::Type::CONFIGURATION_CHANGED:...
            case EventEntry::Type::DEVICE_RESET: ...
        

        // Check the result.
        if (status)   /// 不为 0 = OK , 说明派发失败
            if (status == WOULD_BLOCK) 
                if (connection->waitQueue.empty())  // waitQueue 为空,没有需要等待反馈的事件,理论上发送不应该是阻塞的,说明出了问题
                    ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
                          "This is unexpected because the wait queue is empty, so the pipe "
                          "should be empty and we shouldn't have any problems writing an "
                          "event to it, status=%d",
                          connection->getInputChannelName().c_str(), status);
                    abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);// 处理 broken状态
                 else  // 这种情况需等待client处理完之前的事件
                    // Pipe is full and we are waiting for the app to finish process some events
                    // before sending more events to it.
#if DEBUG_DISPATCH_CYCLE
                    ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
                          "waiting for the application to catch up",
                          connection->getInputChannelName().c_str());
#endif
                
             else  // 其他错误
                ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
                      "status=%d",
                      connection->getInputChannelName().c_str(), status);
                abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);// 处理 broken状态
            
            return; // 发送失败,此处直接返回
        

        // Re-enqueue the event on the wait queue.
        connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
                                                    connection->outboundQueue.end(),
                                                    dispatchEntry));  // 从派发队列移除已完成的dispatchEntry
        traceOutboundQueueLength(connection);
        connection->waitQueue.push_back(dispatchEntry);  // 添加dispatchEntry到waitQueue, 等待client发送反馈
        if (connection->responsive)  // 如果connection处理可响应状态, 添加anr追踪
            mAnrTracker.insert(dispatchEntry->timeoutTime, // 超时时间
                               connection->inputChannel->getConnectionToken()); // InputChannel的token
        
        traceWaitQueueLength(connection);
    

InputPublisher.publishKeyEvent

具体进行事件派发的是Connection的成员InputPublisher

/// @frameworks/native/libs/input/InputTransport.cpp
status_t InputPublisher::publishKeyEvent(uint32_t seq, int32_t eventId, int32_t deviceId,
                                         int32_t source, int32_t displayId,
                                         std::array<uint8_t, 32> hmac, int32_t action,
                                         int32_t flags, int32_t keyCode, int32_t scanCode,
                                         int32_t metaState, int32_t repeatCount, nsecs_t downTime,
                                         nsecs_t eventTime) 
    if (DEBUG_TRANSPORT_ACTIONS) 
        ALOGD("channel '%s' publisher ~ publishKeyEvent: seq=%u, deviceId=%d, source=0x%x, "
              "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
              "downTime=%" PRId64 ", eventTime=%" PRId64,
              mChannel->getName().c_str(), seq, deviceId, source, action, flags, keyCode, scanCode,
              metaState, repeatCount, downTime, eventTime);
    

    if (!seq) 
        ALOGE("Attempted to publish a key event with sequence number 0.");
        return BAD_VALUE;
    

    // 将相关信息转换为 InputMessage
    InputMessage msg;
    msg.header.type = InputMessage::Type::KEY;
    msg.body.key.seq = seq;
    msg.body.key.eventId = eventId;
    msg.body.key.deviceId = deviceId;
    msg.body.key.source = source;
    msg.body.key.displayId = displayId;
    msg.body.key.hmac = std::move(hmac);
    msg.body.key.action = action;
    ms

以上是关于Android R input 之 InputDispatcher 工作流程的主要内容,如果未能解决你的问题,请参考以下文章

Android R input 之 InputChannel之发送事件处理反馈

Android R input 之 InputDispatcher 工作流程

Android R input 之 InputDispatcher 工作流程

Android R input 之 InputManagerService 的建立

Android R input 之 InputManagerService 的建立

Android R input 之 InputReader 工作流程