Window Layer

Android在开机初始化时构建了一个WindowContainer树型结构,最顶层是RootWindowContainer,RootWindowContainer的mChildren是DisplayContent,再下面是一些DisplayArea,再下来:

1,如果是系统窗口的话,就是一些DisplayArea.Tokens的Leaf节点,Leaf节点的child是WindowToken,WindowToken的child是WindowState,WindowState代表一个Window,它也可以有child(WindowState)。

2,如果是应用类型窗口的话,就是TaskDisplayArea(DefaultTaskDisplayArea)节点,TaskDisplayArea的child可以是TaskDisplayArea或者Task,Task的child一般是Task或者ActivityRecord,ActivityRecord的child是WindowState,WindowState代表一个Window,它也可以有child(WindowState)。

以上树型结构中所有节点都被抽象成WindowContainer,所有节点都是WindowContainer的直接或间接子类。

WindowContainer中包含几个关键成员:

// 父级
WindowContainer<WindowContainer> mParent;
// 子级
WindowList<E> mChildren = new WindowList<E>();
// Surface句柄,包含可绘制类型和容器类型
SurfaceControl mSurfaceControl;

Window Layer分配

构建WindowContainer树型结构时会调用addChild方法

    protected void addChild(E child, Comparator<E> comparator) {
        if (!child.mReparenting && child.getParent() != null) {
            throw new IllegalArgumentException("addChild: container=" + child.getName()
                    + " is already a child of container=" + child.getParent().getName()
                    + " can't add to container=" + getName());
        }

        int positionToAdd = -1;
        if (comparator != null) {
            final int count = mChildren.size();
            for (int i = 0; i < count; i++) {
                if (comparator.compare(child, mChildren.get(i)) < 0) {
                    positionToAdd = i;
                    break;
                }
            }
        }

        if (positionToAdd == -1) {
            mChildren.add(child);
        } else {
            mChildren.add(positionToAdd, child);
        }

        // Set the parent after we've actually added a child in case a subclass depends on this.
        child.setParent(this);
    }

    final protected void setParent(WindowContainer<WindowContainer> parent) {
        final WindowContainer oldParent = mParent;
        mParent = parent;

        if (mParent != null) {
            mParent.onChildAdded(this);
        } else if (mSurfaceAnimator.hasLeash()) {
            mSurfaceAnimator.cancelAnimation();
        }
        if (!mReparenting) {
            onSyncReparent(oldParent, mParent);
            if (mParent != null && mParent.mDisplayContent != null
                    && mDisplayContent != mParent.mDisplayContent) {
                onDisplayChanged(mParent.mDisplayContent);
            }
            onParentChanged(mParent, oldParent);
        }
    }

    @Override
    void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
        onParentChanged(newParent, oldParent, null);
    }

    void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent,
            PreAssignChildLayersCallback callback) {
        super.onParentChanged(newParent, oldParent);
        if (mParent == null) {
            return;
        }

        if (mSurfaceControl == null) {
            // If we don't yet have a surface, but we now have a parent, we should
            // build a surface.
            createSurfaceControl(false /*force*/);
        } else {
            // If we have a surface but a new parent, we just need to perform a reparent. Go through
            // surface animator such that hierarchy is preserved when animating, i.e.
            // mSurfaceControl stays attached to the leash and we just reparent the leash to the
            // new parent.
            reparentSurfaceControl(getSyncTransaction(), mParent.mSurfaceControl);
        }

        if (callback != null) {
            callback.onPreAssignChildLayers();
        }

        // Either way we need to ask the parent to assign us a Z-order.
        mParent.assignChildLayers();
        scheduleAnimation();
    }

最终会调用WindowContainer的assignChildLayers()方法

// WindowContainer.java

    void assignChildLayers() {
        assignChildLayers(getSyncTransaction());
        scheduleAnimation();
    }

    void assignChildLayers(Transaction t) {
        int layer = 0;

        // We use two passes as a way to promote children which
        // need Z-boosting to the end of the list.
        for (int j = 0; j < mChildren.size(); ++j) {
            final WindowContainer wc = mChildren.get(j);
            // 递归child的child,给child的所有子级分配layer
            wc.assignChildLayers(t);
            if (!wc.needsZBoost()) {
                // 先分配不需要ZBoost的child,需要ZBoost的layer较高
                wc.assignLayer(t, layer++);
            }
        }
        for (int j = 0; j < mChildren.size(); ++j) {
            final WindowContainer wc = mChildren.get(j);
            if (wc.needsZBoost()) {
                // 分配需要ZBoost的layer
                wc.assignLayer(t, layer++);
            }
        }
        if (mOverlayHost != null) {
            mOverlayHost.setLayer(t, layer++);
        }
    }

    void assignLayer(Transaction t, int layer) {
        // Don't assign layers while a transition animation is playing
        // TODO(b/173528115): establish robust best-practices around z-order fighting.
        if (mTransitionController.isPlaying()) return;
        final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
        if (mSurfaceControl != null && changed) {
            setLayer(t, layer);
            mLastLayer = layer;
            mLastRelativeToLayer = null;
        }
    }

    protected void setLayer(Transaction t, int layer) {
        if (mSurfaceFreezer.hasLeash()) {
            // When the freezer has created animation leash parent for the window, set the layer
            // there instead.
            mSurfaceFreezer.setLayer(t, layer);
        } else {
            // Route through surface animator to accommodate that our surface control might be
            // attached to the leash, and leash is attached to parent container.
            mSurfaceAnimator.setLayer(t, layer);
        }
    }

以上是WindowContainer的assignChildLayers和assignLayer方法,

对于assignChildLayers方法,WindowContainer的部分子类还有自己的实现,除了调用WindowContainer的assignChildLayers方法还有些额外的处理。

主要看下TaskDisplayArea和WindowState的assignChildLayers方法实现:

TaskDisplayArea.assignChildLayers方法

// TaskDisplayArea.java

    @Override
    void assignChildLayers(SurfaceControl.Transaction t) {
        // 先给RootTask分配layer
        assignRootTaskOrdering(t);
        
        // 然后递归所有子级并分配layer
        for (int i = 0; i < mChildren.size(); i++) {
            mChildren.get(i).assignChildLayers(t);
        }
    }

    void assignRootTaskOrdering(SurfaceControl.Transaction t) {
        if (getParent() == null) {
            return;
        }
        mTmpAlwaysOnTopChildren.clear();
        mTmpHomeChildren.clear();
        mTmpNormalChildren.clear();
        for (int i = 0; i < mChildren.size(); ++i) {
            final WindowContainer child = mChildren.get(i);
            final TaskDisplayArea childTda = child.asTaskDisplayArea();
            if (childTda != null) {
                final Task childTdaTopRootTask = childTda.getTopRootTask();
                if (childTdaTopRootTask == null) {
                    mTmpNormalChildren.add(childTda);
                } else if (childTdaTopRootTask.isAlwaysOnTop()) {
                    mTmpAlwaysOnTopChildren.add(childTda);
                } else if (childTdaTopRootTask.isActivityTypeHome()) {
                    mTmpHomeChildren.add(childTda);
                } else {
                    mTmpNormalChildren.add(childTda);
                }
                continue;
            }

            // 把所有RootTask归为三类,AlwaysOnTop,HomeTask, Normal
            final Task childTask = child.asTask();
            if (childTask.isAlwaysOnTop()) {
                mTmpAlwaysOnTopChildren.add(childTask);
            } else if (childTask.isActivityTypeHome()) {
                mTmpHomeChildren.add(childTask);
            } else {
                mTmpNormalChildren.add(childTask);
            }
        }

        int layer = 0;
        // Place root home tasks to the bottom.
        // home task在最底部,layer较小
        layer = adjustRootTaskLayer(t, mTmpHomeChildren, layer);
        //Normal其次
        layer = adjustRootTaskLayer(t, mTmpNormalChildren, layer);
        // TODO(b/207185041): Remove this divider workaround after we full remove leagacy split and
        //                    make app pair split only have single root then we can just attach the
        //                    divider to the single root task in shell.
        layer = Math.max(layer, SPLIT_DIVIDER_LAYER + 1);
        // AlwaysOnTop在最上面,layer较大
        adjustRootTaskLayer(t, mTmpAlwaysOnTopChildren, layer);
        t.setLayer(mSplitScreenDividerAnchor, SPLIT_DIVIDER_LAYER);
    }

我们先看下WindowState.assignLayer方法

// WindowState.java

    @Override
    void assignLayer(Transaction t, int layer) {
        if (mStartingData != null) {
            // The starting window should cover the task.
            //mStartingData != null表示这是个starting window,layer分配最高
            t.setLayer(mSurfaceControl, Integer.MAX_VALUE);
            return;
        }
        // See comment in assignRelativeLayerForImeTargetChild
        if (needsRelativeLayeringToIme()) {
            getDisplayContent().assignRelativeLayerForImeTargetChild(t, this);
            return;
        }
        // 调用父类即WindowContainer的assignLayer方法
        super.assignLayer(t, layer);
    }

我们知道,WindowContainer的assignChildLayers方法中,父级给子级分配layer一般是从mChildren的下标0开始遍历所有子级并递增的分配layer,也就是说mChildren列表按z顺序排列,最顶部的窗口容器位于列表的尾部。

那么WindowState添加到其父级的mChildren列表时,是根据什么来确定其在列表的位置呢?

非子Window是根据WindowState的mBaseLayer,mBaseLayer越大,z-order越高;

// WindowToken.java

    void addWindow(final WindowState win) {
        ProtoLog.d(WM_DEBUG_FOCUS,
                "addWindow: win=%s Callers=%s", win, Debug.getCallers(5));

        if (win.isChildWindow()) {
            // Child windows are added to their parent windows.
            return;
        }
        // This token is created from WindowContext and the client requests to addView now, create a
        // surface for this token.
        if (mSurfaceControl == null) {
            createSurfaceControl(true /* force */);

            // Layers could have been assigned before the surface was created, update them again
            reassignLayer(getSyncTransaction());
        }
        if (!mChildren.contains(win)) {
            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", win, this);
            //
            addChild(win, mWindowComparator);
            mWmService.mWindowsChanged = true;
            // TODO: Should we also be setting layout needed here and other places?
        }
    }

    private final Comparator<WindowState> mWindowComparator =
            (WindowState newWindow, WindowState existingWindow) -> {
        final WindowToken token = WindowToken.this;
        if (newWindow.mToken != token) {
            throw new IllegalArgumentException("newWindow=" + newWindow
                    + " is not a child of token=" + token);
        }

        if (existingWindow.mToken != token) {
            throw new IllegalArgumentException("existingWindow=" + existingWindow
                    + " is not a child of token=" + token);
        }

        return isFirstChildWindowGreaterThanSecond(newWindow, existingWindow) ? 1 : -1;
    };

    protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
            WindowState existingWindow) {
        // New window is considered greater if it has a higher or equal base layer.
        // 添加非子Window时,比较mBaseLayer
        return newWindow.mBaseLayer >= existingWindow.mBaseLayer;
    }


// WindowContainer.java
    protected void addChild(E child, Comparator<E> comparator) {
        if (!child.mReparenting && child.getParent() != null) {
            throw new IllegalArgumentException("addChild: container=" + child.getName()
                    + " is already a child of container=" + child.getParent().getName()
                    + " can't add to container=" + getName());
        }

        int positionToAdd = -1;
        if (comparator != null) {
            final int count = mChildren.size();
            for (int i = 0; i < count; i++) {
                // 此处comparator.compare结果<0,新的child就排在前面,layer就小一些
                if (comparator.compare(child, mChildren.get(i)) < 0) {
                    positionToAdd = i;
                    break;
                }
            }
        }

        if (positionToAdd == -1) {
            mChildren.add(child);
        } else {
            mChildren.add(positionToAdd, child);
        }

        // Set the parent after we've actually added a child in case a subclass depends on this.
        child.setParent(this);
    }

子Window是根据WindowState的mSubLayer,mSubLayer越大,z-order越高;

// WindowState.java

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

        // Make sure we initial all fields before adding to parentWindow, to prevent exception
        // during onDisplayChanged.
        if (mIsChildWindow) {
            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", this, parentWindow);
            parentWindow.addChild(this, sWindowSubLayerComparator);
        }

        // ...
    }

    private static final Comparator<WindowState> sWindowSubLayerComparator =
            new Comparator<WindowState>() {
                @Override
                public int compare(WindowState w1, WindowState w2) {
                    final int layer1 = w1.mSubLayer;
                    final int layer2 = w2.mSubLayer;
                    //添加子Window时,mSubLayer越小,layer也相对较低
                    if (layer1 < layer2 || (layer1 == layer2 && layer2 < 0 )) {
                        // We insert the child window into the list ordered by
                        // the sub-layer.  For same sub-layers, the negative one
                        // should go below others; the positive one should go
                        // above others.
                        return -1;
                    }
                    return 1;
                };
            };

WindowState分配子Window的assignChildLayers方法

// WindowState.java

    public void assignChildLayers(Transaction t) {
        // The surface of the main window might be preserved. So the child window on top of the main
        // window should be also on top of the preserved surface.
        int layer = PRESERVED_SURFACE_LAYER + 1;
        for (int i = 0; i < mChildren.size(); i++) {
            final WindowState w = mChildren.get(i);

            // APPLICATION_MEDIA_OVERLAY needs to go above APPLICATION_MEDIA
            // while they both need to go below the main window. However the
            // relative layering of multiple APPLICATION_MEDIA/OVERLAY has never
            // been defined and so we can use static layers and leave it that way.
            // TYPE_APPLICATION_MEDIA和TYPE_APPLICATION_MEDIA_OVERLAY类型子Window
            //分别分配layer值-2和-1,表示在其主Window的下面,
            //如果父Window已经有可绘制的mSurfaceControl,则调用assignRelativeLayer相对的方法
            if (w.mAttrs.type == TYPE_APPLICATION_MEDIA) {
                if (mWinAnimator.hasSurface()) {
                    w.assignRelativeLayer(t, mWinAnimator.mSurfaceController.mSurfaceControl, -2);
                } else {
                    w.assignLayer(t, -2);
                }
            } else if (w.mAttrs.type == TYPE_APPLICATION_MEDIA_OVERLAY) {
                if (mWinAnimator.hasSurface()) {
                    w.assignRelativeLayer(t, mWinAnimator.mSurfaceController.mSurfaceControl, -1);
                } else {
                    w.assignLayer(t, -1);
                }
            } else {
                //其他类型的子Window正常分配layer,正值
                w.assignLayer(t, layer);
            }
            //递归子Window继续为其子级分配layer
            w.assignChildLayers(t);
            layer++;
        }
    }

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在计算机图形学中,Surface、LayerWindow是三个不同的概念,它们之间存在一定的关系。 Surface(表面)是一个二维平面或者三维物体的外部表面,用于表示可见物体或物体的一部分。一个Surface可以由一系列的顶点和面片组成,通过定义顶点的属性来描述物体的外观。 Layer(图层)是在图像处理中用于分别放置不同图像元素的层级。每个图层可以包含不同的图像或者图形元素,可以进行独立的编辑和处理。通过调整每个图层的位置、透明度、混合模式等属性,可以对整个图像进行复杂的合成和编辑。 Window(窗口)是操作系统中用于显示图形界面的矩形区域。一个Window通常包含一个或多个Layer,用于显示窗口中的各种图像元素。不同的窗口可以有不同的Layer组合,从而实现多个窗口的重叠和交互。 因此,Surface可以被认为是Layer的一种表现形式,用于表示可见物体或物体表面。而Window则是包含多个Layer的容器,用于显示图形界面。在渲染过程中,Surface通常会被放置到相应的Layer中,而多个Layer则可以被组合到一个Window中进行显示。 总结起来,Surface用于表示可见物体或物体表面,Layer用于图像处理中的分层管理,而Window则是容纳多个Layer的图形界面显示区域。它们之间存在一定的关系,Surface可以被放置到Layer中,而多个Layer可以被组合到一个Window中进行显示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值