基于 AOSP 15 (Android 15) 源码分析
源码根目录:
~/aosp15/
目录
- [1. 三张图理解窗口层级](#1. 三张图理解窗口层级 "#1-%E4%B8%89%E5%BC%A0%E5%9B%BE%E7%90%86%E8%A7%A3%E7%AA%97%E5%8F%A3%E5%B1%82%E7%BA%A7")
- [2. 核心常量与公式](#2. 核心常量与公式 "#2-%E6%A0%B8%E5%BF%83%E5%B8%B8%E9%87%8F%E4%B8%8E%E5%85%AC%E5%BC%8F")
- [3. 窗口类型→层级映射 (getWindowLayerFromTypeLw)](#3. 窗口类型→层级映射 (getWindowLayerFromTypeLw) "#3-%E7%AA%97%E5%8F%A3%E7%B1%BB%E5%9E%8B%E5%B1%82%E7%BA%A7%E6%98%A0%E5%B0%84-getwindowlayerfromtypelw")
- [4. 子窗口层级偏移](#4. 子窗口层级偏移 "#4-%E5%AD%90%E7%AA%97%E5%8F%A3%E5%B1%82%E7%BA%A7%E5%81%8F%E7%A7%BB")
- [5. DisplayArea 层级树详解](#5. DisplayArea 层级树详解 "#5-displayarea-%E5%B1%82%E7%BA%A7%E6%A0%91%E8%AF%A6%E8%A7%A3")
- [6. 层级分配流程 (assignChildLayers)](#6. 层级分配流程 (assignChildLayers) "#6-%E5%B1%82%E7%BA%A7%E5%88%86%E9%85%8D%E6%B5%81%E7%A8%8B-assignchildlayers")
- [7. 特殊层级处理](#7. 特殊层级处理 "#7-%E7%89%B9%E6%AE%8A%E5%B1%82%E7%BA%A7%E5%A4%84%E7%90%86")
- [8. adb dumpsys 实战指南](#8. adb dumpsys 实战指南 "#8-adb-dumpsys-%E5%AE%9E%E6%88%98%E6%8C%87%E5%8D%97")
- [9. 关键源码文件索引](#9. 关键源码文件索引 "#9-%E5%85%B3%E9%94%AE%E6%BA%90%E7%A0%81%E6%96%87%E4%BB%B6%E7%B4%A2%E5%BC%95")
1. 三张图理解窗口层级
1.1 图一: 窗口类型到基础层级 (mBaseLayer)
scss
Layer 35 TYPE_POINTER 鼠标指针
Layer 34 TYPE_BOOT_PROGRESS 启动进度
Layer 33 TYPE_SECURE_SYSTEM_OVERLAY 安全系统覆盖
Layer 32 TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY 无障碍放大
Layer 31 TYPE_ACCESSIBILITY_OVERLAY 无障碍覆盖
Layer 30 TYPE_DRAG 拖拽
Layer 29 TYPE_DISPLAY_OVERLAY 显示覆盖
Layer 28 TYPE_MAGNIFICATION_OVERLAY 放大覆盖
Layer 27 TYPE_SYSTEM_ERROR (系统进程) 系统错误
Layer 26 TYPE_SCREENSHOT 截图
Layer 25 TYPE_NAVIGATION_BAR_PANEL 导航栏面板
Layer 24 TYPE_NAVIGATION_BAR 导航栏
Layer 23 TYPE_SYSTEM_OVERLAY (系统进程) 系统覆盖
Layer 22 TYPE_VOLUME_OVERLAY 音量
Layer 21 TYPE_VOICE_INTERACTION 语音交互
Layer 20 TYPE_VOICE_INTERACTION_STARTING 语音交互启动
Layer 19 TYPE_KEYGUARD_DIALOG 锁屏对话框
Layer 18 TYPE_STATUS_BAR_SUB_PANEL 状态栏子面板
Layer 17 TYPE_NOTIFICATION_SHADE 通知栏
Layer 16 TYPE_STATUS_BAR_ADDITIONAL 附加状态栏
Layer 15 TYPE_STATUS_BAR 状态栏
Layer 14 TYPE_INPUT_METHOD_DIALOG 输入法对话框
Layer 13 TYPE_INPUT_METHOD 输入法
Layer 12 TYPE_SYSTEM_ALERT (系统进程) 系统警报
Layer 11 TYPE_APPLICATION_OVERLAY 应用覆盖层 ★
Layer 10 TYPE_SYSTEM_OVERLAY (普通进程) 系统覆盖
Layer 9 TYPE_SYSTEM_ALERT / ERROR (普通进程) 系统警报/错误
Layer 8 TYPE_PRIORITY_PHONE 优先电话
Layer 7 TYPE_TOAST Toast
Layer 6 TYPE_SYSTEM_DIALOG 系统对话框
Layer 5 TYPE_INPUT_CONSUMER 输入消费者
Layer 4 TYPE_SEARCH_BAR 搜索栏
Layer 3 TYPE_PHONE / PRESENTATION / DOCK_DIVIDER 电话/Presentation/分屏
Layer 2 TYPE_APPLICATION (1-99) 应用窗口 ★★★
Layer 1 TYPE_WALLPAPER 壁纸
★ = framework 开发最常接触的层级
1.2 图二: DisplayArea 树形结构
格式:
节点名 [Z最小:Z最大],Z 值越高显示越靠前。 数据来源:adb shell dumpsys window displays→ Display areas in top down Z order
scss
DisplayContent
│
├── Leaf [36:36] ← 圆角覆盖层 (最高层)
│
├── HideDisplayCutout [32:35]
│ ├── OneHanded [34:35]
│ │ └── FullscreenMagnification [34:35]
│ │ └── Leaf [34:35] ← BOOT_PROGRESS(34), POINTER(35)
│ ├── FullscreenMagnification [33:33]
│ │ └── Leaf [33:33] ← SECURE_SYSTEM_OVERLAY(33)
│ └── OneHanded [32:32]
│ └── Leaf [32:32] ← ACCESSIBILITY_MAGNIFICATION_OVERLAY(32)
│
└── WindowedMagnification [0:31] ← ★ 主区域,覆盖 Z=0~31
│
├── HideDisplayCutout [26:31]
│ └── OneHanded [26:31]
│ ├── FullscreenMagnification [29:31]
│ │ └── Leaf [29:31] ← DISPLAY_OVERLAY(29), DRAG(30), ACCESSIBILITY_OVERLAY(31)
│ ├── Leaf [28:28] ← MAGNIFICATION_OVERLAY(28)
│ └── FullscreenMagnification [26:27]
│ └── Leaf [26:27] ← SCREENSHOT(26), SYSTEM_ERROR sys(27)
│
├── Leaf [24:25] ← NAVIGATION_BAR(24), NAVIGATION_BAR_PANEL(25)
│
├── HideDisplayCutout [18:23]
│ └── OneHanded [18:23]
│ └── FullscreenMagnification [18:23]
│ └── Leaf [18:23] ← STATUS_BAR_SUB_PANEL(18) ~ SYSTEM_OVERLAY sys(23)
│
├── OneHanded [17:17]
│ └── FullscreenMagnification [17:17]
│ └── Leaf [17:17] ← NOTIFICATION_SHADE(17)
│
├── HideDisplayCutout [16:16]
│ └── OneHanded [16:16]
│ └── FullscreenMagnification [16:16]
│ └── Leaf [16:16] ← STATUS_BAR_ADDITIONAL(16)
│
├── OneHanded [15:15]
│ └── FullscreenMagnification [15:15]
│ └── Leaf [15:15] ← STATUS_BAR(15)
│
└── HideDisplayCutout [0:14] ← ★ 应用/输入法区域
└── OneHanded [0:14]
├── ImePlaceholder [13:14]
│ └── ImeContainer ← INPUT_METHOD(13), INPUT_METHOD_DIALOG(14)
│ └── WindowToken (IME)
│ └── WindowState ← 使用 assignRelativeLayer 相对输入目标定位
│
└── FullscreenMagnification [0:12]
├── Leaf [3:12] ← PHONE(3)~SYSTEM_ALERT sys(12) 等系统窗口
├── DefaultTaskDisplayArea ← ★★★ 应用 Task 容器 (layer 2)
│ └── Task Stack
│ ├── Task (Launcher)
│ │ └── ActivityRecord
│ │ └── WindowToken (baseLayer=21000)
│ │ └── WindowState (TYPE_APPLICATION)
│ └── Task (Settings)
│ └── ...
└── Leaf [0:1] ← WALLPAPER(1), 其他(layer 0)
Framework 开发要点:
- DefaultTaskDisplayArea (Z=2): 所有应用 Task 的容器,层级调整通常在此操作
- ImeContainer (Z=13): 独立成区,使用
assignRelativeLayer相对于输入目标定位,非固定 Z 值 - Leaf [3:12] : 系统窗口区 (Toast、Phone、SystemAlert 等)
- 同一 Feature 出现多次: HideDisplayCutout 在 [26:31]、[18:23]、[16:16]、[0:14] 各出现一次,分别包装对应 Z 范围的窗口
- Z 值由 assignChildLayers 递归分配: 树中子节点按序获得递增 Z 值
1.3 图三: Z 值分配流程
css
WMS 触发: addWindow / removeWindow / 焦点变化 / 栈变化
│
▼
DisplayContent.assignWindowLayers()
│
▼
DisplayContent.assignChildLayers(transaction)
├── 1. assignRelativeLayerForIme() ← IME 相对层级
└── 2. super.assignChildLayers() ← 递归子节点
│
├── 分配策略 (WindowContainer):
│ 第一轮: 非 Z-Boost 子节点按序分配 layer++
│ 第二轮: Z-Boost 子节点追加到末尾
│
├── DisplayArea.assignChildLayers()
│ └── 递归到 TaskDisplayArea / WindowTokens
│
├── WindowToken.assignChildLayers()
│ ├── 圆角覆盖层: 特殊处理
│ └── 递归到 WindowState
│
└── WindowState.assignChildLayers()
├── MEDIA → assignRelativeLayer(父, -2)
├── MEDIA_OVERLAY → assignRelativeLayer(父, -1)
└── 其他子窗口 → assignLayer(layer++)
2. 核心常量与公式
文件 : frameworks/base/core/java/android/view/WindowManagerPolicyConstants.java
ini
// 核心公式
mBaseLayer = getWindowLayerFromTypeLw(type) × TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET
= layer_number × 10000 + 1000
// 常量
int TYPE_LAYER_MULTIPLIER = 10000; // 同类型窗口间距
int TYPE_LAYER_OFFSET = 1000; // 基础偏移
int APPLICATION_LAYER = 2; // 应用窗口基础层级
// 子窗口层级偏移 (相对于父窗口)
int APPLICATION_MEDIA_SUBLAYER = -2; // 媒体层 (最底)
int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1; // 媒体覆盖层
int APPLICATION_PANEL_SUBLAYER = 1; // 面板
int APPLICATION_SUB_PANEL_SUBLAYER = 2; // 子面板
int APPLICATION_ABOVE_SUB_PANEL_SUBLAYER = 3; // 子面板上方
// 特殊层
int WINDOW_FREEZE_LAYER = TYPE_LAYER_MULTIPLIER * 200; // 窗口冻结层
关键理解:
mBaseLayer仅用于 WindowToken 内部子窗口排序,不是 SurfaceFlinger 的 Z 值- SurfaceFlinger 的 Z 值由
assignChildLayers()递归分配的序号决定 - 同一个 WindowToken 下多个子窗口按
mBaseLayer + mSubLayer排序
3. 窗口类型→层级映射 (getWindowLayerFromTypeLw)
文件 : frameworks/base/services/core/java/com/android/server/policy/WindowManagerPolicy.java
kotlin
default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow,
boolean roundedCornerOverlay) {
if (roundedCornerOverlay && canAddInternalSystemWindow) {
return getMaxWindowLayer(); // 36, 圆角覆盖层最高
}
if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
return APPLICATION_LAYER; // 2, 所有应用窗口共享同一基础层
}
switch (type) {
case TYPE_WALLPAPER: return 1;
case TYPE_PHONE: return 3;
case TYPE_PRESENTATION:
case TYPE_PRIVATE_PRESENTATION:
case TYPE_DOCK_DIVIDER:
case TYPE_QS_DIALOG: return 3;
case TYPE_SEARCH_BAR: return 4;
case TYPE_INPUT_CONSUMER: return 5;
case TYPE_SYSTEM_DIALOG: return 6;
case TYPE_TOAST: return 7;
case TYPE_PRIORITY_PHONE: return 8;
case TYPE_SYSTEM_ALERT: // ⚠️ 条件分支
return canAddInternalSystemWindow ? 12 : 9;
case TYPE_APPLICATION_OVERLAY: return 11;
case TYPE_INPUT_METHOD: return 13;
case TYPE_INPUT_METHOD_DIALOG: return 14;
case TYPE_STATUS_BAR: return 15;
case TYPE_STATUS_BAR_ADDITIONAL: return 16;
case TYPE_NOTIFICATION_SHADE: return 17;
case TYPE_STATUS_BAR_SUB_PANEL: return 18;
case TYPE_KEYGUARD_DIALOG: return 19;
case TYPE_VOICE_INTERACTION_STARTING: return 20;
case TYPE_VOICE_INTERACTION: return 21;
case TYPE_VOLUME_OVERLAY: return 22;
case TYPE_SYSTEM_OVERLAY: // ⚠️ 条件分支
return canAddInternalSystemWindow ? 23 : 10;
case TYPE_NAVIGATION_BAR: return 24;
case TYPE_NAVIGATION_BAR_PANEL: return 25;
case TYPE_SCREENSHOT: return 26;
case TYPE_SYSTEM_ERROR: // ⚠️ 条件分支
return canAddInternalSystemWindow ? 27 : 9;
case TYPE_MAGNIFICATION_OVERLAY: return 28;
case TYPE_DISPLAY_OVERLAY: return 29;
case TYPE_DRAG: return 30;
case TYPE_ACCESSIBILITY_OVERLAY: return 31;
case TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY: return 32;
case TYPE_SECURE_SYSTEM_OVERLAY: return 33;
case TYPE_BOOT_PROGRESS: return 34;
case TYPE_POINTER: return 35;
default: return 3;
}
}
条件层级 (framework 开发常遇):
| 窗口类型 | 系统进程 (有 INTERNAL_SYSTEM_WINDOW) | 普通进程 | 原因 |
|---|---|---|---|
| TYPE_SYSTEM_ALERT | Layer 12 | Layer 9 | 系统警报需要高于应用覆盖层 |
| TYPE_SYSTEM_OVERLAY | Layer 23 | Layer 10 | 系统覆盖需要高于导航栏 |
| TYPE_SYSTEM_ERROR | Layer 27 | Layer 9 | 系统错误需要高于截图 |
4. 子窗口层级偏移
文件 : frameworks/base/services/core/java/com/android/server/policy/WindowManagerPolicy.java
go
default int getSubWindowLayerFromTypeLw(int type) {
switch (type) {
case TYPE_APPLICATION_PANEL: // +1 (父窗口之上)
case TYPE_APPLICATION_ATTACHED_DIALOG: // +1
return APPLICATION_PANEL_SUBLAYER;
case TYPE_APPLICATION_MEDIA: // -2 (父窗口之下)
return APPLICATION_MEDIA_SUBLAYER;
case TYPE_APPLICATION_MEDIA_OVERLAY: // -1 (媒体之上)
return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
case TYPE_APPLICATION_SUB_PANEL: // +2
return APPLICATION_SUB_PANEL_SUBLAYER;
case TYPE_APPLICATION_ABOVE_SUB_PANEL: // +3 (最高)
return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER;
}
return 0;
}
5. DisplayArea 层级树详解
5.1 Feature 定义
文件 : frameworks/base/core/java/android/window/DisplayAreaOrganizer.java
| Feature ID | 常量名 | 用途 | Framework 相关性 |
|---|---|---|---|
| 0 | FEATURE_ROOT | 根节点 | 低 |
| 1 | FEATURE_DEFAULT_TASK_CONTAINER | Task 容器 | ★★★ 高 |
| 2 | FEATURE_WINDOW_TOKENS | 窗口 Token 容器 | ★★★ 高 |
| 3 | FEATURE_ONE_HANDED | 单手模式 | ★ 中 |
| 4 | FEATURE_WINDOWED_MAGNIFICATION | 放大镜区域 | ★ 中 |
| 5 | FEATURE_FULLSCREEN_MAGNIFICATION | 全屏放大 | ★ 中 |
| 6 | FEATURE_HIDE_DISPLAY_CUTOUT | 隐藏刘海 | ★★ 中高 |
| 7 | FEATURE_IME_PLACEHOLDER | IME 占位 | ★★ 中高 |
| 8 | FEATURE_IME | 输入法区域 | ★★★ 高 |
| 9 | FEATURE_WINDOWING_LAYER | 窗口化层 | ★ 中 |
5.2 层级树构建 (configureTrustedHierarchyBuilder)
文件 : frameworks/base/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
java
// Feature 按层级从高到低添加,形成嵌套结构
static void configureTrustedHierarchyBuilder(DisplayAreaPolicyBuilder.HierarchyBuilder builder,
WindowManagerService wmService, DisplayContent content) {
// 每个 Feature 创建一个 DisplayArea 层级,按添加顺序嵌套
builder.addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(wmService, content,
"WindowedMagnification", FEATURE_WINDOWED_MAGNIFICATION)
.upTo(TYPE_INPUT_METHOD) // 覆盖到 IME 层
.and(TYPE_INPUT_METHOD_DIALOG)
.and(TYPE_NAVIGATION_BAR_PANEL)
.build());
builder.addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(wmService, content,
"HideDisplayCutout", FEATURE_HIDE_DISPLAY_CUTOUT)
.upTo(TYPE_STATUS_BAR_ADDITIONAL)
.and(TYPE_NAVIGATION_BAR)
.and(TYPE_NOTIFICATION_SHADE)
.build());
builder.addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(wmService, content,
"OneHanded", FEATURE_ONE_HANDED)
.upTo(TYPE_STATUS_BAR_ADDITIONAL)
.and(TYPE_NAVIGATION_BAR)
.and(TYPE_NOTIFICATION_SHADE)
.build());
builder.addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(wmService, content,
"FullscreenMagnification", FEATURE_FULLSCREEN_MAGNIFICATION)
.upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
.except(TYPE_ACCESSIBILITY_OVERLAY)
.build());
builder.addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(wmService, content,
"ImePlaceholder", FEATURE_IME_PLACEHOLDER)
.upTo(TYPE_INPUT_METHOD)
.build());
builder.addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(wmService, content,
"ImeContainer", FEATURE_IME)
.upTo(TYPE_INPUT_METHOD)
.build());
}
5.3 Feature 覆盖范围表
| Feature | 覆盖范围 (窗口类型) | 说明 | 层级数 |
|---|---|---|---|
| WindowedMagnification | TYPE_INPUT_METHOD, INPUT_METHOD_DIALOG, NAVIGATION_BAR_PANEL | 放大镜可见区域 | 0-31 |
| HideDisplayCutout | STATUS_BAR_ADDITIONAL 及以下, NAVIGATION_BAR, NOTIFICATION_SHADE | 刘海遮蔽区域 | 0-14、16、18-23、26-35 |
| OneHanded | 同 HideDisplayCutout | 单手模式偏移区域 | 0-23、26-31、34-35 |
| FullscreenMagnification | ACCESSIBILITY_MAGNIFICATION_OVERLAY 及以下 (排除 ACCESSIBILITY_OVERLAY) | 全屏放大区域 | 0-12、15-23、26-27、29-31、33-35 |
| ImePlaceholder | TYPE_INPUT_METHOD 及以下 | IME 容器占位 | 13--14 |
5.4 实际设备上的层级结构树
获取命令:
adb shell dumpsys window displays→ 找到 "Display areas in top down Z order",更详细用adb shell dumpsys window containers
markdown
Display areas in top down Z order:
* Leaf:36:36
* HideDisplayCutout:32:35
* OneHanded:34:35
* FullscreenMagnification:34:35
* Leaf:34:35
* FullscreenMagnification:33:33
* Leaf:33:33
* OneHanded:32:32
* Leaf:32:32
* WindowedMagnification:0:31
* HideDisplayCutout:26:31
* OneHanded:26:31
* FullscreenMagnification:29:31
* Leaf:29:31
* Leaf:28:28
* FullscreenMagnification:26:27
* Leaf:26:27
* Leaf:24:25
* HideDisplayCutout:18:23
* OneHanded:18:23
* FullscreenMagnification:18:23
* Leaf:18:23
* OneHanded:17:17
* FullscreenMagnification:17:17
* Leaf:17:17
* HideDisplayCutout:16:16
* OneHanded:16:16
* FullscreenMagnification:16:16
* Leaf:16:16
* OneHanded:15:15
* FullscreenMagnification:15:15
* Leaf:15:15
* HideDisplayCutout:0:14
* OneHanded:0:14
* ImePlaceholder:13:14
* ImeContainer
* FullscreenMagnification:0:12
* Leaf:3:12
* DefaultTaskDisplayArea (organized)
* Leaf:0:1
6. 层级分配流程 (assignChildLayers)
6.1 入口
java
// DisplayContent.java
void assignWindowLayers(boolean setLayoutNeeded) {
assignChildLayers(getSyncTransaction());
if (setLayoutNeeded) {
requestTraversal();
}
}
6.2 核心递归 (WindowContainer)
java
// WindowContainer.java
void assignChildLayers(Transaction t) {
int layer = 0;
// 第一轮: 非 Z-Boost 子节点按序分配
for (int j = 0; j < mChildren.size(); ++j) {
final WindowContainer wc = mChildren.get(j);
wc.assignChildLayers(t); // 先递归子节点
if (!wc.needsZBoost()) {
wc.assignLayer(t, layer++);
}
}
// 第二轮: Z-Boost 子节点追加到末尾
for (int j = 0; j < mChildren.size(); ++j) {
final WindowContainer wc = mChildren.get(j);
if (wc.needsZBoost()) {
wc.assignLayer(t, layer++);
}
}
}
6.3 WindowState 子窗口特殊处理
java
// WindowState.java
@Override
public void assignChildLayers(Transaction t) {
int layer = PRESERVED_SURFACE_LAYER + 1;
for (int i = 0; i < mChildren.size(); i++) {
final WindowState w = mChildren.get(i);
if (w.mAttrs.type == TYPE_APPLICATION_MEDIA) {
// MEDIA: 相对层级 -2 (在父窗口 Surface 之下)
w.assignRelativeLayer(t, mWinAnimator.mSurfaceControl, -2);
} else if (w.mAttrs.type == TYPE_APPLICATION_MEDIA_OVERLAY) {
// MEDIA_OVERLAY: 相对层级 -1 (在父窗口 Surface 之下但在 MEDIA 之上)
w.assignRelativeLayer(t, mWinAnimator.mSurfaceControl, -1);
} else {
// 其他子窗口: 顺序递增
w.assignLayer(t, layer++);
}
w.assignChildLayers(t);
}
}
6.4 assignLayer → SurfaceFlinger
java
// WindowContainer.java
void assignLayer(Transaction t, int layer) {
if (mSurfaceControl != null && (layer != mLastLayer || mLastRelativeToLayer != null)) {
setLayer(t, layer);
mLastLayer = layer;
mLastRelativeToLayer = null;
}
}
// 最终调用链:
// assignLayer() → setLayer() → SurfaceAnimator.setLayer() → Transaction.setLayer()
// → SurfaceFlinger 更新 Z 序
7. 特殊层级处理
7.1 IME 相对层级 (重要)
文件 : frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
IME 不使用固定层级,而是相对于当前输入目标窗口定位:
java
// DisplayContent.assignChildLayers()
@Override
void assignChildLayers(SurfaceControl.Transaction t) {
assignRelativeLayerForIme(t, false);
super.assignChildLayers(t);
}
private void assignRelativeLayerForIme(SurfaceControl.Transaction t, boolean forceUpdate) {
final WindowState imeTarget = mImeLayeringTarget;
if (imeTarget != null) {
// IME 放在输入目标窗口上方
mImeWindowsContainer.assignRelativeLayer(t,
imeTarget.getSurfaceControl(), 1);
} else {
// 无目标时使用中间层
mImeWindowsContainer.assignLayer(t, Integer.MAX_VALUE / 2);
}
}
Framework 开发要点:
- IME 始终显示在输入焦点窗口正上方
- 调试 IME 层级问题要关注
mImeLayeringTarget而非固定 Z 值 adb shell dumpsys window tokens | grep -A10 "InputMethod"可查看 IME 目标
7.2 圆角覆盖层
java
// WindowToken.java
@Override
void assignLayer(SurfaceControl.Transaction t, int layer) {
if (mRoundedCornerOverlay) {
super.assignLayer(t, WindowManagerPolicy.COLOR_FADE_LAYER + 1);
} else {
super.assignLayer(t, layer);
}
}
7.3 Z-Boost 机制
嵌入式 Activity 需要提升到同层级之上:
java
// WindowState.java
boolean needsZBoost() {
if (mIsChildWindow) return false;
if (mAttrs.type == TYPE_APPLICATION || mAttrs.type == TYPE_ACTIVITY) {
return activity != null && activity.needsZBoost();
}
return false;
}
Z-Boost 窗口在 assignChildLayers() 第二轮处理,确保排在所有非 Boost 窗口之后。
8. adb dumpsys 实战指南
8.1 查看所有窗口及层级
bash
# 完整窗口列表 (含 mBaseLayer/mSubLayer)
adb shell dumpsys window windows
输出关键字段:
bash
Window #5 Window{abc1234 u0 com.example.app/com.example.Activity}:
mOwnerPackage=com.example.app mOwnerUid=10123
mBaseLayer=21000 mSubLayer=0 ← 层级=2, 2×10000+1000=21000
mFrame=[0,0][1080,2400] mShown=true
8.2 查看层级摘要 (快速诊断)
perl
# 所有窗口按 mBaseLayer 排序
adb shell dumpsys window windows | grep "mBaseLayer" | sort -t= -k2 -n
# 当前焦点窗口
adb shell dumpsys window windows | grep -E "mCurrentFocus|mFocusedApp"
输出示例:
bash
mCurrentFocus=Window{abc1234 u0 com.example.app/com.example.Activity}
mFocusedApp=AppWindowToken{abc123 ActivityRecord{... u0 com.example.app/.Activity t123}}
8.3 查看 DisplayArea 层级树 (重要)
bash
# 简约
adb shell dumpsys window displays
# 详细
adb shell dumpsys window containers
输出:
bash
Display 0:
DisplayAreas:
DisplayArea{Root, type=0, featureId=0}
DisplayArea{WindowedMagnification, type=0, featureId=4}
DisplayArea{HideDisplayCutout, type=0, featureId=6}
...
TaskDisplayArea{DefaultTaskDisplayArea}
DisplayArea{WindowTokens, type=1, featureId=2}
DisplayArea{ImeContainer, type=0, featureId=8}
8.4 查看 WindowToken 结构
bash
adb shell dumpsys window tokens
输出:
bash
WindowToken{abc123 ActivityRecord{... u0 com.example.app/.Activity t123}}:
windows:
Window#0 Window{abc001 u0 com.example.app/com.example.Activity}:
windowType=2 hasVisible=true
8.5 查看指定应用窗口
javascript
adb shell dumpsys window windows | grep -A 20 "com.example.app"
8.6 查看 SurfaceFlinger 层级 (需 root)
bash
# 列出所有 Layer
adb shell dumpsys SurfaceFlinger --list
# 查看 Layer Z 值和父子关系
adb shell dumpsys SurfaceFlinger --children
输出:
bash
Layer 0xabc123 (com.example.app/com.example.Activity#0)
Z=15 parent=...
children:
Layer 0xabc124 (SurfaceView#0) Z=1
Layer 0xabc125 (PopupWindow#0) Z=2
8.7 常用诊断命令
bash
# 查看输入法窗口和目标
adb shell dumpsys window windows | grep -B1 -A5 "InputMethod"
# 查看 Toast 窗口
adb shell dumpsys window windows | grep -B1 -A5 "Toast"
# 所有应用窗口 (baseLayer=21000)
adb shell dumpsys window windows | grep "mBaseLayer=21000"
# 窗口动画状态
adb shell dumpsys window animator
# 窗口策略
adb shell dumpsys window policy
8.8 dumpsys 输出字段速查
| 字段 | 含义 | 计算方式 |
|---|---|---|
mBaseLayer |
基础层级值 | layer × 10000 + 1000 |
mSubLayer |
子窗口偏移 | getSubWindowLayerFromTypeLw() |
windowType |
窗口类型值 | WindowManager.LayoutParams.type |
mFrame |
窗口位置大小 | [left,top][right,bottom] |
mShown |
是否可见 | true/false |
9. 关键源码文件索引
| 文件 | 路径 | 职责 |
|---|---|---|
| WindowManagerPolicyConstants | frameworks/base/core/java/android/view/WindowManagerPolicyConstants.java |
层级常量 (TYPE_LAYER_MULTIPLIER 等) |
| WindowManagerPolicy | frameworks/base/services/core/java/com/android/server/policy/WindowManagerPolicy.java |
窗口类型→层级映射 |
| DisplayAreaOrganizer | frameworks/base/core/java/android/window/DisplayAreaOrganizer.java |
DisplayArea Feature ID 定义 |
| DisplayAreaPolicy | frameworks/base/services/core/java/com/android/server/wm/DisplayAreaPolicy.java |
DisplayArea 树构建策略 |
| WindowState | frameworks/base/services/core/java/com/android/server/wm/WindowState.java |
mBaseLayer/mSubLayer 计算, 子窗口层级 |
| WindowToken | frameworks/base/services/core/java/com/android/server/wm/WindowToken.java |
子窗口排序, 圆角覆盖层 |
| WindowContainer | frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java |
assignChildLayers/assignLayer 基类 |
| DisplayContent | frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java |
assignWindowLayers 入口, IME 相对层级 |