文章目录
- [WMS 及其成员](#WMS 及其成员)
-
- [WMS 的职责](#WMS 的职责)
- [WMS 的重要成员](#WMS 的重要成员)
- [WMS 的创建过程](#WMS 的创建过程)
基于Android U
WMS 及其成员
WMS 的职责

- 窗口管理
WMS 是窗口的管理者,它负责窗口的启动、添加和删除,另外窗口的大小和层级也是由 WMS 进行管理的。窗口管理的核心成员有 DisplayContent、WindowToken 和 WindowState。
- 窗口动画
窗口间进行切换时,使用窗口动画可以显得更炫一些,窗口动画由 WMS 的动画子系统来负责,动画子系统的管理者为 WindowAnimator。
- 输入系统的中转站
通过对窗口的触摸从而产生触摸事件,InputManagerService(IMS)会对触摸事件进行处理,它会寻找一个最合适的窗口来处理触摸反馈信息,WMS 是窗口的管理者,它作为输入系统的中转站再合适不过了。
- Surface 管理
窗口并不具备绘制的功能,因此每个窗口都需要有一块 Surface 来供自己绘制,为每个窗口分配 Surface 是由 WMS 来完成的。
WMS 的重要成员
- mPolicy: WindowManagerPolicy
mPolicy 是 WindowManagerPolicy(WMP)类型的变量。WindowManagerPolicy 是窗口管理策略的接口类,用来定义一个窗口策略所要遵循的通用规范,并提供了 WindowManager 所有的特定的 UI 行为。它的具体实现类为 PhoneWindowManager,这个实现类在 WMS 创建时被创建。WMP 允许定制窗口层级和特殊窗口类型以及关键的调度和布局。
- mSessions: ArraySet
mSessions 是 ArraySet 类型的变量,元素类型为 Session,它主要用于进程间通信,其他的应用程序进程想要和 WMS 进程进行通信就需要经过 Session,并且每个应用程序进程都会对应一个 Session,WMS 保存这些 Session 用来记录所有向 WMS 提出窗口管理服务的客户端。
- mWindowMap: HashMap
mWindowMap 是 HashMap 类型的变量,用来保存 WMS 中各种窗口的集合。key 值的类型为 IBinder,value 值的类型为 WindowState。WindowState 用于保存窗口的信息,在 WMS 中它用来描述一个窗口。
- mResizingWindows: ArrayList
mResizingWindows 是 ArrayList 类型的变量,元素类型为 WindowState。mResizingWindows 是用来存储正在调整大小的窗口的列表。与 mResizingWindows 类型的还有 mForceRemoves、mDestroySurface 等,其中 mForceRemoves 是在内存耗尽时设置的,里面存有需要强制删除的窗口,mDestroySurface 里面存有需要被销毁的 Surface。
- mAnimator: WindowAnimator
mAnimator 是 WindowAnimator 类型的变量,用于管理窗口的动画以及特效动画。
- mH: H
mH 是 H 类型的变量,系统的 Handler 类,用于将任务加入到主线程的消息队列中,这样代码逻辑就会在主线程中执行。
- mInputManager: InputManagerService
mInputManager 是 InputManagerService 类型的变量,输入系统的管理者。InputManagerService(IMS)会对触摸事件进行处理,它会寻找一个最合适的窗口来处理触摸反馈信息,WMS 是窗口的管理者,因此 WMS 作为输入系统的中转站是再合适不过了。
WMS 的创建过程
WMS 是在 SystemServer 中创建的。
java
frameworks/base/services/java/com/android/server/SystemServer.java
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
...
t.traceBegin("StartWatchdog");
final Watchdog watchdog = Watchdog.getInstance(); // 1
watchdog.start();
mDumper.addDumpable(watchdog);
t.traceEnd();
...
t.traceBegin("InitWatchdog");
watchdog.init(mSystemContext, mActivityManagerService); // 2
t.traceEnd();
...
}
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
...
WindowManagerService wm = null;
...
InputManagerService inputManager = null;
...
try {
...
t.traceBegin("StartInputManagerService");
inputManager = new InputManagerService(context); // 3
t.traceEnd();
...
t.traceBegin("StartWindowManagerService");
// WMS needs sensor service ready
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);
wm = WindowManagerService.main(context, inputManager, !mFirstBoot,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager); // 4
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO); // 5
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL); // 6
t.traceEnd();
t.traceBegin("SetWindowManagerService");
mActivityManagerService.setWindowManager(wm);
t.traceEnd();
t.traceBegin("WindowManagerServiceOnInitReady");
wm.onInitReady(); // 7
t.traceEnd();
...
} catch (Throwable e) {
...
}
...
t.traceBegin("MakeDisplayReady");
try {
wm.displayReady(); // 8
} catch (Throwable e) {
...
}
t.traceEnd();
...
t.traceBegin("MakeWindowManagerServiceReady");
try {
wm.systemReady(); // 9
} catch (Throwable e) {
...
}
t.traceEnd();
...
}
注释1、2处分别得到 Watchdog 实例并对它进行初始化,Watchdog 用来监控系统的一些关键服务的运行状况。
注释3处创建了 IMS,并赋值给 IMS 类型的 inputManager 对象。
注释4处执行了 WMS 的 main() 方法,其内部会创建 WMS,需要注意的是 main() 方法其中一个传入的参数就是在注释3处创建的 IMS,WMS 是输入事件的中转站,其内部包含了 IMS 引用并不意外。WMS 的 main() 方法是运行在 SystemServer 的 run() 方法中的,换句话说就是运行在 "system_server" 线程中。
在注释5、6处分别将 WMS 和 IMS 注册到 ServiceManager 中,这样如果某个客户端想要使用 WMS,就需要先去 ServiceManager 中查询信息,然后根据信息与 WMS 所在的进程建立通信通路,客户端就可以使用 WMS 了。
注释7处用来初始化窗口管理策略的接口类,以及将 WMS 添加到 Watchdog 中。
注释8处用来初始化屏幕显示信息。
注释9处用来通知WMS,系统的初始化工作已经完成,其内部调用了 WindowManagerPolicy 的 systemReady() 方法。
- WindowManagerService.main()
java
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean showBootMsgs, WindowManagerPolicy policy,
ActivityTaskManagerService atm) {
return main(context, im, showBootMsgs, policy, atm, new DisplayWindowSettingsProvider(),
SurfaceControl.Transaction::new, SurfaceControl.Builder::new);
}
/**
* Creates and returns an instance of the WindowManagerService. This call allows the caller
* to override factories that can be used to stub native calls during test.
*/
@VisibleForTesting
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean showBootMsgs, WindowManagerPolicy policy, ActivityTaskManagerService atm,
DisplayWindowSettingsProvider displayWindowSettingsProvider,
Supplier<SurfaceControl.Transaction> transactionFactory,
Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
final WindowManagerService[] wms = new WindowManagerService[1];
DisplayThread.getHandler().runWithScissors(() -> // 1
wms[0] = new WindowManagerService(context, im, showBootMsgs, policy, atm,
displayWindowSettingsProvider, transactionFactory,
surfaceControlFactory), 0); // 2
return wms[0];
}
注释1处调用了 DisplayThread 的 getHandler() 方法,用来得到 DisplayThread 的 Handler 实例。DisplayThread 是一个单例的前台线程,这个线程用来处理需要低延时显示的相关操作,并只能由 WindowManager、DisplayManager 和 InputManager 实时执行快速操作。
注释2处创建了 WMS 的实例,这个过程运行在 Runnable 的 run() 方法中,而 Runnable 则传到了 DisplayThread 对应的 Handler 的 runWithScissors() 方法中,说明 WMS 的创建是运行在 android.display 线程中的。需要注意的是,runWithScissors() 方法的第二个参数传入的是0。
java
frameworks/base/core/java/android/os/Handler.java
public final boolean runWithScissors(@NonNull Runnable r, long timeout) {
if (r == null) {
throw new IllegalArgumentException("runnable must not be null");
}
if (timeout < 0) {
throw new IllegalArgumentException("timeout must be non-negative");
}
if (Looper.myLooper() == mLooper) { // 1
r.run();
return true;
}
BlockingRunnable br = new BlockingRunnable(r);
return br.postAndWait(this, timeout);
}
开头对传入的 Runnable 和 timeout 进行了判断,如果 Runnable 为 null 或者 timeout 小于0则抛出异常。在注释1处根据每个线程只有一个 Looper 的原理来判断当前的线程(system_server 线程)是否是 Handler 所指向的线程(android.display 线程),如果是则直接执行 Runnable 的 run() 方法,如果不是则调用 BlockingRunnable 的 postAndWait() 方法,并将当前线程的 Runnable 作为参数传进去,BlockingRunnable 是 Handler 的内部类。
java
frameworks/base/core/java/android/os/Handler.java
private static final class BlockingRunnable implements Runnable {
private final Runnable mTask;
private boolean mDone;
public BlockingRunnable(Runnable task) {
mTask = task;
}
@Override
public void run() {
try {
mTask.run(); // 1
} finally {
synchronized (this) {
mDone = true;
notifyAll();
}
}
}
public boolean postAndWait(Handler handler, long timeout) {
if (!handler.post(this)) { // 2
return false;
}
synchronized (this) {
if (timeout > 0) {
final long expirationTime = SystemClock.uptimeMillis() + timeout;
while (!mDone) {
long delay = expirationTime - SystemClock.uptimeMillis();
if (delay <= 0) {
return false; // timeout
}
try {
wait(delay);
} catch (InterruptedException ex) {
}
}
} else {
while (!mDone) {
try {
wait(); // 3
} catch (InterruptedException ex) {
}
}
}
}
return true;
}
}
在注释2处将当前的 BlockingRunnable 添加到 Handler 的任务队列中。前面的 runWithScissors() 方法的第二个参数为0,因此 timeout 等于0,这样如果 mDone 为 false 的话会一直调用注释3处的 wait() 方法使得当前线程(system_server 线程)进入等待状态,那么等待的是哪个线程呢?我们往上看,在注释1处执行了传入的 Runnable 的 run() 方法(运行在 android.display 线程),执行完毕后在 finally 代码块中将 mDone 设置为 true,并调用 notifyAll() 方法唤醒处于等待状态的线程,这样就不会继续调用注释3处的 wait() 方法。因此得出结论,system_server 线程等待的就是 android.display 线程,这是因为 android.display 线程内部执行了 WMS 的创建,而 WMS 的创建优先级要更高。
java
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
private WindowManagerService(Context context, InputManagerService inputManager,
boolean showBootMsgs, WindowManagerPolicy policy, ActivityTaskManagerService atm,
DisplayWindowSettingsProvider displayWindowSettingsProvider,
Supplier<SurfaceControl.Transaction> transactionFactory,
Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
...
mInputManager = inputManager; // 1
...
mAnimator = new WindowAnimator(this); // 2
...
mActivityManager = ActivityManager.getService(); // 3
...
}
注释1处用来保存传进来的 IMS,这样 WMS 就持有了 IMS 的引用。
注释2处创建了 WindowAnimator,它用于管理所有的窗口动画。
注释3处得到 AMS 实例,并赋值给 mActivityManager,这样 WMS 就持有了 AMS 的引用。
- WindowManagerService.onInitReady()
java
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public void onInitReady() {
initPolicy(); // 1
Watchdog.getInstance().addMonitor(this); // 2
...
}
注释1处初始化了窗口管理策略的接口类 WindowManagerPolicy(WMP),它用来定义一个窗口策略所要遵循的通用规范。
注释2处将自身也就是 WMS 通过 addMonitor() 方法添加到 Watchdog 中,Watchdog 用来监控系统的一些关键服务的运行状况(比如传入的 WMS 的运行状况),这些被监控的服务都会实现 Watchdog.Monitor 接口。Watchdog 每分钟都会对被监控的系统服务进行检查,如果被监控的系统出现了死锁,则会杀死 Watchdog 所在的进程,也就是 SystemServer 进程。
java
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
private void initPolicy() {
UiThread.getHandler().runWithScissors(new Runnable() {
public void run() {
WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
mPolicy.init(mContext, WindowManagerService.this); // 1
}
}, 0);
}
initPolicy() 方法和此前讲的 WMS 的 main() 方法的实现类似,在注释1处执行了 WMP 的 init() 方法,WMP 是一个接口,init() 方法具体在 PhoneWindowManager(PWM)中实现。PWM 的 init() 方法运行在 android.ui 线程中,它的优先级要高于 initPolicy() 方法所在的 android.display 线程,因此 android.display 线程要等 PWM 的 init() 方法执行完毕后,处于等待状态的 android.display 线程才会被唤醒从而继续执行下面的代码。
线程间关系
本文共提到了三个线程,分别是 system_server、android.display 和 android.ui,为了便于理解,下面给出这三个线程之间的关系。

从上图可以看出,三个线程之间的关系可以分为三个步骤来实现:
- 首先在 system_server 线程中执行了 SystemServer 的 startOtherServices() 方法,在 startOtherServices() 方法中会调用 WMS 的 main() 方法,main() 方法会创建 WMS,创建的过程在 android.display 线程中实现,创建 WMS 的优先级更高,因此 system_server 线程要等 WMS 创建完成后,处于等待状态的 system_server 线程才会被唤醒从而继续执行下面的代码。
- 在 WMS 的构造方法中会调用 WMS 的 initPolicy() 方法,在 initPolicy() 方法中又会调用 PWM.init() 方法,PWM 的 init() 方法在 android.ui 线程中运行,它的优先级要高于 android.display 线程,因此 android.display 线程要等 PWM 的 init() 方法执行完毕后,处于等待状态的 android.display 线程才会被唤醒从而继续执行下面的代码。
- PWM 的 init() 方法执行完毕后,android.display 线程就完成了 WMS 的创建,等待的 system_server 线程被唤醒后继续执行 WMS 的 main() 方法后的代码逻辑,比如 WMS 的 displayReady() 方法用来初始化屏幕显示信息(SystemServer 的 startOtherServices() 方法的注释8处)。