【Android Framework】InputManagerService—inputDispatcher

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

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>