1. WMS 与 Input 系统概述:理解 WindowManagerService 和 Input 系统的角色与关系
做 Android 系统优化这些年,我碰到最多的性能问题,十有八九都能追溯到两个地方——WindowManagerService(WMS)和Input 系统。说白了,一个管窗口怎么摆,一个管触摸怎么传,但一旦它们配合不好,用户就感觉“卡顿”“点不上”“反应慢”。想优化响应,必须先把这两个角色的分工和协作机制搞清楚。
1.1 WindowManagerService:窗口的“总调度员”
WMS 是 Android 框架层里最核心的服务之一,运行在 system_server 进程里。它的本职工作很简单:管理所有窗口的创建、顺序、大小、动画和焦点。每次你打开一个 Activity、弹出对话框、显示 Toast,背后都是 WMS 在安排窗口的叠放次序。
举个例子,我去年优化一个多窗口应用时,发现切换任务卡了 200ms。一查,WMS 在做窗口重排序时占了 80ms。问题出在哪?它每收到一次窗口变化,就要遍历整个窗口链表并重新计算 z-order。嗯,这在窗口少的时候没问题,但一旦超过 30 个,就开始卡了。
WMS 的主要职责可以归纳成这样:
- 窗口管理:addWindow、removeWindow、relayoutWindow
- 焦点管理:谁拥有输入焦点(Focus)
- 输入法交互:调整窗口避开软键盘
- 动画与过渡:启动窗口动画、窗口缩略图
- 转场控制:多窗口切换时的表面合成
1.2 Input 系统:从手指到屏幕的“快递员”
Input 系统则负责把用户的触摸、按键事件,从硬件设备一路送到对应的窗口。它包括内核里的 InputReader 和 InputDispatcher 两个主要线程,以及框架层的 InputManagerService(IMS)。
我记得以前有个线上 bug:用户快速滑动列表时,偶尔会“跳帧”。抓到日志发现,InputDispatcher 分发事件的间隔不均匀,有时候两个事件之间隔了 30ms,有时候却只有 2ms。后来定位到原因是 WMS 在调整窗口时,临时抢占了 InputDispatcher 需要的锁——说白了就是资源竞争。
Input 系统的关键流程:
- 内核驱动读取原始触摸数据
- InputReader 解析成 RawInputEvent
- InputDispatcher 查找焦点窗口
- 通过 SocketPair 发送 MotionEvent 到应用进程
- 应用主线程处理并反馈
1.3 它们的关系:互相依赖,也互相掣肘
WMS 管“窗口去哪儿”,Input 管“事件去哪儿”。两者通过一个关键机制连接——焦点窗口查询。当 InputDispatcher 收到一个触摸事件,它必须问 WMS:“当前触摸点下面是谁的窗口?” WMS 根据窗口的 hit-test 区域返回窗口 ,InputDispatcher 才会把事件发过去。
看起来简单,对吧?但实际中,这两个系统运行在同一个进程(system_server)里,共享着大量锁。一旦某个环节变慢——比如 WMS 正在执行一个耗时的 relayout——它就会阻塞 InputDispatcher 的查询请求。这就是很多“触摸无响应”问题的根源。
我建议你在做优化前,先把这张图记在脑子里:
1.4 一张表理清分工
| 维度 | WMS | Input 系统 |
|---|---|---|
| 核心职责 | 窗口布局、焦点、动画 | 事件读取、分发、策略 |
| 运行线程 | UI 线程 + WMS 内部 Handler | InputReader / InputDispatcher 两个线程 |
| 主要耗时操作 | relayout、动画回调、焦点切换 | 事件解析、窗口命中检测、Socket写入 |
| 与性能相关的常见问题 | 窗口同步锁导致 ANR,密集窗口操作卡顿 | 事件分发延迟,丢帧,焦点命中失败 |
1.5 为什么要把它们放在一起优化?
你可能觉得,WMS 和 Input 是两套独立的逻辑,各自保各自不就行了吗?我在实际项目中踩过的坑告诉我:它们之间有一条隐形的“快速通道”。任何一个环节出现瓶颈,都会通过锁或者消息队列传染给另一方。
所以,想要做好响应优化,不能只盯着 WMS 或者只盯着 Input。你得把它们看作一个协作体:
- WMS 尽量缩短窗口更新的临界区
- Input 系统尽量提前获取窗口焦点布局信息(比如通过缓存)
- 表面合成环节(SurfaceFlinger)也要配合,减少 VSYNC 漂移
嗯,到了这里你应该明白了。这一章就是搭个骨架,后面的章节我们会逐层深入:从 WMS 的窗口排序算法,到 Input 的调度策略,再到实战中的代码级优化。你想想看,如果能在这两个系统之间画出清晰的协作流程,很多疑难杂症就不再神秘了。
最后留一个思考点:当你发现某个场景下触摸延迟明显增加时,优先查一下 WMS 当前是否有窗口正在 relayout 或动画。那往往是 Input 事件被阻塞的第一个信号。