WindowManagerService (WMS)
WMS 是 Android 系统中一个极其重要的系统服务,它负责管理所有窗口的启动、添加、删除、更新、布局以及输入事件的分发等,可以说是 App 与用户交互的“总导演”
一. WindowManagerService 的启动过程
WMS 的启动遵循 Android 系统服务的标准启动流程,主要发生在 SystemServer
进程中
1)系统启动阶段:
① 手机启动时,Linux 内核启动后,会启动 Init 进程
② Init 进程会启动 Zygote 进程和 ServiceManager 进程
③ Zygote 进程孵化出 SystemServer
进程
2)SystemServer 主线程运行:
④ SystemServer
的 main()
方法被调用,它创建了一个 SystemServer
实例并调用其 run()
方法
3)启动引导服务:
⑤ 在 SystemServer
的 run()
方法中,会分阶段启动各种系统服务。WMS 属于引导服务,在 startBootstrapServices()
阶段之后,startOtherServices()
阶段中被启动
4)创建 WMS 实例:
⑥ 在 startOtherServices()
方法中,会调用 WindowManagerService.main()
这个静态方法。注意,这里不是直接 new
一个对象
// 代码位于:frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {...traceBeginAndSlog("InitWatchdog");final Watchdog watchdog = Watchdog.getInstance();watchdog.init(context, mActivityManagerService);traceEnd();traceBeginAndSlog("StartInputManagerService");inputManager = new InputManagerService(context);traceEnd();traceBeginAndSlog("StartWindowManagerService");// WMS 需要持有 IMS 的引用,因为窗口管理和输入事件分发密不可分wm = WindowManagerService.main(context, inputManager,mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,!mFirstBoot, mOnlyCore, new PhoneWindowManager());ServiceManager.addService(Context.WINDOW_SERVICE, wm);ServiceManager.addService(Context.INPUT_SERVICE, inputManager);...// 设置 AMS 和 WMS 的相互引用mActivityManagerService.setWindowManager(wm);...// 初始化显示信息,非常重要wm.displayReady();...// 通知 WMS 系统初始化完成wm.systemReady();
}
5)WMS.main() 方法:
⑦ 这个静态方法是创建 WMS 实例的核心
// 代码位于:frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
public static WindowManagerService main(final Context context,final InputManagerService im,final boolean haveInputMethods,final boolean showBootMsgs,final boolean onlyCore,WindowManagerPolicy policy) {// 创建主线程的 Handlerfinal WindowManagerService[] holder = new WindowManagerService[1];DisplayThread.getHandler().runWithScissors(() ->holder[0] = new WindowManagerService(context, im, haveInputMethods,showBootMsgs, onlyCore, policy), 0);return holder[0];
}
○ 这里的关键是 DisplayThread.getHandler().runWithScissors(...)
。DisplayThread
是一个单例的系统级线程,专门用于处理需要低延迟的显示操作
○ 这意味着 WMS 的构造函数是在 DisplayThread
中执行的,而不是在 SystemServer
的主线程中。这是因为 WMS 的工作需要极高的响应速度,需要一个专用的线程来处理消息队列
6)WMS 构造函数:
⑧ 在构造函数中,WMS 完成了大量的初始化工作:
○ 创建关键对象:如 mH
(主线程 Handler)、mWindowMap
(存储所有窗口的 HashMap)、mSessions
(存储所有应用连接的 ISession) 等
○ 创建窗口管理策略对象:mPolicy
(如 PhoneWindowManager
),它负责定义窗口的层级、类型、行为等策略
○ 创建动画控制器:mAnimator
,负责所有窗口动画
○ 创建显示控制器:mRoot
(RootWindowContainer),管理所有物理显示设备和上面的窗口根节点
○ 初始化输入事件分发:通过 InputManagerService
注册 InputMonitor
,建立窗口与输入事件的联系
○ 开启消息循环:DisplayThread
开始处理消息队列
7)注册到 ServiceManager:
⑨ 创建成功后,SystemServer
调用 ServiceManager.addService(Context.WINDOW_SERVICE, wm)
,将 WMS 注册到 Binder 机制中。这样,其他进程(如 App 进程)就可以通过 getSystemService(Context.WINDOW_SERVICE)
来获取 WMS 的 Binder 代理对象 (IWindowManager
),进而与 WMS 通信
总结启动流程:
SystemServer.main
-> SystemServer.run
-> startOtherServices
-> WindowManagerService.main()
-> (在 DisplayThread
中) new WindowManagerService()
-> ServiceManager.addService()
-> wm.displayReady()
-> wm.systemReady()
二. WindowManagerService 的核心原理
1)架构与关键角色
- WindowManagerService (服务端):运行在
SystemServer
进程,是窗口管理的核心,负责所有窗口的增删改查、布局和渲染 - WindowManagerGlobal / WindowManagerImpl (客户端):运行在 App 进程,是 App 与 WMS 交互的代理。我们平时调用
getWindowManager()
或windowManager
获取到的就是这个客户端对象 - IWindowManager / IWindowSession (Binder 接口):定义了 WMS 与客户端通信的协议。
IWindowManager
用于进程间通信,IWindowSession
用于一个应用进程与 WMS 建立一个会话,一个进程只有一个 Session,但可以有多个 Window - SurfaceFlinger:另一个重要的系统服务,负责将各个窗口的 Surface 数据合成并最终渲染到屏幕上。WMS 管理窗口的层级和布局,而 SurfaceFlinger 管理像素数据
2)窗口添加过程(以 Activity 为例)
- App 请求添加窗口:
○ Activity 的onCreate
中调用setContentView
○ 该方法会创建PhoneWindow
和DecorView
○ 在ActivityThread
的handleResumeActivity
中,会调用WindowManager.addView(decorView, params)
- 跨进程调用:
○WindowManagerImpl.addView
会委托给WindowManagerGlobal.addView
○ 在WindowManagerGlobal
中,会通过IWindowManager
创建一个IWindowSession
(如果还没有的话)
○ 然后调用session.addToDisplay(...)
,这是一个 Binder 调用,会切换到 WMS 所在的DisplayThread
执行 - WMS 处理添加请求:
○WMS.addWindow
方法被调用
○ 权限校验:检查该 App 是否有权限添加指定类型的窗口(如 TYPE_SYSTEM_ALERT)
○ 创建 WindowToken:针对不同的窗口类型(如应用窗口、子窗口、系统窗口)进行身份认证和归类
○ 创建 WindowState:WindowState
是 WMS 中表示一个窗口的核心对象,它包含了窗口的所有信息(如参数、令牌、父窗口等)。它被放入mWindowMap
中管理
○ 创建 Surface:WMS 会请求SurfaceFlinger
为这个新窗口分配一块图形缓冲区(Surface)。此时 Surface 是空的,但已经分配
○ 布局与计算:触发performLayoutAndPlaceSurfacesLocked
流程:
◎ 计算窗口层级:根据Z-order
、窗口类型、启动顺序等,确定窗口在屏幕上的前后关系
◎ 计算窗口大小:根据LayoutParams
、屏幕尺寸、父窗口大小等,计算窗口的最终位置和尺寸
◎ 安排动画:如果需要,安排窗口显示的动画 - App 绘制 UI:
○ WMS 将创建好的Surface
通过IWindow
回调给 App 端的ViewRootImpl
○ViewRootImpl
获得Surface
后,会启动Choreographer
监听 VSYNC 信号
○ 当 VSYNC 信号到来时,ViewRootImpl
会遍历DecorView
,发起测量、布局、绘制流程
○ 绘制命令(SKIA/OpenGL)会被记录到Surface
的Canvas
或EGLSurface
中
○ 绘制完成后,Surface
的内容被提交到BufferQueue
- 合成与显示:
○SurfaceFlinger
在下一个 VSYNC 信号到来时,会从所有窗口的BufferQueue
中取出最新的图形缓冲区
○ 根据 WMS 提供的窗口层级信息(Z-order),将这些缓冲区进行混合(合成)
○ 最终将合成后的图像数据输出到帧缓冲区,显示在屏幕上
3)核心机制
- 窗口层级管理:WMS 使用
Z-order
来管理窗口的上下叠加关系。Z-order
值越大的窗口,显示在越上面。应用窗口、子窗口、系统窗口都有其特定的基础 Z 序范围 - 布局过程:
performLayoutAndPlaceSurfacesLocked
是 WMS 的核心循环。它遍历所有DisplayContent
->TaskStack
->Task
->ActivityRecord
->WindowState
,依次为每个窗口计算其帧(Frame)。这个过程非常复杂,涉及到WindowManagerPolicy
的干预 - 输入事件分发:
InputReader
从设备读取输入事件,交给InputDispatcher
。InputDispatcher
会查询 WMS,找到输入事件坐标位置下最顶层的、可获取焦点的窗口,然后将事件通过InputChannel
发送给该窗口对应的应用进程 - 动画管理:WMS 有一个专门的
Animator
线程,它负责执行所有窗口的动画(如打开/关闭、切换)。动画的本质是在每一帧中不断改变窗口的属性(如位置、透明度),并请求重新布局和渲染 - Surface 管理:WMS 是
Surface
的“生命周期的管理者”。它决定何时为窗口分配Surface
,何时销毁或释放Surface
。Surface
的最终合成则由SurfaceFlinger
负责
总结
方面 | 描述 |
---|---|
角色 | 窗口的大管家,负责管理所有窗口的秩序(层级、布局、焦点、动画、输入) |
启动 | 由 SystemServer 在 startOtherServices 阶段,在专用的 DisplayThread 中创建,并注册到 ServiceManager |
通信 | 通过 Binder 机制(IWindowManager /IWindowSession )与客户端 App 交互 |
核心对象 | WindowState (服务端窗口对象),Session (应用进程连接),RootWindowContainer (显示设备管理) |
协作服务 | AMS (管理Activity生命周期),SurfaceFlinger (合成渲染Surface),InputManagerService (分发输入事件) |
核心流程 | 添加窗口、布局、动画、输入事件分发、Surface 分配与管理 |
可以把 WMS 想象成舞台剧的导演,而每个 App 窗口是演员,Surface
是演员的表演区域,SurfaceFlinger
是舞台灯光和幕布控制。导演指挥演员何时上场、站什么位置、做什么动作(布局、动画),并告诉灯光师哪个演员在最前面(层级)。演员在自己的表演区域(Surface)表演(绘制),最后由灯光师(SurfaceFlinger)将所有演员的表演合成最终的画面呈现给观众(用户)