理解 WindowManagerService
WMS 的职责
WMS 是 Android 中重要的服务,它是 WindowManager 的管理者,除此之外,它还有很多重要的职责,每个职责都会涉及重要且复杂的系统。
窗口管理
WMS 是窗口的管理者,它负责窗口的启动、添加和删除,另外窗口的大小和层级也是由 WMS 进行管理的。窗口管理的核心成员有 DisplayContent、WindowToken 和 WindowState。
窗口动画
窗口间进行切换时,使用窗口动画可以显得更炫一些,窗口动画由 WMS 的动画子系统来负责,动画子系统的管理者为 WindowAnimator。
输入系统的中转站
通过对窗口的触摸从而产生触摸事件,InputManagerService(IMS)会对触摸事件进行处理,它会寻找一个最合适的窗口来处理触摸反馈信息,WMS 是窗口的管理者,它作为输入系统的中转站再合适不过了。
Surface 管理
窗口并不具备绘制的能力,因此每个窗口都需要有一块 Surface 来供自己绘制,为每个窗口分配 Surface 是由 WMS 来完成的。
从 WMS 的职责可以看出 WMS 很复杂,与它关联的有窗口管理、
窗口动画、输入系统和 Surface,它们每一个都是重要且复杂的系统,本章只介绍其中的窗口管理,因为它和应用开发的关联比较紧密。
WMS 的创建过程
WMS 是在 SystemServer 进程中创建的,先查看 SystemServer 的 main 方法。SystemServer.java
1 | public static void main(String[] args) { |
1 | private void run() { |
WMS 就是其他服务的一种,查看 startOtherServices 方法中是如何启动 WMS 的。
1 | /** |
接下来查看 WMS 的 main 方法。WindowManagerService.java
1 | public static WindowManagerService main(final Context context, final InputManagerService im, |
接下来查看 Handler 的 runWithScissors 方法。Handler.java
1 | public final boolean runWithScissors(final Runnable r, long timeout) { |
1 | private static final class BlockingRunnable implements Runnable { |
WMS 的创建就到这里。最后查看 WMS 的构造方法。WindowManagerService.java
1 | private WindowManagerService(Context context, InputManagerService inputManager, |
1 | private void initPolicy() { |
三个线程之间的关系分为三个步骤来实现:
- 首先在 system_server 线程中执行了 SystemServer 的 startOtherService 方法,在 startOtherService 方法中会调用 WMS 的 main 方法,main 方法会创建 WMS,创建的过程在 android.display 线程中实现,创建 WMS 的优先级更高,因此 system_server 线程要等 WMS 创建完成后,处于等待状态的 system_server 线程才会被唤醒从而继续执行下面的代码。
- 在 WMS 的构造方法中会调用 WMS 的 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 方法用来初始化屏幕显示信息。
##
WMS 的重要成员
WMS 的部分成员变量如下:WindowManagerService.java
1 | // WMP 类型变量。WMP 是窗口管理策略的接口类,用来定义一个窗口策略索要遵循的通用规范,并提供了 WindowManager 所有的特定的 UI 行为。它的具体实现类为 PhoneWindowManager,这个实现类在 WMS 创建时被创建。WMP 允许定制窗口层级和特殊窗口类型以及关键的调度和布局。 |
Window 的添加过程
Window 的操作分为两大部分,WindowManager 处理部分和 WMS 处理部分,接下来看 WMS 处理部分。无论是系统窗口还是 Activity,它们的 Window 的添加过程都会调用 WMS 的 addWindow 方法:WindowManagerService.java
1 | /** |
addView 方法总结:主要做了如下 4 件事
- 对所要添加的窗口进行检查,如果窗口不满足一些条件,就不会再执行下面的代码逻辑。
- WindowToken 相关的处理,比如有的窗口类型需要提供 WindowToken,没有提供的话就不会执行下面的代码逻辑,有的窗口类型则需要由 WMS 隐式创建 WindowToken。
- WindowState 的创建和相关处理,将 WindowToken 和 WindowState 相关联。
- 创建和配置 DisplayContent,完成窗口添加到系统前的准备工作。
Window 的删除过程
为了表述的更易于理解,下面将要删除的 Window(View)简称为 V。从 WindowManagerGlobal 的 removeView 方法开始查看。WindowManagerGlobal.java
1 | public void removeView(View view, boolean immediate) { |
1 | private void removeViewLocked(int index, boolean immediate) { |
查看 ViewRootImpl 的 die 方法。ViewRootImpl.java
1 | boolean die(boolean immediate) { |
1 | void doDie() { |
查看 WindowManagerGlobal 的 doRemoveView 方法。WindowManagerGlobal.java
1 | void doRemoveView(ViewRootImpl root) { |
查看 ViewRootImpl 的 doDie 方法中的 dispatchDetachedFromWindow 方法。ViewRootImpl.java
1 | void dispatchDetachedFromWindow() { |
查看 Session 的 remove 方法。Session.java
1 | public void remove(IWindow window) { |
接着查看 WMS 的 removeWindow 方法。WindowManagerService.java
1 | void removeWindow(Session session, IWindow client) { |
查看 WindowState 的 removeIfPossible 方法。WindowState.java
1 |
|
1 | private void removeIfPossible(boolean keepVisibleDeadWindow) { |
1 |
|
Window 的删除过程可以简单地总结为以下 4 点:
- 检查删除线程的正确性,如果不正确就抛出异常。
- 从 ViewRootImpl 列表、布局参数列表和 View 列表中删除与 V 对应的元素。
- 判断是否可以直接执行删除操作,如果不能就推迟删除操作。
- 执行删除操作,清理和释放与 V 相关的一切资源。
备注
注:基于 Android 8.0 版本源码
参考资料: