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 I

本文详细解析了Android系统的InputDispatcher如何处理输入事件,包括线程启动、事件循环、事件分发等核心流程。重点介绍了针对不同类型的输入事件(如按键、触摸等)的处理方式,以及焦点窗口的寻找和设置。通过对InputDispatcher、InputThread、InputEvent、InputTarget等关键组件的分析,展示了Android输入事件从捕获到传递给应用的完整路径。
最低0.47元/天 解锁文章
822

被折叠的 条评论
为什么被折叠?



