591 lines
18 KiB
Markdown
591 lines
18 KiB
Markdown
|
|
# 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图形系统、输入系统的必备知识。
|