Android Framework重要服务之InputManagerService(三) inputDispatcher

951 阅读9分钟

InputDispatcher线程用于从mInboundQueue队列获取及分发事件,本章将介绍InputDispatcher的相关知识。

threadLoop

InputDispatcherThread线程启动后,同样会调用一个thredLoop方法,该方法mInboundQueue队列获取事件,并进行后续处理,相关代码位于frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp:

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

void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        AutoMutex _l(mLock);
        // 唤醒等待线程,monitor()用于监控dispatcher是否发生死锁
        mDispatcherIsAliveCondition.broadcast();
        
        // 当mInboundQueue中有事件产生时,获得锁并处理相关事件
        if (!haveCommandsLocked()) {
            dispatchOnceInnerLocked(&nextWakeupTime);
        }
 
    } // release lock
    ...
    
     //inputReader读取事件最后把事件放入minBoundQueue后,调用loop::wake唤醒inputDispatcher
    mLooper->pollOnce(timeoutMillis);  
}
 
bool InputDispatcher::haveCommandsLocked() const {
    return !mCommandQueue.isEmpty();
}

线程执行Looper->pollOnce,进入epoll_wait等待状态,当发生以下任一情况则退出等待状态:

  • callback:通过回调方法来唤醒;
  • timeout:到达nextWakeupTime时间,超时唤醒;
  • wake: 主动调用Looper的wake()方法;

1.1 dispatchOnceInnerLocked

dispatchOnceInnerLocked会从mInboundQueue队头取出EntryEvent赋值给mPendingEvent,并根据输入事件的类型作不同的处理,处理完成之后再释放mPendingEvent,相关代码位于frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp:

void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
    // 获取当前时间
    nsecs_t currentTime = now();
    ...
    
    // 优化app切换延迟,当切换超时,则抢占分发,丢弃其他所有即将要处理的事件。
    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
    if (mAppSwitchDueTime < *nextWakeupTime) {
        *nextWakeupTime = mAppSwitchDueTime;
    }
    ...

    // mPendingEvent初始化为空
    if (!mPendingEvent) {
        if (mInboundQueue.empty()) {
            if (isAppSwitchDue) {
                // The inbound queue is empty so the app switch key we were waiting
                // for will never arrive.  Stop waiting for it.
                resetPendingAppSwitchLocked(false);
                isAppSwitchDue = false;
            }
            ...
            
            if (!mPendingEvent) {
                // 如果mInboundQueue队列为空,没有事件需要处理时直接返回
                return;
            }
        } else {
            // 从mInboundQueue取出头部的事件
            mPendingEvent = mInboundQueue.front();
            mInboundQueue.pop_front();
            traceInboundQueueLengthLocked();
        }
        ...
        
    }
    ...
    
    // 事件分发
    switch (mPendingEvent->type) {
        // 分发配置改变事件
        case EventEntry::Type::CONFIGURATION_CHANGED: {
            ...
            
        }

        // 分发输入设备重置事件
        case EventEntry::Type::DEVICE_RESET: {
            ...
            
        }

        // 分发焦点事件
        case EventEntry::Type::FOCUS: {
            ...
            
        }

        // 分发多点触控时,触控点改变事件
        case EventEntry::Type::POINTER_CAPTURE_CHANGED: {
            ...
            
        }

        // 分发拖拽事件
        case EventEntry::Type::DRAG: {
            ...
            
        }

        // 分发按键事件
        case EventEntry::Type::KEY: {
            ...
            
        }

        // 分发触控事件
        case EventEntry::Type::MOTION: {
            // 将mPendingEvent强转为MotionEntry
            std::shared_ptr<MotionEntry> motionEntry =
                    std::static_pointer_cast<MotionEntry>(mPendingEvent);
            if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
                dropReason = DropReason::APP_SWITCH;
            }
            if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) {
                dropReason = DropReason::STALE;
            }
            if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
                dropReason = DropReason::BLOCKED;
            }
            // 如果是Motion Event则会走dispatchMotionLocked分支
            done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime);
            break;
        }
        
        // 分发传感器事件
        case EventEntry::Type::SENSOR: {
           ...
           
        }
    }

    if (done) {
        if (dropReason != DropReason::NOT_DROPPED) {
            dropInboundEventLocked(*mPendingEvent, dropReason);
        }
        mLastDropReason = dropReason;

        // 处理完成之后释放mPendingEvent
        releasePendingEventLocked();
        *nextWakeupTime = LONG_LONG_MIN;
    }
}

从上述代码中可以看出,当inputDispatcher获取到一个事件后,会根据事件类型不同进行分发,目前有以下几种事件会被分发:

  • 配置改变事件[EventEntry::Type::CONFIGURATION_CHANGED]
  • 输入设备重置事件[EventEntry::Type::DEVICE_RESET]
  • 焦点事件[EventEntry::Type::FOCUS]
  • 触控点改变事件[EventEntry::Type::POINTER_CAPTURE_CHANGED]
  • 拖拽事件[EventEntry::Type::DRAG]
  • 按键事件[EventEntry::Type::KEY]
  • 触控事件[EventEntry::Type::MOTION]
  • 传感器事件[EventEntry::Type::SENSOR] 下面以MotionEvent事件为例来分析输入事件的处理流程。

1.2 dispatchMotionLocked

dispatchMotionLocked被用来处理触控事件,相关代码位于frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp:

bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<MotionEntry> entry,
                                           DropReason* dropReason, nsecs_t* nextWakeupTime) {
    ...

    // 判断是否是Touch事件
    bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;

    // Identify targets.
    std::vector<InputTarget> inputTargets;

    bool conflictingPointerActions = false;
    InputEventInjectionResult injectionResult;
    if (isPointerEvent) {
        // 寻找Touch事件的焦点窗口
        injectionResult =
                findTouchedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime,
                                               &conflictingPointerActions);
    } else {
        // 寻找非Touch事件的焦点窗口
        injectionResult =
                findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);
    }

    // 对于MotionEvent有4种情况会返回INPUT_EVENT_INJECTION_PENDING状态
    // 焦点窗口为空而焦点应用不为空时分两种情况:
    // 1.未设置焦点窗口缺失的超时时间;
    // 2.焦点窗口缺少的超时时间还未到;
    // 3.焦点窗口和焦点应用都不为空时:
    // 4.焦点窗口处于暂停状态;
    if (injectionResult == InputEventInjectionResult::PENDING) {
        return false;
    }
    ...

    // 找到目标窗口之后开始分发事件
    if (conflictingPointerActions) {
        CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
                                   "conflicting pointer actions");
        synthesizeCancelationEventsForAllConnectionsLocked(options);
    }
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}

针对Touch事件非Touch事件,有两种不同的逻辑来寻找焦点窗口:findTouchedWindowTargetsLocked中有很多关于分屏和多display id的处理逻辑,相比findFocusedWindowTargetsLocked而言代码逻辑稍显复杂,为了聚焦事件分发的主线流程,我们以findFocusedWindowTargetsLocked为例来说明焦点窗口的寻找过程;

1.3 findFocusedWindowTargetsLocked

findFocusedWindowTargetsLocked用于寻找焦点窗口,相关代码位于frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp:

int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
                                                        const EventEntry& entry,
                                                        std::vector<InputTarget>& inputTargets,
                                                        nsecs_t* nextWakeupTime) {
    std::string reason;
    // 寻找输入事件的display id,由于Android支持多屏设备,所以可能会有多个display id,默认为0
    int32_t displayId = getTargetDisplayId(entry);
    // 根据display id查找InputWindowHandle
    std::shared_ptr<InputApplicationHandle> focusedApplicationHandle =
        getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
    // 根据display id查找InputApplicationHandle
    sp<InputApplicationHandle> focusedApplicationHandle =
            getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);

    // 如果focusedWindowHandle和focusedApplicationHandle同时为空,代表当前即无焦点应用也无焦点窗口,所以直接将此事件丢弃
    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;
    }
    
    // 焦点应用不为空而焦点窗口为空
    if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr) {
        // 未设置焦点窗口缺失的超时时间
        if (!mNoFocusedWindowTimeoutTime.has_value()) {
            // We just discovered that there's no focused window. Start the ANR timer
            // 获取超时时间,默认为5s
            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;
        } else if (currentTime > *mNoFocusedWindowTimeoutTime) {
            // 如果已经超时,则直接丢弃该事件
            ALOGE("Dropping %s event because there is no focused window",
                  EventEntry::typeToString(entry.type));
            return INPUT_EVENT_INJECTION_FAILED;
        } else {
            // 还未到超时时间则继续等待
            return INPUT_EVENT_INJECTION_PENDING;
        }
    }

    // 重置超时时间和等待的焦点应用
    resetNoFocusedWindowTimeoutLocked();

    // Check permissions.
    if (!checkInjectionPermission(focusedWindowHandle, entry.injectionState)) {
        return INPUT_EVENT_INJECTION_PERMISSION_DENIED;
    }

    // 焦点窗口已经paused
    if (focusedWindowHandle->getInfo()->paused) {
        ALOGI("Waiting because %s is paused", focusedWindowHandle->getName().c_str());
        return INPUT_EVENT_INJECTION_PENDING;
    }

    // 成功找到焦点窗口后,将其添加到inputTargets
    addWindowTargetLocked(focusedWindowHandle,
                          InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
                          BitSet32(0), inputTargets);

    // Done.
    return INPUT_EVENT_INJECTION_SUCCEEDED;
}

这里有两个非常重要的map:mFocusedWindowHandlesByDisplaymFocusedApplicationHandlesByDisplay,它们分别存储着当前每个display对应的焦点应用和焦点窗口,这些map在frameworks/native/services/inputflinger/dispatcher/InputDispatcher.h被声明:

// key为display id,value为InputWindowHandle即焦点窗口
std::unordered_map<int32_t, sp<InputWindowHandle>> mFocusedWindowHandlesByDisplay
        GUARDED_BY(mLock);

// key为display id,value为InputApplicationHandle即焦点应用
std::unordered_map<int32_t, sp<InputApplicationHandle>> mFocusedApplicationHandlesByDisplay
        GUARDED_BY(mLock);

1.4 setInputWindowsLocked

setInputWindowsLocked用于设置焦点窗口,相关代码位于frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp:

void InputDispatcher::setInputWindowsLocked(
        const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId) {
    ...
    
    // 根据displayId从mWindowHandlesByDisplay中查找出当前所有的InputWindowHandle,包括焦点窗口和非焦点窗口
    const std::vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
    ...

    sp<InputWindowHandle> newFocusedWindowHandle = nullptr;
    bool foundHoveredWindow = false;
    for (const sp<InputWindowHandle>& windowHandle : getWindowHandlesLocked(displayId)) {
        // Set newFocusedWindowHandle to the top most focused window instead of the last one
        // 遍历更新之后的所有窗口列表,并将可见并且获得焦点的窗口置为新的焦点窗口
        if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus &&
            windowHandle->getInfo()->visible) {
            newFocusedWindowHandle = windowHandle;
        }
        if (windowHandle == mLastHoverWindowHandle) {
            foundHoveredWindow = true;
        }
    }

    if (!foundHoveredWindow) {
        mLastHoverWindowHandle = nullptr;
    }

    // 根据displayId从mFocusedWindowHandlesByDisplay中查找出当前的焦点窗口
    sp<InputWindowHandle> oldFocusedWindowHandle =
            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);

    // 不同的InputWindowHandle有不同的token
    if (!haveSameToken(oldFocusedWindowHandle, newFocusedWindowHandle)) {
        if (oldFocusedWindowHandle != nullptr) {
            if (DEBUG_FOCUS) {
                ALOGD("Focus left window: %s in display %" PRId32,
                      oldFocusedWindowHandle->getName().c_str(), displayId);
            }
            // 根据InputWindowHandle中的Token获取到对应的额InputChannel
            sp<InputChannel> focusedInputChannel =
                    getInputChannelLocked(oldFocusedWindowHandle->getToken());
            if (focusedInputChannel != nullptr) {
                CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
                                           "focus left window");
                synthesizeCancelationEventsForInputChannelLocked(focusedInputChannel, options);
                // 往mInboundQueue里添加失去焦点的FocusEntry
                enqueueFocusEventLocked(*oldFocusedWindowHandle, false /*hasFocus*/);
            }
            // 从mFocusedWindowHandlesByDisplay中移除历史的InputWindowHandle
            mFocusedWindowHandlesByDisplay.erase(displayId);
        }
        if (newFocusedWindowHandle != nullptr) {
            if (DEBUG_FOCUS) {
                ALOGD("Focus entered window: %s in display %" PRId32,
                      newFocusedWindowHandle->getName().c_str(), displayId);
            }
            // 更新mFocusedWindowHandlesByDisplay
            mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
            // 往mInboundQueue里添加得到焦点的FocusEntry
            enqueueFocusEventLocked(*newFocusedWindowHandle, true /*hasFocus*/);
        }

        // 往mCommandQueue里添加焦点改变的CommandEntry,通知上层焦点窗口改变
        if (mFocusedDisplayId == displayId) {
            onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
        }
    }
}

每个display都对应若干个InputWindowHandle和一个焦点InputWindowHandle,此方法会根据传入的InputWindowHandle列表来更新mWindowHandlesByDisplaymFocusedWindowHandlesByDisplay,调用流程如下所示:

-->frameworks/native/services/surfaceflinger/SurfaceFlinger.onMessageInvalidate
-->frameworks/native/services/surfaceflinger/SurfaceFlinger.updateInputFlinger
-->frameworks/native/services/surfaceflinger/SurfaceFlinger.updateInputWindowInfo
-->frameworks/native/services/inputflinger/IInputFlinger.setInputWindows
-->frameworks/native/services/inputflinger/InputManager.setInputWindows
-->frameworks/native/services/inputflinger/InputDispatcher.setInputWindows
-->frameworks/native/services/inputflinger/InputDispatcher.setInputWindowsLocked

1.5 setFocusedApplication

setFocusedApplication用于设置焦点应用,相关代码位于frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp:

void InputDispatcher::setFocusedApplication(
        int32_t displayId, const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
    if (DEBUG_FOCUS) {
        ALOGD("setFocusedApplication displayId=%" PRId32 " %s", displayId,
              inputApplicationHandle ? inputApplicationHandle->getName().c_str() : "<nullptr>");
    }
    { // acquire lock
        std::scoped_lock _l(mLock);
        // 设置焦点应用
        setFocusedApplicationLocked(displayId, inputApplicationHandle);
    } // release lock

    // Wake up poll loop since it may need to make new input dispatching choices.
    mLooper->wake();
}

1.6 dispatchEventLocked

dispatchEventLocked用于传递输入事件,相关代码位于frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp:

void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* eventEntry,
                                          const std::vector<InputTarget>& inputTargets) {
    ...
    
    for (const InputTarget& inputTarget : inputTargets) {
        // 找到InputChannel对应的Connection
        sp<Connection> connection =
                getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
        if (connection != nullptr) {
            // 如果Connection不为空,则开始准备分发输入事件
            prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
        }
    }
}

ispatchEventLocked函数根据InputTarget查找到对应的Connection,它是连接native的应用进程的通道,有了它就可以开始准备分发输入事件了。

1.7 prepareDispatchCycleLocked

prepareDispatchCycleLocked函数用于准备分发输入事件,在这个函数中,将校验连接状态,当连接状态正常时,将入队输入事件,相关代码位于frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
                                                 const sp<Connection>& connection,
                                                 EventEntry* eventEntry,
                                                 const InputTarget& inputTarget) {
    // 如果Connection状态不正常,则直接返回不会把输入事件添加到mOutbound队列
    if (connection->status != Connection::STATUS_NORMAL) {
            return;
    }
    ...

    // 入队输入事件
    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}

1.8 enqueueDispatchEntriesLocked

enqueueDispatchEntriesLocked函数用于入队输入事件,相关代码位于frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp:

void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
                                                   const sp<Connection>& connection,
                                                   EventEntry* eventEntry,
                                                   const InputTarget& inputTarget) {
    ...
    
    // 判断Connection的outboundQueue是否为空
    bool wasEmpty = connection->outboundQueue.empty();

    // 入队输入事件
    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()) {
        // 如果之前outboundQueue为空,经过enqueueDispatchEntryLocked之后不为空,则开始分发事件
        startDispatchCycleLocked(currentTime, connection);
    }
}

1.9 startDispatchCycleLocked

startDispatchCycleLocked用于分发输入事件,相关代码位于frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp:

void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
                                               const sp<Connection>& connection) {
    ...
    
    // 经过enqueueDispatchEntryLocked之后,connection->outboundQueue不为空
    while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.empty()) {
        DispatchEntry* dispatchEntry = connection->outboundQueue.front();
        // 记录事件分发的时间
        dispatchEntry->deliveryTime = currentTime;
        // 默认超时时间为5s
        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);
                ...
                
                // 获取事件签名
                std::array<uint8_t, 32> hmac = getSignature(*motionEntry, *dispatchEntry);

                // 通过Connection的InputPublisher.publishMotionEvent将输入事件发布
                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;
            }
            ...
            
        }

        // 发布完之后将DispatchEntry从Connection的outboundQueue中移除
        connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
                                                    connection->outboundQueue.end(),
                                                    dispatchEntry));
        // 然后将DispatchEntry加入Connection的waitQueue
        connection->waitQueue.push_back(dispatchEntry);
        if (connection->responsive) {
            // 往AnrTracker中插入一条记录
            mAnrTracker.insert(dispatchEntry->timeoutTime,
                               connection->inputChannel->getConnectionToken());
        }
        traceWaitQueueLength(connection);
    }   
}

1.10 publishMotionEvent

publishMotionEvent函数将事件发布出去,相关代码位于frameworks/native/libs/input/InputTransport.cpp:

status_t InputPublisher::publishMotionEvent(
        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 actionButton, int32_t flags,
        int32_t edgeFlags, int32_t metaState, int32_t buttonState,
        MotionClassification classification, float xScale, float yScale, float xOffset,
        float yOffset, float xPrecision, float yPrecision, float xCursorPosition,
        float yCursorPosition, nsecs_t downTime, nsecs_t eventTime, uint32_t pointerCount,
        const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) {
    InputMessage msg;
    msg.header.type = InputMessage::Type::MOTION;
    msg.body.motion.seq = seq;
    msg.body.motion.eventId = eventId;
    msg.body.motion.deviceId = deviceId;
    msg.body.motion.source = source;
    msg.body.motion.displayId = displayId;
    msg.body.motion.hmac = std::move(hmac);
    msg.body.motion.action = action;
    msg.body.motion.actionButton = actionButton;
    msg.body.motion.flags = flags;
    msg.body.motion.edgeFlags = edgeFlags;
    msg.body.motion.metaState = metaState;
    msg.body.motion.buttonState = buttonState;
    msg.body.motion.classification = classification;
    msg.body.motion.xScale = xScale;
    msg.body.motion.yScale = yScale;
    msg.body.motion.xOffset = xOffset;
    msg.body.motion.yOffset = yOffset;
    msg.body.motion.xPrecision = xPrecision;
    msg.body.motion.yPrecision = yPrecision;
    msg.body.motion.xCursorPosition = xCursorPosition;
    msg.body.motion.yCursorPosition = yCursorPosition;
    msg.body.motion.downTime = downTime;
    msg.body.motion.eventTime = eventTime;
    msg.body.motion.pointerCount = pointerCount;
    for (uint32_t i = 0; i < pointerCount; i++) {
        msg.body.motion.pointers[i].properties.copyFrom(pointerProperties[i]);
        msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]);
    }
    // 将输入事件封装成InputMessage,并继续通过InputChannel.sendMessage发送消息
    return mChannel->sendMessage(&msg);
}

1.11 sendMessage

sendMessage将事件发送到应用进程,相关代码位于frameworks/native/libs/input/InputTransport.cpp:

status_t InputChannel::sendMessage(const InputMessage* msg) {
    const size_t msgLength = msg->size();
    InputMessage cleanMsg;
    msg->getSanitizedCopy(&cleanMsg);
    ssize_t nWrite;
    do {
        // 通过socket将InputMessage发送给应用进程
        nWrite = ::send(mFd.get(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
    } while (nWrite == -1 && errno == EINTR);
    ......
    return OK;
}

总结

至此InputDispatcher的工作算是告一段落,事件最终通过socket发送给客户端,下面给出inputDispatcher的整体流程图供大家餐参考: image.png

参考资料