Android WindowManageService 笔记

1 阅读6分钟

WindowManagerService(WMS)是Android Framework中负责管理所有窗口的核心系统服务。你可以把它理解为整个屏幕界面的“总导演”:SurfaceFlinger是只负责渲染的“摄像师”,而WMS决定每个窗口(Activity、对话框、状态栏、输入法等)该在什么时候、出现在哪里、有多大、谁盖住谁,以及谁该获得用户的触摸事件。

由于WMS极其复杂,我将从以下五个层面为你拆解,涵盖职责、启动、数据结构、核心机制及与其他模块的协作:

一、WMS的核心职责

WMS在系统中扮演四个关键角色,这四点被多个源码分析文章反复印证,是其最稳定的核心定义:

核心职责具体说明
窗口管理负责窗口的添加、删除、更新;管理窗口的大小、位置、Z轴顺序(层叠关系)。这是最基础的职能
Surface管理窗口本身不具备绘图能力。客户端向WMS添加窗口的过程,本质是WMS为其分配一块Surface的过程。Window的本质就是Surface
窗口动画管理窗口切换、启动、关闭时的动画效果,由WindowAnimator专门负责
输入中转站WMS掌握所有窗口的位置和状态,因此InputManagerService(IMS)收到触摸事件后,必须由WMS来找出“当前哪个窗口应该接收此事件”

经典比喻:SurfaceFlinger是摄像机,只负责捕捉画面;WMS是导演,负责舞台效果、演员站位;ViewRoot是演员的长相表情。

二、WMS的诞生(启动流程)

WMS是在SystemServer进程中启动的。SystemServer会启动三大类服务(引导、核心、其他),WMS属于“其他服务”。

关键启动代码逻辑(基于Android 8.0+,近年版本质不变):

  1. 入口SystemServer.startOtherServices()
  2. 创建IMS:先创建InputManagerService——WMS需要持有它的引用。
  3. 调用WMS.main():这是创建WMS的静态方法。
  4. 线程切换
    • main()方法通过DisplayThread.getHandler().runWithScissors()强制将WMS的构造逻辑扔到android.display线程执行。
    • 为什么要这样?因为WMS涉及显示初始化,优先级必须高于当前system_server线程。runWithScissors会使system_server线程阻塞,直到android.display线程创建完WMS才唤醒。
  5. 注册服务ServiceManager.addService(Context.WINDOW_SERVICE, wm),使客户端(如应用进程)能通过Binder获取WMS代理。
  6. 后续初始化displayReady()systemReady()

构造方法的关键动作

  • 保存IMS引用(mInputManager
  • 初始化策略类PhoneWindowManager(即mPolicy,定义窗口行为的规范,如状态栏多高、键盘怎么顶)
  • 创建WindowAnimator
  • 创建RootWindowContainer(根容器)
  • 将自己加入Watchdog监控(防止死锁)

重要知识点:这里涉及三个线程的协作关系:system_server(主调)、android.display(创建WMS)、android.ui(初始化PhoneWindowManager)。优先级:android.ui > android.display > system_server

三、WMS的核心数据结构

WMS为了管理成百上千个窗口,设计了一套严谨的“令牌-窗口”映射模型。理解这三个核心类,就理解了WMS的骨架:

1. WindowToken(窗口令牌)

  • 是什么:一组拥有相同令牌的窗口集合。
  • 作用:同一个Activity(或输入法、壁纸)的所有窗口(主窗口、子窗口、启动窗口)共享同一个Token。
  • 来源:对于Activity,Token来自AMS的ActivityRecord;对于输入法/壁纸,来自对应服务传递的Binder。

2. AppWindowToken(Activity窗口令牌)

  • 继承自WindowToken,专门代表Activity组件
  • WMS中通过mAppTokens(ArrayList)按Z轴顺序维护所有Activity窗口。

3. WindowState(窗口状态)

  • 这是WMS中“真正的窗口”。每个添加到WMS的窗口都会对应一个WindowState对象。
  • 记录该窗口的所有实时信息:尺寸、位置、Z轴层值、包名、是否可见、动画状态、对应的Session等。
  • 保存在mWindowMap(HashMap)中,key为IBinder。

组织关系示意图

AMS层:ActivityRecord A → 对应 → WMS层:AppWindowToken A
                                    ↓
                             包含一组WindowState:
                             - 主窗口WindowState
                             - 启动窗口WindowState
                             - 子窗口WindowState

所有WindowState在WMS中按Z轴低→高排列,形成窗口堆栈(Window Stack),决定了谁盖住谁。

四、窗口管理的核心流程(添加与删除)

应用添加一个窗口(如Activity启动、Dialog显示)为例,走通客户端到WMS的路径:

4.1 窗口添加流程

  1. 客户端发起WindowManager.addView()WindowManagerGlobal.addView() → 创建ViewRootImpl
  2. 跨进程通信ViewRootImpl.setView()mWindowSession.addToDisplayAsUser()
    • mWindowSession是每个应用进程与WMS保持的Binder会话Session对象),由WMS为该进程创建。
  3. WMS处理Session.addWindow()WMS.addWindow()):
    • 前置检查:权限、参数合法性、窗口是否已存在等。
    • Token处理:根据窗口类型(应用窗口/子窗口/系统窗口)获取或隐式创建WindowToken
    • 创建WindowState:将此窗口的信息封装为WindowState,存入mWindowMap,并与Token关联。
    • 分配Surface:向SurfaceFlinger申请一块绘图表面(经简化)。
    • 层值分配:通过assignLayersLocked()计算Z轴顺序。
    • 焦点处理:如果此窗口可聚焦,更新焦点窗口。
    • 布局与放置:触发performLayoutAndPlaceSurfacesLocked()——这是WMS最核心、最复杂的函数(曾长达1200+行),计算所有窗口的最终位置并告知SF。

4.2 窗口删除流程

  • 显式删除:调用WindowManager.removeView()
  • 隐式删除:Activity销毁(finish()),AMS回调WMS移除AppWindowToken
  • 核心动作:释放Surface、移除WindowState、重新布局剩余窗口、转移焦点。

五、WMS与三大兄弟模块的协作

WMS不是孤岛,它与AMS、SurfaceFlinger、IMS紧密交织:

5.1 WMS ↔ AMS

  • 双向调用
    • AMS启动Activity时,会调用WMS的addAppToken()(添加令牌)、setAppStartingWindow()(设置启动窗口)、resumeTopActivities()触发窗口显示。
    • WMS在横竖屏切换、杀死应用时也会回调AMS。
  • 核心纽带AppWindowToken。AMS的ActivityRecord与WMS的AppWindowToken一一对应。

5.2 WMS ↔ SurfaceFlinger (SF)

  • WMS不直接绘制,但它通过SurfaceControl(封装了Surface)向SF申请/释放Layer,并设置Layer的尺寸、位置、Z-order等属性。
  • 简单理解:WMS“指挥”SF“怎么叠图层”,SF“执行”合成渲染。

5.3 WMS ↔ InputManagerService (IMS)

  • IMS从驱动读取原始输入事件,但它不知道这些事件该发给谁。
  • WMS提供“窗口地图”:每个WindowState在创建时会注册InputChannel,并将窗口的点击区域(hit region)同步给IMS。
  • IMS通过Socket找到目标窗口后,事件直接派发给对应的ViewRootImpl。

总结与学习建议

WMS的复杂性主要源于它要同时协调应用进程(Binder通信)、系统策略(PhoneWindowManager)、图形系统(SurfaceFlinger)和输入系统(IMS)

对于深入源码的学习,建议采用**“分而治之”**的策略,按以下情境逐个击破:

  1. 窗口添加/删除流程(最基础)
  2. Z轴顺序计算与窗口组织(理解WindowToken/WindowState)
  3. 输入法/壁纸窗口的特殊调整(理解WMS策略性)
  4. 窗口动画原理(WindowAnimator)
  5. 启动窗口(StartingWindow)的显示与移除