本博客在 https://wkmcyz.notion.site/InputManagerService-616004c0a3fa4324b952f7e8563a010f 可以获得更好的阅读体验。
Android 的触摸事件,可以分为三部分。
第一部分是硬件部分,检测触摸事件,这一步需要传感器之类的组件来完成。这部分主要是硬件相关的知识。
第二部分是操作系统部分, 将触摸事件传递给应该接受它的目标应用。本篇后面会说的 InputManagerService 的相关内容就是解释这部分的流程的。
第三部分是控件级别(即各个 View 类)的处理,来消化该触摸事件。这是 Android 应用的 view 触摸事件处理,不在此讨论
InputManagerService 是 Android 的一个系统服务,运行在 system_server 进程中,和 WMS 一起配合维护着 Android 的输入事件的管理,也就是上面提到的 “操作系统处理” 的部分。
想象一下,这样一个传递触摸事件的管理者需要进行哪些操作。主要应该分为三步,第一是从硬件部分接收事件;第二是进行一些自己的处理;第三是将这部分事件传递给其对应的进程以及对应的控件。我们也主要对这三步进行说明。
第一步:从设备读取原始的输入事件
Android 设备在发生输入事件的时候,会将触摸事件写入一个文件,InputManagerService 依赖 epoll 机制从该文件读取触摸事件的信息,读取到的便是原始的输入事件。这就是最初 InputManagerService 的输入。
第二步:IMS 对输入事件进行处理
IMS 会执行一个中间者的职责,将原始输入信息转化成应用希望得到的方便好用的信息——也就是 Android 系统提供的输入事件类型。上面提到 IMS 接受设备给出的原始输入信息,其中设备会有很多不同的种类,例如外接的键盘、外接的鼠标、手柄以及触摸屏幕等。
这些不同的输入设备会将不同的操作映射为自己独特的事件 id,例如按下键盘的某个按键会被记录为一次 id 为 1 的事件,或者鼠标左键回应设为 id 为 1 的事件等。IMS 接收到以后,该怎么样不同的 id 映射为指定的事件呢?这是根据输入设备的类型来决定的。所以这里 IMS 会先根据输入设备的类型获得一个对应表,也就是一个 Map。其负责将将读入的原始输入信息进行映射处理,这可以认为是一次“解码”。
第三步:IMS 进行输入事件的分发
第二步的处理会将原始输入事件转变成 Android 框架提供的事件类型进行分发,这些事件类型包括 1) Key 事件 ,2)Motion 事件。分发的过程涉及到了当前输入事件的接受者的寻找,因此这部分是需要和 WMS 互相配合以实现该判断的。
WMS 会在管理的窗口布局发生变化的时候,将新的窗口信息都通知给 IMS,这包括每个窗口的位置、宽高、zOrder 、窗口的 flag 等信息,还有焦点窗口等信息,以供 IMS 为输入事件选择目标。
IMS 的分发相关的处理,简单描述如下:
其中分发步骤会有很多处理,会根据 IMS 服务所处的状态决定处理逻辑,这包括在系统休眠的时候或者设备正在旋转的时候,这时候的输入事件会被缓存下来或者丢弃掉。
IMS 会根据当前系统的窗口布局情况以及输入事件的属性选择适合的窗口来处理输入事件。比如有一些特定属性的输入事件不会交给用户进程处理;也可能会因为一些原因将输入事件丢弃。
IMS 在为输入事件选择好目标对象——也就是接受输入事件的窗口——的时候,会判断目标是否可以接收输入事件,如果可以的话,将事件发送给目标。如果目标无法接收的话,会先将输入事件缓存起来,在其可以接受的时候重新发送,或者是在 5s 之后上报 ANR。
相关类的对应关系
IMS 从操作系统读取原始输入事件 :
IMS 将原始输入事件转成 Android 系统的输入事件 :
IMS 将输入事件分派给指定窗口 :
IMS 将输入事件传输给指定窗口 :
窗口接收输入事件:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Blazor Hybrid适配到HarmonyOS系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 分享4款.NET开源、免费、实用的商城系统
· 解决跨域问题的这6种方案,真香!
· 一套基于 Material Design 规范实现的 Blazor 和 Razor 通用组件库