本文深入解析 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 启动涉及三个关键线程:
- system_server 主线程:启动入口,调用
WMS.main()触发初始化。 - android.display 线程:执行 WMS 构造函数,负责显示相关初始化(如 Surface、多屏)。
- 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 启动的 “三步曲”
-
线程与服务创建:
- 在 android.display 线程创建 WMS 实例,关联 IMS 和显示管理。
- 通过跨线程同步初始化
PhoneWindowManager策略。
-
显示与策略配置:
- 初始化多屏支持,配置默认显示参数。
- 启动锁屏、系统手势等核心功能。
-
系统就绪:
完成所有初始化,通知 AMS 更新配置,进入可交互状态。
关键意义:
WMS 的启动是 Android 系统图形界面可用的前提,其线程管理和策略初始化确保了窗口布局、输入响应和动画渲染的稳定性。理解其启动流程有助于分析窗口显示异常、输入延迟等系统级问题。