Files
mkdocs/docs/学习笔记/Android WindowManagerService核心原理深度解析(专家第二次提示词).md

319 lines
17 KiB
Markdown
Raw Normal View History

2026-02-28 01:44:55 +08:00
好的遵照您的指示我将基于您提供的详细提示词和搜索材料为您创作一份《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 & AMSActivity状态与窗口的同步
- WMS & SurfaceFlinger通过`Transaction`提交变更
- UML简化类图核心协作关系
7. **高级主题与案例分析**(可选)
-`dumpsys window`看窗口状态
- 常见问题分析:窗口泄漏、事件丢失
8. **总结与Q&A**
---
## 1. 引言为什么需要深入理解WMS
各位同事,在日常开发中,我们面对的挑战往往不止于业务逻辑的实现。当遇到**多窗口适配的诡异布局**、**悬浮窗权限的反复横跳**、**应用启动或转场时的莫名卡顿**,甚至是**触摸事件偶尔“灵异”丢失**的问题时,我们是否感到束手无策,只能依靠试错或搜索碎片化的解决方案?
这些复杂UI场景和性能瓶颈的根源往往深藏在Android Framework的核心——**WindowManagerServiceWMS** 之中。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<WindowState> {
// 指向持有该窗口的客户端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系统的设计哲学有更深刻的体会。