好的,遵照您的指示,我将基于您提供的详细提示词和搜索材料,为您创作一份《Android WindowManagerService核心原理深度解析》培训课件。 --- # Android WindowManagerService核心原理深度解析 ## 目录 1. **引言**:为什么需要深入理解WMS? 2. **WMS概览与架构定位** - 系统服务中的WMS - 核心概念定义 (`Window`, `Token`, `State`) - WMS核心职责 3. **窗口的生命周期管理** - 从`ViewRootImpl`到`WindowState`的旅程 - 关键流程序列图:添加窗口 - 核心数据结构:`WindowState` 解析 4. **布局、动画与Surface管理** - 布局循环的核心:`performSurfacePlacement` - 窗口动画的管理者:`WindowAnimator` - Surface的申请与合成协调 5. **输入事件的中转与分发** - WMS作为IMS的中转站 - 关键流程序列图:触摸事件分发 - 命中测试(Hit Test)与`InputChannel` 6. **与关键系统服务的协同** - WMS & AMS:Activity状态与窗口的同步 - WMS & SurfaceFlinger:通过`Transaction`提交变更 - UML简化类图:核心协作关系 7. **高级主题与案例分析**(可选) - 从`dumpsys window`看窗口状态 - 常见问题分析:窗口泄漏、事件丢失 8. **总结与Q&A** --- ## 1. 引言:为什么需要深入理解WMS? 各位同事,在日常开发中,我们面对的挑战往往不止于业务逻辑的实现。当遇到**多窗口适配的诡异布局**、**悬浮窗权限的反复横跳**、**应用启动或转场时的莫名卡顿**,甚至是**触摸事件偶尔“灵异”丢失**的问题时,我们是否感到束手无策,只能依靠试错或搜索碎片化的解决方案? 这些复杂UI场景和性能瓶颈的根源,往往深藏在Android Framework的核心——**WindowManagerService(WMS)** 之中。WMS是Android图形系统的“总调度中心”和“交通警察”,它管理者所有窗口的创建、布局、显示顺序以及它们与输入系统的交互。 本次培训旨在穿透API层面,深入Framework核心,系统性地揭示从**应用视图请求**到**最终像素显示**的完整链路。我们将聚焦WMS在其中扮演的核心角色,帮助大家建立起完整的窗口系统知识体系,从而在面对疑难杂症时,能够**定位根因、精准施策**。 ## 2. WMS概览与架构定位 ### 2.1 系统服务中的WMS WMS是System Server中最早启动的核心服务之一。它在SystemServer的`startOtherServices`方法中被创建和启动。 ```java // frameworks/base/services/java/com/android/server/SystemServer.java private void startOtherServices() { // ... traceBeginAndSlog("StartWindowManagerService"); // 注意:WMS的main方法运行在"android.display"线程,优先级高于"system_server"线程 wm = WindowManagerService.main(context, inputManager, ...); traceEnd(); // ... // 将WMS和IMS注册到ServiceManager ServiceManager.addService(Context.WINDOW_SERVICE, wm); ServiceManager.addService(Context.INPUT_SERVICE, inputManager); // ... } ``` *代码示例:WMS在SystemServer中的启动 * WMS的启动涉及多线程同步(`system_server`, `android.display`, `android.ui`),体现了其初始化对UI相关线程的优先级要求。 ### 2.2 核心概念定义 在深入代码前,我们必须统一对以下几个核心抽象的理解: - **`Window`(窗口)**:一个抽象的概念,不是实体,可以理解为**绘制表面(Surface)** 的载体或容器。每一个窗口都对应着一个用于绘制的`Surface`。在应用层,`PhoneWindow`是`Window`的唯一实现类。 - **`WindowManager`**:应用层与WMS通信的接口。它是一个Binder客户端,应用通过它发送添加、删除窗口的请求。其实现类`WindowManagerImpl`将工作委托给单例的`WindowManagerGlobal`。 - **`View`**:窗口的实体表现形式。窗口的内容正是通过`View`树来填充和呈现的。可以说,**Window是View的载体,View是Window的内容**。 - **`WindowToken`**:一个**令牌**。用于建立Binder通信的映射关系,并**将一组相关的窗口(例如同一个Activity的所有窗口,包括主窗口和子窗口)组织在一起**。对于Activity,它是`AppWindowToken`。 - **`WindowState`**:WMS内部用于**描述一个窗口所有状态**的真实对象。它保存了窗口的尺寸、位置、Z-order、是否可见、对应的`Session`、`InputChannel`等所有信息。它是WMS管理窗口的“活档案”。 - **`DisplayContent`**:用于**描述一块逻辑屏幕**。它管理着显示在这个屏幕上的所有窗口的根层级。WMS通过`DisplayContent`来管理多屏(如双屏、折叠屏)的窗口。 ### 2.3 WMS核心职责 1. **窗口管理**:负责窗口的添加、删除、Z-order排序、焦点管理。 2. **Surface管理**:作为“仲裁者”,为窗口分配`Surface`,并协调应用与`SurfaceFlinger`的关系。 3. **窗口动画**:管理所有窗口切换、移动时的动画效果。 4. **输入事件中转**:配合`InputManagerService`,将触摸或按键事件准确地分发给合适的窗口。 ## 3. 窗口的生命周期管理 ### 3.1 从`ViewRootImpl`到`WindowState`的旅程 以一个典型的Activity窗口创建为例,看看它是如何被WMS纳入管理的。 **核心流程序列图:添加窗口** ```mermaid sequenceDiagram participant App as 应用进程(UI Thread) participant ViewRoot as ViewRootImpl participant WMS as WindowManagerService participant SF as SurfaceFlinger App->>ViewRoot: 1. requestLayout() ViewRoot->>ViewRoot: 2. scheduleTraversals() ViewRoot->>WMS: 3. relayoutWindow() (Binder调用) Note over WMS: 4. 创建/获取Surface WMS->>SF: 5. createSurface() (通过SurfaceSession) SF-->>WMS: 返回SurfaceControl WMS-->>ViewRoot: 返回relayoutResult & Surface (Binder返回) Note over ViewRoot: 6. 将Surface保存到mSurface ViewRoot->>ViewRoot: 7. performMeasure/Layout/Draw ViewRoot->>SF: 8. 通过Canvas/Skia渲染到Surface的BufferQueue ``` **关键步骤详解:** 1. **发起请求**:当View树需要布局时,`ViewRootImpl`的`requestLayout`被调用,最终通过Binder调用进入WMS的`relayoutWindow`方法。 2. **WMS处理 (核心逻辑)**: - **权限与合法性检查**:WMS首先检查调用者的权限和窗口参数(`LayoutParams`)是否合法。 - **创建/获取WindowState**:如果是首次添加,WMS会创建一个`WindowState`对象,并将其添加到全局的`mWindowMap`中,同时根据`WindowToken`建立层级关系。 - **Surface分配**:如果窗口需要新的绘图表面,WMS会通过`Session`(内部封装了与SurfaceFlinger的`SurfaceSession`连接)请求`SurfaceFlinger`创建一个`Layer`(在WMS侧对应为`SurfaceControl`)。 3. **返回与绘制**:WMS将分配好的`Surface`(实际上是`SurfaceControl`的句柄)通过Binder返回给应用层的`ViewRootImpl`。应用层拿到`Surface`后,便可以开始渲染内容。 ### 3.2 核心数据结构:`WindowState` 解析 `WindowState`是WMS中最重要的数据结构,我们可以通过简化源码来理解其核心成员: ```java // frameworks/base/services/core/java/com/android/server/wm/WindowState.java class WindowState extends WindowContainer { // 指向持有该窗口的客户端Session (每个应用进程一个) final Session mSession; // 应用层 ViewRootImpl 的 W Binder对象,用于向应用进程通信 final IWindow mClient; // 与该窗口关联的窗口令牌 (如 AppWindowToken) final WindowToken mToken; // 窗口的布局参数 (x, y, width, height, type, flags...) final WindowManager.LayoutParams mAttrs; // 窗口所属的逻辑屏幕 final DisplayContent mDisplayContent; // 窗口在WMS侧控制的Surface句柄,用于设置位置、大小、层级等 SurfaceControl mSurfaceControl; // 接收输入事件的通道 InputChannel mInputChannel; // 窗口的帧大小和位置信息 (包含四个矩形:包含框架、内容框架、可见框架等) final Rect mFrame = new Rect(); final Rect mContentFrame = new Rect(); // 窗口当前的Z-order 值 int mLayer; // ... 以及其他大量状态和方法 } ``` *代码示例:WindowState核心成员变量 * `WindowState`不仅保存了窗口的属性,其本身也参与到`WindowContainer`的层级管理中,构成了WMS内部对窗口树的描述。 ## 4. 布局、动画与Surface管理 ### 4.1 布局循环的核心:`performSurfacePlacement` WMS的核心工作引擎是`performSurfacePlacement`(旧称`performLayoutAndPlaceSurfacesLocked`)。这个方法会在窗口状态发生变化(如添加窗口、更改大小、动画更新)时被触发。 **它的主要任务**是遍历所有`DisplayContent`及其下的`WindowState`,计算每个窗口最终的**位置、大小和Z-order**。然后,它会将这些变更通过`SurfaceControl.Transaction`提交给SurfaceFlinger。 ### 4.2 窗口动画的管理者:`WindowAnimator` WMS内部有一个`WindowAnimator`对象,专门负责管理所有窗口动画。 - 当一个窗口需要执行动画(如启动、退出、旋转)时,WMS会创建相应的动画对象(如`MoveAnimation`, `AlphaAnimation`)。 - `WindowAnimator`会定期(在VSync信号驱动下)更新动画状态,并再次触发`performSurfacePlacement`,将动画过程中的新位置、透明度等属性通过`Transaction`设置给SurfaceFlinger,从而实现流畅的动画效果。 ### 4.3 Surface的申请与合成协调 WMS并不负责绘制,它只负责**“布局”和“定序”**。 - **应用侧Surface**:由`ViewRootImpl`持有,用于应用线程绘制UI。 - **WMS侧SurfaceControl**:由`WindowState`持有,用于WMS控制该窗口在屏幕上的最终呈现属性。 - **与SurfaceFlinger的交互**:WMS通过一系列的`Transaction`,将窗口的**位置、大小、旋转、透明度、Z-order**等信息同步给SurfaceFlinger。SurfaceFlinger则根据这些信息,将所有窗口的Surface(图形缓冲区)进行混合(Compose),最终输出到屏幕硬件。 ## 5. 输入事件的中转与分发 ### 5.1 WMS作为IMS的中转站 `InputManagerService`(IMS)负责从内核读取原始输入事件,但它不知道这些事件该发给谁。这时,WMS作为窗口的管理者,就成为了理想的“导航员”。 ### 5.2 关键流程序列图:触摸事件分发 ```mermaid sequenceDiagram participant IMS as InputManagerService participant WMS as WindowManagerService participant Dispatcher as InputDispatcher (Native) participant AppView as 目标窗口 (View) IMS->>Dispatcher: 1. 读取并派发事件 Dispatcher->>WMS: 2. 查询目标窗口 (通过InputMonitor) WMS-->>Dispatcher: 3. 返回焦点窗口及其InputChannel Dispatcher->>Dispatcher: 4. 命中测试,确定目标 Dispatcher->>AppView: 5. 通过InputChannel发送事件 (Socket) AppView->>AppView: 6. ViewRootImpl$WindowInputEventReceiver 处理 AppView->>AppView: 7. 事件分发 (dispatchTouchEvent) ``` ### 5.3 命中测试与`InputChannel` 1. **建立通道**:在窗口添加时(`WMS.addWindow`),如果窗口需要接收输入,WMS会为它创建一对`InputChannel`(基于Socket)。服务端的一端注册到IMS的`InputDispatcher`,客户端的一端通过Binder返回给`ViewRootImpl`,并封装成`WindowInputEventReceiver`。 ```java // WMS.addWindow 中创建InputChannel的片段 if (outInputChannel != null && (attrs.inputFeatures & ...) == 0) { String name = win.makeInputChannelName(); InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); // 创建Socket对 win.setInputChannel(inputChannels[0]); inputChannels[1].transferTo(outInputChannel); // 将客户端Channel返回 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle); // 注册服务端Channel } ``` *代码示例:InputChannel的创建与注册 * 2. **命中测试**:当IMS的`InputDispatcher`有事件到来时,它会调用WMS(通过`InputMonitor`)获取当前所有窗口的信息(Z-order、位置、焦点状态)。`InputDispatcher`执行**命中测试**,找到最合适的窗口,然后通过之前建立的Socket连接(`InputChannel`)直接将事件发送给目标应用进程。 3. **应用内处理**:应用进程的`WindowInputEventReceiver`收到事件后,将其传递给`ViewRootImpl`,进而开始我们在应用层熟悉的`View`树事件分发流程。 ## 6. 与关键系统服务的协同 ### 6.1 WMS & AMS:状态同步 AMS和WMS是一对紧密协作的“好基友”。以Activity启动为例: 1. **AMS准备**:AMS在启动一个Activity时,首先会调用WMS的`addAppToken`,告诉WMS:“我要启动一个Activity了,这是它的令牌(`AppWindowToken`)”。WMS将其加入到`mAppTokens`列表中。 2. **WMS同步**:当Activity在应用进程创建完毕,并通过`ViewRootImpl`请求添加窗口时,WMS会通过`AppWindowToken`找到这个窗口属于哪个Activity,并将其与已有的`Token`关联起来。 3. **状态回调**:当窗口显示或隐藏时,WMS也会回调AMS的方法,通知它窗口的`finishedStarting`、`finishedPausing`等状态,以便AMS继续执行生命周期的下一步。 ### 6.2 UML简化类图:核心协作关系 下图展示了WMS、AMS及其核心内部类与周边服务的关系,有助于建立宏观印象。 ```mermaid classDiagram class WindowManagerService { - InputManagerService mInputManager - ActivityManagerService mActivityManager - WindowAnimator mAnimator - HashMap~IBinder, WindowState~ mWindowMap - ArrayList~AppWindowToken~ mAppTokens + addWindow() + relayoutWindow() + performSurfacePlacement() } class ActivityManagerService { + startActivity() + resumeTopActivity() } class InputManagerService { - InputDispatcher mDispatcher + registerInputChannel() } class SurfaceFlinger { + createSurface() + setTransaction() } class WindowState { - IWindow mClient - WindowToken mToken - SurfaceControl mSurfaceControl - InputChannel mInputChannel } class AppWindowToken { - IApplicationToken mAppToken } class DisplayContent { - int mDisplayId - WindowList mWindows } WindowManagerService --> ActivityManagerService : 持有引用 WindowManagerService --> InputManagerService : 持有引用 WindowManagerService --> SurfaceFlinger : Binder通信 WindowManagerService *-- WindowAnimator WindowManagerService *-- WindowState : 管理 (mWindowMap) WindowManagerService *-- AppWindowToken : 管理 (mAppTokens) WindowManagerService *-- DisplayContent : 管理 WindowState --> WindowToken AppWindowToken --|> WindowToken DisplayContent --> WindowState : 包含 ``` ## 7. 高级主题与案例分析(可选) ### 7.1 从`dumpsys window`看窗口状态 `adb shell dumpsys window`是我们调试窗口问题的利器。通过它,我们可以看到: - **`Display`信息**:当前有几个逻辑屏幕,分辨率如何。 - **`Window Hierarchy`**:当前所有窗口的堆叠顺序,最上层的是焦点窗口。 - **`WindowState`详情**:每个窗口的包名、token、`mSurfaceControl`是否有效、`mFrame`坐标、`mInputChannel`状态等。 - **`Focus`**:当前焦点窗口是哪个。 **案例分析:** 当遇到窗口无法显示时,可以通过`dumpsys window`查看对应`WindowState`是否存在。如果存在,检查`mSurfaceControl`是否有效;如果不存在,说明窗口添加失败,可能是权限或token问题。 ### 7.2 常见问题分析 - **问题1:悬浮窗无法显示或显示位置不对** - **可能原因**:未正确申请`SYSTEM_ALERT_WINDOW`权限;LayoutParams中的`type`设置错误;在Android 10+上,未对`Display`进行适配。 - **WMS视角**:检查`dumpsys window`中该悬浮窗的`WindowState`是否存在,以及其`mFrame`和`mAttrs.gravity`是否符合预期。 - **问题2:触摸事件“被窃取”或无法传递到目标View** - **可能原因**:有其它窗口(如系统弹窗、输入法窗口)覆盖在目标窗口之上,但被设置为可触摸(`FLAG_NOT_TOUCH_MODAL`处理不当);焦点窗口不是你期望的那个。 - **WMS视角**:通过`dumpsys window`查看`Window Hierarchy`,确认Z-order的顺序。点击事件会首先发给Z-order最大的窗口。检查焦点窗口`Focus`是否正确。 ## 8. 总结与Q&A ### 总结 WMS作为Android GUI系统的“大脑”,其核心价值在于: 1. **集中管理**:通过`WindowState`、`WindowToken`和`DisplayContent`,统一维护所有窗口的状态和层级。 2. **协调调度**:作为中心枢纽,协调应用进程的绘制请求(`relayoutWindow`)、输入系统的派发请求(命中测试)以及SurfaceFlinger的合成请求(`Transaction`)。 3. **状态同步**:与AMS深度绑定,确保Activity的生命周期与窗口的显示状态同步。 深入理解WMS,不仅能帮助我们诊断疑难杂症,更能让我们对整个Android系统的设计哲学有更深刻的体会。