Jimmy Chen

A Programmer

(转载)Input系统: InputReader概要性分析

从 InputManagerService: 创建与启动 可知,Input 系统的主要功能,主要集中在 native 层,并且Input 系统的 native 层又包含 InputReader, InputClassifer, InputDispatcher 三个子模块。本文来分析 InputReader 从创建到启动的基本流程,为后续分析 InputReader 的每一个功能打好基础。

InputReader 的创建

从 InputManagerService: 创建与启动 可知, InputReader 的创建过程如下

InputReader 依赖 EventHub,因此首先要看下 EventHub 的创建过程

EventHub 创建过程如下

  1. 创建 epoll 实例。
  2. 初始化 inotify 实例,并用 epoll 监听它的事件。当输入设备添加/删除时,epoll 就会收到 inotify 的可读事件,因此 EventHub 和 InputReader 就可以动态地处理输入设备的添加/删除。
  3. 创建管道。
  4. epoll 监听管道的读端的事件。当配置更新时,会向管道的写端写入数据,epoll 就会收到管道的可读事件,如果此时 InputReader 线程处于休眠状态,那么 InputReader 将被唤醒来处于配置更新。

epoll, inotify, pipe,它们的作用和使用方式,请读者自行查阅 Unix/Linux 资料。

现在让我们继续看下 InputReader 的创建过程

InputReader 的构造函数很简单,就是成员变量的初始化。其中需要重点看下 refreshConfigurationLocked(0) 是如何刷新 InputReader 配置

原来 InputReader::mConfig 代表的就是 InputReader 的配置,并且是通过 InputReaderPolicyInterface mPolicy 获取配置的。

从 InputManagerService: 创建与启动 可知,InputReaderPolicyInterface 接口的实现者是 NativeInputManager ,而 NativeInputManager 是 Input 系统的上层与底层沟通的桥梁,因此 InputReader 必定是通过 NativeInputManager 向上层获取配置

从整体看,获取 InputReader 配置的方式有两种

  1. 通过 JNI 向上层的 InputManagerService 获取配置。
  2. 从 NativeInputManager::mLocked 获取配置。

从 InputManagerService: 创建与启动 可知,NativeInputManager::mLocked 是在 NativeInputManager 的构造函数中进行初始化的,但是它并不是不变的,而是上层经由 InputManagerService 进行操控的。

例如,mLocked.showTouches 对应开发者模式下的 Show taps 功能,InputManagerService 会监听这个开关的状态,相应地改变 mLocked.showTouches,并且会通知 InputReader 配置改变了,InputReader 在处理配置改变的过程时,会重新获取 mLocked.showTouches 这个配置。

有 一部分 的配置是可以通过 adb shell dumpsys input 命令进行查看的

而另外一部分配置,由于会对输入设备进行配置,因此可以从 dump 出的输入设备的信息中查看。

InputReader 的运行

从 InputManagerService: 创建与启动 可知,InputReader 通过线程,循环调用 InputReader::loopOnce() 执行任务

InputReader 所做的事情如下

  1. 如果配置改变了,那么就更新配置。
  2. 从 EventHub 获取事件,并处理获取到的事件。在处理事件的过程中,InputReader 会对事件进行加工,然后保存到 QueuedInputListener 缓存队列中。
  3. 如果设备发生改变,那么重新获取新的设备信息,并通知监听者。
  4. QueuedInputListener 刷新缓存的事件,其实就是把 InputReader 加工后的事件分发给 InputClassifer。

EventHub 提供事件

InputReader 的本质就是处理从 EventHub 获取的事件,然后分发给下一环。因为我们必须了解 EventHub::getEvents() 是如何为 InputReader 提供事件的

EventHub::getEvent() 提供事件的过程很长,但是现在我们不必去了解所有的细节,我们要有从整体看局部的眼光。EventHub 其实只生成了两类事件

  1. 设备的添加/删除事件。这种事件不是通过操作设备而产生的,系统称之为合成事件。
  2. 输入事件。这种事件是通过操作设备产生的,例如手指在触摸屏上滑动,系统称之为元输入事件。

看来我们得分两部分来分析这两类事件的生成以及处理过程,因此下一篇文章,我们分析合成事件的生成以及处理过程。

本文转自 https://juejin.cn/post/7164221690203865119,如有侵权,请联系删除。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注