一、基础概念
1. 什么是 WMS?它的核心职责是什么?
-
管理窗口的添加、删除、更新
-
计算窗口大小和位置(Layout)
-
管理窗口的层级关系(Z-order)
-
分配 Surface,与 SurfaceFlinger 协作完成显示
-
管理窗口动画
-
处理输入事件的分发
2. WMS 在系统架构中的位置?与 AMS、SurfaceFlinger 的关系?
-
WMS 属于 SystemServer 中的核心服务
-
与 AMS:AMS 负责 Activity 生命周期管理,WMS 负责 Activity 对应窗口的显示;AMS 通过 WMS 添加/移除窗口
-
与 SurfaceFlinger:WMS 负责窗口逻辑管理,SurfaceFlinger 负责图层合成与显示;WMS 为每个窗口申请 Surface,SurfaceFlinger 将这些 Surface 合成到屏幕上
二、Window 的添加流程
3. 从 addView() 到 WMS 的完整流程是怎样的?
-
WindowManagerImpl.addView()→WindowManagerGlobal.addView() -
创建
ViewRootImpl,调用ViewRootImpl.setView() -
通过 IPC 调用
WMS.addWindow()(Session → WMS) -
WMS 创建
WindowState,检查权限和窗口类型 -
分配
Surface,建立与 SurfaceFlinger 的连接 -
执行
performTraversals()触发测量、布局、绘制
4. WindowToken 和 AppWindowToken 是什么?
-
WindowToken:窗口的令牌,用于标识一组窗口的归属,是 WMS 中窗口的"身份证" -
AppWindowToken:继承自 WindowToken,专门用于 Activity 对应的窗口,与 AMS 中的ActivityRecord一一对应
5. WindowState 是什么?
-
WMS 中用于表示一个窗口的对象,包含了窗口的所有属性(位置、大小、类型、层级等)
-
每个通过 WMS 添加的窗口都会对应一个 WindowState
三、窗口层级与类型
6. Android 窗口有哪些类型?层级如何划分?
-
Application Window(1-99):普通应用窗口,如 Activity
-
Sub Window(1000-1999):子窗口,如 Dialog,必须依附于父窗口
-
System Window(2000-2999):系统窗口,如状态栏、Toast、输入法
7. 什么是 type 和 layer?
-
type:窗口类型,决定窗口的基本层级 -
layer:实际计算的层级值,由 type 加上一些调整值(如子窗口的相对位置)计算得出,决定窗口在 Z 轴上的顺序
8. 为什么 Dialog 的 Window 类型是 TYPE_APPLICATION 而不是子窗口?
-
实际上 Dialog 使用的是
TYPE_APPLICATION,属于应用窗口 -
但 Dialog 的 token 必须和 Activity 的 token 一致,这是通过
mParentWindow关联实现的 -
真正的子窗口(如 PopupWindow)使用
TYPE_APPLICATION_PANEL等类型
四、测量、布局与绘制
9. performTraversals() 在 WMS 流程中的作用?
-
ViewRootImpl 中的核心方法,触发整个 View 树的遍历
-
内部调用
measure()、layout()、draw() -
在 WMS 流程中,窗口大小确定后会触发
performTraversals(),进而申请 Surface 并进行绘制
10. WMS 如何确定窗口的大小?
-
考虑因素:屏幕尺寸、系统装饰(状态栏、导航栏)、窗口的 LayoutParams(宽高、gravity、margin 等)
-
WindowFrames类记录了窗口的各种边界(parent frame、display frame、content frame 等) -
通过
computeFrames()方法计算最终大小
11. 什么是 mAttachInfo?
-
View.AttachInfo对象,在 ViewRootImpl 中创建 -
包含了窗口相关的关键信息(如 WindowToken、Surface、硬件加速状态等)
-
通过
dispatchAttachedToWindow()传递给 View 树中的每个 View
五、Surface 与显示
12. Surface 是什么时候创建的?
-
在
ViewRootImpl.relayoutWindow()中,通过 WMS 的relayout()方法请求创建 -
WMS 与 SurfaceFlinger 通信,创建对应的 Layer,返回 Surface 给应用端
-
应用端通过
Surface.lockCanvas()获取 Canvas 进行绘制
13. 什么是 SurfaceControl?
-
Android 高版本(Android 10+)引入的 Surface 控制类
-
用于更精细地控制 Surface 的属性(位置、大小、透明度等)
-
减少了应用层与 SurfaceFlinger 的直接交互,通过 WMS 统一管理
14. 硬件加速与 WMS 的关系?
-
WMS 在创建窗口时会判断是否开启硬件加速
-
硬件加速使用
RenderThread进行绘制,最终通过 OpenGL ES 渲染到 Surface -
WMS 通过
SurfaceControl.Transaction提交图层变化给 SurfaceFlinger
六、事件分发
15. 触摸事件是如何传递到窗口的?
-
输入事件由
InputManagerService(IMS)从驱动读取 -
IMS 通过
InputDispatcher将事件分发给目标窗口 -
WMS 维护着窗口的触摸区域信息,帮助 InputDispatcher 确定事件该发给哪个窗口
-
最终通过
InputChannel(基于 socket)将事件发送到应用端的ViewRootImpl -
应用端进行事件分发:
dispatchTouchEvent()→onInterceptTouchEvent()→onTouchEvent()
16. 什么是 InputChannel?
-
用于 IMS 与应用程序之间传递输入事件的通道
-
基于 Unix Domain Socket 实现
-
在添加窗口时创建,与窗口一一对应
七、Activity 启动与窗口
17. Activity 启动时窗口是如何显示出来的?
-
AMS 请求 WMS 创建
AppWindowToken -
Activity 执行
onCreate()→onResume() -
ViewRootImpl.setView()调用 WMS.addWindow() -
WMS 创建 WindowState,分配 Surface
-
执行
performTraversals()进行首次绘制 -
绘制完成后通知 WMS,WMS 通知 SurfaceFlinger 合成显示
18. 为什么会出现黑屏/白屏?如何优化?
-
原因:Activity 启动到第一帧绘制完成需要时间,期间显示的是 Window 的背景色
-
优化方案:
-
设置
windowBackground为启动图(Splash Screen 方案) -
延迟初始化,减少
onCreate()工作量 -
使用
PreviewWindow机制
-
八、多窗口与特殊场景
19. 分屏/多窗口模式下 WMS 如何工作?
-
WMS 维护
TaskStack和Task的层级结构 -
多窗口模式下,窗口的 bounds 不再是全屏,而是根据分屏比例计算
-
WindowContainer体系(Android 8+)引入了更灵活的容器管理
20. 什么是 WindowContainer?
-
Android 8.0 引入的窗口容器体系
-
包含:
WindowContainer→RootWindowContainer→DisplayContent→TaskDisplayArea→Task→ActivityRecord→WindowToken→WindowState -
提供了更清晰的层级管理和遍历能力
21. Toast 为什么使用系统窗口?
-
Toast 使用
TYPE_TOAST(系统窗口类型) -
不需要依附于 Activity,可以在应用退出后显示
-
Android 7.0 后限制了普通应用使用
TYPE_TOAST的权限,防止恶意弹窗
九、高频深入问题
22. Choreographer 与 WMS 的关系?
-
Choreographer 负责接收 VSync 信号,协调动画、输入、绘制的时机
-
WMS 的窗口更新和 SurfaceFlinger 的合成都是基于 VSync 的
-
ViewRootImpl通过 Choreographer 安排performTraversals()的执行
23. 窗口动画是谁负责的?
-
WMS 负责窗口动画的管理(如打开、关闭、切换动画)
-
通过
WindowAnimator和RemoteAnimationController实现 -
动画可以运行在系统进程(WMS)或应用进程(通过 SurfaceControl.Transaction)
24. 如何理解 relayout() 方法?
-
ViewRootImpl调用 WMS.relayout() 来更新窗口属性 -
主要工作:重新计算窗口大小、创建/调整 Surface、更新窗口层级
-
是窗口变化时的核心调度方法
25. Android 12 的 SplashScreen API 与 WMS 的关系?
-
Android 12 系统实现了原生的 SplashScreen 机制
-
WMS 在创建 AppWindowToken 时自动添加 SplashScreen 窗口
-
应用第一帧绘制完成后,WMS 负责过渡切换