IMS 与输入系统:一次触摸如何从屏幕走到 View
2026/8/9大约 4 分钟IMS 专题Android 14IMS输入系统InputDispatcher
输入系统全景:一次触摸如何从屏幕走到 View
View 分发只是最后一段
| 常见误解 | 正确理解 |
|---|---|
| 输入系统就是 View 的事件分发 | View 分发只是主链最后一环,前面还有设备、读取、加工与调度 |
| 触摸事件直接发给“焦点窗口” | 按键事件才发给焦点窗口;触摸事件按坐标做窗口命中测试 |
| IMS 只是个 Java 服务 | IMS 的 Java 部分是服务壳,真正的读取与分发在 Native 的两个线程里 |
dispatchTouchEvent() 到 onTouchEvent() 只发生在应用进程。此前,内核设备节点先产生 原始事件,EventHub 读取,InputReader 解释并变换坐标,InputDispatcher 再选择目标窗口, 最后通过 InputChannel 把事件送入应用 Looper。
InputManagerService 位于 system_server,Java 层负责服务管理,核心读取与分发工作由 Native 层的 InputReader 和 InputDispatcher 线程完成。WMS 提供窗口元数据,IMS 据此完成输入投递。
核心结论
- 输入主链:内核输入设备 → EventHub 读取原始事件 → InputReader 加工成 InputEvent → InputDispatcher 选择目标窗口 → InputChannel 送达应用进程 → View 分发。
- 前四段都在 system_server:EventHub 与 InputReader 在 InputReader 线程,InputDispatcher 在独立的 InputDispatcher 线程。
- 应用侧在自己进程的 Looper 线程接收事件,再切到主线程交给 View 体系。
- IMS 负责设备、加工与分发;WMS 负责窗口、焦点与触摸区域等元数据,两者通过 InputWindowHandle 协作。
- 排障入口固定三处:
getevent看内核原始事件、dumpsys input看 reader/dispatcher 状态、ANR trace 看应用是否消费。
输入主链全景
逐步解释:
- 内核产生原始事件:触摸屏、按键等硬件驱动把事件写入
/dev/input/eventX。 - EventHub 读取:IMS 的 Native 层打开设备,循环读取原始事件。
- InputReader 加工:在 InputReader 线程把原始事件按设备类型与配置变成
MotionEvent、KeyEvent等统一事件。 - InputDispatcher 分发:在 InputDispatcher 线程做命中测试,决定事件送给哪个窗口, 并通过 InputChannel 送达。
- 应用接收:应用进程的
InputEventReceiver在自己的 Looper 线程收到事件,ViewRootImpl再交给 View 体系分发。
这条主链上的每一段,后续各章都会拆开讲;排查输入问题时,先判断断在哪一段,再进入对应章节。
常用在哪些地方
输入系统贯穿所有交互场景,按排查频率排列:
- 触摸:点击、滑动、多指、手势,主链是“触摸屏 → 触摸目标窗口 → View”。
- 按键:物理按键、导航键、音量键,按键事件发给焦点窗口。
- 键盘与鼠标:外接设备通过同一套 EventHub/Reader/Dispatcher 流程进入。
- 系统手势:全面屏手势、三键导航等由 SystemUI 与 WindowManager 监听,仍走输入主链。
- 输入注入:
adb shell input tap、自动化测试通过 IMS 注入事件,走同一分发路径。
验证与排障
环境:开发设备或模拟器;getevent 与 dumpsys input 不需要 root。
adb shell getevent -lt /dev/input/event2
adb shell dumpsys input
adb shell input tap 500 1000
adb logcat -v threadtime | grep -E "InputDispatcher|InputReader|InputManager"getevent 确认硬件层有没有事件;dumpsys input 看设备、reader 与 dispatcher 状态; input tap 验证注入路径;logcat 看关键日志。这三处对应主链的前中后三段,具体分析在 系列末章展开。
源码入口
| 文件 | 关键位置 | 作用 |
|---|---|---|
InputManagerService.java | start() / Native 桥接 | Java 服务壳 |
EventHub.cpp | getEvents() / openDevice() | 设备读取 |
InputReader.cpp | loopOnce() / processEventsLocked() | 事件加工 |
InputDispatcher.cpp | dispatchOnce() | 事件分发 |
InputEventReceiver.java | dispatchInputEvent() | 应用侧接收 |
公共路径:Java 服务 frameworks/base/services/core/java/com/android/server/input/, Native 输入在 frameworks/base/services/inputflinger/,应用侧接收在 frameworks/base/core/java/android/view/。行号以 r75 检索为准。
从输入设备读取原始记录的入口,见 EventHub。