# Android WindowManagerService (WMS) 架构深度解析

**版本**: Android 13 (API 33)  
**面向对象**: Framework层高级工程师  
**作者**: Android系统团队

---

## 1. WMS概述

### 1.1 架构地位与服务初始化

WindowManagerService作为Android图形系统的中枢，运行于`system_server`进程，管理所有窗口的生命周期、布局、层级与输入事件分发。它与ActivityManagerService(AMS)、SurfaceFlinger构成Android Framework的三驾马车。

**服务启动时序 (SystemServer.java)**:
```java
// frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
    // 1. 初始化WMS
    wm = WindowManagerService.main(context, inputManager, ...);
    ServiceManager.addService(Context.WINDOW_SERVICE, wm);
    
    // 2. WMS就绪后通知AMS
    wm.displayReady();
    wm.systemReady();
}
```

**核心初始化链路**:
- `main()` → 创建`WindowManagerService`实例
- 初始化`WindowManagerPolicy` (策略接口，实际为`PhoneWindowManager`)
- 创建`DisplayContent`管理多显示器
- 关联`InputManagerService`建立输入通道

### 1.2 核心架构类图

```mermaid
classDiagram
    class WindowManagerService {
        - WindowManagerPolicy mPolicy
        - WindowHashMap mWindowMap
        - RootWindowContainer mRoot
        - H mH
        + addWindow()
        + removeWindow()
        + relayoutWindow()
        - performLayoutAndPlaceSurfacesLocked()
    }
    
    class WindowState {
        - IWindow mClient
        - WindowToken mToken
        - WindowManager.LayoutParams mAttrs
        - Session mSession
        - SurfaceControl mSurfaceControl
        + openInputChannel()
        + attach()
    }
    
    class WindowToken {
        - IBinder token
        - int windowType
        - DisplayContent mDisplayContent
        + addWindow()
    }
    
    class DisplayContent {
        - Display mDisplay
        - TaskDisplayArea mTaskDisplayArea
        - DisplayPolicy mDisplayPolicy
        - InputMonitor mInputMonitor
        + getWindowToken()
        + computeImeTarget()
    }
    
    class InputMonitor {
        - InputWindowHandle mInputWindowHandles
        + updateInputWindowsLw()
        + setInputFocusLw()
    }
    
    WindowManagerService --> DisplayContent : 管理
    WindowManagerService --> WindowState : 管理
    DisplayContent --> WindowToken : 包含
    WindowToken --> WindowState : 包含
    WindowManagerService --> InputMonitor : 持有
    InputMonitor --> WindowState : 监控
```

---

## 2. 窗口管理核心

### 2.1 核心数据结构

| 类名 | 作用 | 关键成员 |
|------|------|----------|
| **WindowState** | 真实窗口状态实体 | mAttrs(窗口参数), mFrame(显示区域), mSurfaceControl(Surface句柄) |
| **WindowToken** | 窗口令牌，同一组窗口的集合 | token(Binder令牌), mChildren(子窗口列表) |
| **DisplayContent** | 逻辑屏幕管理 | mDisplay(物理显示), mTaskDisplayArea(任务区) |
| **ActivityRecord** | Activity对应的窗口Token | 继承自WindowToken，绑定AMS生命周期 |
| **Session** | 应用进程与WMS的会话 | 每个应用进程对应一个Session |

### 2.2 窗口添加流程 (`addWindow`)

```mermaid
sequenceDiagram
    participant App as 应用进程
    participant WMS as WindowManagerService
    participant DC as DisplayContent
    participant SF as SurfaceFlinger
    
    App->>WMS: Session.addToDisplayAsUser()
    activate WMS
    
    WMS->>WMS: 权限校验(mPolicy.checkAddPermission)
    WMS->>DC: displayContent.getWindowToken()
    
    alt Token不存在
        WMS->>WMS: 创建WindowToken
    end
    
    WMS->>WMS: 创建WindowState
    WMS->>WMS: displayPolicy.adjustWindowParamsLw()
    WMS->>WMS: validateAddingWindowLw()
    
    WMS->>WindowState: openInputChannel()
    Note right of WindowState: 创建InputChannel对，<br/>一端给WMS，一端给应用
    
    WMS->>WMS: win.attach() → 加入容器
    WMS->>mWindowMap: put(client.asBinder(), win)
    WMS->>WindowToken: addWindow(win)
    
    WMS->>WMS: updateFocusedWindowLocked()
    WMS->>DC: getInputMonitor().setInputFocusLw()
    WMS->>WindowState: getParent().assignChildLayers()
    
    WMS-->>SF: SurfaceControl.openTransaction()
    WMS-->>SF: 创建Surface
    WMS-->>SF: SurfaceControl.closeTransaction()
    
    deactivate WMS
```

**源码核心片段 (Android 13)** :
```java
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int addWindow(Session session, IWindow client, LayoutParams attrs, ...) {
    synchronized (mGlobalLock) {
        // 1. 重复添加检查
        if (mWindowMap.containsKey(client.asBinder())) {
            return WindowManagerGlobal.ADD_DUPLICATE_ADD;
        }
        
        // 2. Token获取/创建
        WindowToken token = displayContent.getWindowToken(attrs.token);
        if (token == null) {
            token = new WindowToken.Builder(this, binder, type)
                    .setDisplayContent(displayContent)
                    .build();
        }
        
        // 3. 创建WindowState
        final WindowState win = new WindowState(this, session, client, token, 
                parentWindow, appOp[0], attrs, viewVisibility, ...);
        
        // 4. 打开输入通道
        if (outInputChannel != null) {
            win.openInputChannel(outInputChannel);
        }
        
        // 5. 加入管理容器
        win.attach();
        mWindowMap.put(client.asBinder(), win);
        win.mToken.addWindow(win);
        
        // 6. 触发布局与焦点更新
        performLayoutAndPlaceSurfacesLocked();
    }
}
```

### 2.3 窗口删除流程

**主要步骤**:
1. **线程检查**: 确保调用线程与创建线程一致
2. **移除引用**: 从`ViewRootImpl`列表、布局参数列表、View列表中删除
3. **动画处理**: 如果窗口正在运行动画，延迟删除
4. **资源释放**: 释放Surface、关闭InputChannel

```java
// WindowManagerService.removeWindow() 核心逻辑
void removeWindow(Session session, IWindow client) {
    synchronized(mGlobalLock) {
        WindowState win = mWindowMap.remove(client.asBinder());
        if (win == null) return;
        
        // 关闭输入通道
        win.removeInputChannel();
        
        // 从Token中移除
        win.mToken.removeWindow(win);
        
        // 释放Surface
        win.mSurfaceControl.reparent(null);
        win.mSurfaceControl = null;
        
        // 重新计算焦点
        updateFocusedWindowLocked();
        performLayoutAndPlaceSurfacesLocked();
    }
}
```

### 2.4 窗口层级管理 (Z-order)

Android窗口分为三大类，层级规则如下：

| 窗口类型 | 范围 | 层级特点 |
|---------|------|----------|
| **应用窗口** | 1 ~ 99 | 随Activity生命周期，由Task组织 |
| **子窗口** | 1000 ~ 1999 | 必须依附于父窗口，Z-order在父窗口之上 |
| **系统窗口** | 2000 ~ 2999 | 最高层级，如状态栏、输入法、Toast |

**层级分配算法**:
- `assignLayersLocked()` 在每次布局时调用
- 基于`BaseLayer + (type * 10000) + subLayerOffset`计算
- 系统窗口 > 输入法窗口 > 应用窗口 > 壁纸窗口

```java
// frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
void assignChildLayers() {
    for (int i = 0; i < mChildren.size(); i++) {
        WindowContainer child = mChildren.get(i);
        child.assignLayer(getPrefix(), ++layer);
    }
}
```

---

## 3. 布局与合成机制

### 3.1 布局流程核心方法

`performLayoutAndPlaceSurfacesLocked()` (简称**LAPS**) 是WMS的心脏，处理所有窗口位置、大小、可见性的计算。

**调用时机**:
- 窗口添加/删除/更新
- 配置变化(横竖屏切换、多窗口调整)
- 动画更新
- VSync信号到达

**执行流程**:
```java
// 简化版LAPS流程
void performLayoutAndPlaceSurfacesLocked() {
    // 1. 布局窗口位置
    performLayoutLocked();
    
    // 2. 分配Surface层值
    assignLayersLocked();
    
    // 3. 准备Surface (与SurfaceFlinger交互)
    for (WindowState win : mWindows) {
        if (win.hasSurface() && win.shouldPrepareSurface()) {
            win.prepareSurfaceLocked();
        }
    }
    
    // 4. 提交事务给SurfaceFlinger
    mSurfaceControlFactory.getTransaction().apply();
    
    // 5. 更新输入焦点窗口信息
    mInputMonitor.updateInputWindowsLw();
}
```

### 3.2 relayoutWindow 核心流程

应用通过`ViewRootImpl.relayoutWindow()`请求WMS重新计算窗口布局并分配Surface。

```mermaid
sequenceDiagram
    participant AppThread as UI线程
    participant VRI as ViewRootImpl
    participant WMS as WindowManagerService
    participant SF as SurfaceFlinger
    
    AppThread->>VRI: performTraversals()
    VRI->>WMS: relayoutWindow()
    activate WMS
    
    WMS->>WMS: 获取mGlobalLock
    WMS->>WindowState: 计算新Frame
    WMS->>WindowState: 更新可见区域
    
    alt Surface需要重建
        WMS->>WindowState: createSurfaceControl()
        WMS-->>SF: createSurface()
    else Surface无变化
        WMS->>WindowState: setPosition/setSize
    end
    
    WMS->>WMS: performLayoutAndPlaceSurfaces()
    WMS-->>VRI: 返回RelayoutResult
    deactivate WMS
    
    VRI->>AppThread: 通知布局完成
    VRI->>SF: 队列绘制命令
```

**性能关键点**: `relayoutWindow` 持有`mGlobalLock`，长时间操作会阻塞其他窗口更新，导致丢帧。

### 3.3 与SurfaceFlinger的交互

WMS通过`SurfaceControl`与SurfaceFlinger通信：

```java
// WindowState.createSurfaceControl() 核心逻辑
void createSurfaceControl() {
    SurfaceControl.Builder b = new SurfaceControl.Builder()
        .setName(mAttrs.getTitle().toString())
        .setSize(mFrame.width(), mFrame.height())
        .setFormat(mAttrs.format)
        .setFlags(flags)
        .setParent(mToken.getSurfaceControl());
    
    mSurfaceControl = b.build();
    
    // 设置初始属性
    SurfaceControl.Transaction t = new SurfaceControl.Transaction();
    t.setPosition(mSurfaceControl, mFrame.left, mFrame.top);
    t.setLayer(mSurfaceControl, mLayer);
    t.setAlpha(mSurfaceControl, mAttrs.alpha);
    t.apply();
}
```

**关键事务类型**:
- `setPosition` / `setSize`: 更新位置尺寸
- `setLayer`: 设置Z-order
- `setAlpha` / `setMatrix`: 动画相关
- `reparent`: 改变Surface父子关系(用于窗口切换动画)

---

## 4. 输入事件分发机制

### 4.1 完整分发链路

```mermaid
flowchart TD
    A[InputReader读取事件] --> B[InputDispatcher派发]
    B --> C{InputMonitor筛选窗口}
    
    C -->|焦点窗口| D[获取窗口InputChannel]
    C -->|触摸坐标命中测试| E[获取命中窗口]
    
    D --> F[通过socket发送]
    E --> F
    
    F --> G[应用进程ViewRootImpl]
    G --> H[InputEventReceiver接收]
    H --> I[ViewRootImpl处理]
    I --> J[View树分发]
```

### 4.2 InputMonitor角色

`InputMonitor`是WMS中的核心组件，负责维护输入窗口信息并传递给InputDispatcher：

```java
// frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
void updateInputWindowsLw(boolean force) {
    // 遍历所有窗口，收集输入窗口信息
    mDisplayContent.forAllWindows((w) -> {
        InputWindowHandle handle = w.getInputWindowHandle();
        handle.setTouchableRegion(w.getTouchableRegion());
        handle.setFocus(w == mDisplayContent.mCurrentFocus);
        handle.setLayer(w.getLayer());
        
        // 添加到列表
        mInputWindowHandles.add(handle);
    }, true);
    
    // 提交给InputDispatcher
    mInputManager.setInputWindows(mInputWindowHandles);
}
```

### 4.3 InputChannel建立

每个窗口在添加时通过`openInputChannel`创建一对Socket连接：

```java
// WindowState.openInputChannel()
void openInputChannel(InputChannel outInputChannel) {
    String name = getName();
    InputChannel[] channels = InputChannel.openInputChannelPair(name);
    
    // 服务端注册到InputDispatcher
    mInputWindowHandle = new InputWindowHandle(this);
    mService.mInputManager.registerInputChannel(channels[0], mInputWindowHandle);
    
    // 客户端通道通过Binder返回
    channels[1].transferTo(outInputChannel);
    
    // 保存服务端通道
    mClientChannel = channels[0];
}
```

---

## 5. 跨服务协作机制

### 5.1 WMS与AMS协作

AMS与WMS通过`ActivityRecord`(继承自`WindowToken`)建立绑定关系：

```mermaid
sequenceDiagram
    participant AMS
    participant WMS
    participant Activity as ActivityRecord
    
    AMS->>WMS: setAppWindowToken(token, activity)
    Note right of WMS: 绑定Activity与WindowToken
    
    AMS->>AMS: startActivityLocked()
    AMS->>WMS: setAppStartingWindow()
    WMS-->>Activity: 创建启动窗口
    
    AMS->>WMS: setAppVisibility(visible)
    WMS->>Activity: 显示/隐藏Activity窗口
    
    AMS->>WMS: moveTaskToFront()
    WMS->>Activity: 调整Task层值
    
    AMS->>WMS: setFocusedApp(token)
    WMS->>Activity: 设置焦点窗口
```

**关键交互场景**:
1. **Activity启动**: AMS通知WMS创建`AppWindowToken`
2. **窗口可见性**: AMS控制生命周期，WMS控制显示/隐藏
3. **Configuration变化**: 横竖屏切换需两服务协同
4. **Task管理**: AMS维护Task栈，WMS维护显示层级

### 5.2 WMS与InputManagerService

```java
// WMS持有IMS引用，IMS回调WMS
class WindowManagerService {
    InputManagerService mInputManager;
    
    // IMS回调WMS处理注入事件
    boolean injectInputEvent(InputEvent event, int mode) {
        return mInputManager.injectInputEvent(event, mode);
    }
}
```

### 5.3 容器遍历机制 (Android 13新特性)

WMS基于`WindowContainer`树形结构管理，提供统一的遍历API：

```java
// 遍历所有叶子Task执行操作
void forAllLeafTasks(Consumer<Task> callback) {
    mRoot.forAllLeafTasks(callback, true);
}

// 遍历所有Activity
void forAllActivities(Consumer<ActivityRecord> callback) {
    mRoot.forAllActivities(callback, true);
}

// 实际应用：pause所有后台Task
void pauseBackTasks() {
    mRoot.forAllLeafTasks((task) -> {
        if (task.isVisible()) task.startPausing();
    }, false);
}
```

---

## 6. 性能优化与问题排查

### 6.1 锁竞争优化

WMS重度依赖`mGlobalLock`，优化策略：

| 问题 | 优化方案 |
|------|----------|
| 长时间持有锁 | 拆分锁粒度，`DisplayContent`独立锁 |
| 布局计算耗时 | 异步布局预览 |
| Surface创建阻塞 | 预创建Surface池，复用缓冲区 |
| Binder调用同步 | 增加异步接口，如`relayoutAsync` |

**典型案例**: ANR日志分析
```
"android.fg" Blocked -> "JobScheduler" Blocked -> "WMS.relayoutWindow" Blocked
```
→ 表明`relayoutWindow`持有锁时间过长，导致前台线程阻塞

### 6.2 常见异常及解决方案

| 异常 | 触发条件 | 排查方向 |
|------|----------|----------|
| `BadTokenException` | 窗口Token无效 | 检查Activity是否已销毁，WindowToken是否正确传递 |
| 窗口闪烁 | Surface频繁重建 | 检查`relayoutWindow`调用频率，View层级是否稳定 |
| 触摸事件错乱 | InputChannel未正确关闭 | 使用`dumpsys input`查看窗口注册状态 |
| 多窗口卡顿 | Z-order计算复杂 | 简化窗口层级，减少重叠窗口数量 |

### 6.3 调试命令

```bash
# 查看所有窗口状态
adb shell dumpsys window windows

# 查看输入系统状态
adb shell dumpsys input

# 查看显示信息
adb shell dumpsys display

# 查看WMS内部锁状态
adb shell dumpsys window traces

# 开启WMS详细日志
adb shell setprop log.tag.WindowManager VERBOSE
adb logcat -s WindowManager
```

**关键输出解读**:
```
Window #7 Window{...}:
  mDisplayId=0
  mSession=Session{...}
  mClient=android.view.IWindow$Stub$Proxy
  mSurfaceControl=Surface(name=...)
  mFrame=[0,0][1080,1920]
  mAttrs=WM.LayoutParams{... flags=0x... type=TYPE_BASE_APPLICATION}
```

---

## 7. 附录

### 7.1 核心源码路径

| 组件 | 源码路径 |
|------|----------|
| WMS主类 | `frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java` |
| WindowState | `frameworks/base/services/core/java/com/android/server/wm/WindowState.java` |
| DisplayContent | `frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java` |
| InputMonitor | `frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java` |
| RootWindowContainer | `frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java` |
| ActivityRecord | `frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java` |

### 7.2 版本演进特性

| Android版本 | WMS关键变化 |
|-------------|-------------|
| **Android 10** | 引入`TaskFragment`，支持更细粒度窗口组织 |
| **Android 11** | 窗口同步机制优化，减少Surface重建 |
| **Android 12** | 新增`WindowInsets`动画，改进多窗口布局 |
| **Android 13** | 容器遍历API标准化，锁粒度细化 |

### 7.3 推荐文献

1. 《深入理解Android内核设计思想》- 窗口系统章节
2. AOSP官方文档: [source.android.com/docs/core/graphics](https://source.android.com/docs/core/graphics)
3. 老罗的Android之旅: WMS系列博客

---

## 总结

WindowManagerService作为Android窗口系统的中枢，承担着窗口生命周期管理、布局计算、输入事件路由三大核心职责。理解WMS需要把握以下几点：

1. **架构分层**: 客户端(WindowManager) ↔ 服务端(WMS) ↔ 底层(SurfaceFlinger)的三层模型
2. **核心对象**: WindowState(窗口实体)、WindowToken(逻辑分组)、DisplayContent(显示区域)
3. **关键流程**: addWindow/removeWindow/relayoutWindow 构成窗口生命周期
4. **锁机制**: `mGlobalLock`是性能关键点，异步化是优化方向
5. **协同机制**: AMS控制生命周期，WMS控制显示，SurfaceFlinger负责合成

掌握WMS原理不仅是解决窗口相关问题的基石，更是深入理解Android图形系统、输入系统的必备知识。