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

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

文末

要想成为架构师,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
在这里插入图片描述
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

一、架构师筑基必备技能

1、深入理解Java泛型
2、注解深入浅出
3、并发编程
4、数据传输与序列化
5、Java虚拟机原理
6、高效IO
……

在这里插入图片描述

二、Android百大框架源码解析

1.Retrofit 2.0源码解析
2.Okhttp3源码解析
3.ButterKnife源码解析
4.MPAndroidChart 源码解析
5.Glide源码解析
6.Leakcanary 源码解析
7.Universal-lmage-Loader源码解析
8.EventBus 3.0源码解析
9.zxing源码分析
10.Picasso源码解析
11.LottieAndroid使用详解及源码解析
12.Fresco 源码分析——图片加载流程

在这里插入图片描述

三、Android性能优化实战解析

  • 腾讯Bugly:对字符串匹配算法的一点理解
  • 爱奇艺:安卓APP崩溃捕获方案——xCrash
  • 字节跳动:深入理解Gradle框架之一:Plugin, Extension, buildSrc
  • 百度APP技术:Android H5首屏优化实践
  • 支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」
  • 携程:从智行 Android 项目看组件化架构实践
  • 网易新闻构建优化:如何让你的构建速度“势如闪电”?

在这里插入图片描述

四、高级kotlin强化实战

1、Kotlin入门教程
2、Kotlin 实战避坑指南
3、项目实战《Kotlin Jetpack 实战》

  • 从一个膜拜大神的 Demo 开始

  • Kotlin 写 Gradle 脚本是一种什么体验?

  • Kotlin 编程的三重境界

  • Kotlin 高阶函数

  • Kotlin 泛型

  • Kotlin 扩展

  • Kotlin 委托

  • 协程“不为人知”的调试技巧

  • 图解协程:suspend

在这里插入图片描述

五、Android高级UI开源框架进阶解密

1.SmartRefreshLayout的使用
2.Android之PullToRefresh控件源码解析
3.Android-PullToRefresh下拉刷新库基本用法
4.LoadSir-高效易用的加载反馈页管理框架
5.Android通用LoadingView加载框架详解
6.MPAndroidChart实现LineChart(折线图)
7.hellocharts-android使用指南
8.SmartTable使用指南
9.开源项目android-uitableview介绍
10.ExcelPanel 使用指南
11.Android开源项目SlidingMenu深切解析
12.MaterialDrawer使用指南
在这里插入图片描述

六、NDK模块开发

1、NDK 模块开发
2、JNI 模块
3、Native 开发工具
4、Linux 编程
5、底层图片处理
6、音视频开发
7、机器学习

在这里插入图片描述

七、Flutter技术进阶

1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter开发环境搭建和调试
5、Dart语法篇之基础语法(一)
6、Dart语法篇之集合的使用与源码解析(二)
7、Dart语法篇之集合操作符函数与源码分析(三)

在这里插入图片描述

八、微信小程序开发

1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战……

在这里插入图片描述

全套视频资料:

一、面试合集
在这里插入图片描述
二、源码解析合集

在这里插入图片描述
三、开源框架合集

在这里插入图片描述
欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取【保证100%免费】↓↓↓

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值