WMS(Window Manager Service)是Android Framework中负责窗口管理的核心系统服务,其核心机制围绕窗口的创建、管理、显示和交互展开。
###一、WMS的核心职责与架构
WMS作为系统服务,运行在system_server进程中,通过Binder IPC与应用进程通信。其主要职责如下表所示:
| 核心职责 | 具体说明 |
|---|---|
| 窗口管理 | 管理所有窗口(Window)的添加、删除、更新、层级(Z-order)和焦点。 |
| Surface管理 | 为每个窗口分配和管理绘图表面(Surface),并与SurfaceFlinger协作进行合成与显示。 |
| 输入事件中转 | 接收来自InputManagerService的输入事件(触摸、按键),并根据窗口层级和焦点状态分发给正确的窗口。 |
| 窗口动画 | 管理窗口打开、关闭、切换时的动画效果。 |
| 布局与测量 | 根据窗口类型、策略和屏幕状态,计算窗口的最终位置和大小。 |
其整体架构涉及多个关键组件:
- WindowManager:客户端(应用)使用的接口,通过
WindowManagerGlobal与WMS交互。 - ViewRootImpl:连接
View体系与Window的桥梁,是窗口管理的实际执行者。 - Session:每个应用进程与WMS建立的Binder会话,用于IPC调用。
- WindowState:WMS内部代表一个窗口的对象,存储其所有状态信息。
- DisplayContent:管理特定物理或虚拟显示屏上的所有窗口。
二、核心流程与原理
1.窗口添加流程(以Activity添加View为例)
当Activity启动并调用setContentView后,最终会通过WindowManager.addView()添加窗口。其核心流程如下:
// 伪代码流程示意 // 1. 应用进程:通过WindowManager添加View WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); wm.addView(view, params); // params为WindowManager.LayoutParams // 2. WindowManagerGlobal.addView() 内部public void addView(View view, ViewGroup.LayoutParams params, ...) { ViewRootImpl root = new ViewRootImpl(view.getContext(), display); root.setView(view, wparams, panelParentView); // 关键调用 } // 3. ViewRootImpl.setView() 内部 public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { // ... 请求布局、初始化输入通道等 // 4. 通过IPC调用WMS的addWindow方法 res = mWindowSession.addToDisplay(...); // mWindowSession是App进程与WMS的Binder代理 }// 5. WMS端:addWindow 方法(system_server进程) public int addWindow(Session session, IWindow client, ...) { // 创建WindowState对象,代表这个窗口 WindowState win = new WindowState(...); // 为窗口创建SurfaceSession,用于后续分配Surface win.attach(); // 将WindowState添加到对应DisplayContent的窗口列表中 mWindowMap.put(client.asBinder(), win); // 执行布局(relayout),确定窗口位置大小,并创建/更新Surface result = createSurfaceControl(...); // 更新窗口层级,安排动画等 return result; }此流程完成了从应用视图到系统窗口的注册,并为绘图准备了Surface。
2. Surface的分配与绘图WMS并不直接绘制,而是管理Surface。Surface是一块图形缓冲区,View的内容通过Canvas绘制到其上。
- 分配:在
relayoutWindow或performSurfacePlacement时,WMS通过SurfaceControl向SurfaceFlinger申请或更新Surface。 - 绘图:应用进程通过
Surface.lockCanvas()获取Canvas,执行View树的draw方法,然后unlockCanvasAndPost()将绘制内容提交到缓冲区。 - 合成:SurfaceFlinger收集所有窗口的
Surface缓冲区,根据WMS提供的Z-order等信息进行混合,最终输出到显示屏。
3. 输入事件分发流程
// 伪代码流程示意 // 1. InputReader读取硬件事件 -> InputDispatcher进行分发 // 2. InputDispatcher通过Socket将事件发送到system_server的InputChannel // 3. WMS的InputMonitor负责找到目标窗口 WindowState targetWin = findFocusedWindowTargetLocked(...); // 4. 通过已建立的InputChannel,将事件发送到应用进程的ViewRootImpl // 5. ViewRootImpl的ViewPostImeInputStage处理事件,并传递给DecorView,开始View树的事件传递WMS根据触摸坐标、窗口可见区域、焦点状态,精确计算事件应派发到哪个WindowState。
4. 窗口层级(Z-order)与焦点管理
WMS使用多种令牌(Token)来组织窗口:
- WindowToken: 将属于同一应用或同一类型的窗口分组(如所有Activity窗口)。
- AppWindowToken: 继承自WindowToken,专门用于管理Activity的窗口栈。
窗口的Z-order由多个因素决定,主要包括:
- 窗口类型: 系统定义的类型(如
TYPE_APPLICATION,TYPE_SYSTEM_ALERT),类型值越大,通常层级越高。 - 子窗口: 附加在父窗口上,层级随父窗口。
- 窗口在栈中的顺序: 对于同类型的窗口(如多个Activity),后显示的通常在先显示的之上。
焦点窗口是当前接收输入事件的窗口。WMS通过setFocusedWindow来更新焦点,并通知InputDispatcher。
三、关键数据结构与类
| 类名 | 所在进程 | 作用 |
| :--- | :--- | :--- |
|WindowManager.LayoutParams| 应用进程 | 描述窗口的属性,如类型、尺寸、软键盘模式等。 |
|ViewRootImpl| 应用进程 | 连接View和WMS的核心类,负责请求布局、接收输入、管理Surface等。 |
|Session| 两端均有 | Binder IPC的会话对象,应用端为代理,WMS端为实体。 |
|WindowState| WMS(system_server) | WMS内部描述一个窗口状态的核心对象,包含其所有信息。 |
|DisplayContent| WMS(system_server) | 管理一个逻辑显示屏上的所有窗口、窗口令牌和屏幕信息。 |
|WindowToken| WMS(system_server) | 窗口令牌,用于将一组窗口绑定在一起管理。 |
|SurfaceControl| 两端均有 | 用于与SurfaceFlinger通信,创建和控制Surface。 |
WMS机制是Android图形显示和用户交互的基石,它通过精细的窗口状态管理和跨进程协作,确保了多窗口环境下的有序显示与流畅交互。
参考来源
- Android Framework底层原理——WMS机制_android wms 机制流程
- Android Framework底层原理——WMS机制_android wms 机制流程
- Android Framework底层原理——WMS机制
- 最全Android Framework底层原理——WMS机制_android wms 机制流程,2024年最新高级程序员面试题
- 杂谈-Android源码(AMS、PMS、WMS)及部分原理机制