anadroid inputmanager详细分析

本文详细分析了Android系统的InputManager,重点探讨InputReader和InputDispatcher的工作流程。InputReader从设备读取事件,InputDispatcher负责事件分发。通过监听InputReader,InputDispatcher确保事件正确传递。文中还介绍了EventHub、InputListener接口和QueuedInputListener的使用,揭示了Input事件处理的内部机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<pre name="code" class="cpp"><pre name="code" class="cpp">a

先上一张图,对input整体框架有个总体认识:


InputManager是输入控制中心,它有两个关键线程InputReaderThreadInputDispatcherThread,它们的主要功能部分分别在InputReaderInputDispacher。前者用于从设备中读取事件,后者将事件分发给目标窗口。EventHub是输入设备的控制中心,它直接与inputdriver打交道。负责处理输入设备的增减,查询,输入事件的处理并向上层提供getEvents()接口接收事件。在它的构造函数中,主要做三件事:
1. 
创建epoll对象,之后就可以把各输入设备的fd挂在上面多路等待输入事件。
2. 
建立用于唤醒的pipe,把读端挂到epoll上,以后如果有设备参数的变化需要处理,而getEvents()又阻塞在设备上,就可以调用wake()pipe的写端写入,就可以让线程从等待中返回。
3. 
利用inotify机制监听/dev/input目录下的变更,如有则意味着设备的变化,需要处理。


事件的处理是流水线,需要InputReader先读事件,然后InputDispatcher才能进一步处理和分发。因此InputDispatcher需要监听InputReader。这里使用了Listener模式,InputDispacher作为InputReader构造函数的第三个参数,它实现InputListenerInterface接口。到了InputReader的构造函数中,将之包装成QueuedInputListenerQueuedInputListener中的成员变量mArgsQueue是一个缓冲队列,只有在flush()时,才会一次性通知InputDispatcherQueuedInputListener应用了Command模式(感觉更像观察者模式,这个设计模式待定),它通过包装InputDispatcher(实现InputListenerInterface接口),将事件的处理请求封装成NotifyArgs,使其有了缓冲执行的功能。

下面分析inputmanager的inputReader和InputDispatcher,分析后应该知道inputReader是怎么发送input事件给InputDispatcher,并且InputDispatcher是怎么把inut事件发送出去的。

先看一张序列图:


先分析inputReader:

bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}


 
 
void InputReader::loopOnce() {
....

size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

if (count) {
            processEventsLocked(mEventBuffer, count);
        }
.....
mQueuedListener->flush();
}

这里只摘出了,我们需要分析的流程代码,EventHub先读取驱动中上报的input事件,然后再调用mQueueListener->flush()。

这个mQueueListener->flush()是什么东西?

这里用到了通知者模式:

进入InputListener.cpp查看代码可以看到,notifyXXXX,这里以notifyMotion举例说明,

void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
    mArgsQueue.push(new NotifyMotionArgs(*args));
}

这里是实现了被通知者注册的函数,想要被通知方都可以注册,然后当通知方发送通知的时候,被通知方都能够收到消息。

被通知方类:

NotifyMotionArgs::NotifyMotionArgs(......) {
    for (uint32_t i = 0; i < pointerCount; i++) {
        this->pointerProperties[i].copyFrom(pointerProperties[i]);
        this->pointerCoords[i].copyFrom(pointerCoords[i]);
    }
}

NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other):.... {
    for (uint32_t i = 0; i < pointerCount; i++) {
        pointerProperties[i].copyFrom(other.pointerProperties[i]);
        pointerCoords[i].copyFrom(other.pointerCoords[i]);
    }
}

void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const {
    listener->notifyMotion(this);
}
在哪里注册了这个NotifyMotionArgs?

void TouchInputMapper::dispatchMotion(){
  
    .....
    NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
            action, flags, metaState, buttonState, edgeFlags,
            mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
            xPrecision, yPrecision, downTime);
    getListener()->notifyMotion(&args);
}

这里就注册了被通知者,当然还有一些其他的被通知者类型,大家可以看InputListener.cpp文件。

QueuedInputListener::flush()函数的实现:

void QueuedInputListener::flush() {
    size_t count = mArgsQueue.size();
    for (size_t i = 0; i < count; i++) {
        NotifyArgs* args = mArgsQueue[i];
        args->notify(mInnerListener);
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值