Files
mkdocs/docs/学习笔记/Android WindowManagerService核心原理深度解析(专家第二次提示词).md
2026-02-28 01:44:55 +08:00

17 KiB
Raw Blame History

好的遵照您的指示我将基于您提供的详细提示词和搜索材料为您创作一份《Android WindowManagerService核心原理深度解析》培训课件。


Android WindowManagerService核心原理深度解析

目录

  1. 引言为什么需要深入理解WMS
  2. WMS概览与架构定位
    • 系统服务中的WMS
    • 核心概念定义 (Window Token, State)
    • WMS核心职责
  3. 窗口的生命周期管理
    • ViewRootImplWindowState的旅程
    • 关键流程序列图:添加窗口
    • 核心数据结构:WindowState 解析
  4. 布局、动画与Surface管理
    • 布局循环的核心:performSurfacePlacement
    • 窗口动画的管理者:WindowAnimator
    • Surface的申请与合成协调
  5. 输入事件的中转与分发
    • WMS作为IMS的中转站
    • 关键流程序列图:触摸事件分发
    • 命中测试Hit TestInputChannel
  6. 与关键系统服务的协同
    • WMS & AMSActivity状态与窗口的同步
    • WMS & SurfaceFlinger通过Transaction提交变更
    • UML简化类图核心协作关系
  7. 高级主题与案例分析(可选)
    • dumpsys window看窗口状态
    • 常见问题分析:窗口泄漏、事件丢失
  8. 总结与Q&A

1. 引言为什么需要深入理解WMS

各位同事,在日常开发中,我们面对的挑战往往不止于业务逻辑的实现。当遇到多窗口适配的诡异布局悬浮窗权限的反复横跳应用启动或转场时的莫名卡顿,甚至是触摸事件偶尔“灵异”丢失的问题时,我们是否感到束手无策,只能依靠试错或搜索碎片化的解决方案?

这些复杂UI场景和性能瓶颈的根源往往深藏在Android Framework的核心——WindowManagerServiceWMS 之中。WMS是Android图形系统的“总调度中心”和“交通警察”它管理者所有窗口的创建、布局、显示顺序以及它们与输入系统的交互。

本次培训旨在穿透API层面深入Framework核心系统性地揭示从应用视图请求最终像素显示的完整链路。我们将聚焦WMS在其中扮演的核心角色帮助大家建立起完整的窗口系统知识体系从而在面对疑难杂症时能够定位根因、精准施策

2. WMS概览与架构定位

2.1 系统服务中的WMS

WMS是System Server中最早启动的核心服务之一。它在SystemServer的startOtherServices方法中被创建和启动。

// frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
    // ...
    traceBeginAndSlog("StartWindowManagerService");
    // 注意WMS的main方法运行在"android.display"线程,优先级高于"system_server"线程
    wm = WindowManagerService.main(context, inputManager, ...);
    traceEnd();
    // ...
    // 将WMS和IMS注册到ServiceManager
    ServiceManager.addService(Context.WINDOW_SERVICE, wm);
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
    // ...
}

*代码示例WMS在SystemServer中的启动 *

WMS的启动涉及多线程同步system_server android.display, android.ui体现了其初始化对UI相关线程的优先级要求。

2.2 核心概念定义

在深入代码前,我们必须统一对以下几个核心抽象的理解:

  • Window(窗口):一个抽象的概念,不是实体,可以理解为绘制表面Surface 的载体或容器。每一个窗口都对应着一个用于绘制的Surface。在应用层,PhoneWindowWindow的唯一实现类。
  • WindowManager应用层与WMS通信的接口。它是一个Binder客户端应用通过它发送添加、删除窗口的请求。其实现类WindowManagerImpl将工作委托给单例的WindowManagerGlobal
  • View:窗口的实体表现形式。窗口的内容正是通过View树来填充和呈现的。可以说,Window是View的载体View是Window的内容
  • WindowToken:一个令牌。用于建立Binder通信的映射关系将一组相关的窗口例如同一个Activity的所有窗口包括主窗口和子窗口组织在一起。对于Activity它是AppWindowToken
  • WindowStateWMS内部用于描述一个窗口所有状态的真实对象。它保存了窗口的尺寸、位置、Z-order、是否可见、对应的SessionInputChannel等所有信息。它是WMS管理窗口的“活档案”。
  • DisplayContent:用于描述一块逻辑屏幕。它管理着显示在这个屏幕上的所有窗口的根层级。WMS通过DisplayContent来管理多屏(如双屏、折叠屏)的窗口。

2.3 WMS核心职责

  1. 窗口管理负责窗口的添加、删除、Z-order排序、焦点管理。
  2. Surface管理:作为“仲裁者”,为窗口分配Surface,并协调应用与SurfaceFlinger的关系。
  3. 窗口动画:管理所有窗口切换、移动时的动画效果。
  4. 输入事件中转:配合InputManagerService,将触摸或按键事件准确地分发给合适的窗口。

3. 窗口的生命周期管理

3.1 从ViewRootImplWindowState的旅程

以一个典型的Activity窗口创建为例看看它是如何被WMS纳入管理的。

核心流程序列图:添加窗口

sequenceDiagram
    participant App as 应用进程(UI Thread)
    participant ViewRoot as ViewRootImpl
    participant WMS as WindowManagerService
    participant SF as SurfaceFlinger

    App->>ViewRoot: 1. requestLayout()
    ViewRoot->>ViewRoot: 2. scheduleTraversals()
    ViewRoot->>WMS: 3. relayoutWindow() (Binder调用)
    Note over WMS: 4. 创建/获取Surface
    WMS->>SF: 5. createSurface() (通过SurfaceSession)
    SF-->>WMS: 返回SurfaceControl
    WMS-->>ViewRoot: 返回relayoutResult & Surface (Binder返回)
    Note over ViewRoot: 6. 将Surface保存到mSurface
    ViewRoot->>ViewRoot: 7. performMeasure/Layout/Draw
    ViewRoot->>SF: 8. 通过Canvas/Skia渲染到Surface的BufferQueue

关键步骤详解:

  1. 发起请求当View树需要布局时ViewRootImplrequestLayout被调用最终通过Binder调用进入WMS的relayoutWindow方法。
  2. WMS处理 (核心逻辑)
    • 权限与合法性检查WMS首先检查调用者的权限和窗口参数LayoutParams)是否合法。
    • 创建/获取WindowState如果是首次添加WMS会创建一个WindowState对象,并将其添加到全局的mWindowMap中,同时根据WindowToken建立层级关系。
    • Surface分配如果窗口需要新的绘图表面WMS会通过Session内部封装了与SurfaceFlinger的SurfaceSession连接)请求SurfaceFlinger创建一个Layer在WMS侧对应为SurfaceControl)。
  3. 返回与绘制WMS将分配好的Surface(实际上是SurfaceControl的句柄通过Binder返回给应用层的ViewRootImpl。应用层拿到Surface后,便可以开始渲染内容。

3.2 核心数据结构:WindowState 解析

WindowState是WMS中最重要的数据结构我们可以通过简化源码来理解其核心成员

// frameworks/base/services/core/java/com/android/server/wm/WindowState.java
class WindowState extends WindowContainer<WindowState> {
    // 指向持有该窗口的客户端Session (每个应用进程一个)
    final Session mSession;
    // 应用层 ViewRootImpl 的 W Binder对象用于向应用进程通信
    final IWindow mClient;
    // 与该窗口关联的窗口令牌 (如 AppWindowToken)
    final WindowToken mToken;
    // 窗口的布局参数 (x, y, width, height, type, flags...)
    final WindowManager.LayoutParams mAttrs;
    // 窗口所属的逻辑屏幕
    final DisplayContent mDisplayContent;
    // 窗口在WMS侧控制的Surface句柄用于设置位置、大小、层级等
    SurfaceControl mSurfaceControl;
    // 接收输入事件的通道
    InputChannel mInputChannel;
    // 窗口的帧大小和位置信息 (包含四个矩形:包含框架、内容框架、可见框架等)
    final Rect mFrame = new Rect();
    final Rect mContentFrame = new Rect();
    // 窗口当前的Z-order 值
    int mLayer;
    // ... 以及其他大量状态和方法
}

*代码示例WindowState核心成员变量 *

WindowState不仅保存了窗口的属性,其本身也参与到WindowContainer的层级管理中构成了WMS内部对窗口树的描述。

4. 布局、动画与Surface管理

4.1 布局循环的核心:performSurfacePlacement

WMS的核心工作引擎是performSurfacePlacement(旧称performLayoutAndPlaceSurfacesLocked)。这个方法会在窗口状态发生变化(如添加窗口、更改大小、动画更新)时被触发。

它的主要任务是遍历所有DisplayContent及其下的WindowState,计算每个窗口最终的位置、大小和Z-order。然后,它会将这些变更通过SurfaceControl.Transaction提交给SurfaceFlinger。

4.2 窗口动画的管理者:WindowAnimator

WMS内部有一个WindowAnimator对象,专门负责管理所有窗口动画。

  • 当一个窗口需要执行动画如启动、退出、旋转WMS会创建相应的动画对象MoveAnimation AlphaAnimation)。
  • WindowAnimator会定期在VSync信号驱动下更新动画状态并再次触发performSurfacePlacement,将动画过程中的新位置、透明度等属性通过Transaction设置给SurfaceFlinger从而实现流畅的动画效果。

4.3 Surface的申请与合成协调

WMS并不负责绘制它只负责**“布局”和“定序”**。

  • 应用侧Surface:由ViewRootImpl持有用于应用线程绘制UI。
  • WMS侧SurfaceControl:由WindowState持有用于WMS控制该窗口在屏幕上的最终呈现属性。
  • 与SurfaceFlinger的交互WMS通过一系列的Transaction,将窗口的位置、大小、旋转、透明度、Z-order等信息同步给SurfaceFlinger。SurfaceFlinger则根据这些信息将所有窗口的Surface图形缓冲区进行混合Compose最终输出到屏幕硬件。

5. 输入事件的中转与分发

5.1 WMS作为IMS的中转站

InputManagerServiceIMS负责从内核读取原始输入事件但它不知道这些事件该发给谁。这时WMS作为窗口的管理者就成为了理想的“导航员”。

5.2 关键流程序列图:触摸事件分发

sequenceDiagram
    participant IMS as InputManagerService
    participant WMS as WindowManagerService
    participant Dispatcher as InputDispatcher (Native)
    participant AppView as 目标窗口 (View)

    IMS->>Dispatcher: 1. 读取并派发事件
    Dispatcher->>WMS: 2. 查询目标窗口 (通过InputMonitor)
    WMS-->>Dispatcher: 3. 返回焦点窗口及其InputChannel
    Dispatcher->>Dispatcher: 4. 命中测试,确定目标
    Dispatcher->>AppView: 5. 通过InputChannel发送事件 (Socket)
    AppView->>AppView: 6. ViewRootImpl$WindowInputEventReceiver 处理
    AppView->>AppView: 7. 事件分发 (dispatchTouchEvent)

5.3 命中测试与InputChannel

  1. 建立通道:在窗口添加时(WMS.addWindow如果窗口需要接收输入WMS会为它创建一对InputChannel基于Socket。服务端的一端注册到IMS的InputDispatcher客户端的一端通过Binder返回给ViewRootImpl,并封装成WindowInputEventReceiver

    // WMS.addWindow 中创建InputChannel的片段
    if (outInputChannel != null && (attrs.inputFeatures & ...) == 0) {
        String name = win.makeInputChannelName();
        InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); // 创建Socket对
        win.setInputChannel(inputChannels[0]);
        inputChannels[1].transferTo(outInputChannel); // 将客户端Channel返回
        mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle); // 注册服务端Channel
    }
    

    *代码示例InputChannel的创建与注册 *

  2. 命中测试当IMS的InputDispatcher有事件到来时它会调用WMS通过InputMonitor获取当前所有窗口的信息Z-order、位置、焦点状态InputDispatcher执行命中测试找到最合适的窗口然后通过之前建立的Socket连接InputChannel)直接将事件发送给目标应用进程。

  3. 应用内处理:应用进程的WindowInputEventReceiver收到事件后,将其传递给ViewRootImpl,进而开始我们在应用层熟悉的View树事件分发流程。

6. 与关键系统服务的协同

6.1 WMS & AMS状态同步

AMS和WMS是一对紧密协作的“好基友”。以Activity启动为例

  1. AMS准备AMS在启动一个Activity时首先会调用WMS的addAppToken告诉WMS“我要启动一个Activity了这是它的令牌AppWindowToken”。WMS将其加入到mAppTokens列表中。
  2. WMS同步当Activity在应用进程创建完毕并通过ViewRootImpl请求添加窗口时WMS会通过AppWindowToken找到这个窗口属于哪个Activity并将其与已有的Token关联起来。
  3. 状态回调当窗口显示或隐藏时WMS也会回调AMS的方法通知它窗口的finishedStartingfinishedPausing等状态以便AMS继续执行生命周期的下一步。

6.2 UML简化类图核心协作关系

下图展示了WMS、AMS及其核心内部类与周边服务的关系有助于建立宏观印象。

classDiagram
    class WindowManagerService {
        - InputManagerService mInputManager
        - ActivityManagerService mActivityManager
        - WindowAnimator mAnimator
        - HashMap~IBinder, WindowState~ mWindowMap
        - ArrayList~AppWindowToken~ mAppTokens
        + addWindow()
        + relayoutWindow()
        + performSurfacePlacement()
    }

    class ActivityManagerService {
        + startActivity()
        + resumeTopActivity()
    }

    class InputManagerService {
        - InputDispatcher mDispatcher
        + registerInputChannel()
    }

    class SurfaceFlinger {
        + createSurface()
        + setTransaction()
    }

    class WindowState {
        - IWindow mClient
        - WindowToken mToken
        - SurfaceControl mSurfaceControl
        - InputChannel mInputChannel
    }

    class AppWindowToken {
        - IApplicationToken mAppToken
    }

    class DisplayContent {
        - int mDisplayId
        - WindowList mWindows
    }

    WindowManagerService --> ActivityManagerService : 持有引用
    WindowManagerService --> InputManagerService : 持有引用
    WindowManagerService --> SurfaceFlinger : Binder通信
    WindowManagerService *-- WindowAnimator
    WindowManagerService *-- WindowState : 管理 (mWindowMap)
    WindowManagerService *-- AppWindowToken : 管理 (mAppTokens)
    WindowManagerService *-- DisplayContent : 管理
    WindowState --> WindowToken
    AppWindowToken --|> WindowToken
    DisplayContent --> WindowState : 包含

7. 高级主题与案例分析(可选)

7.1 从dumpsys window看窗口状态

adb shell dumpsys window是我们调试窗口问题的利器。通过它,我们可以看到:

  • Display信息:当前有几个逻辑屏幕,分辨率如何。
  • Window Hierarchy:当前所有窗口的堆叠顺序,最上层的是焦点窗口。
  • WindowState详情每个窗口的包名、token、mSurfaceControl是否有效、mFrame坐标、mInputChannel状态等。
  • Focus:当前焦点窗口是哪个。

案例分析: 当遇到窗口无法显示时,可以通过dumpsys window查看对应WindowState是否存在。如果存在,检查mSurfaceControl是否有效如果不存在说明窗口添加失败可能是权限或token问题。

7.2 常见问题分析

  • 问题1悬浮窗无法显示或显示位置不对

    • 可能原因:未正确申请SYSTEM_ALERT_WINDOW权限LayoutParams中的type设置错误在Android 10+上,未对Display进行适配。
    • WMS视角:检查dumpsys window中该悬浮窗的WindowState是否存在,以及其mFramemAttrs.gravity是否符合预期。
  • 问题2触摸事件“被窃取”或无法传递到目标View

    • 可能原因:有其它窗口(如系统弹窗、输入法窗口)覆盖在目标窗口之上,但被设置为可触摸(FLAG_NOT_TOUCH_MODAL处理不当);焦点窗口不是你期望的那个。
    • WMS视角:通过dumpsys window查看Window Hierarchy确认Z-order的顺序。点击事件会首先发给Z-order最大的窗口。检查焦点窗口Focus是否正确。

8. 总结与Q&A

总结

WMS作为Android GUI系统的“大脑”其核心价值在于

  1. 集中管理:通过WindowStateWindowTokenDisplayContent,统一维护所有窗口的状态和层级。
  2. 协调调度:作为中心枢纽,协调应用进程的绘制请求(relayoutWindow、输入系统的派发请求命中测试以及SurfaceFlinger的合成请求Transaction)。
  3. 状态同步与AMS深度绑定确保Activity的生命周期与窗口的显示状态同步。

深入理解WMS不仅能帮助我们诊断疑难杂症更能让我们对整个Android系统的设计哲学有更深刻的体会。