AOSP15 WMS/AMS系统开发 - 窗口层级源码分析

基于 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 相对层级
相关推荐
whuhewei2 小时前
HTTP1/2/3演变
前端·计算机网络
腹黑天蝎座2 小时前
从零实现一个前端监控系统:性能、错误与用户行为全方位监控
前端·监控
Hooray3 小时前
为了在 Vue 项目里用上想要的 React 组件,我写了这个 skill
前端·ai编程
咸鱼翻身了么3 小时前
模仿ai数据流 开箱即用
前端
风花雪月_3 小时前
🔥IntersectionObserver:前端性能优化的“隐形监工”
前端
Bigger3 小时前
告别 AI 塑料感:我是如何用 frontend-design skill 重塑项目官网的
前端·ai编程·trae
发际线向北3 小时前
0x02 Android DI 框架解析之Hilt
前端
zhensherlock3 小时前
Protocol Launcher 系列:Overcast 一键订阅播客
前端·javascript·typescript·node.js·自动化·github·js
liangdabiao3 小时前
开源AI拼豆大升级 - 一键部署cloudflare page - 全免费 web和小程序
前端·人工智能·小程序