Android13-Input事件派发(单指move)

1 InputDispatcher代码解析第一部分

void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
    //条件编译指令
#if DEBUG_INBOUND_EVENT_DETAILS
    if (args->action != AMOTION_EVENT_ACTION_MOVE) {
        //当前动作不是AMOTION_EVENT_ACTION_MOVE
        ALOGD("Cnt:%d notifyMotion - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=0x%x, "
            "displayId=%" PRId32 ", policyFlags=0x%x, "
            "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, "
            "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, xCursorPosition=%f, "
            "yCursorPosition=%f, downTime=%" PRId64,
            (((args->action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_POINTER_DOWN) ||
             ((args->action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN))
                ? (mMotionCntByDisplay[args->displayId] == INT_MAX
                    ? INT_MAX : (mMotionCntByDisplay[args->displayId]++))
                : -1,
            args->id, args->eventTime, args->deviceId, args->source, args->displayId,
            args->policyFlags, args->action, args->actionButton, args->flags, args->metaState,
            args->buttonState, args->edgeFlags, args->xPrecision, args->yPrecision,
            args->xCursorPosition, args->yCursorPosition, args->downTime);
        for (uint32_t i = 0; i < args->pointerCount; i++) {
            //遍历多指,每个触控点的数据
            ALOGD("  Pointer %d: id=%d, toolType=%d, "
                "x=%f, y=%f, pressure=%f, size=%f, "
                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
                "orientation=%f",
                i, args->pointerProperties[i].id, args->pointerProperties[i].toolType,
                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
        }
    }
#endif
    //验证是否是有效motion事件
    if (!validateMotionEvent(args->action, args->actionButton, args->pointerCount,
                             args->pointerProperties)) {
        return;
    }

    uint32_t policyFlags = args->policyFlags;
    //定义InputReader上来的事件是值得信任的
    policyFlags |= POLICY_FLAG_TRUSTED;

    android::base::Timer t;
    //事件入队前通过策略是java端(InputManagerService)进行拦截
    mPolicy->interceptMotionBeforeQueueing(args->displayId, args->eventTime, /*byref*/ policyFlags);
    if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
        ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
              std::to_string(t.duration().count()).c_str());
    }

    bool needWake;
    { // acquire lock
        mLock.lock();
        //判断事件是否需要过滤 可以通过setInputFilterEnabled设置
        if (shouldSendMotionToInputFilterLocked(args)) {
            mLock.unlock();

            MotionEvent event;
            event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC,
                             args->action, args->actionButton, args->flags, args->edgeFlags,
                             args->metaState, args->buttonState, args->classification, 1 /*xScale*/,
                             1 /*yScale*/, 0 /* xOffset */, 0 /* yOffset */, args->xPrecision,
                             args->yPrecision, args->xCursorPosition, args->yCursorPosition,
                             args->downTime, args->eventTime, args->pointerCount,
                             args->pointerProperties, args->pointerCoords);
          //添加过滤flag
            policyFlags |= POLICY_FLAG_FILTERED;
            if (!mPolicy->filterInputEvent(&event, policyFlags)) {
                //policy消费了当次事件
                return; // event was consumed by the filter
            }

            mLock.lock();
        }

        // Just enqueue a new motion event.
        //构建触摸事件
        MotionEntry* newEntry =
                new MotionEntry(args->id, args->eventTime, args->deviceId, args->source,
                                args->displayId, policyFlags, args->action, args->actionButton,
                                args->flags, args->metaState, args->buttonState,
                                args->classification, args->edgeFlags, args->xPrecision,
                                args->yPrecision, args->xCursorPosition, args->yCursorPosition,
                                args->downTime, args->pointerCount, args->pointerProperties,
                                args->pointerCoords, 0, 0);
        //进入dispatcher的队列等待dispatcher处理派发
        needWake = enqueueInboundEventLocked(newEntry);
        mLock.unlock();
    } // release lock

    if (needWake) {
        //派发队列来事件了,唤醒InputDispatcher
        mLooper->wake();
    }
}

1 根据inputReader上来的数据参数action判断如果不是AMOTION_EVENT_ACTION_MOVE
打印inputReader上报上来的数据信息,如果涉及多指
会遍历每一个触控点数据打印。
2 验证是否是有效事件
3 设置事件是值得信任的
4 事件进入队列前通过dispatchPolicy进行事件拦截
5 判断事件是否需要过滤需要就添加POLICY_FLAG_FILTERED标记,如果事件被过滤掉了就直接return了,如果事件没被过滤掉。
6 根据inputreader上来的数据构建触摸事件
7 触摸事件构建成功 唤醒InputDispatcher线程处理事件

1.1 验证是否是有效事件
static bool validateMotionEvent(int32_t action, int32_t actionButton, size_t pointerCount,
                                const PointerProperties* pointerProperties) {
    if (!isValidMotionAction(action, actionButton, pointerCount)) {
        //验证action是否有效
        ALOGE("Motion event has invalid action code 0x%x", action);
        return false;
    }
    if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
        //验证触控点数量是否正常
        ALOGE("Motion event has invalid pointer count %zu; value must be between 1 and %d.",
              pointerCount, MAX_POINTERS);
        return false;
    }
    BitSet32 pointerIdBits;
    for (size_t i = 0; i < pointerCount; i++) {
        int32_t id = pointerProperties[i].id;
        if (id < 0 || id > MAX_POINTER_ID) {
            //验证Pointer Id是否正常
            ALOGE("Motion event has invalid pointer id %d; value must be between 0 and %d", id,
                  MAX_POINTER_ID);
            return false;
        }
        if (pointerIdBits.hasBit(id)) {
            //验证pointer的id 是否有对应的bit
            ALOGE("Motion event has duplicate pointer id %d", id);
            return false;
        }
        pointerIdBits.markBit(id);
    }
    return true;
}

1 isValidMotionAction 验证事件的action类型是否有效
2 验证触控点数量正常
3 验证触控点id是否正常

1.2 dispatchPolicy进行事件拦截
void NativeInputManager::interceptMotionBeforeQueueing(const int32_t displayId, nsecs_t when,
        uint32_t& policyFlags) {
    ATRACE_CALL();
    // Policy:
    // - Ignore untrusted events and pass them along.
    // - No special filtering for injected events required at this time.
    // - Filter normal events based on screen state.
    // - For normal events brighten (but do not wake) the screen if currently dim.
    bool interactive = mInteractive.load();
    if (interactive) {
        //flag定义当一个输入事件携带了 POLICY_FLAG_INTERACTIVE 标志时,
        //系统可能会将其视为需要交互式处理的事件,这意味着该事件可能需要立即响应
        //事件是否需要立即响应
        policyFlags |= POLICY_FLAG_INTERACTIVE;
    }
    //携带了 POLICY_FLAG_INJECTED 标志时,
    //系统会将其视为是由应用程序或者其他实体主动注入(inject)到输入事件流中的事件
    if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {
        if (policyFlags & POLICY_FLAG_INTERACTIVE) {
            //当输入事件携带了这个标志时,系统会将其视为需要将事件传递给用户进行处理。
            policyFlags |= POLICY_FLAG_PASS_TO_USER;
        } else {
            JNIEnv* env = jniEnv();
            jint wmActions = env->CallIntMethod(mServiceObj,
                        gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive,
                        displayId, when, policyFlags);
            if (checkAndClearExceptionFromCallback(env,
                    "interceptMotionBeforeQueueingNonInteractive")) {
                wmActions = 0;
            }

            handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
        }
    } else {
        if (interactive) {
            //如果是其他注入的事件(满足可交互)  也可以发给用户
            policyFlags |= POLICY_FLAG_PASS_TO_USER;
        }
    }
}

策略过滤会回调到上层InputManagerService最后通过windowCallBack来考虑

1.3 InputFilter过滤
bool NativeInputManager::filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
    ATRACE_CALL();
    jobject inputEventObj;

    JNIEnv* env = jniEnv();
    //判断事件类型
    switch (inputEvent->getType()) {
    case AINPUT_EVENT_TYPE_KEY:
    //转换成key事件
        inputEventObj = android_view_KeyEvent_fromNative(env,
                static_cast<const KeyEvent*>(inputEvent));
        break;
    case AINPUT_EVENT_TYPE_MOTION:
    //转换成motion事件
        inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
                static_cast<const MotionEvent*>(inputEvent));
        break;
    default:
        return true; // dispatch the event normally
    }

    if (!inputEventObj) {
        ALOGE("Failed to obtain input event object for filterInputEvent.");
        return true; // dispatch the event normally
    }

    // The callee is responsible for recycling the event.
    //来到java层的InputManagerService
    jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent,
            inputEventObj, policyFlags);
    if (checkAndClearExceptionFromCallback(env, "filterInputEvent")) {
        pass = true;
    }
    env->DeleteLocalRef(inputEventObj);
    return pass;
}

native层根据事件类型将事件对象由c++转换成java给到InputManagerService

    final boolean filterInputEvent(InputEvent event, int policyFlags) {
        synchronized (mInputFilterLock) {
            if (mInputFilter != null) {
                try {
                    mInputFilter.filterInputEvent(event, policyFlags);
                } catch (RemoteException e) {
                    /* ignore */
                }
                return false;
            }
        }
        event.recycle();
        return true;
    }

将事件给到InputFilter

final public void filterInputEvent(InputEvent event, int policyFlags) {
        mH.obtainMessage(MSG_INPUT_EVENT, policyFlags, 0, event).sendToTarget();
    }

通过Handler发送MSG_INPUT_EVENT消息

   private final class H extends Handler {
        public H(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_INSTALL:
                    mHost = (IInputFilterHost) msg.obj;
                    if (mInboundInputEventConsistencyVerifier != null) {
                        mInboundInputEventConsistencyVerifier.reset();
                    }
                    if (mOutboundInputEventConsistencyVerifier != null) {
                        mOutboundInputEventConsistencyVerifier.reset();
                    }
                    onInstalled();
                    break;

                case MSG_UNINSTALL:
                    try {
                        onUninstalled();
                    } finally {
                        mHost = null;
                    }
                    break;

                case MSG_INPUT_EVENT: {
                    final InputEvent event = (InputEvent)msg.obj;
                    try {
                        if (mInboundInputEventConsistencyVerifier != null) {
                            mInboundInputEventConsistencyVerifier.onInputEvent(event, 0);
                        }
                    //处理输入事件
                        onInputEvent(event, msg.arg1);
                    } finally {
                        event.recycle();
                    }
                    break;
                }
            }
        }

最后由view的InputFilter处理事件

1.4 事件入派发队列
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
    //事件加入之前如果之前队列是空的 要唤醒InputDispatcher
    bool needWake = mInboundQueue.empty();
    //添加队列末尾
    mInboundQueue.push_back(entry);
    traceInboundQueueLengthLocked();

    switch (entry->type) {
        case EventEntry::Type::KEY: {
            // Optimize app switch latency.
            // If the application takes too long to catch up then we drop all events preceding
            // the app switch key.
            const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*entry);
            if (isAppSwitchKeyEvent(keyEntry)) {
                if (keyEntry.action == AKEY_EVENT_ACTION_DOWN) {
                    mAppSwitchSawKeyDown = true;
                } else if (keyEntry.action == AKEY_EVENT_ACTION_UP) {
                    if (mAppSwitchSawKeyDown) {
#if DEBUG_APP_SWITCH
                        ALOGD("App switch is pending!");
#endif
                        mAppSwitchDueTime = keyEntry.eventTime + APP_SWITCH_TIMEOUT;
                        mAppSwitchSawKeyDown = false;
                        needWake = true;
                    }
                }
            }
            break;
        }

        case EventEntry::Type::MOTION: {
            //检查和修剪输入事件队列中的 Motion 事件
            if (shouldPruneInboundQueueLocked(static_cast<MotionEntry&>(*entry))) {
                //mNextUnblockedEvent 保证下次事件可以及时响应
                mNextUnblockedEvent = entry;
                needWake = true;
            }
            break;
        }
        case EventEntry::Type::FOCUS: {
            LOG_ALWAYS_FATAL("Focus events should be inserted using enqueueFocusEventLocked");
            break;
        }
        case EventEntry::Type::CONFIGURATION_CHANGED:
        case EventEntry::Type::DEVICE_RESET: {
            // nothing to do
            break;
        }
    }

    return needWake;
}

如果添加事件到派发队列时 当前队列如果没有事件那么needWake = true

2 InputDispatcher第二部分

void InputDispatcher::dispatchOnce() {
    //下次唤醒时间 默认无限长
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        std::scoped_lock _l(mLock);
        mDispatcherIsAlive.notify_all();

        // Run a dispatch loop if there are no pending commands.
        // The dispatch loop might enqueue commands to run afterwards.
        if (!haveCommandsLocked()) {
            //保证命令队列(一次事件处理完整结束)无事件才会执行
            dispatchOnceInnerLocked(&nextWakeupTime);
        }

        // Run all pending commands if there are any.
        // If any commands were run then force the next poll to wake up immediately.
        //根据遍历CommandQueue里的元素执行command函数决定是否立刻唤醒
        if (runCommandsLockedInterruptible()) {
            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();
        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();
        }
    } // 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);
}

1 当前commandQueue无command 或者一次事件完整处理完
执行下一次事件处理
2 考虑遍历commandQueue的元素来决定是否立刻唤醒派发线程

2.1 一次事件处理
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) {
        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;
    if (mAppSwitchDueTime < *nextWakeupTime) {
        *nextWakeupTime = mAppSwitchDueTime;
    }

    // Ready to start a new event.
    // If we don't already have a pending event, go grab one.
    if (!mPendingEvent) {
        //如果mPendingEvent是null
        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.
                //清除AppSwitch事件应用切换标志为false
                //为什么事件队列为空 就不需要在等了呢
                //原因 isAppSwitchDue 为 true
                //代表下次事件一定是app切换事件 但是事件队列没有
                //那么他肯定就不会再来了
                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) {
                //如果经历了应用切换和重复按键情况都没有事件那就可以退出
                //等待下次队列存在事件
                return;
            }
        } else {
            // Inbound queue has at least one entry.
            //事件队列不为空从事件队列取出缓存事件
            mPendingEvent = mInboundQueue.front();
            //事件队列移除取出的事件    
            mInboundQueue.pop_front();
            traceInboundQueueLengthLocked();
        }

        // Poke user activity for this event.
        //检查缓存事件的flag是否有POLICY_FLAG_PASS_TO_USER flag
        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
            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;
    //POLICY_FLAG_PASS_TO_USER
    //标记表示输入法在处理用户输入时,会充分尊重用户的交互需求,
    //让用户能够参与到输入过程并及时调整
    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
        //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: {
            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: {
            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: {
            KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
            if (isAppSwitchDue) {
                if (isAppSwitchKeyEvent(*typedEntry)) {
                    resetPendingAppSwitchLocked(true);
                    isAppSwitchDue = false;
                } else if (dropReason == DropReason::NOT_DROPPED) {
                    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 = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
            break;
        }

        case EventEntry::Type::MOTION: {
            MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
            //因为应用切换丢弃当前事件 并且声明丢弃原因
            if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
                dropReason = DropReason::APP_SWITCH;
            }
            if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *typedEntry)) {
                dropReason = DropReason::STALE;
            }
            //如果存在mNextUnblockedEvent事件 需要丢弃当次事件
            if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
                dropReason = DropReason::BLOCKED;
            }
            //处理motion事件
            done = dispatchMotionLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
            break;
        }
    }

    if (done) {
        //如果事件被丢弃
        if (dropReason != DropReason::NOT_DROPPED) {
            //Log打印事件丢弃原因
            dropInboundEventLocked(*mPendingEvent, dropReason);
        }
        //记录上次丢弃原因
        mLastDropReason = dropReason;
        //清除当次缓存事件 开启下一次事件循环
        releasePendingEventLocked();
        *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
    }
}

1 查看派发是否开启
2 查看派发是否被冻结 例如横竖屏转换
3 检查当前是否处于应用切换按键操作
4 获取缓存事件
4.1 事件队列有事件
直接从队列头部取出事件

4.2 事件队列无事件
1 如果当前是应用切换状态 那么可以直接重置应用切换相关缓存
2 如果存在重复事件 则根据上次事件生成当次事件
缓存事件为空 直接返回 等待下一次事件处理
5 检查缓存事件Flag
POLICY_FLAG_PASS_TO_USER
标记表示输入法在处理用户输入时,会充分尊重用户的交互需求,
让用户能够参与到输入过程并及时调整 及时交互反馈
6 根据事件类型 强制转换相关事件
7 根据应用是否切换isAppSwitchDue
是否为stale event
下一次事件是否提前执行mNextUnblockedEvent
来定义当次事件丢弃原因
8 执行dispatchMotionLocked 处理当次motion事件
9 处理完成 根据dropReason 打印相关丢弃事件原因log
对丢弃原因进行记录
释放当次缓存事件
设置下次唤醒时间为LONG_LONG_MIN

2.2 dispatchMotionLocked函数处理
bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry,
                                           DropReason* dropReason, nsecs_t* nextWakeupTime) {
    ATRACE_CALL();
    // Preprocessing.
    //如果当前未处于派发中 那就设置当次事件处于派发中
    if (!entry->dispatchInProgress) {
        entry->dispatchInProgress = true;

        logOutboundMotionDetails("dispatchMotion - ", *entry);
    }

    // Clean up if dropping the event.
    if (*dropReason != DropReason::NOT_DROPPED) {
        //根据DropReason设置注入结果
        setInjectionResult(entry,
                           *dropReason == DropReason::POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED
                                                             : INPUT_EVENT_INJECTION_FAILED);
        return true;
    }
    //确认当次事件是否为手指事件
    bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;

    // Identify targets.
    //派发目标集合
    std::vector<InputTarget> inputTargets;

    bool conflictingPointerActions = false;
    int32_t injectionResult;
    if (isPointerEvent) {
        // Pointer event.  (eg. touchscreen)
        //手指事件 根据touch找到合适窗口
        injectionResult =
                findTouchedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime,
                                               &conflictingPointerActions);
    } else {
        // Non touch event.  (eg. trackball)
        //非手指触摸事件 通过窗口焦点找到合适窗口
        injectionResult =
                findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);
    }
    //注入结果为INPUT_EVENT_INJECTION_PENDING
    //退出当次事件派发 等待下一次
    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
        return false;
    }
    //设置对应事件的注入结果
    setInjectionResult(entry, injectionResult);
    if (injectionResult == INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
        //如果注入结果为INPUT_EVENT_INJECTION_PERMISSION_DENIED
        ALOGW("Permission denied, dropping the motion (isPointer=%s)", toString(isPointerEvent));
        return true;
    }
    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
        //如果注入的结果不是成功 那么根据是否是手指触摸事件生成cancel事件
        //注入到事件队列
        CancelationOptions::Mode mode(isPointerEvent
                                              ? CancelationOptions::CANCEL_POINTER_EVENTS
                                              : CancelationOptions::CANCEL_NON_POINTER_EVENTS);
        CancelationOptions options(mode, "input event injection failed");
        synthesizeCancelationEventsForMonitorsLocked(options);
        return true;
    }

    // Add monitor channels from event's or focused display.
    //查看当前是否属于touch的down事件
    bool isShowTouchDump = false;
        if ((entry->action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN
        || (entry->action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_POINTER_DOWN) {
        isShowTouchDump = true;
    }
     //根据touch事件或者key事件 打印相关log 窗口信息 等等
    ALOGD("addGlobalMonitoringTargetsLocked isShowTouchDump: %s", isShowTouchDump ? "true" : "false");
    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry), isShowTouchDump, false);

    if (isPointerEvent) {
        std::unordered_map<int32_t, TouchState>::iterator it =
                mTouchStatesByDisplay.find(entry->displayId);
        if (it != mTouchStatesByDisplay.end()) {
            const TouchState& state = it->second;
            if (!state.portalWindows.empty()) {
                // The event has gone through these portal windows, so we add monitoring targets of
                // the corresponding displays as well.
                for (size_t i = 0; i < state.portalWindows.size(); i++) {
                    const InputWindowInfo* windowInfo = state.portalWindows[i]->getInfo();
                    addGlobalMonitoringTargetsLocked(inputTargets, windowInfo->portalToDisplayId, false, false,
                                                     -windowInfo->frameLeft, -windowInfo->frameTop);
                }
            }
        }
    }

    // Dispatch the motion.
    //如果手指行为action存在冲突 那会生成cancel事件加入事件队列在分发到窗口
    if (conflictingPointerActions) {
        CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
                                   "conflicting pointer actions");
        synthesizeCancelationEventsForAllConnectionsLocked(options);
    }
    //派发事件到指定窗口
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}

1 查看当前事件是否处于派发中
2 根据丢弃原因设置注入结果
3 判断当前事件是否为触摸事件
4 查找touch窗口
5 根据查找窗口的结果进行下一步动作
1 INPUT_EVENT_INJECTION_PENDING
当前事件处于缓存状态
退出当前事件,等待下一次派发
2 INPUT_EVENT_INJECTION_PERMISSION_DENIED
当前事件没有权限
退出当次事件
3 != INPUT_EVENT_INJECTION_SUCCEEDED
注入结果失败
根据是否touch事件 生成对应cancel 事件
加入事件队列 等待下一次事件派发循环将事件给到对应窗口
6 根据得到的输入目标窗口 遍历打印相关log
7 如果touch事件存在冲突 和5.3一样
8 将事件注入指定窗口

2.3 输入事件进入派发队列
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);
    //遍历touch的窗口
    for (const InputTarget& inputTarget : inputTargets) {
        //只要通道不为空
        sp<Connection> connection =
                getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
        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());
            }
        }
    }
}
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
                                                 const sp<Connection>& connection,
                                                 EventEntry* eventEntry,
                                                 const InputTarget& inputTarget) {
    if (ATRACE_ENABLED()) {
        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) {
#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);
}

检查输入目标的标志中是否包含InputTarget::FLAG_SPLIT。如果是拆分事件,会对事件类型进行检查,然后对原始的运动事件进行拆分处理,生成新的拆分事件,并将其加入到事件派发队列中。最后释放拆分事件的资源。

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();

    // 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);
    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.empty()) {
        startDispatchCycleLocked(currentTime, connection);
    }
}

输入事件进入派发队列
这里涉及请求模式
InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT
,表示将事件派发到输入窗口,并将其标记为鼠标悬停退出事件。这通常用于处理鼠标悬停操作。当鼠标从一个窗口的可接收悬停事件的区域移出时,会触发该标志位对应的派发操作,通知窗口处理鼠标悬停退出的逻辑。
InputTarget::FLAG_DISPATCH_AS_OUTSIDE
表示将事件派发到输入窗口,并将其标记为外部触摸事件。这通常用于处理触摸事件在窗口之外的情况。当触摸事件发生在窗口之外时,会触发该标志位对应的派发操作,通知窗口处理外部触摸事件的逻辑

InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER
表示将事件派发到输入窗口,并将其标记为鼠标悬停进入事件。这通常用于处理鼠标悬停操作。当可接收悬停事件进入一个窗口时,会触发该标志位对应的派发操作,通知窗口处理鼠标悬停进入的逻辑。

InputTarget::FLAG_DISPATCH_AS_IS
表示将事件派发到输入窗口,并将其标记为普通的输入事件。这通常用于处理普通的输入操作,如键盘输入、鼠标点击等。当普通的输入事件发生时,会触发该标志位对应的派发操作,通知窗口处理普通的输入事件的逻辑。

InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT
表示将事件派发到输入窗口,但是不会造成焦点的变化。这通常用于处理“滑动”场景,在滑动过程中,我们需要不断向当前焦点窗口发送滑动事件,但是不能改变窗口的焦点状态

InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER
表示将事件派发到输入窗口,并且在派发事件时不会改变窗口的焦点状态。这通常用于处理“滑动”场景,在滑动过程中,我们需要不断向当前焦点窗口发送滑动事件,但是不能改变窗口的焦点状态,直到滑动结束才能改变焦点状态

void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
                                                 EventEntry* eventEntry,
                                                 const InputTarget& inputTarget,
                                                 int32_t dispatchMode) {
std::unique_ptr<DispatchEntry> dispatchEntry =
            createDispatchEntry(inputTarget, eventEntry, inputTargetFlags);

 switch (newEntry->type) {
case EventEntry::Type::MOTION: {
            const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*newEntry);
            // Assign a default value to dispatchEntry that will never be generated by InputReader,
            // and assign a InputDispatcher value if it doesn't change in the if-else chain below.
            constexpr int32_t DEFAULT_RESOLVED_EVENT_ID =
                    static_cast<int32_t>(IdGenerator::Source::OTHER);
            dispatchEntry->resolvedEventId = DEFAULT_RESOLVED_EVENT_ID;
            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;
                dispatchEntry->resolvedEventId = motionEntry.id;
            }

}

// Enqueue the dispatch entry.
    //通过调用dispatchEntry.release()方法,我们释放了dispatchEntry智能指针的所有权,
    //并返回一个指向该对象的裸指针。然后,使用push_back()方法将该裸指针
    //添加到connection对象的outboundQueue队列的末尾。

    //这样做的目的是将dispatchEntry对象添加到outboundQueue队列中,
    //以便后续进行处理或发送给其他组件。注意,由于我们已经释放了dispatchEntry的所有权,
    //所以在outboundQueue中存储的是裸指针,而不是智能指针。
    //需要确保在适当的时候管理和释放这些指针,以避免内存泄漏。
    connection->outboundQueue.push_back(dispatchEntry.release());
}

1 根据InputTarget eventEntry InputTargetFlags 构建dispatchEntry对象
2 根据EventEntry的类型是MOTION 构建motionEntry
来设置dispatchEntry->resolvedAction dispatchEntry->resolvedEventId
3 dispatchEntry对象添加到outboundQueue队列中

2.4 从派发队列派发事件
if (wasEmpty && !connection->outboundQueue.empty()) {
        startDispatchCycleLocked(currentTime, connection);
    }
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 =
                getDispatchingTimeoutLocked(connection->inputChannel->getConnectionToken());
        dispatchEntry->timeoutTime = currentTime + timeout;

        // Publish the event.
        status_t status;
        EventEntry* eventEntry = dispatchEntry->eventEntry;
        switch (eventEntry->type) {
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 and X and Y scale depending on the input source.
                float xOffset = 0.0f, yOffset = 0.0f;
                float xScale = 1.0f, yScale = 1.0f;
                if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) &&
                    !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
                    float globalScaleFactor = dispatchEntry->globalScaleFactor;
                    xScale = dispatchEntry->windowXScale;
                    yScale = dispatchEntry->windowYScale;
                    xOffset = dispatchEntry->xOffset * xScale;
                    yOffset = dispatchEntry->yOffset * yScale;
                    //代表设备无关的坐标转换设备相关的坐标
                    if (globalScaleFactor != 1.0f) {
                        //遍历指针数量
                        for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
                            //将当前motionEntry->pointerCoords[i]赋值到scaledCoords[i]
                            scaledCoords[i] = motionEntry->pointerCoords[i];
                            // Don't apply window scale here since we don't want scale to affect raw
                            // coordinates. The scale will be sent back to the client and applied
                            // later when requesting relative coordinates.
                            //坐标缩放调整
                            scaledCoords[i].scale(globalScaleFactor, 1 /* windowXScale */,
                                                  1 /* windowYScale */);
                        }
                        //将scaledCoords给到usingCoords
                        usingCoords = scaledCoords;
                    }
                } else {
                    // We don't want the dispatch target to know.
                    //输入目标需要将坐标归零,清空scaledCoords数组
                    if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
                        for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
                            scaledCoords[i].clear();
                        }
                        //赋值给usingCoords
                        usingCoords = scaledCoords;
                    }
                }

                std::array<uint8_t, 32> hmac = getSignature(*motionEntry, *dispatchEntry);

                // Publish the motion event.
                //上传该motion事件
                status = connection->inputPublisher
                                 .publishMotionEvent(dispatchEntry->seq,
                                                     dispatchEntry->resolvedEventId,
                                                     motionEntry->deviceId, motionEntry->source,
                                                     motionEntry->displayId, std::move(hmac),
                                                     dispatchEntry->resolvedAction,
                                                     motionEntry->actionButton,
                                                     dispatchEntry->resolvedFlags,
                                                     motionEntry->edgeFlags, motionEntry->metaState,
                                                     motionEntry->buttonState,
                                                     motionEntry->classification, xScale, yScale,
                                                     xOffset, yOffset, motionEntry->xPrecision,
                                                     motionEntry->yPrecision,
                                                     motionEntry->xCursorPosition,
                                                     motionEntry->yCursorPosition,
                                                     motionEntry->downTime, motionEntry->eventTime,
                                                     motionEntry->pointerCount,
                                                     motionEntry->pointerProperties, usingCoords);
                reportTouchEventForStatistics(*motionEntry);
                break;
            }

}
        // Re-enqueue the event on the wait queue.
        //从派发队列中移除该事件
        connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
                                                    connection->outboundQueue.end(),
                                                    dispatchEntry));
        traceOutboundQueueLength(connection);
        //在等待队列中添加该事件
        connection->waitQueue.push_back(dispatchEntry);
        if (connection->responsive) {
            //如果窗口无响应将派发事件的超时时间和派发窗口token加入到ANR触发器
            mAnrTracker.insert(dispatchEntry->timeoutTime,
                               connection->inputChannel->getConnectionToken());
        }
        traceWaitQueueLength(connection);
    }
}

}

1 确认连接通道正常 且派发队列事件不为空
2 outboundQueue头部取出数据
设置分发时间 当前时间
获取超时时间间隔
设置超时时间
3 根据事件类型MOTION
创建窗口可用指针数组scaledCoords
usingCoords指向motion事件的pointerCoords
4 设置默认x y 偏移 和 x y 缩放
5 判断当前source是POINTER 并且targetFlaget 不是InputTarget::FLAG_ZERO_COORDS标志
6 全局缩放因子globalScaleFactor == 1.0f代表不需要调整设备坐标
7 全局缩放因子globalScaleFactor != 1.0f 需要将当前motionEntry->pointerCoords[i]通过缩放调整为scaledCoords[i]
同时 usingCoords也被赋值为scaledCoords
8 如果targetFlaget 是InputTarget::FLAG_ZERO_COORDS标志
需要将 scaledCoords数组信息清空 赋值给usingCoords
9 通过connection->inputPublisher 将motionEvent发布出去
10 connection->outboundQueue 派发队列删除该事件
11connection->waitQueue 等待队列加入该事件
12 如果窗口无响应将派发事件的超时时间和派发窗口token加入到ANR触发器

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容