美文网首页
Android WindowManagerService--03

Android WindowManagerService--03

作者: DarcyZhou | 来源:发表于2023-11-08 08:10 被阅读0次

    本文转载自:Android R WindowManagerService模块(1) WMS整体架构及启动过程

    本文基于Android 11.0源码分析

    前言

      Android系统中,WindowManagerService(以下简称WMS)负责一切窗口的管理,窗口可以理解为屏幕上的各种显示区域,如状态栏、Activity、锁屏等对于WMS来说,都是一个具体的窗口实例。从这篇文章开始,将会对WindowManagerService模块进行整理总结。WMS的职责可以简单总结为下图:

    WMS04.PNG

    1.WMS架构

      在WindowManagerService中,以容器+树结构的形式对窗口进行管理,最顶层容器为ConfigurationContainer,它是所有容器的父容器,各个容器继承关系如下:

    WMS05.PNG

    上图中包含了WMS中的所有容器,各个子容器含义如下:

    1. ConfigurationContainer:最顶层容器,定义了多个Configuration对象,以及提供了用来组织各容器层级的公共逻辑;

    2. WindowProcessController:用于和AMS中的ProcessRecord进行通讯,当ProcessRecord中对应用进程作出调整后,通过WindowProcessController和WM进行通信;

    3. WindowContainer:作为可以保存窗口类的父类,定义了用于操作窗口的所有公共方法;

    4. RootWindowContainer:窗口容器在树结构中的根节点;

    5. DisplayContent:作为RootWindowContainer的子节点,用于管理同一个逻辑屏的窗口;

    6. DisplayChildWindowContainer:DisplayContent中的所有子节点的父类;

    7. NonAppWindowContainers:继承于DisplayChildWindowContainer,主要保存非来自应用的WindowToken;

    8. WindowContainers:只包含一个子节点——DisplayArea.Root,大部门窗口都会保存在这个容器中;

    9. DisplayArea:用于对DisplayContent中的节点进行分组管理,主要分为了三类;

    10. DisplayArea.Root:DisplayArea的子类,该容器作为DisplayContent中最顶层的显示区域,用来保存Tokens、TaskDisplayArea、ImeContainer容器;

    11. TaskDisplayArea:DisplayArea的子类,此类容器用于管理Task;

    12. TaskDisplayArea.Tokens:DisplayArea的子类,该容器用来保存正常窗口的WindowToken;

    13. ImeContainer:Tokens的子类,该容器用来保存IME窗口的WindowToken;

    14. Task:用来保存ActivityRecord,即我们常说的"任务";

    15. ActivityStack:Task的子类,用来管理处于同一个栈的Activity,特殊栈可以保存Task;

    16. WindowToken:用来管理窗口,多个窗口可以被一个WindowToken进行管理;

    17. ActivityRecord:继承于WindowToken,表示ActivityStack中的一个Activity实例;

    18. WallpaperWindowToken:继承于WindowToken,壁纸窗口比较特殊,因此由WallpaperWindowToken进行管理;

    19. WindowState:窗口对象实例。

    DisplayArea是Android R上新添加的容器,目的就是将复杂的窗口层级管理简单化、低耦合。

      而在树结构中,各个容器结构如下:

    WMS06.PNG

    可以看到,在树结构中,根节点为RootWindowContainer,叶子节点为WindowState。 正是通过这种结构,WMS中将系统中所有的窗口显示管理得井井有条,并将所有窗口以Surface的形式送到SurfacaFlinger中进行合成和显示。

    2.WMS启动流程

      接下来我们看下WMS的启动过程。WindowManagerService没有继承与SystemService,而是直接继承了IWindowManager.Stub接口,因此启动过程中,和SytemService的启动有区别。在system_server中,通过以下这些操作完成了WMS的启动:

    // frameworks/base/services/java/com/android/server/SystemServer.java
    
        private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
                // 2.1 创建WMS
                wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                        new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
                // 2.2 进行初始化
                wm.onInitReady();
                // 2.3 设置InputCallback接口
                inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
                // 2.4 进行Display配置更新
                wm.displayReady();
                // 2.5 系统启动完成
                wm.systemReady();
                // 2.6 计算Configuration
            final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);
            DisplayMetrics metrics = new DisplayMetrics();
            context.getDisplay().getMetrics(metrics);
            context.getResources().updateConfiguration(config, metrics);
        }
    

    注:上面筛选出wm相关的操作,下面对这些操作分别进行分析。

    2.1 WMS#main()创建WMS对象

      在执行main()方法后,最终会在android.display线程去创建WMS的实例:

    // frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    
        public static WindowManagerService main(final Context context, final InputManagerService im,
                final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
                ActivityTaskManagerService atm) {
            return main(context, im, showBootMsgs, onlyCore, policy, atm,
                    SurfaceControl.Transaction::new, Surface::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, final boolean onlyCore, WindowManagerPolicy policy,
                ActivityTaskManagerService atm, Supplier<SurfaceControl.Transaction> transactionFactory,
                Supplier<Surface> surfaceFactory,
                Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
            // DisplayThread就是android.display线程
            // runWithScissors的执行会导致system_server线程等待android.display执行完再进行下一步操作。
            DisplayThread.getHandler().runWithScissors(() ->
                    sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
                            atm, transactionFactory, surfaceFactory, surfaceControlFactory), 0);
            return sInstance;
        }
    ------------------------
        private WindowManagerService(Context context, InputManagerService inputManager,
                boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
                ActivityTaskManagerService atm, Supplier<SurfaceControl.Transaction> transactionFactory,
                Supplier<Surface> surfaceFactory,
                Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
            ......
    
            // Tranaction对象
            mTransaction = mTransactionFactory.get();
    
            // 创建WindowAnimator对象
            mAnimator = new WindowAnimator(this);
            // 创建RootWindowContainer对象
            mRoot = new RootWindowContainer(this);
            // 创建WindowSurfacePlacer对象
            mWindowPlacerLocked = new WindowSurfacePlacer(this);
            // 创建TaskSnapshotController对象
            mTaskSnapshotController = new TaskSnapshotController(this);
            // 创建DisplayWindowListenerController对象
            mDisplayNotificationController = new DisplayWindowListenerController(this);
            ......
            // 创建SurfaceAnimationRunner对象
            mSurfaceAnimationRunner = new SurfaceAnimationRunner(mTransactionFactory,
                    mPowerManagerInternal);
            // 创建TaskPositioningController
            mTaskPositioningController = new TaskPositioningController(
                    this, mInputManager, mActivityTaskManager, mH.getLooper());
            // 创建DragDropController对象
            mDragDropController = new DragDropController(this, mH.getLooper());
            // 创建EmbeddedWindowController
            mEmbeddedWindowController = new EmbeddedWindowController(mAtmService);
            // 创建 DisplayAreaPolicy.Provider对象
            mDisplayAreaPolicyProvider = DisplayAreaPolicy.Provider.fromResources(
                    mContext.getResources());
            .....
        }
    
    

    构造方法中,创建了WMS所用到的多个对象。

    2.2 WMS#onInitReady()对Policy进行初始化

      接下来执行onInitReady()方法进行初始化:

     // frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
    
        public void onInitReady() {
            initPolicy();//初始化policy
    
            // Add ourself to the Watchdog monitors.
            Watchdog.getInstance().addMonitor(this);
            createWatermark();
            showEmulatorDisplayOverlayIfNeeded();
        }
    -------------------------------------
        private void initPolicy() {
            UiThread.getHandler().runWithScissors(new Runnable() {
                @Override
                public void run() {
                    WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
                    mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
                } // android.ui线程
            }, 0);
        }
    

    在android.ui线程中调用WindowManagerPolicy#init()方法进行初始化,其中WindowManagerPolicy就是SystemServer.java中WindowManagerService.main()方法传进来的PhoneWindowManager。

    // frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
    
        public void init(Context context, IWindowManager windowManager,
                WindowManagerFuncs windowManagerFuncs) {
            mContext = context;
            mWindowManager = windowManager;
            mWindowManagerFuncs = windowManagerFuncs;
            ......
        }
    
    

    这个方法中做了大量的初始化操作。PhoneWindowManager继承于WindowManagerPolicy,是WMS中管理窗口过程中的一个策略类,窗口的显示、事件的派发等都受到PhoneWindowManager中的策略影响。mWindowManager和mWindowManagerFuncs都是WMS对象本身。

      这里的initPolicy()方法最终执行在android.ui线程中,并且也是使用runWithScissors,所以中和前面的两个线程,有如下的线程执行关系:

    WMS07.png

    initPolicy方法和此前讲的WMS的main方法的实现类似,它的具体实现在PhoneWindowManager(PWM)中。PWM的init方法运行在”android.ui”线程中,它的优先级要高于initPolicy方法所在的”android.display”线程,因此”android.display”线程要等PWM的init方法执行完毕后,处于等待状态的”android.display”线程才会被唤醒从而继续执行下面的代码:WMS.displayRead()。

    2.3 IMS#setWindowManagerCallbacks()设置InputCallback回调

      这个方法用来向IMS中设置InputManagerCallback回调:

    // frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
    
        public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
            mWindowManagerCallbacks = callbacks;
        }
    

    InputManagerCallback对象在WMS加载时完成创建:

    // frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    
        // 创建InputManagerCallback对象
        final InputManagerCallback mInputManagerCallback = new InputManagerCallback(this);
    ------------------------------
        public InputManagerCallback getInputManagerCallback() {
            return mInputManagerCallback;
        }
    

    InputManagerCallback接口用于接受IMS中的回调,如input事件派发过程中发生的ANR等,就是通过该接口向WMS中传递。

    2.4 WMS#displayReady()更新DisplayContent配置

      这个方法用来进行Display相关配置的第一次更新:

    // frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    
        public void displayReady() {
            synchronized (mGlobalLock) {
                if (mMaxUiWidth > 0) {
                    mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
                }
                applyForcedPropertiesForDefaultDisplay();
                // 告知WindowAnimator初始化完成
                mAnimator.ready();
                // 表示Display准备完成
                mDisplayReady = true;
                // Reconfigure all displays to make sure that forced properties and
                // DisplayWindowSettings are applied.
                // 更新Configuration
                mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked);
                mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
                        PackageManager.FEATURE_TOUCHSCREEN);
            }
    
            try {
                // 更新Configuration
                mActivityTaskManager.updateConfiguration(null);
            } catch (RemoteException e) {
            }
        }
    

    这里通过DisplayContent#reconfigureDisplayLocked()更新DisplayContent相关配置。

    2.5 WMS#systemReady()方法

      这个方法的执行,表示system_server启动完成,WMS中会分别执行其他组件的systemReady()方法:

    // frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
    
        public void systemReady() {
            // 系统
            mSystemReady = true;
            // PhoneWindowManager
            mPolicy.systemReady();
            // 执行DisplayPolicy#systemReady
            mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady);
            mTaskSnapshotController.systemReady();
            mHasWideColorGamutSupport = queryWideColorGamutSupport();
            mHasHdrSupport = queryHdrSupport();
            UiThread.getHandler().post(mSettingsObserver::loadSettings);
            IVrManager vrManager = IVrManager.Stub.asInterface(
                    ServiceManager.getService(Context.VR_SERVICE));
            if (vrManager != null) {
                try {
                    final boolean vrModeEnabled = vrManager.getVrModeState();
                    synchronized (mGlobalLock) {
                        vrManager.registerListener(mVrStateCallbacks);
                        if (vrModeEnabled) {
                            mVrModeEnabled = vrModeEnabled;
                            mVrStateCallbacks.onVrStateChanged(vrModeEnabled);
                        }
                    }
                } catch (RemoteException e) {
                    // Ignore, we cannot do anything if we failed to register VR mode listener
                }
            }
        }
    

    2.6 WMS#computeNewConfiguration()

      这个方法是启动过程中执行的最后一个方法,用来更新全局配置状态:

    // frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    
        public Configuration computeNewConfiguration(int displayId) {
            synchronized (mGlobalLock) {
                return computeNewConfigurationLocked(displayId);
            }
        }
    
        private Configuration computeNewConfigurationLocked(int displayId) {
            if (!mDisplayReady) {
                return null;
            }
            final Configuration config = new Configuration();
            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
            displayContent.computeScreenConfiguration(config);
            return config;
        }
    

    在该方法中,会根据逻辑屏id,获得对应的DisplayContent对象来进行配置的更新,并在更新完成后,设置给对应Context的Resource对象。 关于DisplayContent中的更新配置更新流程,会在之后的文章中结合具体场景详细说明。

      经过以上几个步骤,WMS启动完成。

    相关文章

      网友评论

          本文标题:Android WindowManagerService--03

          本文链接:https://www.haomeiwen.com/subject/otvvvdtx.html