Android底层事件分发机制-完结篇

前序

书接上文,前面我们讲了下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, 
  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值