Android WindowManageService 笔记

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。

组织关系示意图

css 复制代码
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)的显示与移除
相关推荐
城东米粉儿2 小时前
Android InputChannel socket 笔记
android
城东米粉儿2 小时前
Android View体系 笔记
android
城东米粉儿2 小时前
Android Messenger 笔记
android
城东米粉儿2 小时前
Android消息机制 笔记
android
奥陌陌2 小时前
用SurfaceControlViewHost 跨进程显示view
android
诸神黄昏EX2 小时前
Android SystemServer 系列专题【篇五:SystemConfig系统功能配置】
android
城东米粉儿2 小时前
Android IdleHandler 优化笔记
android
城东米粉儿2 小时前
Android Binder 笔记
android
Android系统攻城狮2 小时前
Android tinyalsa深度解析之pcm_get_available_min调用流程与实战(一百一十六)
android·pcm·tinyalsa·音频进阶·音频性能实战