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,如有侵权,请联系删除。

发表回复

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