WindowManagerService探索——窗口主次序

2019-03-26  本文已影响0人  Monster_de47

前言

上一章中通过添加Window为例,介绍了WMS的第一种职责——窗口管理,今天我们以上一章内容为基础,深入探索一下。众所周知,每个Window被添加或者更新后,WMS是怎样处理它们的显示次序呢?

窗口的显示次序

在addWindow()函数的前半部分中,WMS为窗口创建了用于描述窗口状态的WindowState,接下来便会为新建的窗口确定显示次序。为了方便窗口显示次序的管理,手机屏幕用X、Y、Z轴来表示,很奇怪的是,明明手机只有长宽的平面,为什么会有Z轴呢?这里就要简要说明一下WMS的窗口次序管理机制了,Z轴垂直于屏幕,从里指向外,这个次序也称作Z-Oder。前面章节中讲到的Type就是根据Z-Oder为依据定义的,理论上Type的值越大Z-Oder排序越靠前,窗口越靠近用户。

主序与子序

又回到上一章中提到的WindowState,这里看一下它的构造方法:

    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
            int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow,
            PowerManagerWrapper powerManagerWrapper) {
        ...

        // 为子窗口分配Z-Oder
        if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) {
            // The multiplier here is to reserve space for multiple
            // windows in the same type layer.
            mBaseLayer = mPolicy.getWindowLayerLw(parentWindow)
                    * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
            mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);
            mIsChildWindow = true;

            if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + parentWindow);
            parentWindow.addChild(this, sWindowSubLayerComparator);

            mLayoutAttached = mAttrs.type !=
                    WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
            mIsImWindow = parentWindow.mAttrs.type == TYPE_INPUT_METHOD
                    || parentWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
            mIsWallpaper = parentWindow.mAttrs.type == TYPE_WALLPAPER;
        } else {
            // 为普通窗口分配Z-Oder
            // The multiplier here is to reserve space for multiple
            // windows in the same type layer.
            mBaseLayer = mPolicy.getWindowLayerLw(this)
                    * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
            mSubLayer = 0;
            mIsChildWindow = false;
            mLayoutAttached = false;
            mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
                    || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
            mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
        }
        ... 
    }

窗口的显示次序由两个成员变量描述:主序mBaseLayer和子序mSubLayer。主序用于描述窗口及其子窗口在所有窗口中的显示位置。而子序则描述了一个子窗口在其兄弟窗口中的显示位置。

窗口的主序:

窗口类型 主序
TYPE_UNIVERSE_BACKGROUND 11000
TYPE_PHONE 31000
TYPE_RECENTS_OVERLAY 51000
TYPE_TOAST 61000
TYPE_DREAM 81000
TYPE_INPUT_METHOD 101000
TYPE_KEYGUARD 121000
TYPE_STATUS_BAR_SUB_PANEL 141000
TYPE_WALLPAPER 21000
TYPE_SEARCH_BAR 41000
TYPE_SYSTEM_DIALOG 51000
TYPE_PRIORITY_PHONE 71000
TYPE_SYSTEM_ALERT 91000
TYPE_INPUT_METHOD_DIALOG 111000
TYPE_KEYGUARD_DIALOG 131000
应用窗口与未知类型的窗口 21000

窗口的子序:

窗口类型 主序
TYPE_UNIVERSE_BACKGROUND 11000
TYPE_PHONE 31000
TYPE_RECENTS_OVERLAY 51000
TYPE_TOAST 61000
TYPE_DREAM 81000
TYPE_INPUT_METHOD 101000
TYPE_KEYGUARD 121000
TYPE_STATUS_BAR_SUB_PANEL 141000
TYPE_WALLPAPER 21000
上一篇下一篇

猜你喜欢

热点阅读