Android Framework 窗口子系统 (01)WindowMangerService基础知识

系列文章解读&说明:

Android Framework 窗口子系统 的 分析主要分为以下部分:

(01)WindowMangerService基础知识

(02)应用进程和WindowManagerService之间的关系

(03)窗口显示次序

(04)确定窗口尺寸

(05)窗口布局说明

(06)Choreographer机制

(07)窗口动画系统

本模块分享的内容:WindowMangerService基础知识

本章关键点总结 & 说明:

该图主要讲解windowManagerService的基础知识,从WMS概念、WMS启动到WMS的成员变量,最后到窗口类型进行了说明。旨在对整个WindowManagerService有个概要的了解。

1 WindowMangerService基本概念

windowManagerService中一些常见以及相关的基本概念进行阐述:

基本概念 阐述说明
WindowManagerService(WMS) Framework层的窗口管理服务,职责是管理Android系统中的所有的Window。窗口管理服务,继承IWindowManager.Stub,Binder服务端,因此WM与WMS的交互也是一个IPC的过程。
Window 手机上一块显示区域,添加一个Window的过程,也就是申请分配一块Surface的过程。
Surface 每个显示界面的窗口都是一个Surface。
WindowManager(WM) 应用与窗口管理服务WindowManagerService交互的接口
PhoneWindowManager 实现了窗口的各种策略。
Choreographer 用于控制窗口动画、屏幕旋转等操作。
DisplayContent

用于描述多屏输出相关信息。

根据窗口的显示位置将其分组。隶属于同一个DisplayContent的窗口将会被显示在同一个屏幕中。每一个DisplayContent都对应这唯一ID,在添加窗口时可以通过指定这个ID决定其将被显示在那个屏幕中。

DisplayContent是一个非常具有隔离性的一个概念。处于不同DisplayContent的两个窗口在布局、显示顺序以及动画处理上不会产生任何耦合。

WindowState 描述窗口的状态信息以及和WindowManagerService进行通信,一般一个窗口对应一个WindowState。它用来表示一个窗口的所有属性。
WindowToken

窗口Token,用来做Binder通信;同时也是一种标识,比如

@1 在进行窗口Zorder排序时,属于同一个WindowToken的窗口会被安排在一起,而且在其中定义的一些属性将会影响所有属于此WindowToken的窗口,这些都表明了属于同一个WindowToken的窗口之间的紧密联系;

@2 应用组件在需要新的窗口时,必须提供WindowToken以表明自己的身份,并且窗口的类型必须与所持有的WindowToken的类型一致。

@3 在创建系统类型的窗口时不需要提供一个有效的Token,WMS会隐式地为其声明一个WindowToken,看起来谁都可以添加个系统级的窗口。难道Android为了内部使用方便而置安全于不顾吗?非也,addWindow()函数一开始的mPolicy.checkAddPermission()的目的就是如此。它要求客户端必须拥有SYSTEM_ALERT_WINDOW或INTERNAL_SYSTEM_WINDOW权限才能创建系统类型的窗口。

Session 信对象,App进程通过建立Session代理对象和Session对象通信,进而和WMS建立连接。
SurfaceFlinger SurfaceFlinger负责管理Android系统的帧缓冲区(Frame Buffer),Android设备的显示屏被抽象为一个帧缓冲区,而Android系统中的SurfaceFlinger服务就是通过向这个帧缓冲区写入内容来绘制应用程序的用户界面的。

同时,由于AMS、WMS、ViewRootImpl这些都是显示系统的相关环节,因此有必要对Activity相关信息,尤其是关键成员变量有一定的了解,这里Activity持有一个Window,负责UI的展示与用户交互,里保存了很多重要的信息,关键信息如下:

关键成员变量 意义
mWindow PhoneWindow对象,继承于Window,是窗口对象。
mWindowManager WindowManagerImpl对象,实现WindowManager接口。
mMainThread Activity对象,并非真正的线程,是运行在主线程里的对象。
mUIThread: Thread对象,主线程。
mHandler Handler对象,主线程Handler。
mDecor View对象,用来显示Activity里的视图。

每个Android应用中都有唯一的WindowManagerGlobal对象,这个对象包含了能和WMS进行双向通信的通道,如图所示:

2 WindowManagerService启动流程分析

在SystemServer中startOtherServices函数中启动,代码如下:

private void startOtherServices() {
    ...
	wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore);
            ServiceManager.addService(Context.WINDOW_SERVICE, wm);
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);

            mActivityManagerService.setWindowManager(wm);

            inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
            inputManager.start();
	...
	wm.displayReady(); //初始化显示尺寸信息,结束后WMS会根据AMS进行一次configure
	...
	wm.systemReady(); //直接调用mPolicy的systemready方法
}

这里继续分析WindowManagerService.main,代码如下:

public static WindowManagerService main(final Context context,final InputManagerService im,
        final boolean haveInputMethods, final boolean showBootMsgs,final boolean onlyCore) {
    final WindowManagerService[] holder = new WindowManagerService[1];
    DisplayThread.getHandler().runWithScissors(new Runnable() {
        @Override
        public void run() {
            holder[0] = new WindowManagerService(context, im,
                    haveInputMethods, showBootMsgs, onlyCore);
        }
    }, 0);
    return holder[0];
}

继续看WindowManagerService的实现,代码如下:

private WindowManagerService(Context context, InputManagerService inputManager,
        boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
    //...
    LocalServices.addService(WindowManagerPolicy.class, mPolicy);
    //...
	InputManager.monitorInput(TAG));

    mFxSession = new SurfaceSession();
    mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
    Display[] displays = mDisplayManager.getDisplays();
    for (Display display : displays) {
        createDisplayContentLocked(display);
    }

    mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);

    mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
    mPowerManagerInternal.registerLowPowerModeObserver(
            new PowerManagerInternal.LowPowerModeListener() {
        @Override
        public void onLowPowerModeChanged(boolean enabled) {
            synchronized (mWindowMap) {
                if (mAnimationsDisabled != enabled) {
                    mAnimationsDisabled = enabled;
                    dispatchNewAnimatorScaleLocked(null);
                }
            }
        }
    });
    //...
    mAnimator = new WindowAnimator(this);
    mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
            com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);

    LocalServices.addService(WindowManagerInternal.class, new LocalService());
    initPolicy();//在android ui线程初始化完成后进行策略初始化

    // Add ourself to the Watchdog monitors.
    Watchdog.getInstance().addMonitor(this);
    //...
}

这里继续分析initPolicy,代码如下:

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);
            mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
                    * TYPE_LAYER_MULTIPLIER
                    + TYPE_LAYER_OFFSET;
        }
    }, 0);
}

这里说明下:

  1. WMS的启动主要涉及3个线程:system_server、android.display、android.ui;其中WMS.H.handleMessage 运行在android.display线程中。
  2. WMS中3个关键步骤:创建WMS对象,初始化显示信息,处理systemready通知

3 WMS中 关键成员变量说明

说明:这里只是对WMS中最核心,有用的变量进行分析和解读。

3.1 最关键成员变量说明:

 

成员变量 变量说明
mInputManager IMS实例。管理每个窗口的输入事件通道(InputChannel)以及向通道上派发事件。
mChoreographer 它拥有从显示子系统获取VSYNC同步事件的能力,从而可以在合适的时机通知渲染动作,避免在渲染的过程中因为发生屏幕重绘而导致的画面撕裂。WMS使用Choreographer负责驱动所有的窗口动画、屏幕旋转动画、墙纸动画的渲染。
mAnimator 所有窗口动画的总管(WindowStateAnimator对象)。在Choreographer的驱动下,逐个渲染所有的动画。
mPolicy 分析后,就是PhoneWindowManager类,一个实现类。mPolicy定义了窗口相关策略,比如:告诉WMS某一个类型Window的Z-Order的值是多少,帮助WMS矫正不合理的窗口属性,为WMS监听屏幕旋转的状态,预处理一些系统按键事件(例如HOME、BACK键等的默认行为就是在这里实现的)等。。。
mDisplayContents DisplayContent类型List。描述了一块可绘制窗口的屏幕。每个DisplayContent都用一个整型变量作为其ID。

 3.2 重要成员变量说明:

mTokenMap,HashMap,保存所有显示令牌(类型为WindowToken),一个窗口必须隶属于某一个显示令牌。衍生变量还有:

  • mAppTokens,保存了所有属于Activity的显示令牌(WindowToken的子类AppWindowToken),mAppTokens列表是有序的,它与AMS中的mHistory列表的顺序保持一致,反映了系统中Activity的顺序。
  • mExitingTokens,保存了正在退出过程中的显示令牌等。

mWindowMap,HashMap,保存所有窗口的状态信息(类型为WindowState),衍生变量还有:

  • mPendingRemove,保存了那些退出动画播放完成并即将被移除的窗口
  • mLosingFocus,保存了那些失去了输入焦点的窗口。
  • 在DisplayContent中,也有一个windows列表,这个列表存储了显示在此DisplayContent中的窗口,并且它是有序的。窗口在这个列表中的位置决定了其最终显示时的Z序。

mSessions,List,这个列表保存了当前所有想向WMS寻求窗口管理服务的客户端。注意Session是具有进程唯一性。

4 窗口类型定义
WMS中定义了3类窗口,应用窗口,子窗口和系统窗口,分别对这3种窗口进行说明,该图列举了几种常见的窗口,如下所示:

这里涉及几类窗口:

  1. 应用程序窗口 (Application Window): 包括所有应用程序自己创建的窗口,以及在应用起来之前系统负责显示的窗口。
  2. 子窗口(Sub Window):比如应用自定义的对话框,或者输入法窗口,子窗口必须依附于某个应用窗口(设置相同的token)。
  3. 系统窗口(System Window): 系统设计,不依附于任何应用窗口,比如:状态栏(Status Bar)、导航栏(Navigation Bar)、壁纸(Wallpaper)、来电显示窗口(Phone)、锁屏窗口(KeyGuard)、信息提示窗口(Toast)、音量调整窗口、鼠标光标等等。

4.1 应用窗口

第一种窗口类型为应用窗口,所谓的应用窗口是指该窗口对应一个Activity,由于加载Activity是由AmS完成的,因此,对于应用程序来说,要创建一个应用类窗口,只能在Activity内部完成。应用窗口包含以下几类:

4.2 子窗口
第二种窗口类型是子窗口,子窗口是指该窗口必须要有一个父窗口,父窗口可以是一个应用类型窗口,也可以是任何其他类型的窗口。子窗口包含以下几类:

4.3 系统窗口
第三种窗口类型是系统窗口,系统窗口不需要对应任何Activity,也不需要有父窗口,对于应用程序而言,理论上是无法创建系统窗口的,因为所有的应用程序都没有这个权限,然而系统进程却可以创建系统窗口。系统窗口有以下类型:

猜你喜欢

转载自blog.csdn.net/vviccc/article/details/93970505
今日推荐