From 0ce8f409c3d996eae6c7ad0b83bc213ed8d6f705 Mon Sep 17 00:00:00 2001
From: renjianbo <263303411@qq.com>
Date: Sun, 1 Mar 2026 22:10:59 +0800
Subject: [PATCH] aa
---
.obsidian/workspace.json | 40 +-
...rService (WMS) 架构深度解析(第一次提示词).md | 591 ++++++++++++++++++
.../Android整机性能分析与问题定位实战指南.md | 235 +++++++
3 files changed, 839 insertions(+), 27 deletions(-)
create mode 100644 docs/学习笔记/Android WindowManagerService (WMS) 架构深度解析(第一次提示词).md
create mode 100644 docs/学习笔记/Android整机性能分析与问题定位实战指南.md
diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json
index 5ab58f7..751ce22 100644
--- a/.obsidian/workspace.json
+++ b/.obsidian/workspace.json
@@ -27,30 +27,16 @@
"state": {
"type": "markdown",
"state": {
- "file": "docs/Obsidian笔记体系/Daily/2026-01-13.md",
+ "file": "docs/学习笔记/Android整机性能分析与问题定位实战指南.md",
"mode": "source",
"source": false
},
"icon": "lucide-file",
- "title": "2026-01-13"
- }
- },
- {
- "id": "59894255df52f532",
- "type": "leaf",
- "state": {
- "type": "markdown",
- "state": {
- "file": "docs/学习笔记/两份提示词对比.md",
- "mode": "source",
- "source": false
- },
- "icon": "lucide-file",
- "title": "两份提示词对比"
+ "title": "Android整机性能分析与问题定位实战指南"
}
}
],
- "currentTab": 2
+ "currentTab": 1
}
],
"direction": "vertical"
@@ -212,19 +198,24 @@
"bases:Create new base": false
}
},
- "active": "59894255df52f532",
+ "active": "25c9f7051aac05b3",
"lastOpenFiles": [
+ "docs/Obsidian笔记体系/Projects/aitsc/ai提示词常用命令.md",
+ "docs/学习笔记/Android整机性能分析与问题定位实战指南.md",
+ "docs/学习笔记/Android WindowManagerService (WMS) 架构深度解析(第一次提示词).md",
"docs/学习笔记/Android WindowManagerService核心原理深度解析(专家第二次提示词).md",
"docs/学习笔记/两份提示词对比.md",
- "docs/# Android WindowManagerService (WMS) 架构深度解析(专家第一次提示词).md",
- "docs/学习笔记/Android游戏整机性能卡顿与丢帧根因分析与优化指南.md",
+ "docs/学习笔记/前端学习.md",
+ "docs/学习笔记/腾讯云相关账户.md",
+ "docs/学习笔记/效率提升.md",
"docs/学习笔记/Android性能分析标准化操作手册.md",
- "docs/Obsidian笔记体系/Projects/aitsc/ai提示词常用命令.md",
+ "docs/Obsidian笔记体系/Daily/2026-01-13.md",
+ "docs/学习笔记/Android游戏整机性能卡顿与丢帧根因分析与优化指南.md",
+ "docs/# Android WindowManagerService (WMS) 架构深度解析(专家第一次提示词).md",
"docs/Obsidian笔记体系/Projects/知你-调测/知你--调测.md",
"docs/Obsidian笔记体系/Projects/aitsc",
"docs/Obsidian笔记体系/Daily/2026-01-14.md",
"docs/Obsidian笔记体系/Daily/2024-06-02.md",
- "docs/Obsidian笔记体系/Daily/2026-01-13.md",
"docs/Obsidian笔记体系/Daily/2026-01-15.md",
"docs/Obsidian笔记体系/Daily/2026-01-20.md",
"docs/学习笔记/高级性能问题分析.md",
@@ -236,11 +227,6 @@
"docs/Obsidian笔记体系/Areas/09-调试与工具链/Systrace_Perfetto全解读.md",
"docs/学习笔记/php/未命名.md",
"docs/git/git设置用户名和邮箱.md",
- "docs/学习笔记/产品经理/产品经理--写文档.md",
- "docs/学习笔记/产品经理/沟通与表达详解.md",
- "docs/学习笔记/产品经理/数据分析详解.md",
- "docs/学习笔记/产品经理/产品运营详解.md",
- "docs/学习笔记/产品经理/产品设计详解.md",
"docs/学习笔记/产品经理",
"Pasted image 20260129111501.png",
"Pasted image 20260129111451.png",
diff --git a/docs/学习笔记/Android WindowManagerService (WMS) 架构深度解析(第一次提示词).md b/docs/学习笔记/Android WindowManagerService (WMS) 架构深度解析(第一次提示词).md
new file mode 100644
index 0000000..f89dbda
--- /dev/null
+++ b/docs/学习笔记/Android WindowManagerService (WMS) 架构深度解析(第一次提示词).md
@@ -0,0 +1,591 @@
+# 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对,
一端给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 callback) {
+ mRoot.forAllLeafTasks(callback, true);
+}
+
+// 遍历所有Activity
+void forAllActivities(Consumer 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图形系统、输入系统的必备知识。
\ No newline at end of file
diff --git a/docs/学习笔记/Android整机性能分析与问题定位实战指南.md b/docs/学习笔记/Android整机性能分析与问题定位实战指南.md
new file mode 100644
index 0000000..f6fe27c
--- /dev/null
+++ b/docs/学习笔记/Android整机性能分析与问题定位实战指南.md
@@ -0,0 +1,235 @@
+好的,遵照您的指示。作为一名高级Android开发工程师,我将基于您提供的详细规范,为您撰写一份关于“Android整机性能分析与问题定位”的实战指南。这份指南将严格遵循您设定的技术背景、流程规范、质量标准和交付要求。
+
+---
+
+# 版本历史
+| 版本 | 日期 | 作者 | 变更描述 |
+| :--- | :--- | :--- | :--- |
+| 1.0 | 2024-05-24 | AI Assistant | 初始版本,根据高级开发工程师规范制定 |
+
+## 一、引言
+本指南旨在为高级Android开发工程师提供一个系统化、标准化的整机性能分析框架。当面对海量性能日志和Trace数据时,工程师可依据此文档进行高效、精准的问题定位,并产出高质量的根因分析与优化建议。
+
+## 二、分析准备:数据预处理与验证
+
+在开始深入分析前,必须确保输入数据的完整性和一致性。这是所有后续分析的基石。
+
+### 2.1 数据完整性检查清单
+收到测试团队的bugreport或日志包后,请使用自动化脚本或手动验证以下核心文件是否存在且内容有效:
+
+```bash
+# 示例脚本片段: check_integrity.sh
+#!/bin/bash
+BUGREPORT_DIR=$1
+echo "正在验证数据完整性于: $BUGREPORT_DIR"
+
+# 必须文件列表
+REQUIRED_FILES=(
+ "bugreport-*.txt" # 主bugreport报告
+ "logcat.txt" # 完整logcat
+ "kernel.log" | "dmesg.txt" # 内核日志
+ "traces.txt" # ANR traces
+ "perfetto-trace.perfetto-trace" | "systrace.html" # Perfetto或Systrace
+ "dumpstate_board.txt" # 板级信息
+)
+
+for pattern in "${REQUIRED_FILES[@]}"; do
+ if ! ls $BUGREPORT_DIR/$pattern 1> /dev/null 2>&1; then
+ echo "警告: 未找到匹配模式 '$pattern' 的文件。"
+ else
+ echo "✓ 找到: $(ls $BUGREPORT_DIR/$pattern | head -n 1)"
+ fi
+done
+```
+
+### 2.2 时间同步与归一化
+不同日志源(如`logcat`和`kernel`)可能使用不同的时间基准。为统一分析,需将所有日志时间戳转换为相对时间(例如,相对于开机时间或第一个关键事件的时间)。
+
+- **kernel (dmesg)**:通常为`[ 秒.微秒]`格式,表示系统启动后的时间。
+- **logcat**:可显示绝对时间或相对时间。在bugreport中通常包含绝对时间。
+
+**最佳实践**:找到第一个ANR或关键事件在`logcat`中的绝对时间,然后在`dmesg`中找到对应时间点的内核日志,以建立时间关联。
+
+## 三、系统性分析流程(黄金四步法)
+
+按照“由粗到细、由表及里”的原则,分步执行分析。
+
+### 3.1 第一步:初步症状定位与关键事件捕获 (5-10分钟)
+目标是快速识别问题的表象、发生时间和影响的进程。
+
+1. **快速扫描ANR与崩溃**:
+ ```bash
+ # 扫描logcat.txt
+ grep -n "ANR in" logcat.txt --color=always
+ grep -n "FATAL EXCEPTION" logcat.txt --color=always
+ grep -n "am_anr" logcat.txt # ActivityManagerService的ANR事件日志
+ ```
+
+2. **定位UI卡顿**:
+ ```bash
+ # 查找Choreographer丢帧记录,通常以"Choreographer"或"Skipped X frames"开头
+ grep -n "Choreographer.*Skipped" logcat.txt --color=always
+ ```
+
+3. **检查系统关键错误**:
+ ```bash
+ # 内核错误、低内存、服务死亡等
+ grep -n "cancelled due to low memory" logcat.txt
+ grep -ni "service.*died" logcat.txt
+ grep -n "Out of memory" kernel.log
+ ```
+
+4. **记录关键信息**:
+ - **问题进程名与PID**:`com.example.app` (PID: 1234)
+ - **发生时间戳**:`2024-05-24 10:30:15.123`
+ - **问题类型**:`ANR (Input dispatching timed out)` 或 `UI Jank`
+
+### 3.2 第二步:系统资源瓶颈分析 (15-30分钟)
+判断问题是否由系统全局资源(CPU、内存、IO)紧张引起。
+
+#### 3.2.1 CPU调度分析
+- **工具**:Perfetto UI (ui.perfetto.dev) 或 `systrace`。
+- **操作**:加载trace文件。
+- **关注点**:
+ 1. **整体负载**:查看CPU Frequency和Core C-State图,是否存在长时间满频运行或核心被限频?
+ 2. **关键进程调度**:找到问题进程(PID)的“Slices”轨道。分析其在ANR/卡顿期间的调度情况:
+ - **Running**:绿色,表示正在执行。如果占比高,说明它在忙于自己的计算。
+ - **Runnable**:蓝色或深色,表示它想运行但CPU被其他任务抢占。这指向**CPU资源竞争**。
+ - **Sleep/Uninterruptible Sleep**:灰色,表示它在等待(锁、IO、Binder)。这指向**锁竞争或IO阻塞**。
+ 3. **寻找“大胃王”**:按CPU占用排序,找出在问题时间段内抢占CPU的高负载进程(如媒体编解码、后台压缩任务)。
+
+#### 3.2.2 内存压力检测
+- **工具**:`bugreport.txt` 中的 `meminfo` 部分,`dumpsys meminfo`,以及 `kernel.log`。
+- **操作**:在`bugreport`中搜索`Total RAM`和`Free Memory`。
+- **关注点**:
+ 1. **可用内存低**:`MemFree` + `Cached` 是否远低于总内存的20%?
+ 2. **Low Memory Killer(LMK) 日志**:在 `kernel.log` 或 `logcat` 中搜索 `lowmemorykiller` 或 `lmk`。频繁的LMK杀进程是内存严重不足的铁证。
+ ```
+ [ pid= 937, uid= 123] (com.android.systemui) 杀进程以回收内存
+ ```
+ 3. **Zone Normal 水位**:在`dmesg`中查看`zoneinfo`,判断`normal` zone是否频繁进入`min`水位以下,触发直接或kswapd内存回收。内存回收(尤其是直接回收)是巨大的性能开销。
+
+#### 3.2.3 I/O阻塞分析
+- **工具**:Perfetto (添加`f2fs`/`ext4` 和 `block` 数据源)。
+- **操作**:在Perfetto UI中放大问题时间窗口。
+- **关注点**:
+ 1. **进程状态为Uninterruptible Sleep (D状态)**:在进程的“State”轨道中,如果大量出现灰色(且工具提示为 `D`),表示进程正在执行不可中断的I/O等待。
+ 2. **Binder事务延迟**:查看Binder相关trace事件(`binder_transaction`, `binder_reply`)。在问题进程的Binder线程中,是否存在长时间未完成的Binder调用?调用方和被调用方分别是谁?
+ 3. **I/O操作**:打开`ftrace`事件中的`f2fs/iostat`或`block_rq_issue`,查看是否有大量或超大的块读写请求发生。
+
+### 3.3 第三步:进程内细粒度分析 (30-60分钟)
+在排除或确认系统瓶颈后,深入分析问题进程自身的执行流。
+
+#### 3.3.1 ANR根因分析
+- **工具**:`traces.txt` 文件,Perfetto。
+- **操作**:
+ 1. 在`traces.txt`中找到发生ANR的进程及其主线程的堆栈。
+ 2. **关键时间线分析 (P0要求)**:结合Perfetto,精确到微秒级,重建事件序列:
+ - **T0**: Input事件发送到system_server。
+ - **T1**: system_server将该事件分发给目标应用进程(通过Binder)。
+ - **T2**: 目标应用主线程收到Binder调用,开始处理。
+ - **T3 (ANR触发点)**: 5秒后,system_server未收到处理完成的信号,输出ANR。
+ 3. **调用栈深度分析 (P0要求)**:`traces.txt`中主线程的栈顶往往就是“罪魁祸首”。
+ - **常见情况**:
+ - **锁等待**:`waiting to lock <0x...>`,表明主线程在等待一个被其他线程持有的锁。需找到持锁线程的堆栈。
+ - **Binder调用**:正在执行一个Binder同步调用,等待其他进程(通常是system_server)返回。需分析被调用端的耗时。
+ - **自身耗时**:在应用代码或某系统库函数中循环,如复杂的布局、Json解析、数据库查询。
+
+#### 3.3.2 UI Jank/渲染卡顿分析
+- **工具**:Perfetto (启用`vsync`, `gfx`, `input`)。
+- **操作**:
+ 1. 找到`SurfaceFlinger`和应用的`RenderThread`轨道。
+ 2. 分析一帧的完整流水线:
+ - **App主线程 (UI Thread)**:处理Input,执行`onMeasure`, `onLayout`, `onDraw`。耗时过长会导致帧错过vsync。
+ - **RenderThread**:将DisplayList绘制指令提交给GPU。耗时可能由复杂绘制指令引起。
+ - **hwui**:等待GPU完成。可能由GPU负载过高或驱动问题引起。
+ - **SurfaceFlinger**:合成各应用图层。如果此阶段耗时,可能是合成层数过多(Overdraw)或硬件合成器(HWC)能力不足。
+ 3. **定位最慢阶段**:哪一阶段的彩色条形图最长?哪个阶段导致了帧截止时间(红色垂直线)的错过?
+
+### 3.4 第四步:关联分析与根因确认 (15分钟)
+将以上各步骤的发现关联起来,形成完整证据链。
+
+- **案例**:初步定位有ANR,第二步发现内存紧张,LMK频繁杀进程。第三步发现被杀进程恰好是ANR进程依赖的一个关键服务(如ContentProvider所在进程)。那么,**根本原因**就不是主线程阻塞,而是**系统内存不足导致依赖服务被回收**,从而造成调用方ANR。
+- **验证**:查看ANR发生前,`logcat`中是否有`lmk`杀掉关键服务的日志?查看`traces.txt`中主线程是否在`binderTransaction`等待一个不存在的进程返回?
+
+## 四、问题分类与优先级判定
+
+根据分析结果,对问题进行定级。
+
+- **P0级 (阻塞性)**:
+ - **标准**:ANR持续时间 > 5秒,或连续丢帧 > 16帧。
+ - **示例**:任何用户可见的ANR;启动应用时黑屏/白屏超过5秒;滑动列表持续卡顿。
+- **P1级 (严重)**:
+ - **标准**:UI响应延迟 > 100ms,或内存泄漏 > 50MB,或发生系统服务重启。
+ - **示例**:点击按钮后200ms才有反应;后台长期占用大量内存导致其他应用被LMK;system_server或surfaceflinger重启。
+- **P2级 (一般)**:
+ - **标准**:单次操作偶尔延迟,或资源占用在极端场景下才出现问题。
+ - **示例**:首次打开相册慢;在某些特定网络条件下,列表图片加载慢。
+
+## 五、交付成果与质量标准
+
+### 5.1 核心交付物:性能分析报告 (示例模板)
+
+```markdown
+## 问题概述
+- **现象**:在视频播放界面快速滑动评论区时,界面严重卡顿,帧率降至个位数。
+- **影响范围**:视频类应用 `com.media.video` (PID: 9876) ,Android 12 设备。
+- **P等级**:P1 (严重 UI Jank)
+
+## 根因分析
+### 关键时间线
+在Perfetto trace的时间窗口 `12:05:30.000` - `12:05:32.000` 内:
+
+1. **UI Thread (TID 9876)**:在 `RecyclerView` 的 `onBindViewHolder` 中调用了 `MediaMetadataUtils.getAlbumArt()`,耗时约 **45ms**。
+2. **RenderThread (TID 9882)**:主线程耗时导致错过了 `Choreographer` 的 `doFrame` 回调,无法开始下一帧的绘制。
+3. **后续帧**:UI Thread 在多个连续的 `doFrame` 中均耗时 > 30ms,导致连续丢帧超过30帧。
+ *(此处应插入Perfetto标记帧超时的截图)*
+
+### 调用栈深度分析
+通过 `simpleperf` 对主线程采样,发现 `getAlbumArt()` 中的耗时操作最终调用到了 `BitmapFactory.decodeStream()` 从本地文件系统加载一张较大分辨率的图片。
+*(此处应插入调用栈火焰图或堆栈列表)*
+- **层1 (应用层)**:`com.media.video.adapter.CommentAdapter.onBindViewHolder`
+- **层2 (应用层)**:`com.media.video.utils.MediaMetadataUtils.getAlbumArt`
+- **层3 (Framework)**:`android.graphics.BitmapFactory.decodeStream`
+- **层4 (Native)**:`libskia.so` 中的 `SkCodec::getPixels`,显示正在解码一张 JPEG 图片。
+- **根因**:`RecyclerView` 滑动时,主线程同步解码磁盘上的高清图片,阻塞了UI绘制。
+
+## 优化建议
+### 代码修改建议
+1. **异步加载**:使用 `Glide` 或 `Coil` 等图片加载库,在后台线程异步加载评论区的用户头像和缩略图。
+ ```kotlin
+ // 原代码 (可能导致卡顿)
+ // val bitmap = MediaMetadataUtils.getAlbumArt(context, mediaId)
+ // holder.albumArt.setImageBitmap(bitmap)
+
+ // 优化后代码 (使用Coil)
+ holder.albumArt.load(MediaMetadataUtils.getAlbumArtUri(mediaId)) {
+ crossfade(true)
+ placeholder(R.drawable.placeholder)
+ }
+ ```
+2. **图片压缩**:如果必须直接解码,确保使用 `BitmapFactory.Options` 进行采样,降低加载到内存中的图片尺寸,减少解码时间。
+
+### 配置调整方案
+- 无。此问题主要源于应用代码,无需系统配置调整。
+
+## 支持证据
+1. `perfetto_trace_jank.html` (已标记问题区间)
+2. `trace_ui_thread_jank.txt` (主线程堆栈片段)
+3. `cpu_profile.data` (Simpleperf性能采样数据)
+```
+
+### 5.2 可复现分析脚本
+创建自动化脚本来提取关键指标,例如:
+- `extract_anr_traces.py`:自动解析`traces.txt`和`logcat`,生成ANR摘要报告。
+- `perfetto_metric.sh`:调用Perfetto命令行工具,计算指定时间段内的平均帧率、Jank次数。
+
+### 5.3 质量检查清单
+在提交报告前,使用以下清单进行自查:
+
+- [x] **P0/P1问题全覆盖**:所有ANR、严重卡顿均有关联分析。
+- [x] **根因精确**:是否定位到具体函数/代码行/系统配置?(例如:`com.example.app$MyClass.onClick (line: 250)`, 而不是“主线程阻塞”)
+- [x] **证据链完整**:是否从现象、日志、trace到代码修改建议形成了逻辑闭环?
+- [x] **数据量化**:优化前后的性能对比是否有数据支撑?(例如:帧率从15fps提升到55fps,内存占用降低80MB)
+- [x] **报告规范**:报告格式是否符合Markdown模板要求?关键部分是否包含截图?
+- [x] **可复现性**:分析脚本是否能在Linux/macOS环境顺利运行?依赖是否清晰?
\ No newline at end of file