前序
书接上文,前面我们讲了下Android输入事件的全貌,从底层硬件产生事件,经过IMS的InputReader加工转换再经过InputDspatcher分发转给WMS中间层,再通过WMS定位到准确的window进行我们熟悉的上层事件处理。
上文我们详细讲解了IMS的初始化流程及底层事件的拦截处理流程,今天我们继续讲解InputReader处理完的事件怎么进行分发的。
InputDspatcher 分发事件
将封装的事件压入到队列中并唤醒 InputDispatchert 线程进行分发处理。
InputDispatcher线程唤醒
status_t InputDispatcher::start() {
if (mThread) {
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>(
"InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
return OK;
}
和InputReader一样运行在单独的线程,执行 threadLoop 时的回调函数dispatchOnce
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
std::scoped_lock _l(mLock);
mDispatcherIsAlive.notify_all();
//注释1
if (!haveCommandsLocked()) {
//注释2
dispatchOnceInnerLocked(&nextWakeupTime);
}
// 注释3
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
const nsecs_t nextAnrCheck = processAnrsLocked();
nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
// We are about to enter an infinitely long sleep, because we have no commands or
// pending or queued events
if (nextWakeupTime == LONG_LONG_MAX) {
mDispatcherEnteredIdle.notify_all();
}
} // release lock
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
mLooper->pollOnce(timeoutMillis);
}
首先判断是否有指令需要执行,如果没有,则调用注释2处的dispatchOnceInnerLocked去根据事件类型进行处理,如果有则优先调用3处的runCommandsLockedInterruptible处理事件, 为了让线程可以立即进入事件处理,将nextWakeupTime 设置为LONG_LONG_MIN,这样线程在指令执行完毕后可以立即被唤醒去处理输入事件。
我们先看下2处的事件处理
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
.....
// 如果 InputDispatcher 被冻结,则不进行派发操作
if (mDispatchFrozen) {
if (DEBUG_FOCUS) {
ALOGD("Dispatch frozen. Waiting some more.");
}
return;
}
.......
// 如果没有待分发的事件,去 mInboundQueue 取出一个事件
if (!mPendingEvent) {
//如果没有待分发的事件,就去 mInboundQueue 中取出一个事件
if (mInboundQueue.empty()) {
.......
if (!mPendingEvent) {
return;
}
} else {
//不为空,则从头部取出一个事件
mPendingEvent = mInboundQueue.front();
mInboundQueue.pop_front();
traceInboundQueueLengthLocked();
}
// Poke user activity for this event.
if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
pokeUserActivityLocked(*mPendingEvent);
}
}
ALOG_ASSERT(mPendingEvent != nullptr);
bool done = false;
DropReason dropReason = DropReason::NOT_DROPPED; //1
.....
switch (mPendingEvent->type) {
case EventEntry::Type::CONFIGURATION_CHANGED: .....
case EventEntry::Type::DEVICE_RESET: .....
case EventEntry::Type::FOCUS: .....
case EventEntry::Type::DRAG: .....
case EventEntry::Type::KEY:.....
case EventEntry::Type::MOTION: { //2
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;
}
//3
done = dispatchMotionLocked(currentTime, motionEntry,