Android 系统架构 —— WMS 的启动

 

前言

之前的文章介绍了 IMS 的启动过程, 也了解了 IMS 的事件分发与窗体是息息相关的, 这里我们就来学习一下 WMS 的启动流程

public final class SystemServer {

    private void startOtherServices() {
        ......
        WindowManagerService wm = null;
        ......
        InputManagerService inputManager = null;
        try {
            ......
            // 1. 创建 WMS
            wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore, new PhoneWindowManager());
            // 发布到 ServiceManager 中
            ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
            ......
            // 2. 准备初始化
            wm.onInitReady();
            
            // 3. 调用 displayReady 准备显示
            wm.displayReady();
            ......
            // 4. 调用 systemReady
            wm.systemReady();
        }
        ......
    }
    
}

WindowManagerService 的启动流程如同上述所示, 我们这里主要从以下几个方面来分析

  • WMS 的创建
  • onInitReady
  • displayReady
  • systemReady

一. WMS 的创建

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    
    private static WindowManagerService sInstance;
    
    public static WindowManagerService main(final Context context, final InputManagerService im,
            final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
            WindowManagerPolicy policy) {
        // 在 DisplayThread 中创建 WMS
        DisplayThread.getHandler().runWithScissors(() ->
                // 调用了 WMS 的构造函数, 为静态成员变量 sInstance 赋值
                sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
                        onlyCore, policy), 0);
        return sInstance;
    }
            
}

这里的构建过程非常有意思, 它调用了 DisplayThread 线程的 getHandler 的 runWithScissors 方法, 我们知道 DisplayThread 在 IMS 构建时便会创建

这个 Handler 绑定的是 DisplayThread 的 Looper, 我们看看 Handler.runWithScissors 操作

Handler.runWithScissors

public class Handler {

    public final boolean runWithScissors(final Runnable r, long timeout) {
        ......
        // 若当前线程的 Looper 与 Handler 的绑定的 Looper 相同, 则直接执行
        if (Looper.myLooper() == mLooper) {
            r.run();
            return true;
        }
        // 包装成 BlockingRunnable
        BlockingRunnable br = new BlockingRunnable(r);
        // 调用 postAndWait
        return br.postAndWait(this, timeout);
    }
    
    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();
            } finally {
                // 3. 唤醒 postAndWait 中的阻塞
                synchronized (this) {
                    mDone = true;
                    notifyAll();
                }
            }
        }
        
        public boolean postAndWait(Handler handler, long timeout) {
            // 1. 投递到 Handler 绑定 Looper 的消息队列中执行
            if (!handler.post(this)) {
                return false;
            }
            synchronized (this) {
                // 由传参可只 timeout 为 0
                if (timeout > 0) {
                   ......
                } else {
                    // 2. 使用并发管程模型, 等待 mTask 完成
                    while (!mDone) {
                        try {
                            wait();
                        } catch (InterruptedException ex) {
                        }
                    }
                }
            }
            return true;
        }
    }
    
}

好的, Handler 的 runWithScissors 做了如下的操作

  • 当前处于 Handler 的 Looper 绑定的线程, 则直接回调 run 方法, 如同同步代码
  • 当前非 Handler 的 Looper 绑定的线程, 则通过 postAndWait 投递到 DisplayThread 中进行初始化
    • 使用并发管程模型的阻塞唤醒机制, 保证代码的串行

当 runWithScissors 执行完成之后, sInstance 就已经被 WMS 赋值了, 使用 Handler 大费周折的操作的意义是什么呢?

  • 这保证了 WMS 在 DisplayThread 线程中创建

下面我们看看 WMS 的构造流程

WMS 的构造

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {

    // 窗体动画
    final WindowAnimator mAnimator;
    // 所有窗体的根容器    
    RootWindowContainer mRoot;
    // 窗体管理策略
    final WindowManagerPolicy mPolicy;
    
    private WindowManagerService(Context context, InputManagerService inputManager,
            boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
            WindowManagerPolicy policy) {
        ......
        mContext = context;
        ......
        // 保存 IMS
        mInputManager = inputManager;
        ....
        // 保存 PhoneWindowManager
        mPolicy = policy;
        // 窗体动画控制器
        mAnimator = new WindowAnimator(this);
        // 初始化根容器
        mRoot = new RootWindowContainer(this);
        ......
        // DMS
        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
        // PMS
        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
        ......
        // AMS
        mActivityManager = ActivityManager.getService();
        ......
    }   
}

在 WMS 的构建中, 创建了一些核心对象

  • mInputManager: IMS
  • mPolicy: 窗体管理策略, 实现类为 PhoneWindowManager
  • WindowAnimator mAnimator: 窗体动画
  • RootWindowContainer mRoot: Window 的根容器
  • mDisplayManager: 显示管理者
  • mActivityManager: AMS

WMS 的构造中关联的数据对象非常多, 这里笔者只列出常见的一些, 关于他们的作用, 到后面应用进程与 WMS 交互时再具体分析

下面我们看看 onInitReady 中做了什么操作

二. WMS.onInitReady

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
   
    public void onInitReady() {
        // 初始化管理策略
        initPolicy();
        ......
    }
    
    private void initPolicy() {
        UiThread.getHandler().runWithScissors(new Runnable() {
            @Override
            public void run() {
                WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
                // 调用 PhoneWindowManager 的初始化方法
                mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
            }
        }, 0);
    }
}

onInitReady 方法中执行了初始化管理策略的操作, mPolicy 的初始化操作在 UiThread 中进行, 下面看看 PhoneWindowManager 的 init 中做了什么处理

public class PhoneWindowManager implements WindowManagerPolicy {
    
    @Override
    public void init(Context context, IWindowManager windowManager,
            WindowManagerFuncs windowManagerFuncs) {
        mContext = context;
        mWindowManager = windowManager;
        mWindowManagerFuncs = windowManagerFuncs;
        // 这个 Handler 运行在 UiThread 上
        mHandler = new PolicyHandler();
        ......
        mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
        mOrientationListener = new MyOrientationListener(mContext, mHandler);
        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
        mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                "PhoneWindowManager.mBroadcastWakeLock");
        mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                "PhoneWindowManager.mPowerKeyWakeLock");
        ......
        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
                Context.ACCESSIBILITY_SERVICE);
        mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
        ......
        mWindowManagerInternal.registerAppTransitionListener(......);
    }
}

PhoneWindowManager.init 中需要注意的是, 它创建一个 PolicyHandler, 因为 init 在 UiThread 的下执行, 所以这个 PolicyHandler 绑定的也是 UIThread 的 Looper

三. WMS.displayReady

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
        
    public void displayReady() {
        final int displayCount = mRoot.mChildren.size();
        // 1. 初始化 RootWindowContainer 的子窗体
        for (int i = 0; i < displayCount; ++i) {
            // 获取 DisplayContent 这也是一个 WindowContainer 的实现类, 描述一个窗体
            final DisplayContent display = mRoot.mChildren.get(i);
            // 1.1 初始化子窗体
            displayReady(display.getDisplayId());
        }
        synchronized(mWindowMap) {
            //2. 获取默认的窗体
            final DisplayContent displayContent = getDefaultDisplayContentLocked();
            // 2.1 设置 UI 的最大宽度
            if (mMaxUiWidth > 0) {
                displayContent.setMaxUiWidth(mMaxUiWidth);
            }
            // 2.2 表示窗体已经初始化完毕
            mDisplayReady = true;
        }
        ......
    }

    private void displayReady(int displayId) {
        synchronized(mWindowMap) {
            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
            if (displayContent != null) {
                ......
                // 1.2 初始化窗体的信息
                displayContent.initializeDisplayBaseInfo();
                ......
            }
        }
    }
    
}

displayReady 中主要任务如下

  • 遍历并且初始化 RootWindowContainer 中的子窗体
    • 调用子窗体的 initializeDisplayBaseInfo 执行初始化操作
  • 初始化默认窗体
    • 设置最大的 UI 宽度
    • 更新 flag 表示初始化完毕

四. WMS.systemReady

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
        
    public void systemReady() {
        mPolicy.systemReady();
        ......
    }
    
}

WindowManagerService 的 systemReady 操作转发到了 PhoneWindowManager 中处理

public class PhoneWindowManager implements WindowManagerPolicy {

    @Override
    public void systemReady() {
        // In normal flow, systemReady is called before other system services are ready.
        // So it is better not to bind keyguard here.
        mKeyguardDelegate.onSystemReady();

        mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
        if (mVrManagerInternal != null) {
            mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
        }

        readCameraLensCoverState();
        updateUiMode();
        synchronized (mLock) {
            updateOrientationListenerLp();
            mSystemReady = true;
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    updateSettings();
                }
            });
            // If this happens, for whatever reason, systemReady came later than systemBooted.
            // And keyguard should be already bound from systemBooted
            if (mSystemBooted) {
                mKeyguardDelegate.onBootCompleted();
            }
        }

        mSystemGestures.systemReady();
        mImmersiveModeConfirmation.systemReady();

        mAutofillManagerInternal = LocalServices.getService(AutofillManagerInternal.class);
    }
    
}

到这里 WMS 的 systemReady 就执行完毕了

总结

WMS 的启动流程如下

  • WMS 的创建
    • 在 DisplayThread 执行创建操作
  • WMS.onInitReady
    • 执行了 PhoneWindowManager 的初始化
  • WMS.displayReady
    • 初始化 RootWindowContainer 子窗体
  • WMS.systemReady
    • 执行了 PhoneWindowManager 的初始化

比起前面的 AMS 和 IMS, WMS 的启动流程看起来感觉就有些过于简单了, 不过启动流程简单不代表背后的实现一样简单

关于 WMS 的更多的操作, 我们到应用窗体架构中再进行分析