【Android关键流程】WMS的创建

文章目录

  • [WMS 及其成员](#WMS 及其成员)
    • [WMS 的职责](#WMS 的职责)
    • [WMS 的重要成员](#WMS 的重要成员)
  • [WMS 的创建过程](#WMS 的创建过程)

基于Android U

WMS 及其成员

WMS 的职责

  1. 窗口管理

WMS 是窗口的管理者,它负责窗口的启动、添加和删除,另外窗口的大小和层级也是由 WMS 进行管理的。窗口管理的核心成员有 DisplayContent、WindowToken 和 WindowState。

  1. 窗口动画

窗口间进行切换时,使用窗口动画可以显得更炫一些,窗口动画由 WMS 的动画子系统来负责,动画子系统的管理者为 WindowAnimator。

  1. 输入系统的中转站

通过对窗口的触摸从而产生触摸事件,InputManagerService(IMS)会对触摸事件进行处理,它会寻找一个最合适的窗口来处理触摸反馈信息,WMS 是窗口的管理者,它作为输入系统的中转站再合适不过了。

  1. 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() 方法。

  1. 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 的引用。

  1. 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,为了便于理解,下面给出这三个线程之间的关系。

从上图可以看出,三个线程之间的关系可以分为三个步骤来实现:

  1. 首先在 system_server 线程中执行了 SystemServer 的 startOtherServices() 方法,在 startOtherServices() 方法中会调用 WMS 的 main() 方法,main() 方法会创建 WMS,创建的过程在 android.display 线程中实现,创建 WMS 的优先级更高,因此 system_server 线程要等 WMS 创建完成后,处于等待状态的 system_server 线程才会被唤醒从而继续执行下面的代码。
  2. 在 WMS 的构造方法中会调用 WMS 的 initPolicy() 方法,在 initPolicy() 方法中又会调用 PWM.init() 方法,PWM 的 init() 方法在 android.ui 线程中运行,它的优先级要高于 android.display 线程,因此 android.display 线程要等 PWM 的 init() 方法执行完毕后,处于等待状态的 android.display 线程才会被唤醒从而继续执行下面的代码。
  3. PWM 的 init() 方法执行完毕后,android.display 线程就完成了 WMS 的创建,等待的 system_server 线程被唤醒后继续执行 WMS 的 main() 方法后的代码逻辑,比如 WMS 的 displayReady() 方法用来初始化屏幕显示信息(SystemServer 的 startOtherServices() 方法的注释8处)。
相关推荐
我是阿亮啊2 小时前
Android Handler 机制完全解析
android·handler·handler机制
STCNXPARM2 小时前
Android camera子系统概述
android·图像处理·摄像头·车载
牛马1112 小时前
flutter Riverpod 中的 overrideWith
android·java·flutter
2501_937193142 小时前
TV 电视影视大全:全终端流畅观影技术解析
android·源码·源代码管理·机顶盒
catchadmin2 小时前
PHP 现在可以零成本构建原生 iOS 和 Android 应用 NativePHP for Mobile v3 发布
android·ios·php
独自破碎E3 小时前
【回溯】二叉树的所有路径
android·java
安卓机器3 小时前
安卓玩机工具推荐------免root权限使用的 支持安卓4至安卓16系统的系统开源应用 推荐
android·反编译apk
summerkissyou19873 小时前
android-蓝牙-广播启动-startAdvertising和startAdvertisingSet区别
android·蓝牙
雪球Snowball3 小时前
【Android关键流程】Configuration变更时更新应用程序配置
android