Android input事件处理流程

一、Android input事件机制
Android 系统是由事件驱动的,而 Input 是最常见的事件之一,用户的点击、滑动、长按等操作,都属于 Input 事件驱动,其中的核心就是 InputReader 和 InputDispatcher。InputReader 和 InputDispatcher 是跑在 system_server进程中的两个 Native循环线程,负责读取和分发 Input 事件。整个处理过程大致流程如下:

触摸屏会按照屏幕硬件的触控采样率周期,每隔几毫秒扫描一次,如果有触控事件就会上报到对应的设备驱动;系统封装了一个叫EventHub的对象,它利用inotify和epoll机制监听/dev/input目录下的input设备驱动节点,通过EventHub的getEvents接口就可以监听并获取到Input事件;

InputReader负责从EventHub里面把Input事件读取出来,然后交给 InputDispatcher 进行事件分发;

InputDispatcher在拿到 InputReader获取的事件之后,对事件进行包装后,寻找并分发到目标窗口;

InboundQueue队列(“iq”)中放着InputDispatcher从InputReader中拿到的input事件;

OutboundQueue(“oq”)队列里面放的是即将要被派发给各个目标窗口App的事件;

WaitQueue队列里面记录的是已经派发给 App(“wq”),但是 App还在处理没有返回处理成功的事件;

PendingInputEventQueue队列(“aq”)中记录的是应用需要处理的Input事件,这里可以看到input事件已经传递到了应用进程;

deliverInputEvent 标识 App UI Thread 被 Input 事件唤醒;

InputResponse 标识 Input 事件区域,这里可以看到一个 Input_Down 事件 + 若干个 Input_Move 事件 + 一个 Input_Up 事件的处理阶段都被算到了这里;

App 响应处理Input 事件,内部会在其界面View树中逐层分发和处理。

请添加图片描述
二、结合Systrace分析
从上面的系统机制的分析可以看出,整个Input触控事件的分发与处理主要涉及到两个进程:一个是system_server系统进程,另一个是当前焦点窗口所属的Setting应用进程。

  • system_server进程的处理过程:
  1. 当用户手指在Setting应用界面滑动时,系统system_server进程中的native线程InputReader会从EventHub中读取其利用linux的epoll机制监听到的屏幕驱动上报的Input触控事件,然后唤醒另外一条native线程InputDispatcher负责进行事件的进一步分发处理。

  2. InputDispatcher被唤醒后会先将事件放到InboundQueue队列(也就是Systrace上看到的“iq”队列)中,然后找到具体处理此input事件的应用目标窗口,并将Input事件放入对应的应用目标窗口的OutboundQueue队列(也就是Systrace上看到的“oq”队列)中,等待进一步通过SocketPair双工信道发送input事件到应用目标窗口中;

  3. 最后当事件发送给具体的应用目标窗口后,会将事件移动到WaitQueue队列中(也就是Systrace上看到的“wq”队列)并一直等待收到到目标应用处理Input事件完成后的反馈后再从队列中移除,如果5秒内没有收到目标应用窗口处理完成此次Input事件的反馈,就会报该应用ANR异常事件。以上整个过程在Android系统AOSP源码中都加有相应的Systrace tag,如下Systrace截图所示:

在这里插入图片描述

  • 应用进程的处理过程

当Input触控事件通过socket传递到Settings应用进程这边后,会唤醒应用的UI线程在ViewRootImpl#deliverInputEvent的流程中进行Input事件的具体分发与处理。具体的处理流程:

  1. 先交给之前在添加应用PhoneWindow窗口时的ViewRootImpl#setView流程中创建的多个不同类型的InputUsage中依次进行处理(比如对输入法处理逻辑的封装ImeInputUsage,某些key类型的Input事件会由它先交给输入法进程处理完后再交给应用窗口的InputUsage处理),整个处理流程是按照责任链的设计模式进行;

  2. 最后会交给负责应用窗口Input事件分发处理的ViewPostImeInputUsage中具体处理,这里面会从View布局树的根节点DecorView开始遍历整个View树上的每一个子View或ViewGroup控件执行事件的分发、拦截、处理的逻辑;

  3. 最后触控事件处理完成后会调用finishInputEvent结束应用对触控事件处理逻辑,这里面会通过JNI调用到native层InputConsumer的sendFinishedSignal函数中通过socket消息通知系统框架中的InputDispatcher该Input事件处理完成,触发从"wq"队列中及时移除待处理事件以免报ANR异常。

  4. 一次滑动过程的触控交互的InputResponse区域中一般会包含一个Input的ACTION_DOWN事件+多个ACTION_MOVE事件+一个ACTION_UP事件,Settings应用界面中的相关View控件在收到多个ACTION_MOVE触控事件后,经过判断为用户手指滑动行为,一般会调用View#invalidate等相关接口触发UI线程的绘制上帧更新画面的操作,具体流程后文会继续详细分析。以上过程如下
    在这里插入图片描述

  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值