android WMS 详解(二)

一、基础概念

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 启动时窗口是如何显示出来的?

  1. AMS 请求 WMS 创建 AppWindowToken

  2. Activity 执行 onCreate() → onResume()

  3. ViewRootImpl.setView() 调用 WMS.addWindow()

  4. WMS 创建 WindowState,分配 Surface

  5. 执行 performTraversals() 进行首次绘制

  6. 绘制完成后通知 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 负责过渡切换

相关推荐
程序猿追8 小时前
kotlin-retry 接入鸿蒙后,怎样确认它真的会停止重试
开发语言·kotlin·harmonyos
jack1868911 小时前
安卓手机忘记锁屏密码怎么办? 无需密码也可解锁
android·智能手机
应用市场14 小时前
不用一张图片的像素小游戏:小人是字符串,房间是矩形,平衡靠两千个假玩家
android·kotlin·游戏开发
stevenzqzq14 小时前
android 对渠道的理解
android
QEasycloud15 小时前
BOM接口抛转失败钉钉通知策略实战教程:MySQL异常日志到钉钉消息的端到端配置
android·mysql·钉钉
AIsoft_868915 小时前
医患交流内容如何做好记录?
android·iphone
蒸鱼Yuzheng15 小时前
Android Native 崩溃证据链:Tombstone、Build ID 与 Trace 如何联合归因
android·ndk·tombstone·调试符号·崩溃分析
事圆则缓15 小时前
Kotlin 变量与函数:把页面状态和行为写成清楚的契约
android·开发语言·kotlin
hunterandroid16 小时前
MVVM 迁移到 MVI:复杂页面状态如何收敛
android
妖星16 小时前
Android 开机动画定制:从 bootanimation.zip 到源码编译
android