WMS是Android图形和窗口系统的核心枢纽,其复杂性和重要性极高。理解WMS是深入理解Android UI框架、多任务、性能优化乃至安全机制的关键。
核心定位:
WMS是系统级服务,运行在system_server进程中。它是Android窗口管理策略的核心执行者,负责:
- 窗口生命周期管理: 创建、添加、更新、删除窗口。
- 窗口层级管理: 确定窗口的Z-order(前后顺序)、可见性、透明度、动画效果。
- 布局计算: 根据窗口属性、状态、系统策略计算窗口的位置和大小。
- 输入事件分发: 将触摸、按键等输入事件精准路由到正确的窗口(与
InputManagerService紧密协作)。 - 动画管理: 协调窗口的转场动画、属性动画。
- 多窗口模式支持: 分屏、画中画、自由窗口等模式的核心实现者。
- 屏幕旋转管理: 处理屏幕方向改变时的窗口重建和布局。
- 壁纸管理: 特殊窗口(壁纸)的显示策略。
- 聚焦窗口管理: 确定哪个窗口当前拥有输入焦点。
- 与SurfaceFlinger交互: 管理窗口对应的
Surface,通过SurfaceControl控制其属性,并最终驱动图形合成。
核心架构与关键组件:
-
客户端接口:
WindowManagerGlobal/WindowManagerImpl(App端)- 应用通过
getSystemService(Context.WINDOW_SERVICE)获取WindowManager实例。 WindowManagerImpl将应用请求(如addView())通过Binder IPC传递给WMS。- 也负责在主线程(UI线程)执行
ViewRootImpl相关的操作。
- 应用通过
-
服务端核心:
WindowManagerService(WMS)- 窗口容器树:
DisplayContent: 代表一个物理或虚拟显示设备(屏幕)。是窗口管理的顶级容器。Task: 代表一个用户任务(通常对应一个应用栈,但多窗口模式下可能包含多个Activity)。ActivityRecord: 代表一个Activity实例。包含该Activity的所有窗口。WindowToken: 一种令牌,用于将一组窗口关联到特定的实体(如Activity、壁纸、输入法)。是权限和策略控制的关键点。WindowState: WMS内部表示一个窗口的核心对象。包含窗口的所有状态信息:- 关联的
Session(客户端连接) - 关联的
WindowToken - 父容器 (
Task,ActivityRecord) - 窗口属性 (
WindowManager.LayoutParams- type, flags, width/height, gravity, x/y, alpha, etc.) - Z-order计算相关的值 (
mBaseLayer,mSubLayer,mAnimLayer) - 可见性 (
mViewVisibility,mSurfaceShown) - 输入通道 (
InputChannel) - 关联的
SurfaceControl(与图形合成交互的关键句柄) - 动画状态
- 聚焦状态
- 等等。
- 关联的
- 窗口添加流程 (
addWindow):- 权限和参数校验 (
LayoutParams.type的有效性等)。 - 查找或创建对应的
WindowToken(根据token或type)。 - 创建
WindowState对象,并将其添加到正确的容器 (DisplayContent->Task->ActivityRecord->WindowToken) 中。 - 为该窗口创建
InputChannel(用于接收输入事件)。 - 通过
WindowState的SurfaceSession创建SurfaceControl(最终用于在SurfaceFlinger中创建Surface)。 - 触发布局 (
performLayoutAndPlaceSurfacesLocked)。
- 权限和参数校验 (
- 布局流程 (
performLayoutAndPlaceSurfacesLocked): 这是WMS最核心、最频繁的流程之一。- 收集窗口状态 (
buildWindowListLocked): 遍历窗口容器树,收集所有需要考虑的WindowState,并根据Z-order、类型、父容器等进行初步排序。 - 计算可见性 (
computeWindowLayers): 计算每个窗口的最终Z轴层级 (mLayer,mAnimLayer)。考虑:- 窗口类型 (SYSTEM_ALERT > APPLICATION > STATUS_BAR > WALLPAPER)
- 父容器的层级
- 当前正在应用的动画
FLAG_LAYER相关的标志
- 计算位置和大小 (
performLayoutLockedInner):- 根据
LayoutParams(gravity, width/height, x/y offsets, flags)、父容器大小、系统状态栏/导航栏高度、安全区域、Ime状态等,计算每个窗口的最终Frame(位置和大小)。 - 处理
FLAG_LAYOUT_IN_SCREEN,FLAG_LAYOUT_INSET_DECOR等标志的影响。 - 处理窗口大小变化 (
CONFIGURATION_CHANGED)。
- 根据
- 应用布局 (
applySurfaceChangesTransaction): 这是与图形合成交互的关键步骤。- 遍历
WindowState列表。 - 检查窗口状态变化(位置、大小、可见性、透明度、动画等)。
- 使用
SurfaceControl.Transaction(或旧的SurfaceControl.openTransaction()/closeTransaction()) 批量设置SurfaceControl的属性:setPosition(x, y)setSize(width, height)setLayer(Z-order)setAlpha(透明度)setMatrix(旋转/缩放变换)setVisibility(显示/隐藏)reparent(改变父Surface)
- 对于需要创建新
Surface的窗口(首次添加、配置改变后重建),执行relayoutWindow()->createSurfaceControl()。 - 对于需要销毁的窗口,销毁
SurfaceControl。 - 事务提交: 将累积的
Transaction提交给SurfaceFlinger执行。批量提交是优化性能的关键!
- 遍历
- 收集窗口状态 (
- 输入事件分发:
InputManagerService(IMS) 从驱动读取原始输入事件。- IMS根据输入事件发生的屏幕坐标,询问WMS:哪个窗口应该接收这个事件?
- WMS通过
findFocusedWindowTargetsLocked遍历其窗口树(按Z-order从高到低),根据窗口的Frame(位置大小)、可见性、FLAG_NOT_TOUCHABLE等标志,找到最顶部的、可接收触摸事件的窗口。 - WMS将找到的窗口对应的
InputChannel返回给IMS。 - IMS将输入事件写入该
InputChannel。 - 应用端的
ViewRootImpl通过关联的InputEventReceiver从InputChannel读取事件,并分发给视图树。
- 动画系统:
- WMS自身管理窗口级别的动画(如Activity转场动画、窗口打开/关闭动画)。
- 使用
WindowStateAnimator对象来管理每个窗口的动画状态。 - 动画会改变窗口的
mAnimLayer(临时Z-order)、透明度、位置、缩放等属性。 - 动画的执行会触发连续的布局和
Surface属性更新请求 (scheduleAnimationLocked->mChoreographer.postCallback->performLayoutAndPlaceSurfacesLocked)。 - 与应用内的属性动画 (
ObjectAnimator) 协作:当应用视图树做属性动画时,ViewRootImpl会通过scheduleTraversals()请求重绘,并可能通过relayoutWindow()请求WMS更新窗口Surface的属性(如位置变化导致窗口移动)。
- 多窗口模式:
- 分屏: WMS将屏幕划分为不同的区域 (
Task容器),每个区域容纳一个Task。管理这些Task容器的位置、大小、Z-order以及它们内部窗口的布局。 - 画中画: 将特定的
ActivityRecord标记为PIP模式。WMS将其放入一个特殊的容器,管理其固定大小、可拖动位置、特殊的Z-order(始终在最上层特定区域之下)以及焦点策略(点击PIP窗口时切换到全屏)。 - 自由窗口: 更复杂的模式,窗口可以自由缩放和移动。WMS需要动态计算每个自由窗口的
Frame,处理窗口间的Z-order调整(如点击置顶),以及复杂的输入事件路由。
- 分屏: WMS将屏幕划分为不同的区域 (
- 与SurfaceFlinger的关系:
- WMS不直接进行图形绘制,它管理的是
Surface的元数据(位置、大小、Z-order、可见性、变换)。 - 每个窗口对应一个
SurfaceControl(由WMS通过SurfaceSession创建)。 - WMS通过
SurfaceControl.Transaction设置SurfaceControl的属性。 - 应用(通过
SurfaceView或TextureView)向Surface写入图形内容 (BufferQueue Producer)。 SurfaceFlinger作为合成器 (Compositor),根据WMS设置的SurfaceControl属性(层级、位置等)和Surface的内容(BufferQueue Consumer),决定何时以及如何将这些Surface合成到最终的显示帧上。- 关键点: WMS控制“在哪里显示什么”,应用负责“画什么”,SurfaceFlinger负责“把它们拼起来显示”。
- WMS不直接进行图形绘制,它管理的是
- 窗口容器树:
设计哲学与关键挑战:
-
策略与机制分离 (Policy/Mechanism Separation):
- 机制: WMS核心提供了强大的窗口管理基础功能(布局计算、Z-order排序、Surface控制、输入路由)。
- 策略: 具体的窗口行为规则(如哪些窗口类型可以重叠、特定系统窗口的位置、多窗口模式的交互逻辑)很大程度上由
PhoneWindowManager实现。这允许OEM厂商在不修改WMS核心的情况下定制UI行为。
-
性能与响应性:
- 布局计算优化: 增量更新(只处理脏区域/脏窗口)、高效的数据结构(窗口容器树)、避免不必要的重布局。
- 事务批处理: 将多个
Surface属性的修改打包在一个Transaction中提交给SurfaceFlinger,减少IPC和合成器调度开销。 - 异步化: 将部分工作(如动画)委托给
Choreographer在主线程之外调度执行。 - 输入延迟: 精确高效的输入事件路由对用户体验至关重要。WMS与IMS的紧密协作和高效的
InputChannel机制是关键。
-
安全与隔离:
- 窗口令牌 (
WindowToken): 确保只有拥有正确令牌的客户端才能操作属于该令牌的窗口(防止恶意应用随意操作其他应用的窗口)。 - 权限检查: 对特定的窗口类型(如
TYPE_SYSTEM_ALERT,TYPE_APPLICATION_OVERLAY)需要SYSTEM_ALERT_WINDOW权限。 - 输入事件目标检查: 确保事件只发送给拥有对应窗口和
InputChannel的合法客户端。
- 窗口令牌 (
-
复杂性管理:
- 层级化容器模型: 使用
DisplayContent,Task,ActivityRecord,WindowToken,WindowState等对象清晰地组织窗口的从属和层级关系。 - 状态机:
WindowState等对象使用状态机管理复杂的生命周期和状态转换(如NO_SURFACE,DRAW_PENDING,COMMIT_DRAW_PENDING,READY_TO_SHOW,HAS_DRAWN)。
- 层级化容器模型: 使用
深入优化点:
- Transaction 合并: 在
performLayoutAndPlaceSurfacesLocked的一次执行中,所有需要更新的SurfaceControl属性变化会累积到一个Transaction对象中。只有最终需要提交的变化才会真正发送给SurfaceFlinger。中间状态的多次修改会被覆盖(如连续设置位置和大小,最终只提交最新的值)。 - 同步屏障: 当应用调用
invalidate()或requestLayout()时,ViewRootImpl会通过Choreographer安排一次遍历 (performTraversals)。在performTraversals中,会先relayoutWindow(如果需要更新窗口大小/位置/Insets等,这会触发WMS布局和Surface属性更新),然后再进行Measure、Layout、Draw。Choreographer确保了UI更新、WMS更新、VSync信号的同步。 - SurfaceControl 生命周期: WMS负责
SurfaceControl的创建和销毁。当窗口不再需要显示(或被销毁)时,WMS会销毁其SurfaceControl,通知SurfaceFlinger释放相关资源。应用端的Surface对象持有对SurfaceControl的引用,当应用释放Surface时,会通过Binder通知WMS减少引用计数,最终由WMS决定何时真正销毁SurfaceControl。 - Insets 控制: WMS计算并分发系统栏(状态栏、导航栏)占据的区域信息 (
InsetsState)。应用通过ViewCompat.setOnApplyWindowInsetsListener获取这些信息,用于调整自身内容的布局(如避免被系统栏遮挡)。WMS根据窗口的LayoutParams决定哪些窗口需要避开哪些Insets。
总结:
WindowManagerService是Android图形和窗口系统的中央控制器和策略执行引擎。它:
- 管理着屏幕上的所有视觉元素(窗口)的生命周期、层级关系和视觉表现。
- 精确地计算着每个窗口的位置和大小。
- 智能地将用户的输入事件路由到正确的目标。
- 协调着窗口动画和多窗口模式的复杂交互。
- 作为应用与图形合成器 (
SurfaceFlinger) 之间的桥梁,控制着图形缓冲区 (Surface) 的显示属性。
其设计体现了对性能、安全性、灵活性和可扩展性的极致追求。理解WMS的内部运作机制,对于解决复杂的UI问题(如窗口遮挡、触摸事件穿透、动画卡顿、多窗口适配)、进行深度性能优化以及定制Android系统UI行为都至关重要。其代码庞大而复杂(核心代码超过数万行),但其核心逻辑围绕窗口容器树、布局计算、事务管理和输入路由展开,掌握了这些关键概念就掌握了WMS的精髓。