Android 11.0源码系列之IMSInputDispatcher

Posted bubbleben

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 11.0源码系列之IMSInputDispatcher相关的知识,希望对你有一定的参考价值。

本篇涉及到的主要代码:

\\system\\core\\libutils\\Looper.cpp

\\frameworks\\native\\libs\\input\\InputTransport.cpp

\\frameworks\\native\\services\\inputflinger\\dispatcher\\InputDispatcher.h

\\frameworks\\native\\services\\inputflinger\\reader\\InputThread.cpp

\\frameworks\\native\\services\\inputflinger\\reader\\InputDispatcher.cpp

上一篇我们介绍了libinputflinger.soInputManager的创建:它在创建过程中启动了非常重要的两个对象InputReaderInputDispatcher,它们分别用于读取input事件和分发input事件,本篇将先介绍InputDispatcher的工作流程。

1.1 InputDispatcher的构造函数

[-> InputDispatcher.cpp]

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
        // NativeInputManager
      : mPolicy(policy),
        // EventEntry类型的待处理的输入事件,初始化为空
        mPendingEvent(nullptr),
        // 焦点display id,默认为0即main display
        mFocusedDisplayId(ADISPLAY_ID_DEFAULT) {
    // 创建native层Looper[见1.11小节]
    mLooper = new Looper(false);
    // 调用InputManagerService.getKeyRepeatTimeout获取长按超时时间,默认为400ms
    // 调用InputManagerService.getKeyRepeatDelay获取长按延时时间,默认为50ms
    policy->getDispatcherConfiguration(&mConfig);
}

InputDispatcher的构造函数中:将InputDispatcherPolicyInterface类型的policy赋值给mPolicy,在上一篇文章中我们介绍过JNI层的NativeInputManager同时继承了InputDispatcherPolicyInterfaceInputReaderPolicyInterface,所以InputDispatcher就可以通过mPolicy回调NativeInputManager进而调用Java层InputManagerService的方法来完成诸如拦截按键/触摸消息,通知焦点改变,通知ANR等工作,同时创建了native层的Looper,初始化参数allowNonCallbacks为false,接下来我们看看这里的Looper于Java层的Looper有什么区别?

1.11 Looper的创建

[-> /system/core/libutils/Looper.cpp]

Looper::Looper(bool allowNonCallbacks)
    // 传入的allowNonCallbacks为false
    : mAllowNonCallbacks(allowNonCallbacks),
      mSendingMessage(false),
      mPolling(false),
      mEpollRebuildRequired(false),
      mNextRequestSeq(0),
      mResponseIndex(0),
      mNextMessageUptime(LLONG_MAX) {
    // 重置mWakeEventFd
    mWakeEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));
    AutoMutex _l(mLock);
    // 重建epoll[见1.12小节]
    rebuildEpollLocked();
}
1.12 epoll实例的创建
void Looper::rebuildEpollLocked() {
    // Allocate the new epoll instance and register the wake pipe.
    // 创建epoll实例并将其文件描述符赋值给mEpollFd
    mEpollFd.reset(epoll_create1(EPOLL_CLOEXEC));
    
    struct epoll_event eventItem;
    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
    eventItem.events = EPOLLIN;
    eventItem.data.fd = mWakeEventFd.get();
    // 将mWakeEventFd发送给epoll实例,用于唤醒InputDispatcher对应的线程
    int result = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mWakeEventFd.get(), &eventItem);
    
    for (size_t i = 0; i < mRequests.size(); i++) {
        const Request& request = mRequests.valueAt(i);
        struct epoll_event eventItem;
        request.initEventItem(&eventItem);
        // 将Request发送给epoll实例,用于,这里的mRequests是在何时添加的呢?[见1.13小节]
        int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, request.fd, &eventItem);
        if (epollResult < 0) {
            ALOGE("Error adding epoll events for fd %d while rebuilding epoll set: %s",
                  request.fd, strerror(errno));
        }
    }

}
1.13 Request的创建
int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
    // addFd是何时被调用的呢?[见1.14小节]
    if (!callback.get()) {
        if (! mAllowNonCallbacks) {
            // 创建Looper时如果传入的allowNonCallbacks为false,则必须传入callback,否则直接返回
            ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
            return -1;
        }
    }

    { // acquire lock
        AutoMutex _l(mLock);

        // 创建Request
        Request request;
        request.fd = fd;
        request.ident = ident;
        request.events = events;
        request.seq = mNextRequestSeq++;
        request.callback = callback;
        request.data = data;
        if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1

        struct epoll_event eventItem;
        // 构建epoll_event
        request.initEventItem(&eventItem);

        ssize_t requestIndex = mRequests.indexOfKey(fd);
        if (requestIndex < 0) {
            // 之前未添加过,则直接添加
            int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &eventItem);
            mRequests.add(fd, request);
        } else {
            // 否则先修改后再替换
            int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_MOD, fd, &eventItem);
            if (epollResult < 0) {
                if (errno == ENOENT) {
                    epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &eventItem);
                    scheduleEpollRebuildLocked();
                }
            }
            mRequests.replaceValueAt(requestIndex, request);
        }
    } // release lock
    return 1;
}

1.14 Looper.addFd的调用
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
    { // acquire lock
        std::scoped_lock _l(mLock);
        // 获取InputChannel对应的Connection
        sp<Connection> existingConnection = getConnectionLocked(inputChannel->getConnectionToken());
        // 如果之前已经注册过该InputChannel则直接返回
        if (existingConnection != nullptr) {
            ALOGW("Attempted to register already registered input channel '%s'",
                  inputChannel->getName().c_str());
            return BAD_VALUE;
        }
        // 创建InputChannel对应的Connection
        sp<Connection> connection = new Connection(inputChannel, false /*monitor*/, mIdGenerator);
    
        // 获取InputChannel对应的文件描述符
        int fd = inputChannel->getFd();
        mConnectionsByFd[fd] = connection;
        mInputChannelsByToken[inputChannel->getConnectionToken()] = inputChannel;
        // 调用Looper.addFd监听InputChannel的读操作
        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
    } // release lock
    
    // Wake the looper because some connections have changed.
    // 唤醒InputDispatcher对应的线程
    mLooper->wake();
    return OK;
}

这里的Lopper(system/core/libutils/Looper.cpp并非我们Java层常用的``Looper(frameworks/base/core/java/android/os),它基于epoll机制实现主要用于文件描述符的监听,由于epoll并非本文的重点所以我们目前只需要简单了解即可;

1.2 InputDispatcher线程的启动

[-> InputDispatcher.cpp]

status_t InputDispatcher::start() {
    // 如果线程已经启动则直接返回
    if (mThread) {
        return ALREADY_EXISTS;
    }
    // 否则创建InputThread,传入loop和wake方法
    mThread = std::make_unique<InputThread>(
            "InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
    return OK;
}

[-> InputThread.cpp]

// Implementation of Thread from libutils.
class InputThreadImpl : public Thread {
public:
    explicit InputThreadImpl(std::function<void()> loop)
          : Thread(/* canCallJava */ true), mThreadLoop(loop) {}

    ~InputThreadImpl() {}

private:
    std::function<void()> mThreadLoop;

    bool threadLoop() override {
        // dispatchOnce[见1.3小节]
        mThreadLoop();
        return true;
    }
};

} // namespace

InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake)
      : mName(name), mThreadWake(wake) {
    mThread = new InputThreadImpl(loop);
    mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}

InputThread只是对InputThreadImpl的封装,InputThreadImpl才是一个真正的线程,我们传入了三个参数:线程名–“InputDispatcher”,loop函数–dispatchOnce(),wake函数–Looper.wake(),在调用InputThreadImpl.run方法之后,线程就开始运行起来并调用threadLoop方法开始消息队列的循环处理,这样也就回到了dispatchOnce()方法;

1.3 InputDispatcher的消息循环

[-> InputDispatcher.cpp]

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.
        // 如果mCommandQueue没有待处理的Command,则执行dispatchOnceInnerLocked去产生Command[见1.4小节]
        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.
        // 如果mCommandQueue队列消息不为空,则循环从中取出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.
        // 判断是否要触发ANR
        const nsecs_t nextAnrCheck = processAnrsLocked();
        // 下一次唤醒时间
        nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
    } // 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);
    // 等待epoll的响应
    mLooper->pollOnce(timeoutMillis);
}

dispatchOnce()会根据mCommandQueue队列里是否有未执行的Command来判断是否执行dispatchOnceInnerLocked,如果有的话则循环从中取出CommandEntry并执行其command方法,这里CommandEntry的来源除了事件分发以外,还有焦点改变,配置改变以及触发ANR等事件,最后根据消息的超时情况来判断是否需要触发ANR;在开启接下来的流程之前,我们先记下几个比较重要的数据结构和队列,它们都由同一把锁保护,以后我们会频繁的与它们打交道,这其中最重要的及时mInboundQueue,它保存的是即将发送给InputChannel去处理的输入事件,而其来源则是InputReader,我们会在接下来关于InputReader的文章中作更详细的介绍;

// 待处理的输入事件
EventEntry* mPendingEvent GUARDED_BY(mLock);
// Blocked event latency optimization.  Drops old events when the user intends
// to transfer focus to a new application.
// 下一个未阻塞的输入事件
EventEntry* mNextUnblockedEvent GUARDED_BY(mLock);
// mInboundQueue输入事件队列
std::deque<EventEntry*> mInboundQueue GUARDED_BY(mLock);
// mRecentQueue输入事件队列
std::deque<EventEntry*> mRecentQueue GUARDED_BY(mLock);
// mCommandQueue命令队列
std::deque<std::unique_ptr<CommandEntry>> mCommandQueue GUARDED_BY(mLock);
1.4 分类处理输入事件

[-> InputDispatcher.cpp]

void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
    // 记录当前时间
    nsecs_t currentTime = now();

    // Ready to start a new event.
    // If we don't already have a pending event, go grab one.
    // mPendingEvent初始化为空
    if (!mPendingEvent) {
        if (mInboundQueue.empty()) {
            ......
            // 如果mInboundQueue队列为空,而且没有待处理的输入事件则直接返回
            // Nothing to do if there is no pending event.
            if (!mPendingEvent) {
                return;
            }
        } else {
            // 否则直接从mInboundQueue队列头取出一个EventEntry来处理
            // Inbound queue has at least one entry.
            mPendingEvent = mInboundQueue.front();
            mInboundQueue.pop_front();
            traceInboundQueueLengthLocked();
        }

        // Poke user activity for this event.
        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
            pokeUserActivityLocked(*mPendingEvent);
        }
    }

    ......
    switch (mPendingEvent->type) {
        ......
        case EventEntry::Type::MOTION: {
            // 将mPendingEvent强转为MotionEntry
            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;
            }
            if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
                dropReason = DropReason::BLOCKED;
            }
            // 如果是Motion Event则会走dispatchMotionLocked分支[见1.5小节]
            done = dispatchMotionLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
            break;
        }
    }

    if (done) {
        if (dropReason != DropReason::NOT_DROPPED) {
            dropInboundEventLocked(*mPendingEvent, dropReason);
        }
        mLastDropReason = dropReason;
        // 处理完成之后释放mPendingEvent
        releasePendingEventLocked();
        *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
    }
}

dispatchOnceInnerLocked会从mInboundQueue队头取出EntryEvent赋值给mPendingEvent,并根据输入事件的类型作不同的处理,处理完成之后再释放mPendingEvent,这里我们以MotionEvent为例来分析输入事件的处理流程;

1.5 处理触摸事件

[-> InputDispatcher.cpp]

bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry,
                                           DropReason* dropReason, nsecs_t* nextWakeupTime) {
    // 判断是否是Touch事件
    bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
    // Identify targets.
    std::vector<InputTarget> inputTargets;

    if (isPointerEvent) {
        // Pointer event.  (eg. touchscreen)
        // 寻找Touch事件的焦点窗口
        injectionResult =
                findTouchedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime,
                                               &conflictingPointerActions);
    } else {
        // Non touch event.  (eg. trackball)
        // 寻找非Touch事件的焦点窗口[见1.6小节]
        injectionResult =
                findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);
    }
    
    // 对于MotionEvent有3种情况会返回INPUT_EVENT_INJECTION_PENDING状态
    // 焦点窗口为空而焦点应用不为空时分两种情况:
    // 1.未设置焦点窗口缺失的超时时间;
    // 2.焦点窗口缺少的超时时间还未到;
    // 焦点窗口和焦点应用都不为空时: 
    // 3.焦点窗口处于暂停状态;
    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
        return false;
    }

    setInjectionResult(entry, injectionResult);
    if (injectionResult == INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
        ALOGW("Permission denied, dropping the motion (isPointer=%s)", toString(isPointerEvent));
        return true;
    }
    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
        CancelationOptions::Mode mode(isPointerEvent
                                              ? CancelationOptions::CANCEL_POINTER_EVENTS
                                              : CancelationOptions::CANCEL_NON_POINTER_EVENTS);
        CancelationOptions options(mode, "input event injection failed");
        synthesizeCancelationEventsForMonitorsLocked(options);
        return true;
    }

    // 找到目标窗口之后开始分发事件[见1.9小节]
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}

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

1.6 寻找焦点窗口

[-> 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
    sp<InputWindowHandle> focusedWindowHandle =
            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
    // 根据display id查找InputApplicationHandle
    sp<InputApplicationHandle> focusedApplicationHandle =
            getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);

    // If there is no currently focused window and no focused application
    // then drop the event.
    // 如果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;
    }

    // Compatibility behavior: raise ANR if there is a focused application, but no focused window.
    // Only start counting when we have a focused event to dispatch. The ANR is canceled if we
    // start interacting with another application via touch (app switch). This code can be removed
    // if the "no focused window ANR" is moved to the policy. Input doesn't know whether
    // an app is expected to have a focused window.
    // 焦点应用不为空而焦点窗口为空
    if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr) {
        // 未设置焦点窗口缺失的超时时间
        if (!mNoFocusedWindowTimeoutTime.has_value()) {
            // We just discovered that there's no focused window. Start the ANR timer
            // 获取超时时间,默认为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) {
            // Already raised ANR. Drop the event
            // 如果已经超时,则直接丢弃该事件
            ALOGE("Dropping %s event because there is no focused window",
                  EventEntry::typeToString(entry.type));
            return INPUT_EVENT_INJECTION_FAILED;
        } else {
            // Still waiting for the focused window
            // 还未到超时时间则继续等待
            return INPUT_EVENT_INJECTION_PENDING;
        }
    }

    // we have a valid, non-null focused window
    // 重置超时时间和等待的焦点应用
    resetNoFocusedWindowTimeoutLocked();

    // 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;
    }

    // Success!  Output targets.
    // 成功找到焦点窗口后,将其添加到inputTargets[见1.9小节]
    addWindowTargetLocked(focusedWindowHandle,
                          InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
                          BitSet32(0), inputTargets);

    // Done.
    return INPUT_EVENT_INJECTION_SUCCEEDED;
}

这里有两个非常重要的map:mFocusedWindowHandlesByDisplaymFocusedApplicationHandlesByDisplay,它们分别存储着当前每个display对应的焦点应用和焦点窗口;

[-> InputDispatcher.h]

// Focus tracking for keys, trackball, etc.
// key为display id,value为InputWindowHandle即焦点窗口,更新过程见[1.7小节]
std::unordered_map<int32_t, sp<InputWindowHandle>> mFocusedWindowHandlesByDisplay
        GUARDED_BY(mLock);

// key为display id,value为InputApplicationHandle即焦点应用,更新过程见[1.8小节]
// Focused applications.
std::unordered_map<int32_t, sp<InputApplicationHandle>> mFocusedApplicationHandlesByDisplay
        GUARDED_BY(mLock);
1.7 设置焦点窗口

[-> InputDispatcher.cpp]

void InputDispatcher::setInputWindowsLocked(
        const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId) {
    ......
    // Copy old handles for release if they are no longer present.
    // 根据displayId从mWindowHandlesByDisplay中查找出当前所有的InputWindowHandle,包括焦点窗口和非焦点窗口
    const std::vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
    // 根据传入的窗口列表inputWindowHandles来更新mWindowHandlesByDisplay
    updateWindowHandlesForDisplayLocked(inputWindowHandles, 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,调用流程如下所示:可以看出整个过程由SurfaceFlinger触发;

-->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.8 设置焦点应用

[-> InputDispatcher.cpp]

void InputDispatcher::setFocusedApplication(
        int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) {
    {   // acquire lock
        std::scoped_lock _l(mLock);
        // 根据displayId获取历史焦点应用
        sp<InputApplicationHandle> oldFocusedApplicationHandle =
                getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);

        // 如果已经切换到新的应用,而且历史应用之前在等待焦点窗口,那么继续等待已经没有意义,所以重置等待的焦点应用和等待时间
        if (oldFocusedApplicationHandle == mAwaitedFocusedApplication &&
            inputApplicationHandle != oldFocusedApplicationHandle) {
            resetNoFocusedWindowTimeoutLocked();
        }

        if (inputApplicationHandle != nullptr && inputApplicationHandle->updateInfo()) {
            if (oldFocusedApplicationHandle != inputApplicationHandle) {
                // 更新焦点应用
                mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
            }
        } else if (oldFocusedApplicationHandle != nullptr) {
            oldFocusedApplicationHandle.clear();
            // 清除历史焦点应用
            mFocusedApplicationHandlesByDisplay.erase(displayId);
        }
    } // release lock

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

这里会根据传入的InputApplicationHandle来更新焦点应用,由于有多个分支会调用到这里,所以仅只列出最典型的一个,即在切换应用并且新应用Acitivity.onResume时调用:

-->frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.setResumedActivityUncheckLocked
-->frameworks/base/services/core/java/com/android/server/wm/DisplayContent.setFocusedApp
-->frameworks/base/services/core/java/com/android/server/wm/InputMonitor.setFocusedAppLw
-->frameworks/base/services/core/java/com/android/server/input/InputManagerService.setFocusedApplication
-->frameworks/base/services/core/jni/com_android_server_input_InputManagerService.nativeSetFocusedApplication
-->frameworks/base/services/core/jni/com_android_server_input_InputManagerService.NativeInputManager.setFocusedApplication
-->frameworks/native/services/inputflinger/InputDispatcher.setFocusedApplication
1.9 添加窗口目标

[-> InputDispatcher.cpp]

void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
                                            int32_t targetFlags, BitSet32 pointerIds,
                                            std::vector<InputTarget>& inputTargets) {
    // 查找windowHandle对应的InputTarget是否添加过
    std::vector<InputTarget>::iterator it =
            std::find_if(inputTargets.begin(), inputTargets.end(),
                         [&windowHandle](const InputTarget& inputTarget) {
                             return inputTarget.inputChannel->getConnectionToken() ==
                                     windowHandle->getToken();
                         });
    // 获取InputWindowHandle对应的InputWindowInfo
    const InputWindowInfo* windowInfo = windowHandle->getInfo();
    // 如果没有添加过则重新创建一个InputTarget
    if (it == inputTargets.end()) {
        InputTarget inputTarget;
        // 查找InputChannel[见1.9.1小节]
        sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken());
        inputTarget.inputChannel = inputChannel;
        inputTarget.flags = targetFlags;
        inputTarget.globalScaleFactor = windowInfo->globalScaleFactor;
        // 构造InputTarget并将其压入inputTargets中
        inputTargets.push_back(inputTarget);
        it = inputTargets.end() - 1;
    }
    
    it->addPointers(pointerIds, -windowInfo->frameLeft, -windowInfo->frameTop,
                    windowInfo->windowXScale, windowInfo->windowYScale);
}
1.9.1 查找InputChannel

[-> InputDispatcher.cpp]

sp<InputChannel> InputDispatcher::getInputChannelLocked(const sp<IBinder>& token) const {
    // mInputChannelsByToken是在registerInputChannel或者registerInputMonitor时写入的
    size_t count = mInputChannelsByToken.count(token);
    if (count == 0) {
        return nullptr;
    }
    return mInputChannelsByToken.at(token);
}
1.10 传递输入事件

[-> InputDispatcher.cpp]

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

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

1.10.1 获取Connection

[-> InputDispatcher.cpp]

sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConnectionToken) const {
    if (inputConnectionToken == nullptr) {
        return nullptr;
    }

    // 从mConnectionsByFd中找到与InputChannel token一致的Connection
    for (const auto& pair : mConnectionsByFd) {
        const sp<Connection>& connection = pair.second;
        if (connection->inputChannel->getConnectionToken() == inputConnectionToken) {
            return connection;
        }
    }
    
    return nullptr;

}

这里的mConnectionsByFd和1.9.1小节中的mInputChannelsByToken都是在registerInputChannel或者registerInputMonitor时更新的,Connection会持有对InputChannel的引用,所以可以根据InputChannel.getConnectionToken()找到对应的Connection,我们会在下一篇中详细介绍InputChannelConnection的创建;

1.11 准备分发输入事件

[-> InputDispatcher.cpp]

void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
                                                 const sp<Connection>& connection,
                                                 EventEntry* eventEntry,
                                                 const InputTarget& inputTarget) {
    // Skip this event if the connection status is not normal.
    // We don't want to enqueue additional outbound events if the connection is broken.
    // 如果Connection状态不正常,则直接返回不会把输入事件添加到mOutbound队列
    if (connection->status != Connection::STATUS_NORMAL) {
            return;
    }

    // Not splitting.  Enqueue dispatch entries for the event as is.
    // 入队输入事件[见1.12小节]
    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
1.12 入队输入事件

[-> InputDispatcher.cpp]

void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
                                                   const sp<Connection>& connection,
                                                   EventEntry* eventEntry,
                                                   const InputTarget& inputTarget) {
    // 判断Connection的outboundQueue是否为空
    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);
    // 入队输入事件[见1.12.1小节]
    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之后不为空,则开始处理输入事件[见1.13小节]
        startDispatchCycleLocked(currentTime, connection);
    }
}
1.12.1 入队输入事件

[-> InputDispatcher.cpp]

void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
                                                 EventEntry* eventEntry,
                                                 const InputTarget& inputTarget,
                                                 int32_t dispatchMode) {
    ......
    // This is a new event.
    // Enqueue a new dispatch entry onto the outbound queue for this connection.
    // 将EventEntry封装为DispatchEntry
    std::unique_ptr<DispatchEntry> dispatchEntry =
            createDispatchEntry(inputTarget, eventEntry, inputTargetFlags);
    ......
    // Enqueue the dispatch entry.
    // 将DispatchEntry添加到Connection中的outboundQueue队列中,此时outboundQueue不为空
    connection->outboundQueue.push_back(dispatchEntry.release());
    traceOutboundQueueLength(connection);
}
1.13 开始分发输入事件

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

                // Publish the motion event.
                // 通过Connection的InputPublisher.publishMotionEvent将输入事件发布出去[见1.14小节]
                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.
        // 发布完之后将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.14 发布输入事件

[-> 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发送消息[见1.15小节]
    return mChannel->sendMessage(&msg);
}
1.15 发送输入事件给应用进程

[-> 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将输入事件发送给客户端,但是我们的客户端是谁?socket是什么时候创建的?InputChannelConnectionmFdToken这些类分别代表什么含义,我们目前还不得而知,受制于篇幅的限制这些疑问我们会留到下一篇文章来解答。

以上是关于Android 11.0源码系列之IMSInputDispatcher的主要内容,如果未能解决你的问题,请参考以下文章

Android 11.0源码系列之PMSinstalld

Android 11.0源码系列之IMSInputManagerService

Android 11.0源码系列之IMSInputManager

Android 11.0源码系列之IMSInputDispatcher

Android 11.0源码系列之PMSPackageManagerService的创建

Android 11.0源码系列之IMSInputReader