一,WMS简介:
WMS(WindowManagerService),是一项系统服务,位于应用框架层,由SystemServer创建,直到关机才会退出,遇到异常必须要重启。它负责管理窗口。功能如下:
-窗口的添加与删除:当某个进程由显示需求时,它可以请求WMS添加一个窗口,并于不再需要显示时移除该窗口
-启动窗口:当增了一个窗口时,在某些条件下需要添加一个启动窗口
-窗口动画:窗口切换时,采用窗口动画可以加强UI特效。可以定制
-窗口大小: Android系统支持显示不同大小的窗口,如StatusBar就只是屏幕最顶层的一条Bar,还有对话框,浮窗等
-窗口层级:由Z-Order决定,值越大,排序越靠后,会被值小的窗口盖住
-事件派发
二,WMS启动流程:
WMS与AMS一样,同样是由SystemServer启动,不同的是,WMS是在startOtherService()中启动的,
SystemServer.Java:
1. private void startOtherServices() {
2. WindowManagerService wm = null;
3. //...
4. traceBeginAndSlog("StartWindowManagerService");
5. // WMS needs sensor service ready
6. ConcurentUtils.waitForFutureNoInterrupt
7. (mSensorServiceStart,
8. START_SENSOR_SERVICE);
9. mSensorServiceStart = null;
10. // 1 创建 WMS,传入了system上下文、一个 inputManager对象、一个PhoneWindowManager 对象、atm对象
11. wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore, new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
12. // 2 发布 WMS到 SM
13. ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
14. DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
15. // 发布inputManagerService 到SM
16. ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
17. /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
18. traceEnd();
19.
20. traceBeginAndSlog("SetWindowManagerService");
21. // 3 让AMS持有 WMS的引用 ,方便后续调用
22. mActivityManagerService.setWindowManager(wm);
23.|
24. traceBeginAndSlog("WindowManagerServiceOnInitReady");
25. // 4 回调WMS的 onInitReady()方法
26. wm.onInitReady();
27.
28.
29. traceEnd();
30. // 5 回调WMS的
31. wm.displayReady();
32. // 6 回调WMS的
33. wm.systemReady();
34.
35. //...
36. }
只看WMS相关的内容:
1,传入参数,创建WMS对象;
2,让AMS持有WMS对象,方便以后调用;
3,回调onInitReady();
4,回调displayReady();
5,回调systemReady()。
接下来看一下WMS具体的创建流程:
WindowManagerService.Java:
1.public static WindowManagerService main(final Context context, final InputManagerService im, final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm) {
2. return main(context, im, showBootMsgs, onlyCore, policy, atm,
3. SurfaceControl.Transaction::new);
4.}
在上面的WindowManagerService.main()方法中继续调用另一个main()方法:
1.@VisibleForTesting
2.public static WindowManagerService main(final Context context, final InputManagerService im,final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
3. // runnable 提交到 DisplayThread 线程
4. DisplayThread.getHandler().runWithScissors(() ->
5. sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
6. atm, transactionFactory), 0);
7. return sInstance;
8.}
DisplayThread线程名为android.display,调用Handler.runWithScissors()方法,创建一个WMS实例并返回,此时仍在SystemServer主线程中。
Handler.runWithScissors():
1.public final boolean runWithScissors(@NonNull Runnable r, long timeout) {
2. if (r == null) {
3. throw new IllegalArgumentException("runnable must not be null");
4. }
5. if (timeout < 0) {
6. throw new IllegalArgumentException("timeout must be non-negative");
7. }
8. // 如果当前looper与当前handler一样
9. if (Looper.myLooper() == mLooper) {
10. r.run();
11. return true;
12. }
13. // 不一样,则新建 BlockingRunnable对象
14. BlockingRunnable br = new BlockingRunnable(r);
15. return br.postAndWait(this, timeout);
16.}
因为一个线程中只有一个Looper实例,因此上述代码实则判定线程是否一致,Looper.myLooper()得到的是SystemServer主线程的Looper实例,而方法的调用者是DisplayThread.Handler,因此不一致,会新建一个BlockingRunnable对象并post到Handler所在的线程(DispalyThread)并wait(),主线程陷入等待。
1.private static final class BlockingRunnable implements Runnable {
2. private final Runnable mTask;
3. private boolean mDone;
4.
5. public BlockingRunnable(Runnable task) {
6. mTask = task;
7. }
8. @Override
9. public void run() {
10. try {
11. mTask.run();
12. } finally {
13. synchronized (this) {
14. mDone = true;
15. // 唤醒 system server主线程
16. notifyAll();
17. }
18. }
19. }
20. ......
21.}
等run()方法执行后再唤醒主线程,因为WMS是非常重要的服务,必须等WMS初始化完成后才能继续执行后续操作。
至此WMS完成了创建并注册。
启动及注册流程总结:
· system server主线程开始执行,准备创建 WMS 对象
· system server主线程进入wait(),等待 android.display线程去创建WMS对象,因此,WMS中的 mH 发送的消息都在该线程处理。
· 唤醒system server主线程,将WMS注册到ServiceManager,然后继续执行onInitReady()方法
· system server主线程进入wait(),切换到 android.ui线程 ,PhoneWindowManager.init()执行完毕
· 唤醒system server主线程,继续执行后续代码。