WMS之启动过程

222 阅读5分钟

本文深入解析 Android 窗口管理服务(WMS, WindowManagerService)的启动过程,结合 Android源码阐述其核心流程、线程协作及关键类的初始化逻辑,适合理解 Android 系统窗口管理的底层机制。

一、WMS 的核心定位:窗口管理的 “指挥中心”

WMS 是 Android 系统的核心服务之一,负责管理所有窗口的生命周期、布局、层级(Z 轴排序)及显示逻辑。其核心职责包括:

  • Surface 管理:为每个窗口创建画布(Surface),协调 SurfaceFlinger 进行屏幕渲染。
  • 窗口策略:通过PhoneWindowManager实现窗口相关策略(如锁屏、旋转、权限控制)。
  • 多屏支持:管理多显示器输出,如主屏幕、投影屏幕等。
  • 输入系统协作:与InputManagerService(IMS)交互,确定焦点窗口以分发输入事件。

关键类关系

  • WMS:继承自IWindowManager.Stub,作为 Binder 服务端,通过Session与应用进程通信。
  • Session:继承自IWindowSession.Stub,每个应用进程对应一个 Session,负责窗口添加 / 更新 / 删除请求。
  • WindowState:代表一个窗口,记录窗口属性(如位置、大小、可见性),存储于mWindowMap
  • PhoneWindowManager:实现WindowManagerPolicy,处理窗口策略(如按键拦截、锁屏逻辑)。

二、启动流程:从系统服务到线程初始化

WMS 的启动伴随system_server进程启动,核心步骤如下:

1. 入口:system_server 调用 WMS.main ()

java

// SystemServer.java
private void startOtherServices() {
    // 初始化WMS,传入InputManagerService(IMS)
    WindowManagerService wm = WindowManagerService.main(context, inputManager, ...);
    wm.displayReady(); // 显示准备
    wm.systemReady(); // 系统就绪
}

2. WMS.main ():创建 WMS 实例(android.display 线程)

java

// WindowManagerService.java
public static WindowManagerService main(Context context, InputManagerService im, ...) {
    // 在"android.display"线程中创建WMS实例
    DisplayThread.getHandler().runWithScissors(() -> {
        holder[0] = new WindowManagerService(context, im, ...);
    }, 0);
    return holder[0];
}
  • 线程说明
    DisplayThread是 Android 的专用线程(名称为 "android.display"),负责处理显示相关任务(如窗口动画、VSYNC 信号)。

3. WMS 构造函数:核心初始化

java

private WindowManagerService(Context context, InputManagerService inputManager, ...) {
    mContext = context;
    mInputManager = inputManager; // 关联输入管理服务
    mDisplayManager = context.getSystemService(DisplayManager.class); // 多屏管理
    mFxSession = new SurfaceSession(); // 创建Surface会话,管理Surface内存

    // 初始化多屏支持,为每个物理/虚拟屏幕创建DisplayContent
    for (Display display : mDisplays) {
        createDisplayContentLocked(display); // 保存到mDisplayContents
    }

    mAnimator = new WindowAnimator(this); // 窗口动画控制器
    initPolicy(); // 初始化窗口策略(关键步骤)
}

4. 初始化窗口策略:initPolicy ()

java

private void initPolicy() {
    // 在"android.ui"线程中执行策略初始化(同步阻塞)
    UiThread.getHandler().runWithScissors(() -> {
        mPolicy = new PhoneWindowManager(); // 实例化为PhoneWindowManager
        mPolicy.init(mContext, this, this); // 初始化策略,设置按键监听、电源管理等
    }, 0);
}
  • 线程协作
    runWithScissors确保PhoneWindowManager.init()在 "android.ui" 线程执行,当前线程(android.display)会阻塞等待其完成,保证策略初始化的顺序性。

5. 显示准备:displayReady ()

java

public void displayReady() {
    for (Display display : mDisplays) {
        displayReady(display.getDisplayId()); // 配置每个显示器
    }
    configureDisplayPolicyLocked(); // 设置默认显示策略(如触控支持、方向)
    mActivityManager.updateConfiguration(); // 通知AMS更新配置
}
  • 作用:完成显示器初始化,读取显示属性(如分辨率、方向),为窗口显示做准备。

6. 系统就绪:systemReady ()

java

public void systemReady() {
    mPolicy.systemReady(); // 策略层就绪,初始化锁屏、系统手势等
    mKeyguardDelegate.bindService(); // 绑定锁屏服务
    mSystemGestures.systemReady(); // 初始化系统手势(如返回、Home键)
}
  • 关键动作:启动锁屏服务、配置系统手势,确保用户交互可用。

三、线程协作:三线程的同步与阻塞

WMS 启动涉及三个关键线程:

  1. system_server 主线程:启动入口,调用WMS.main()触发初始化。
  2. android.display 线程:执行 WMS 构造函数,负责显示相关初始化(如 Surface、多屏)。
  3. android.ui 线程:执行窗口策略初始化(PhoneWindowManager.init()),处理 UI 相关逻辑(如按键响应)。

同步机制:Handler.runWithScissors

java

// Handler.java
public final boolean runWithScissors(Runnable r, long timeout) {
    if (当前线程与Handler同属一个Looper) {
        r.run(); // 直接执行
    } else {
        // 跨线程时,通过BlockingRunnable阻塞当前线程,直到目标线程执行完毕
        BlockingRunnable br = new BlockingRunnable(r);
        br.postAndWait(handler, timeout); // 等待目标线程完成
    }
}
  • 应用场景
    在 android.display 线程中调用initPolicy()时,通过runWithScissors将任务提交到 android.ui 线程执行,并阻塞等待,确保策略初始化完成后再继续 WMS 启动流程。

四、核心类初始化细节

1. SurfaceSession 与 Surface 管理

  • SurfaceSession:管理 Surface 的内存分配与释放,通过 Binder 与 SurfaceFlinger 通信。
  • 作用:每个 WMS 实例创建一个SurfaceSession,应用窗口的 Surface 通过该会话创建,确保图形资源的有序管理。

2. DisplayContent 与多屏支持

  • DisplayContent:代表一个显示器(如主屏幕、HDMI 外接屏),存储其显示属性(分辨率、密度)和窗口列表。
  • 创建时机:WMS 构造函数中遍历所有显示器,为每个创建DisplayContent,保存到mDisplayContents

3. PhoneWindowManager:策略核心

  • 职责

    • 处理按键事件(如电源键、音量键)。
    • 管理锁屏状态(Keyguard)。
    • 窗口层级策略(如系统窗口始终在顶层)。
  • 初始化步骤

    java

    public void init(Context context, IWindowManager wm, WindowManagerFuncs funcs) {
        mHandler = new PolicyHandler(); // 运行在android.ui线程
        mWakeGestureListener = new MyWakeGestureListener(); // 唤醒手势监听
        mPowerManager = context.getSystemService(PowerManager.class); // 电源管理
    }
    

五、总结:WMS 启动的 “三步曲”

  1. 线程与服务创建

    • 在 android.display 线程创建 WMS 实例,关联 IMS 和显示管理。
    • 通过跨线程同步初始化PhoneWindowManager策略。
  2. 显示与策略配置

    • 初始化多屏支持,配置默认显示参数。
    • 启动锁屏、系统手势等核心功能。
  3. 系统就绪
    完成所有初始化,通知 AMS 更新配置,进入可交互状态。

关键意义

WMS 的启动是 Android 系统图形界面可用的前提,其线程管理和策略初始化确保了窗口布局、输入响应和动画渲染的稳定性。理解其启动流程有助于分析窗口显示异常、输入延迟等系统级问题。