Android T 窗口层级其二 —— 层级结构树的构建(2)

781 阅读10分钟

接着前文分析Android T 窗口层级其二 —— 层级结构树的构建(1)

生成DisplayArea层级结构

return new DisplayAreaPolicyBuilder().setRootHierarchy(rootHierarchy).build(wmService); 我们分两部分看 1.setRootHierarchy(rootHierarchy)把前面创建的rootHierarchy添加到DisplayArea中 代码路径:/frameworks/base/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java

    /** Defines the root hierarchy for the whole logical display. */
    DisplayAreaPolicyBuilder setRootHierarchy(HierarchyBuilder rootHierarchyBuilder) {
        mRootHierarchyBuilder = rootHierarchyBuilder;
        return this;
    }

把前面创建HierarchyBuilder对象rootHierarchy保存到DisplayAreaPolicyBuilder的mRootHierarchyBuilder 2.build(wmService)构建DisplayArea层级结构

    Result build(WindowManagerService wmService) {
        validate();

        // Attach DA group roots to screen hierarchy before adding windows to group hierarchies.
        mRootHierarchyBuilder.build(mDisplayAreaGroupHierarchyBuilders);
        List<RootDisplayArea> displayAreaGroupRoots = new ArrayList<>(
                mDisplayAreaGroupHierarchyBuilders.size());
        for (int i = 0; i < mDisplayAreaGroupHierarchyBuilders.size(); i++) {
            HierarchyBuilder hierarchyBuilder = mDisplayAreaGroupHierarchyBuilders.get(i);
            hierarchyBuilder.build();
            displayAreaGroupRoots.add(hierarchyBuilder.mRoot);
        }
        // Use the default function if it is not specified otherwise.
        if (mSelectRootForWindowFunc == null) {
            mSelectRootForWindowFunc = new DefaultSelectRootForWindowFunction(
                    mRootHierarchyBuilder.mRoot, displayAreaGroupRoots);
        }
        return new Result(wmService, mRootHierarchyBuilder.mRoot, displayAreaGroupRoots,
                mSelectRootForWindowFunc, mSelectTaskDisplayAreaFunc);
    }

其关键代码是mRootHierarchyBuilder.build(mDisplayAreaGroupHierarchyBuilders); 调用HierarchyBuilder.build去生成DisplayArea层级结构,并且有一个传参mDisplayAreaGroupHierarchyBuilders。 在HierarchyBuilder.build方法中可以看出,该参数传递的实际为空值

	/** Builds the {@link DisplayArea} hierarchy below root. */
	private void build() {
	    build(null /* displayAreaGroupHierarchyBuilders */);
	}
	
	/**
	 * Builds the {@link DisplayArea} hierarchy below root. And adds the roots of those
	 * {@link HierarchyBuilder} as children.
	 */
	private void build(@Nullable List<HierarchyBuilder> displayAreaGroupHierarchyBuilders) {
		//1.初始化一些参数
	    final WindowManagerPolicy policy = mRoot.mWmService.mPolicy;
	    final int maxWindowLayerCount = policy.getMaxWindowLayer() + 1;
	    final DisplayArea.Tokens[] displayAreaForLayer =
	            new DisplayArea.Tokens[maxWindowLayerCount];
	    final Map<Feature, List<DisplayArea<WindowContainer>>> featureAreas =
	            new ArrayMap<>(mFeatures.size());
	    for (int i = 0; i < mFeatures.size(); i++) {
	        featureAreas.put(mFeatures.get(i), new ArrayList<>());
	    }
	
	    // This method constructs the layer hierarchy with the following properties:
	    // (1) Every feature maps to a set of DisplayAreas
	    // (2) After adding a window, for every feature the window's type belongs to,
	    //     it is a descendant of one of the corresponding DisplayAreas of the feature.
	    // (3) Z-order is maintained, i.e. if z-range(area) denotes the set of layers of windows
	    //     within a DisplayArea:
	    //      for every pair of DisplayArea siblings (a,b), where a is below b, it holds that
	    //      max(z-range(a)) <= min(z-range(b))
	    //
	    // The algorithm below iteratively creates such a hierarchy:
	    //  - Initially, all windows are attached to the root.
	    //  - For each feature we create a set of DisplayAreas, by looping over the layers
	    //    - if the feature does apply to the current layer, we need to find a DisplayArea
	    //      for it to satisfy (2)
	    //      - we can re-use the previous layer's area if:
	    //         the current feature also applies to the previous layer, (to satisfy (3))
	    //         and the last feature that applied to the previous layer is the same as
	    //           the last feature that applied to the current layer (to satisfy (2))
	    //      - otherwise we create a new DisplayArea below the last feature that applied
	    //        to the current layer
		//2.初始化PendingArea数组
	    PendingArea[] areaForLayer = new PendingArea[maxWindowLayerCount];
	    final PendingArea root = new PendingArea(null, 0, null);
	    Arrays.fill(areaForLayer, root);
	
	    // Create DisplayAreas to cover all defined features.
	    //3.根据不同的Features构建显示区域
	    final int size = mFeatures.size();
	    for (int i = 0; i < size; i++) {
	        // Traverse the features with the order they are defined, so that the early defined
	        // feature will be on the top in the hierarchy.
	        final Feature feature = mFeatures.get(i);
	        PendingArea featureArea = null;
	        for (int layer = 0; layer < maxWindowLayerCount; layer++) {
	            if (feature.mWindowLayers[layer]) {
	                // This feature will be applied to this window layer.
	                //
	                // We need to find a DisplayArea for it:
	                // We can reuse the existing one if it was created for this feature for the
	                // previous layer AND the last feature that applied to the previous layer is
	                // the same as the feature that applied to the current layer (so they are ok
	                // to share the same parent DisplayArea).
	                if (featureArea == null || featureArea.mParent != areaForLayer[layer]) {
	                    // No suitable DisplayArea:
	                    // Create a new one under the previous area (as parent) for this layer.
	                    featureArea = new PendingArea(feature, layer, areaForLayer[layer]);
	                    areaForLayer[layer].mChildren.add(featureArea);
	                }
	                areaForLayer[layer] = featureArea;
	            } else {
	                // This feature won't be applied to this window layer. If it needs to be
	                // applied to the next layer, we will need to create a new DisplayArea for
	                // that.
	                featureArea = null;
	            }
	        }
	    }
	
	    // Create Tokens as leaf for every layer.
	    //4.创建叶子Token节点
	    PendingArea leafArea = null;
	    int leafType = LEAF_TYPE_TOKENS;
	    for (int layer = 0; layer < maxWindowLayerCount; layer++) {
	        int type = typeOfLayer(policy, layer);
	        // Check whether we can reuse the same Tokens with the previous layer. This happens
	        // if the previous layer is the same type as the current layer AND there is no
	        // feature that applies to only one of them.
	        if (leafArea == null || leafArea.mParent != areaForLayer[layer]
	                || type != leafType) {
	            // Create a new Tokens for this layer.
	            leafArea = new PendingArea(null /* feature */, layer, areaForLayer[layer]);
	            areaForLayer[layer].mChildren.add(leafArea);
	            leafType = type;
	            if (leafType == LEAF_TYPE_TASK_CONTAINERS) {
	                // We use the passed in TaskDisplayAreas for task container type of layer.
	                // Skip creating Tokens even if there is no TDA.
	                addTaskDisplayAreasToApplicationLayer(areaForLayer[layer]);
	                addDisplayAreaGroupsToApplicationLayer(areaForLayer[layer],
	                        displayAreaGroupHierarchyBuilders);
	                leafArea.mSkipTokens = true;
	            } else if (leafType == LEAF_TYPE_IME_CONTAINERS) {
	                // We use the passed in ImeContainer for ime container type of layer.
	                // Skip creating Tokens even if there is no ime container.
	                leafArea.mExisting = mImeContainer;
	                leafArea.mSkipTokens = true;
	            }
	        }
	        leafArea.mMaxLayer = layer;
	    }
	    //5.计算MaxLayer
	    root.computeMaxLayer();
	
	    // We built a tree of PendingAreas above with all the necessary info to represent the
	    // hierarchy, now create and attach real DisplayAreas to the root.
	    //6.生成DisplayArea层级结构
	    root.instantiateChildren(mRoot, displayAreaForLayer, 0, featureAreas);
	
	    // Notify the root that we have finished attaching all the DisplayAreas. Cache all the
	    // feature related collections there for fast access.
	    //7.保存Leaf数组
	    mRoot.onHierarchyBuilt(mFeatures, displayAreaForLayer, featureAreas);
	}

这个方法主要做了这几件事:

5.1 初始化一些参数

	    final WindowManagerPolicy policy = mRoot.mWmService.mPolicy;
	    final int maxWindowLayerCount = policy.getMaxWindowLayer() + 1;
	    final DisplayArea.Tokens[] displayAreaForLayer =
	            new DisplayArea.Tokens[maxWindowLayerCount];
	    final Map<Feature, List<DisplayArea<WindowContainer>>> featureAreas =
	            new ArrayMap<>(mFeatures.size());
	    for (int i = 0; i < mFeatures.size(); i++) {
	        featureAreas.put(mFeatures.get(i), new ArrayList<>());
	    }
  • maxWindowLayerCount:前面说过getMaxWindowLayer()返回的是36,即初始化maxWindowLayerCount为37
  • displayAreaForLayer:实例化一个DisplayArea.Tokens[37]数组
  • featureAreas:根据mFeatures(Feature的个数,前面说的5个Feature),创建featureAreas的ArrayMap集合
  • featureAreas.put(mFeatures.get(i), new ArrayList<>()):循环的把每个feature创建对应的ArrayList,如下表
ArrayMap i mFeatures.get(i) ArrayList
featureAreas 0 WindowedMagnification/FEATURE_WINDOWED_MAGNIFICATION new ArrayList<>()
1 HideDisplayCutout/FEATURE_HIDE_DISPLAY_CUTOUT new ArrayList<>()
2 OneHanded/FEATURE_ONE_HANDED new ArrayList<>()
3 FullscreenMagnification/FEATURE_FULLSCREEN_MAGNIFICATION new ArrayList<>()
4 ImePlaceholder/FEATURE_IME_PLACEHOLDER new ArrayList<>()
  • FEATURE_WINDOWED_MAGNIFICATION,在ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW模式下可以对窗口的某些区域进行放大的DisplayArea,对应dump中的WindowedMagnification
  • FEATURE_HIDE_DISPLAY_CUTOUT,隐藏DisplayCutout(刘海屏相关)的DisplayArea,对应dump中的DisplayCutout
  • FEATURE_ONE_HANDED,用于单手模式的DisplayArea,在dump中对应OneHanded
  • FEATURE_FULLSCREEN_MAGNIFICATION,在ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN模式下可以对整个屏幕进行放大的DisplayArea,对应dump中的FullscreenMagnification
  • FEATURE_IME_PLACEHOLDER,存放输入法窗口的DisplayArea,对应dump中的ImePlaceholder

5.2 初始化PendingArea数组

我们先来看看PendingArea定义是什么样的

    static class PendingArea {
        final int mMinLayer;
        final ArrayList<PendingArea> mChildren = new ArrayList<>();
        final Feature mFeature;
        final PendingArea mParent;
        int mMaxLayer;
        ......
        PendingArea(Feature feature, int minLayer, PendingArea parent) {
            mMinLayer = minLayer;
            mFeature = feature;
            mParent = parent;
        }
        ......
    }
  • mMinLayer:当前PendingArea可以容纳的窗口层级的最小值
  • mChildren:当前节点的子节点
  • mFeature:代表各个Feature
  • mParent:当前节点的父节点
  • mMaxLayer:当前PendingArea可以容纳的窗口层级的最大值

从构造方法上看主要传递的参数就是feature、最小层级和父节点 现在我们再来看看PendingArea数组是如何初始化的

	    PendingArea[] areaForLayer = new PendingArea[maxWindowLayerCount];
	    final PendingArea root = new PendingArea(null, 0, null);
	    Arrays.fill(areaForLayer, root);
  • PendingArea[] areaForLayer = new PendingArea[37],创建数组
  • 调用其构造方法,一个没有任何feature和父节点,最小层级为0的root变量
  • 把root填充到所有每个数组中,即
PendingArea数组(areaForLayer[37])初始化(mFeature.mName: mMinLayer: mMaxLayer)
areaForLayer[0]ROOT:0:0
......ROOT:0:0
areaForLayer[36]ROOT:0:0

,后面PendingArea的成员变量以(mFeature.mName: mMinLayer: mMaxLayer)的形式来表示 例如,WindowedMagnification:0:31则表示feature是WindowedMagnification的最小层级是0,最大层级为31。注意:当前代码中mMaxLayer尚未计算,因此为0,所以我们这边表示为WindowedMagnification:0:0

5.3 根据不同的Features构建显示区域

			// Create DisplayAreas to cover all defined features.
            final int size = mFeatures.size();
            for (int i = 0; i < size; i++) {//五个feature跑五次循环
                // Traverse the features with the order they are defined, so that the early defined
                // feature will be on the top in the hierarchy.
                //获取mFeatures中取出每个对应的feature
                final Feature feature = mFeatures.get(i);
                //创建一个空的featureArea
                PendingArea featureArea = null;
                //maxWindowLayerCount是37,前面讲过
                for (int layer = 0; layer < maxWindowLayerCount; layer++) {
                	//1.用来筛选出当前feature的layer中为true的层级
                    if (feature.mWindowLayers[layer]) {
                        // This feature will be applied to this window layer.
                        //
                        // We need to find a DisplayArea for it:
                        // We can reuse the existing one if it was created for this feature for the
                        // previous layer AND the last feature that applied to the previous layer is
                        // the same as the feature that applied to the current layer (so they are ok
                        // to share the same parent DisplayArea).
                        //2.判断(是否有资格认义父)当前的PendingArea对象是否为空 或者 PendingArea对象的父节点不等于当前节点
                        if (featureArea == null || featureArea.mParent != areaForLayer[layer]) {
                            // No suitable DisplayArea:
                            // Create a new one under the previous area (as parent) for this layer.
                            //feature认areaForLayer[layer]为父亲
                            featureArea = new PendingArea(feature, layer, areaForLayer[layer]);
                            //areaForLayer[layer]认featureArea为孩子
                            areaForLayer[layer].mChildren.add(featureArea);
                        }
                        //3.areaForLayer[layer]更新为当前的featureArea
                        areaForLayer[layer] = featureArea;
                    } else {
                        // This feature won't be applied to this window layer. If it needs to be
                        // applied to the next layer, we will need to create a new DisplayArea for
                        // that.
                        //PendingArea对象置空
                        featureArea = null;
                    }
                }
            }

首先,获取mFeatures中取出每个对应的feature,并创建一个创建一个空的featureArea。这段代码中最为关键的就是里面的for循环操作, 第一步if (feature.mWindowLayers[layer]) {...(进入第二步)...} else {featureArea = null;} 这个判断条件是用来筛选出当前feature的layer中为true的层级;如果当前feature的layer中为false,则把featureArea置空。 第二步if (featureArea == null || featureArea.mParent != areaForLayer[layer])之后再来判断(featureArea是否有资格认义父)当前的PendingArea对象是否为空 或者 PendingArea对象的父节点不等于当前节点

  • featureArea = new PendingArea(feature, layer, areaForLayer[layer]); 如果满足条件则当前feature认areaForLayer[layer]为父亲
  • areaForLayer[layer].mChildren.add(featureArea); 且areaForLayer[layer]认featureArea为孩子。

布飘零半生未逢明主,如公不弃,布愿拜为义父~

第三步areaForLayer[layer] = featureArea;areaForLayer[layer]更新为当前的featureArea。

下面我们以五个feature为例子来看看这段代码的实现

WindowedMagnification

按我们上面说的三个步骤把WindowedMagnification带入到我们的这段代码中 第一次循环时: 第一步:WindowedMagnification的mWindowLayers[0]=true。WindowedMagnification是0-31为true,因此32及其以后得全部置为空 第二步:featureArea为空,进入该条件。

  • featureArea = new PendingArea(WindowedMagnification, 0, areaForLayer[0]);【这里的参数0对应的是mMinLayer】 实例化featureArea(WindowedMagnification)并且让其认areaForLayer[0] (ROOT:0:0)为父亲【前面初始化时areaForLayer[0]-areaForLayer[36]全部都为ROOT节点】
  • areaForLayer[0].mChildren.add(featureArea); 之后ROOT:0:0认WindowedMagnification:0:0为儿子。【由于mMaxLayer还没有计算,因此为0】

第三步areaForLayer[0] = featureArea;把areaForLayer[0]更新为WindowedMagnification:0:0

第二次循环时: 第一步:WindowedMagnification的mWindowLayers[1]=true 第二步:featureArea不为空,且 featureArea.mParent是WindowedMagnification:0:0的父亲即ROOT:0:0,areaForLayer[1]也是ROOT:0:0,因此不进入条件。 第三步:把areaForLayer[1]更新为WindowedMagnification:0:0,没有变化。其实还是第一次循环的WindowedMagnification,因为第二步没有创建新的featureArea

后续循环到第31次均和第二次循环相同,因此我们得到下表

PendingArea数组ROOTWindowedMagnification
areaForLayer[0]ROOT:0:0WindowedMagnification:0:0
......ROOT:0:0WindowedMagnification:0:0
areaForLayer[31]ROOT:0:0WindowedMagnification:0:0
......ROOT:0:0null
areaForLayer[36]ROOT:0:0null

转换为树形结构图 在这里插入图片描述

注:其中0-36表示从areaForLayer[0]到areaForLayer[36]


HideDisplayCutout

按我们上面说的三个步骤把HideDisplayCutout带入到代码中 第一次循环时: 第一步:HideDisplayCutout的mWindowLayers[0]=true。HideDisplayCutout是HideDisplayCutout 0-14 16 18-23 26-35为true,其余的部置为空 第二步:featureArea为空,进入该条件。

  • featureArea = new PendingArea(HideDisplayCutout, 0, areaForLayer[0]);【这里的参数0对应的是mMinLayer】 实例化featureArea(HideDisplayCutout)并且让其认areaForLayer[0] (WindowedMagnification:0:0)为父亲【前面第一个feature循环后更新了areaForLayer[0-31]为WindowedMagnification:0:0】
  • areaForLayer[0].mChildren.add(featureArea); 之后WindowedMagnification:0:0认HideDisplayCutout:0:0为儿子。【由于mMaxLayer还没有计算,因此为0】

第三步areaForLayer[0] = featureArea;把areaForLayer[0]更新为HideDisplayCutout:0:0

第二次循环时: 第一步:HideDisplayCutout的mWindowLayers[1]=true 第二步:featureArea不为空,且 featureArea.mParent为areaForLayer[0]的父亲即WindowedMagnification:0:0,areaForLayer[1]还是WindowedMagnification:0:0,因此不进入条件。 第三步:把areaForLayer[1]更新为WindowedMagnification:0:0,没有变化。其实还是第一次循环的WindowedMagnification,因为第二步没有创建新的featureArea

一直到第14次循环均是如此,此时表格为

PendingArea数组ROOTWindowedMagnificationHideDisplayCutout
areaForLayer[0]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0
areaForLayer[14]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0
......ROOT:0:0WindowedMagnification:0:0null
areaForLayer[31]ROOT:0:0WindowedMagnification:0:0null
......ROOT:0:0nullnull
areaForLayer[36]ROOT:0:0nullnull

树状图 在这里插入图片描述

HideDisplayCutout的mWindowLayers[layer]15、17、24和25都为false,因此不会进入第二步的判断,会将featureArea置为空

我们继续看第16次循环 第一步:HideDisplayCutout的mWindowLayers[16]=true 第二步:featureArea为空。

  • featureArea = new PendingArea(HideDisplayCutout, 16, areaForLayer[16]);【这里的参数16对应的是mMinLayer】 实例化featureArea(HideDisplayCutout)并且让其认areaForLayer[16] (WindowedMagnification:0:0)为父亲【前面第一个feature循环后更新了areaForLayer[0-31]为WindowedMagnification:0:0】
  • areaForLayer[16].mChildren.add(featureArea); 之后WindowedMagnification:0:0认HideDisplayCutout:16:0为儿子。【由于mMaxLayer还没有计算,因此为0】

第三步areaForLayer[16] = featureArea;把areaForLayer[16]更新为HideDisplayCutout:16:0

第18次循环 与第16次同理,创建了一个PendingArea:”HideDisplayCutout:18:0“并且认areaForLayer[18] (WindowedMagnification:0:0)为父亲,WindowedMagnification:0:0认HideDisplayCutout:18:0为儿子,把areaForLayer[18]更新为HideDisplayCutout:18:0 第19到第23次循环 areaForLayer[19-23]更新为HideDisplayCutout:18:0

第26循环 创建了一个PendingArea:”HideDisplayCutout:26:0“并且认areaForLayer[26] (WindowedMagnification:0:0)为父亲,WindowedMagnification:0:0认HideDisplayCutout:26:0为儿子,把areaForLayer[26]更新为HideDisplayCutout:26:0 第27到第31次循环 areaForLayer[27-31]更新为HideDisplayCutout:26:0

此时表格更新为

PendingArea数组ROOTWindowedMagnificationHideDisplayCutout
areaForLayer[0]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutou:t0:0
areaForLayer[14]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0
areaForLayer[15]ROOT:0:0WindowedMagnification:0:0null
areaForLayer[16]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:16:0
areaForLayer[17]ROOT:0:0WindowedMagnification:0:0null
areaForLayer[18]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0
areaForLayer[23]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0
areaForLayer[24]ROOT:0:0WindowedMagnification:0:0null
areaForLayer[25]ROOT:0:0WindowedMagnification:0:0null
areaForLayer[26]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0
areaForLayer[31]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0
......ROOT:0:0nullnull
areaForLayer[36]ROOT:0:0nullnull

树状图 在这里插入图片描述

第32到第35次循环 从第32次开始时条件发生变化 第一步:HideDisplayCutout的mWindowLayers[32]=true。 第二步:featureArea不为空,此时featureArea.mParent即HideDisplayCutout26:0的父亲是WindowedMagnification:0:0,但是areaForLayer[32]是ROOT:0:0【前面WindowedMagnification只到了31,后续还是ROOT】,因此featureArea.mParent != areaForLayer[layer]为true,所以是进入该条件。

  • featureArea = new PendingArea(HideDisplayCutout, 32, areaForLayer[32]);【这里的参数32对应的是mMinLayer】 实例化featureArea(HideDisplayCutout)并且让其认areaForLayer[32] (ROOT:0:0)为父亲
  • areaForLayer[0].mChildren.add(featureArea); 之后ROOT:0:0认HideDisplayCutout:26:0为儿子。【由于mMaxLayer还没有计算,因此为0】

第三步areaForLayer[32] = featureArea;把areaForLayer[32]更新为HideDisplayCutout:32:0 从33次到第35次循环后,更新areaForLayer[32-35]为HideDisplayCutout:26:0

此时表格更新为

PendingArea数组ROOTWindowedMagnificationHideDisplayCutout
areaForLayer[0]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0
areaForLayer[14]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0
areaForLayer[15]ROOT:0:0WindowedMagnification:0:0null
areaForLayer[16]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:16:0
areaForLayer[17]ROOT:0:0WindowedMagnification:0:0null
areaForLayer[18]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout18:0
areaForLayer[23]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0
areaForLayer[24]ROOT:0:0WindowedMagnification:0:0null
areaForLayer[25]ROOT:0:0WindowedMagnification:0:0null
areaForLayer[26]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0
areaForLayer[31]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0
areaForLayer[32]ROOT:0:0nullHideDisplayCutout:32:0
......ROOT:0:0nullHideDisplayCutout:32:0
areaForLayer[35]ROOT:0:0nullHideDisplayCutout:32:0
areaForLayer[36]ROOT:0:0nullnull

树状图 在这里插入图片描述


OneHanded

同样按照三步法分析其构建过程 第一次循环时: 第一步:OneHanded的mWindowLayers[0]=true。OneHanded是0-23,26-32,34-35为true,其余全部置为空 第二步:featureArea为空,进入该条件。

  • featureArea = new PendingArea(OneHanded, 0, areaForLayer[0]);【这里的参数0对应的是mMinLayer】 实例化featureArea(OneHanded)并且让其认areaForLayer[0] (HideDisplayCutout:0:0)为父亲【上feature即HideDisplayCutout更新后的节点,可以对照表格】
  • areaForLayer[0].mChildren.add(featureArea); 之后HideDisplayCutout:0:0认OneHanded:0:0为儿子。【由于mMaxLayer还没有计算,因此为0】

第三步areaForLayer[0] = featureArea;把areaForLayer[0]更新为OneHanded:0:0

第二次循环时: 第一步:OneHanded的mWindowLayers[1]=true 第二步:featureArea不为空,且 featureArea.mParent为areaForLayer[0]的父亲即HideDisplayCutout:0:0,areaForLayer[1]是HideDisplayCutout:0:0,因此不进入条件。 第三步:把areaForLayer[1]更新为OneHanded:0:0 到第14次循环时,其父节点一直都是HideDisplayCutout:0:0

第15次循环,OneHanded.mWindowLayers[15]仍然为true,但HideDisplayCutout为空,因此其父节点WindowedMagnification:0:0,areaForLayer[15]更新为OneHanded:15:0 第16次循环,HideDisplayCutout为不空,因此当前节点的为父节点HideDisplayCutout:16:0,areaForLayer[16]更新为OneHanded:16:0 第17次循环与第15次循环同理,父节点WindowedMagnification:0:0,areaForLayer[17]更新为OneHanded:17:0 第18到第23次循环与第16次同理,父节点HideDisplayCutout:18:0,areaForLayer[18]更新为OneHanded:18:0 第26到第31次循环与第16次同理,HideDisplayCutout为不空,因此其父节点HideDisplayCutout:26:0,areaForLayer[26]更新为OneHanded:26:0 第32次循环,HideDisplayCutout为不空,此时areaForLayer[32]的父节点(root:0:0)与areaForLayer[31]的父节点(WindowedMagnification:0:0),因此当前节点的为父节点HideDisplayCutout:32:0,areaForLayer[32]更新为OneHanded:32:0 第34、35次循环,与第16次同理,父节点HideDisplayCutout:34:0,areaForLayer[34]更新为OneHanded:34:0

最终我的表格更新为

PendingArea数组ROOTWindowedMagnificationHideDisplayCutoutOneHanded
areaForLayer[0]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0
areaForLayer[14]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0
areaForLayer[15]ROOT:0:0WindowedMagnification:0:0nullOneHanded:15:0
areaForLayer[16]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:16:0OneHanded:16:0
areaForLayer[17]ROOT:0:0WindowedMagnification:0:0nullOneHanded:17:0
areaForLayer[18]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0OneHanded:18:0
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout18:0OneHanded:18:0
areaForLayer[23]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0OneHanded:18:0
areaForLayer[24]ROOT:0:0WindowedMagnification:0:0nullnull
areaForLayer[25]ROOT:0:0WindowedMagnification:0:0nullnull
areaForLayer[26]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0
areaForLayer[31]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0
areaForLayer[32]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:32:0
areaForLayer[33]ROOT:0:0nullHideDisplayCutout:32:0null
areaForLayer[34]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:34:0
areaForLayer[35]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:34:0
areaForLayer[36]ROOT:0:0nullnullnull

树状图 在这里插入图片描述


FullscreenMagnification

FullscreenMagnification是0-12 15-23 26-27 29-31 33-35为true,根据上面的规律不在赘述我们可以填写出表格内容

PendingArea数组ROOTWindowedMagnificationHideDisplayCutoutOneHandedFullscreenMagnification
areaForLayer[0]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0
areaForLayer[12]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0
areaForLayer[13]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0null
areaForLayer[14]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0null
areaForLayer[15]ROOT:0:0WindowedMagnification:0:0nullOneHanded:15:0FullscreenMagnification:15:0
areaForLayer[16]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:16:0OneHanded:16:0FullscreenMagnification:16:0
areaForLayer[17]ROOT:0:0WindowedMagnification:0:0nullOneHanded:17:0FullscreenMagnification:17:0
areaForLayer[18]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0OneHanded:18:0FullscreenMagnification:18:0
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout18:0OneHanded:18:0FullscreenMagnification:18:0
areaForLayer[23]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0OneHanded:18:0FullscreenMagnification:18:0
areaForLayer[24]ROOT:0:0WindowedMagnification:0:0nullnullnull
areaForLayer[25]ROOT:0:0WindowedMagnification:0:0nullnullnull
areaForLayer[26]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:26:0
areaForLayer[27]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:26:0
areaForLayer[28]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0null
areaForLayer[29]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:29:0
areaForLayer[30]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:29:0
areaForLayer[31]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:29:0
areaForLayer[32]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:32:0null
areaForLayer[33]ROOT:0:0nullHideDisplayCutout:32:0nullFullscreenMagnification:33:0
areaForLayer[34]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:34:0FullscreenMagnification:34:0
areaForLayer[35]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:34:0FullscreenMagnification:34:0
areaForLayer[36]ROOT:0:0nullnullnullnull

树状图 在这里插入图片描述


ImePlaceholder

ImePlaceholder是13-14为true,我们最后可以得到一个完整的表格

PendingArea数组ROOTWindowedMagnificationHideDisplayCutoutOneHandedFullscreenMagnificationImePlaceholder
areaForLayer[0]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0null
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0null
areaForLayer[12]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0null
areaForLayer[13]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0nullImePlaceholder:13:0
areaForLayer[14]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0nullImePlaceholder:13:0
areaForLayer[15]ROOT:0:0WindowedMagnification:0:0nullOneHanded:15:0FullscreenMagnification:15:0null
areaForLayer[16]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:16:0OneHanded:16:0FullscreenMagnification:16:0null
areaForLayer[17]ROOT:0:0WindowedMagnification:0:0nullOneHanded:17:0FullscreenMagnification:17:0null
areaForLayer[18]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0OneHanded:18:0FullscreenMagnification:18:0null
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout18:0OneHanded:18:0FullscreenMagnification:18:0null
areaForLayer[23]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0OneHanded:18:0FullscreenMagnification:18:0null
areaForLayer[24]ROOT:0:0WindowedMagnification:0:0nullnullnullnull
areaForLayer[25]ROOT:0:0WindowedMagnification:0:0nullnullnullnull
areaForLayer[26]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:26:0null
areaForLayer[27]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:26:0null
areaForLayer[28]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0nullnull
areaForLayer[29]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:29:0null
areaForLayer[30]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:29:0null
areaForLayer[31]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:29:0null
areaForLayer[32]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:32:0nullnull
areaForLayer[33]ROOT:0:0nullHideDisplayCutout:32:0nullFullscreenMagnification:33:0null
areaForLayer[34]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:34:0FullscreenMagnification:34:0null
areaForLayer[35]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:34:0FullscreenMagnification:34:0null
areaForLayer[36]ROOT:0:0nullnullnullnullnull

树状图 在这里插入图片描述


小结

实际上表格中的每一行很清晰的描述了PendingArea的数据结构

    static class PendingArea {
        final int mMinLayer;
        final ArrayList<PendingArea> mChildren = new ArrayList<>();
        final Feature mFeature;
        final PendingArea mParent;
        int mMaxLayer;

        PendingArea(Feature feature, int minLayer, PendingArea parent) {
            mMinLayer = minLayer;
            mFeature = feature;
            mParent = parent;
        }

这里的mMaxLayer尚未计算,后面创建叶子节点后才会计算,我们统一先按算作0 WindowedMagnification:0:0则表示mFeature:mMinLayer:mMaxLayer 例如:第一行

PendingArea数组ROOTWindowedMagnificationHideDisplayCutoutOneHandedFullscreenMagnificationImePlaceholder
areaForLayer[0]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0null

当Feature为ROOT时,mChildren是WindowedMagnification:0:0 ,parent为空;

当Feature为WindowedMagnification是,mChildren是HideDisplayCutout:0:0 mMinLayer、mMaxLayer为0,parent为ROOT0:0;

当Feature为HideDisplayCutout是,mChildren是OneHanded:0:0 mMinLayer、mMaxLayer为0,parent为WindowedMagnification:0:0

其他行同理

从整体来看ROOT的直系孩子,实际就是WindowedMagnification:0:0和HideDisplayCutout:32:0 也可通过树形图让我们更加清晰的了解各个层级的关系

5.4 创建叶子Token节点

	    // Create Tokens as leaf for every layer.
	    PendingArea leafArea = null;
	    int leafType = LEAF_TYPE_TOKENS;
	    //循环遍历每层
	    for (int layer = 0; layer < maxWindowLayerCount; layer++) {
	    	//根据层级获取type类型
	        int type = typeOfLayer(policy, layer);
	        // Check whether we can reuse the same Tokens with the previous layer. This happens
	        // if the previous layer is the same type as the current layer AND there is no
	        // feature that applies to only one of them.
	        //判断PendingArea对象是否为空 或者 PendingArea对象的父亲不等于当前areaForLayer中的节点 或者 新获取的type和叶子的type不相等
	        if (leafArea == null || leafArea.mParent != areaForLayer[layer]
	                || type != leafType) {
	            // Create a new Tokens for this layer.
	            //创建新的叶子节点,互认关系结为父子
	            leafArea = new PendingArea(null /* feature */, layer, areaForLayer[layer]);
	            areaForLayer[layer].mChildren.add(leafArea);
	            leafType = type;
	            //叶子类型为LEAF_TYPE_TASK_CONTAINERS做处理
	            if (leafType == LEAF_TYPE_TASK_CONTAINERS) {
	                // We use the passed in TaskDisplayAreas for task container type of layer.
	                // Skip creating Tokens even if there is no TDA.
	                addTaskDisplayAreasToApplicationLayer(areaForLayer[layer]);
	                addDisplayAreaGroupsToApplicationLayer(areaForLayer[layer],
	                        displayAreaGroupHierarchyBuilders);
	                leafArea.mSkipTokens = true;
	            //叶子类型为LEAF_TYPE_IME_CONTAINERS做处理
	            } else if (leafType == LEAF_TYPE_IME_CONTAINERS) {
	                // We use the passed in ImeContainer for ime container type of layer.
	                // Skip creating Tokens even if there is no ime container.
	                leafArea.mExisting = mImeContainer;
	                leafArea.mSkipTokens = true;
	            }
	        }
	        //更新叶子最大层级
	        leafArea.mMaxLayer = layer;
	    }

首先我们看下int type = typeOfLayer(policy, layer);

        private static int typeOfLayer(WindowManagerPolicy policy, int layer) {
            if (layer == APPLICATION_LAYER) {
                return LEAF_TYPE_TASK_CONTAINERS;
            } else if (layer == policy.getWindowLayerFromTypeLw(TYPE_INPUT_METHOD)
                    || layer == policy.getWindowLayerFromTypeLw(TYPE_INPUT_METHOD_DIALOG)) {
                return LEAF_TYPE_IME_CONTAINERS;
            } else {
                return LEAF_TYPE_TOKENS;
            }
        }

对三种层级做了特殊处理

  • 应用层级(APPLICATION_LAYER):其值为2,Leaf的类型为LEAF_TYPE_TASK_CONTAINERS。
  • 输入法层级(TYPE_INPUT_METHOD、TYPE_INPUT_METHOD_DIALOG):其值为13,14,Leaf的类型为LEAF_TYPE_IME_CONTAINERS。
  • 其他层级值对应的Leaf类型为LEAF_TYPE_TOKENS。

这里我们先总结一下整体流程步骤

第一步 int type = typeOfLayer(policy, layer); 判断type类型是三种中的哪一种

第二步 leafArea == null || leafArea.mParent != areaForLayer[layer] || type != leafType 判断PendingArea对象是否为空 或者 PendingArea对象的父亲不等于当前areaForLayer中的节点 或者 新获取的type和叶子的type不相等

  • leafArea = new PendingArea(null /* feature */, layer, areaForLayer[layer]); leafArea认areaForLayer[layer]为父亲
  • areaForLayer[layer].mChildren.add(leafArea); areaForLayer[layer]认leafArea为孩子
  • leafType = type; 更新leafType为type 注: 这里的areaForLayer[layer] 是上面构建Features更新后的结果,也就是我们的表格 这里我们以第一行为例
PendingArea数组ROOTWindowedMagnificationHideDisplayCutoutOneHandedFullscreenMagnificationImePlaceholder
areaForLayer[0]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0null

这里我们看areaForLayer[0] 其最后一次的更新结果,现在对应的实际上就是FullscreenMagnification:0:0 后续通过查表来看areaForLayer数组对应的是哪个节点

第2.5步leafType == LEAF_TYPE_TASK_CONTAINERSleafType == LEAF_TYPE_IME_CONTAINERS分别做特殊处理

第三步 leafArea.mMaxLayer = layer; 更新叶子最大层级

这里我们可以发现叶子节点的添加和其他Features的构建逻辑上类似,我们把第一步的三种类型分别来讨论代码流程。

type = LEAF_TYPE_TOKENS

对应层级0-1,3-14,17-36,这里就先不讨论第3次(层级2:APPLICATION_LAYER)、第14(层级13:TYPE_INPUT_METHOD)和第15次(层级14:TYPE_INPUT_METHOD_DIALOG)循环 第一次循环 第一步: int type = typeOfLayer(policy, 0); type = LEAF_TYPE_TOKENS 第二步: leafArea为null,进入条件

  • leafArea = new PendingArea(null /* feature */, 0, areaForLayer[0]); leafArea认areaForLayer[0] (FullscreenMagnification:0:0)为父亲
  • areaForLayer[layer].mChildren.add(leafArea); areaForLayer[0] (FullscreenMagnification:0:0)认leafArea为孩子
  • leafType = type; 更新leafType为LEAF_TYPE_TOKENS

第三步leafArea.mMaxLayer = 0; 更新叶子最大层级为0

第二次循环 第一步: int type = typeOfLayer(policy, 1); type = LEAF_TYPE_TOKENS 第二步: leafArea不为null;上次循环后leafArea.mParent是 FullscreenMagnification:0:0 , areaForLayer[1] 查表得出同样是 FullscreenMagnification:0:0 ;上次循环后type和leafType都是LEAF_TYPE_TOKENS。因此不进入条件

第三步leafArea.mMaxLayer = 1; 更新叶子最大层级为1

到这里我们可以通过规律发现,实际上这段代码就是在不同的feature底部上添加叶子节点

第四次循环:同理第一次循环,leafArea认areaForLayer[3] (FullscreenMagnification:0:0)为父亲,areaForLayer[3] (FullscreenMagnification:0:0)认leafArea为孩子,更新叶子最大层级为3 第5到第12次循环:同理第二次循环,最后更新叶子最大层级为12

后续不在赘述,见下表

PendingArea数组ROOTWindowedMagnificationHideDisplayCutoutOneHandedFullscreenMagnificationImePlaceholderleaf
areaForLayer[0]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0nullleaf:0:1
areaForLayer[1]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0nullleaf:0:1
areaForLayer[2]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0null尚未讨论
areaForLayer[3]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0nullleaf:3:12
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0nullleaf:3:12
areaForLayer[12]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0nullleaf:3:12
areaForLayer[13]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0nullImePlaceholder:13:0尚未讨论
areaForLayer[14]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0nullImePlaceholder:13:0尚未讨论
areaForLayer[15]ROOT:0:0WindowedMagnification:0:0nullOneHanded:15:0FullscreenMagnification:15:0nullleaf:15:15
areaForLayer[16]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:16:0OneHanded:16:0FullscreenMagnification:16:0nullleaf:16:16
areaForLayer[17]ROOT:0:0WindowedMagnification:0:0nullOneHanded:17:0FullscreenMagnification:17:0nullleaf:17:17
areaForLayer[18]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0OneHanded:18:0FullscreenMagnification:18:0nullleaf:18:23
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout18:0OneHanded:18:0FullscreenMagnification:18:0nullleaf:18:23
areaForLayer[23]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0OneHanded:18:0FullscreenMagnification:18:0nullleaf:18:23
areaForLayer[24]ROOT:0:0WindowedMagnification:0:0nullnullnullnullleaf:24:25
areaForLayer[25]ROOT:0:0WindowedMagnification:0:0nullnullnullnullleaf:24:25
areaForLayer[26]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:26:0nullleaf:26:27
areaForLayer[27]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:26:0nullleaf:26:27
areaForLayer[28]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0nullnullleaf:28:28
areaForLayer[29]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:29:0nullleaf:29:31
areaForLayer[30]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:29:0nullleaf:29:31
areaForLayer[31]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:29:0nullleaf:29:31
areaForLayer[32]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:32:0nullnullleaf:32:32
areaForLayer[33]ROOT:0:0nullHideDisplayCutout:32:0nullFullscreenMagnification:33:0nullleaf:33:33
areaForLayer[34]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:34:0FullscreenMagnification:34:0nullleaf:34:35
areaForLayer[35]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:34:0FullscreenMagnification:34:0nullleaf:34:35
areaForLayer[36]ROOT:0:0nullnullnullnullnullleaf:36:36
type = LEAF_TYPE_TASK_CONTAINERS

对应层级为第2层,即layer为2

// We use the passed in TaskDisplayAreas for task container type of layer.
// Skip creating Tokens even if there is no TDA.
addTaskDisplayAreasToApplicationLayer(areaForLayer[layer]);
addDisplayAreaGroupsToApplicationLayer(areaForLayer[layer],
        displayAreaGroupHierarchyBuilders);
leafArea.mSkipTokens = true;
  • addTaskDisplayAreasToApplicationLayer(areaForLayer[2]); 对应代码为
        /** Adds all {@link TaskDisplayArea} to the application layer. */
        private void addTaskDisplayAreasToApplicationLayer(PendingArea parentPendingArea) {
            final int count = mTaskDisplayAreas.size();
            for (int i = 0; i < count; i++) {
                PendingArea leafArea =
                        new PendingArea(null /* feature */, APPLICATION_LAYER, parentPendingArea);
                leafArea.mExisting = mTaskDisplayAreas.get(i);
                leafArea.mMaxLayer = APPLICATION_LAYER;
                parentPendingArea.mChildren.add(leafArea);
            }
        }

【DisplayAreaPolicy.DefaultProvider】中的第1步,我们可以知道,实际上mTaskDisplayAreas.size()为1 在这里插入图片描述其中leafArea.mExisting = mTaskDisplayAreas.get(i);

        /** If not {@code null}, use this instead of creating a {@link DisplayArea.Tokens}. */
        @Nullable DisplayArea mExisting;

mExisting是PendingArea成员变量,为DisplayArea类型对象,后面调用createArea()方法【后面会讲到这个方法】时会判断mExisting的值做处理,如果mExisting不为空,那么直接用mExisting,而不会再重新创建一个DisplayArea.Tokens对象。

在第二层添加的就是DefaultTaskDisplayArea

  • addDisplayAreaGroupsToApplicationLayer(areaForLayer[2],displayAreaGroupHierarchyBuilders); 对应代码为
        /** Adds roots of the DisplayAreaGroups to the application layer. */
        private void addDisplayAreaGroupsToApplicationLayer(
                DisplayAreaPolicyBuilder.PendingArea parentPendingArea,
                @Nullable List<HierarchyBuilder> displayAreaGroupHierarchyBuilders) {
            if (displayAreaGroupHierarchyBuilders == null) {
                return;
            }
            final int count = displayAreaGroupHierarchyBuilders.size();
            for (int i = 0; i < count; i++) {
                DisplayAreaPolicyBuilder.PendingArea
                        leafArea = new DisplayAreaPolicyBuilder.PendingArea(
                        null /* feature */, APPLICATION_LAYER, parentPendingArea);
                leafArea.mExisting = displayAreaGroupHierarchyBuilders.get(i).mRoot;
                leafArea.mMaxLayer = APPLICATION_LAYER;
                parentPendingArea.mChildren.add(leafArea);
            }
        }

【DisplayAreaPolicy.DefaultProvider】中的第5步(5.生成DisplayArea层级结构)开头说过displayAreaGroupHierarchyBuilders实际为null,因此不需要关注 在这里插入图片描述

  • leafArea.mSkipTokens = true;
        /**
         * Whether to skip creating a {@link DisplayArea.Tokens} if {@link #mExisting} is
         * {@code null}.
         *
         * <p>This will be set for {@link HierarchyBuilder#LEAF_TYPE_IME_CONTAINERS} and
         * {@link HierarchyBuilder#LEAF_TYPE_TASK_CONTAINERS}, because we don't want to create
         * {@link DisplayArea.Tokens} for them even if they are not set.
         */
        boolean mSkipTokens = false;

mSkipTokens是PendingArea成员变量,为DisplayArea类型对象,将为当前节点创建的leafArea的mSkipTokens设置为true,后面调用createArea()方法【后面会讲到这个方法】时会判断mSkipTokens的值,为true就返回null 也就是说后续在根据PendingArea数组生成DisplayArea层级结构的时候,就不会为这个PendingArea对象生成一个DisplayArea对象了。 相当于是用TaskDisplayArea对象替换了为当前节点生成的Leaf。

type = LEAF_TYPE_IME_CONTAINERS

对应层级为第13、14层

 // We use the passed in ImeContainer for ime container type of layer.
 // Skip creating Tokens even if there is no ime container.
 leafArea.mExisting = mImeContainer;
 leafArea.mSkipTokens = true;
  • leafArea.mExisting = mImeContainer;

【DisplayAreaPolicy.DefaultProvider】中的第3.1步有在HierarchyBuilder.mImeContainer的ImeContainer 在这里插入图片描述 和 type = LEAF_TYPE_TASK_CONTAINERS的部分同理 即不再为当前节点生成DisplayArea.Tokens,而是用之前保存在HierarchyBuilder.mImeContainer的ImeContainer。

  • leafArea.mSkipTokens = true; 和前面 type = LEAF_TYPE_TASK_CONTAINERS的部分同理
小结

这里我们更新一下表格

PendingArea数组ROOTWindowedMagnificationHideDisplayCutoutOneHandedFullscreenMagnificationImePlaceholderleaf
areaForLayer[0]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0nullleaf:0:1
areaForLayer[1]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0nullleaf:0:1
areaForLayer[2]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0nullDefaultTaskDisplayArea:2:2
areaForLayer[3]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0nullleaf:3:12
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0nullleaf:3:12
areaForLayer[12]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0FullscreenMagnification:0:0nullleaf:3:12
areaForLayer[13]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0nullImePlaceholder:13:0mImeContainer:13:14
areaForLayer[14]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:0:0OneHanded:0:0nullImePlaceholder:13:0mImeContainer:13:14
areaForLayer[15]ROOT:0:0WindowedMagnification:0:0nullOneHanded:15:0FullscreenMagnification:15:0nullleaf:15:15
areaForLayer[16]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:16:0OneHanded:16:0FullscreenMagnification:16:0nullleaf:16:16
areaForLayer[17]ROOT:0:0WindowedMagnification:0:0nullOneHanded:17:0FullscreenMagnification:17:0nullleaf:17:17
areaForLayer[18]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0OneHanded:18:0FullscreenMagnification:18:0nullleaf:18:23
......ROOT:0:0WindowedMagnification:0:0HideDisplayCutout18:0OneHanded:18:0FullscreenMagnification:18:0nullleaf:18:23
areaForLayer[23]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:18:0OneHanded:18:0FullscreenMagnification:18:0nullleaf:18:23
areaForLayer[24]ROOT:0:0WindowedMagnification:0:0nullnullnullnullleaf:24:25
areaForLayer[25]ROOT:0:0WindowedMagnification:0:0nullnullnullnullleaf:24:25
areaForLayer[26]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:26:0nullleaf:26:27
areaForLayer[27]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:26:0nullleaf:26:27
areaForLayer[28]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0nullnullleaf:28:28
areaForLayer[29]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:29:0nullleaf:29:31
areaForLayer[30]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:29:0nullleaf:29:31
areaForLayer[31]ROOT:0:0WindowedMagnification:0:0HideDisplayCutout:26:0OneHanded:26:0FullscreenMagnification:29:0nullleaf:29:31
areaForLayer[32]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:32:0nullnullleaf:32:32
areaForLayer[33]ROOT:0:0nullHideDisplayCutout:32:0nullFullscreenMagnification:33:0nullleaf:33:33
areaForLayer[34]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:34:0FullscreenMagnification:34:0nullleaf:34:35
areaForLayer[35]ROOT:0:0nullHideDisplayCutout:32:0OneHanded:34:0FullscreenMagnification:34:0nullleaf:34:35
areaForLayer[36]ROOT:0:0nullnullnullnullnullleaf:36:36

转换为树状图 在这里插入图片描述

5.5 计算MaxLayer

root.computeMaxLayer();

代码讲解

调用的是PendingArea的方法

		int computeMaxLayer() {
            for (int i = 0; i < mChildren.size(); i++) {
                mMaxLayer = Math.max(mMaxLayer, mChildren.get(i).computeMaxLayer());
            }
            return mMaxLayer;
        }

如何理解各个层级最大值是如何计算的呢? 我们需要理清思路,大家可以先思考三个问题: 1.代码中mChildren是谁的? 2.mChildren.size()究竟是多大? 3.mChildren.get(i)是谁? 下面我们一起来看看这三个问题

  • 代码中mChildren是谁的? 我们知道mChildren是PendingArea中的一个ArrayList< PendingArea >类型对象,这里是调用的是root.computeMaxLayer();,显然是root的
  • mChildren.size()究竟是多大? 我们既然知道了mChildren属于root这个变量,但是从代码中并未找到root.mChildren相关的操作, mChildren.size()是多大呢? 我们先回顾一下前面之前创建的root
            final PendingArea root = new PendingArea(null, 0, null);
            Arrays.fill(areaForLayer, root);

我们可以看到实际上这里areaForLayer, root两者已经关联了起来,还记得前面添加feature结构时的流程吗?里面有对areaForLayer数组进行更新,也就是说当前mChildren.size()就是root有几个孩子 在这里插入图片描述 root的直系孩子就是WindowedMagnification:0:0和HideDisplayCutout:32:0,还有Leaf:36:36 我们直接从层级树来看,更容易理解 在这里插入图片描述root的mChildren.size()=3

  • mChildren.get(i)是谁? 知道了mChildren对应的是哪个几个Feature,也就知道mChildren.get(i)实际上就是各个Feature
循环案例

第一次循环时,从root出发,其mChildren.size()=3,对应代码实际上是这样:

		int computeMaxLayer() {
            for (int i = 0; i < 3; i++) {
                mMaxLayer = Math.max(mMaxLayer, mChildren.get(0).computeMaxLayer());
            }
            return mMaxLayer;
        }

mChildren.get(0).computeMaxLayer()在进入递归循环,套娃开始

root的mChildren.get(0)是WindowedMagnification,其有7个孩子 在这里插入图片描述

WindowedMagnification的mChildren.get(0)是HideDisplayCutout:0-14

在这里插入图片描述 HideDisplayCutout的mChildren.get(0)是OneHanded:0-14 在这里插入图片描述

OneHanded的mChildren.get(0)是FullscreenMagnification:0-12 在这里插入图片描述 FullscreenMagnification的mChildren.size是3,i = 0,对应代码

		int computeMaxLayer() {
            for (int i = 0; i < 3; i++) {
                mMaxLayer = Math.max(mMaxLayer, mChildren.get(0).computeMaxLayer());
            }
            return mMaxLayer;
        }

一直往下走,递归到没有孩子的叶子节点,这里我们可以看到FullscreenMagnification的mChildren.get(0)是Leaf:0-1 叶子节点没有孩子,不在进入递归(套娃停止 ),之前更新过每个叶子节点的mMaxLayer 简单来说,就是 FullscreenMagnification的mChildren.get(0).computeMaxLayer()为Leaf:0-1,return 1 ,此时mMaxLayer = 1 FullscreenMagnification的mChildren.get(1).computeMaxLayer()为DefaultTaskDisplayArea:2-2,return 2,此时mMaxLayer = 2 FullscreenMagnification的mChildren.get(2).computeMaxLayer()为Leaf:3-12,return 12,此时mMaxLayer = 12 三者比较完大小后再次return mMaxLayer,即FullscreenMagnification的mMaxLayer为12

这个递归的规律实际上就是,每个拥有孩子的节点(ROOT除外)的mMaxLayer,就是其孩子节点中最大的mMaxLayer

最后我们补充完整表格

PendingArea数组ROOTWindowedMagnificationHideDisplayCutoutOneHandedFullscreenMagnificationImePlaceholderleaf
areaForLayer[0]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:0:14OneHanded:0:14FullscreenMagnification:0:12nullleaf:0:1
areaForLayer[1]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:0:14OneHanded:0:14FullscreenMagnification:0:12nullleaf:0:1
areaForLayer[2]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:0:14OneHanded:0:14FullscreenMagnification:0:12nullDefaultTaskDisplayArea:2:2
areaForLayer[3]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:0:14OneHanded:0:14FullscreenMagnification:0:12nullleaf:3:12
......ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:0:14OneHanded:0:14FullscreenMagnification:0:12nullleaf:3:12
areaForLayer[12]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:0:14OneHanded:0:14FullscreenMagnification:0:12nullleaf:3:12
areaForLayer[13]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:0:14OneHanded:0:14nullImePlaceholder:13:14mImeContainer:13:14
areaForLayer[14]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:0:14OneHanded:0:14nullImePlaceholder:13:14mImeContainer:13:14
areaForLayer[15]ROOT:0:0WindowedMagnification:0:31nullOneHanded:15:15FullscreenMagnification:15:15nullleaf:15:15
areaForLayer[16]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:16:16OneHanded:16:16FullscreenMagnification:16:16nullleaf:16:16
areaForLayer[17]ROOT:0:0WWindowedMagnification:0:31nullOneHanded:17:17FullscreenMagnification:17:17nullleaf:17:17
areaForLayer[18]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:18:23OneHanded:18:23FullscreenMagnification:18:23nullleaf:18:23
......ROOT:0:0WindowedMagnification:0:31HideDisplayCutout18:23OneHanded:18:23FullscreenMagnification:18:23nullleaf:18:23
areaForLayer[23]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:18:23OneHanded:18:23FullscreenMagnification:18:23nullleaf:18:23
areaForLayer[24]ROOT:0:0WindowedMagnification:0:31nullnullnullnullleaf:24:25
areaForLayer[25]ROOT:0:0WindowedMagnification:0:31nullnullnullnullleaf:24:25
areaForLayer[26]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:26:27OneHanded:26:27FullscreenMagnification:26:27nullleaf:26:27
areaForLayer[27]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:26:27OneHanded:26:27FullscreenMagnification:26:27nullleaf:26:27
areaForLayer[28]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:26:31OneHanded:26:31nullnullleaf:28:28
areaForLayer[29]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:26:31OneHanded:26:31FullscreenMagnification:29:31nullleaf:29:31
areaForLayer[30]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:26:31OneHanded:26:31FullscreenMagnification:29:31nullleaf:29:31
areaForLayer[31]ROOT:0:0WindowedMagnification:0:31HideDisplayCutout:26:31OneHanded:26:31FullscreenMagnification:29:31nullleaf:29:31
areaForLayer[32]ROOT:0:0nullHideDisplayCutout:32:32OneHanded:32:32nullnullleaf:32:32
areaForLayer[33]ROOT:0:0nullHideDisplayCutout:32:35nullFullscreenMagnification:33:33nullleaf:33:33
areaForLayer[34]ROOT:0:0nullHideDisplayCutout:32:35OneHanded:34:35FullscreenMagnification:34:35nullleaf:34:35
areaForLayer[35]ROOT:0:0nullHideDisplayCutout:32:35OneHanded:34:35FullscreenMagnification:34:35nullleaf:34:35
areaForLayer[36]ROOT:0:0nullnullnullnullnullleaf:36:36

5.6 生成DisplayArea层级结构

// We built a tree of PendingAreas above with all the necessary info to represent the
// hierarchy, now create and attach real DisplayAreas to the root.
root.instantiateChildren(mRoot, displayAreaForLayer, 0, featureAreas);

调用的是DisplayAreaPolicyBuilder.PendingArea.instantiateChildren方法 在看这个方法之前我们先看看传递的参数分别代表什么

参数解析
  • mRoot 在DisplayAreaPolicyBuilder.HierarchyBuilder中

    private final RootDisplayArea mRoot;
    HierarchyBuilder(RootDisplayArea root) {
        mRoot = root;
    }
    

    在HierarchyBuilder构造方法中初始化,该构造方法(前面我们讲过,文章回顾开头)是在DisplayAreaPolicy.DefaultProvider的instantiate方法中调用的

    public DisplayAreaPolicy instantiate(WindowManagerService wmService,
                    DisplayContent content, RootDisplayArea root,
                    DisplayArea.Tokens imeContainer) {
                    .....
        final HierarchyBuilder rootHierarchy = new HierarchyBuilder(root);
        ......
    

    这里看root指的是RootDisplayArea,其中DisplayContent继承RootDisplayArea。 DisplayAreaPolicy在DisplayContent.java中初始化时会调用instantiate,传递参数为this

    mDisplayAreaPolicy = mWmService.getDisplayAreaPolicyProvider().instantiate(
            mWmService, this /* content */, this /* root */,
            mImeWindowsContainer)
    

    这里传递的this就是DisplayContent,实际上mRoot就是DisplayContent

  • displayAreaForLayer 对应的就是我们在【5.1节】中讲到的初始化 final DisplayArea.Tokens[] displayAreaForLayer = new DisplayArea.Tokens[maxWindowLayerCount]; maxWindowLayerCount为37,即displayAreaForLayer是一个DisplayArea.Tokens[37]空数组

  • featureAreas 同样对应我们在【5.1节】中讲到的初始化

    	    final Map<Feature, List<DisplayArea<WindowContainer>>> featureAreas =
    	            new ArrayMap<>(mFeatures.size());
    	    for (int i = 0; i < mFeatures.size(); i++) {
    	        featureAreas.put(mFeatures.get(i), new ArrayList<>());
    	    }
    

    featureAreas对应的就是我们的五个Feature

代码解读
void instantiateChildren(DisplayArea<DisplayArea> parent, DisplayArea.Tokens[] areaForLayer,
                         int level, Map<Feature, List<DisplayArea<WindowContainer>>> areas) {
    //1.先根据当前节点的mChildren的mMinLayer(最小层级)进行排序
    mChildren.sort(Comparator.comparingInt(pendingArea -> pendingArea.mMinLayer));
    //2.循环依次把之前所构建的PendingArea转换为DisplayArea
    for (int i = 0; i < mChildren.size(); i++) {//循环遍历当前节点的mChildren
    	//获取当前mChildren
        final PendingArea child = mChildren.get(i);
        //PendingArea转换为DisplayArea
        final DisplayArea area = child.createArea(parent, areaForLayer);
        //PendingArea对象为空,则跳过该次循环
        if (area == null) {
            // TaskDisplayArea and ImeContainer can be set at different hierarchy, so it can
            // be null.
            continue;
        }
        //把转换后的DisplayArea加入到其父节点,第一次入参是mRoot对应我们这里的parent,就是添加到DisplayContent
        parent.addChild(area, WindowContainer.POSITION_TOP);
        if (child.mFeature != null) {
            areas.get(child.mFeature).add(area);
        }
        //3.最后在递归遍历到每个节点,从而使转换完成
        child.instantiateChildren(area, areaForLayer, level + 1, areas);
    }
}
整体逻辑

入参对应 mRoot(根节点DisplayContent)对应的是parent displayAreaForLayer(空数组)对应的是areaForLayer featureAreas(五个Feature)对应的是areas

该方法简单来说,其作用就是把我们之前所构建的PendingArea树转换为DisplayArea。 结合对应参数我们看看大体流程,总结下来就是三步 第一步.先根据当前节点的mChildren的mMinLayer(最小层级)进行排序 mChildren.sort(Comparator.comparingInt(pendingArea -> pendingArea.mMinLayer)); 第二步.循环依次把之前所构建的PendingArea转换为DisplayArea。之前构建PendingArea是临时的替身,而DisplayArea是我们现在需要构建的真身。我们曾经以ROOT:0:0的方式表现为临时根节点,这里正式变成了DisplayContent。

  • final PendingArea child = mChildren.get(i); 获取当前节点的第i个mChildren
  • final DisplayArea area = child.createArea(parent, areaForLayer); 之前所构建的PendingArea转换为DisplayArea,后面会细讲createArea方法
  • if (area == null) { continue; } 目前area为null的情况对应的就是createArea方法中mSkipTokens为true的情况,而当前只有TaskDisplayArea和ImeContainer的mSkipTokens为true
  • parent.addChild(area, WindowContainer.POSITION_TOP); 把转换后的DisplayArea加入到其父节点,第一次入参是mRoot对应我们这里的parent,也就是说添加到DisplayContent。addChild为各个节点添加的核心方法,后面会有讲到
  • if (child.mFeature != null) { areas.get(child.mFeature).add(area); } 当前节点的mFeature不为空(不为空的就是五个Feature类型的节点),就把该DisplayArea对象加入到当前Feature的List中。

第三步.最后在递归遍历到每个节点,从而使转换完成 child.instantiateChildren(area, areaForLayer, level + 1, areas);,其递归过程与前面计算mMaxLayer的过程相似

这里我们重点讲下第二步的转换 我们先看这句final DisplayArea area = child.createArea(parent, areaForLayer);中的createArea方法

createArea
private DisplayArea createArea(DisplayArea<DisplayArea> parent,
                                       DisplayArea.Tokens[] areaForLayer) {
            //1
            if (mExisting != null) {
                if (mExisting.asTokens() != null) {
                    // Store the WindowToken container for layers
                    fillAreaForLayers(mExisting.asTokens(), areaForLayer);
                }
                return mExisting;
            }
            //2
            if (mSkipTokens) {
                return null;
            }
            //3
            DisplayArea.Type type;
            if (mMinLayer > APPLICATION_LAYER) {
                type = DisplayArea.Type.ABOVE_TASKS;
            } else if (mMaxLayer < APPLICATION_LAYER) {
                type = DisplayArea.Type.BELOW_TASKS;
            } else {
                type = DisplayArea.Type.ANY;
            }
            //4
            if (mFeature == null) {
                final DisplayArea.Tokens leaf = new DisplayArea.Tokens(parent.mWmService, type,
                        "Leaf:" + mMinLayer + ":" + mMaxLayer);
                fillAreaForLayers(leaf, areaForLayer);
                return leaf;
            } else {
                return mFeature.mNewDisplayAreaSupplier.create(parent.mWmService, type,
                        mFeature.mName + ":" + mMinLayer + ":" + mMaxLayer, mFeature.mId);
            }
        }

这个方法我们每个if为一个部分来看 part 1

            if (mExisting != null) {
                if (mExisting.asTokens() != null) {
                    // Store the WindowToken container for layers
                    fillAreaForLayers(mExisting.asTokens(), areaForLayer);
                }
                return mExisting;
            }

当mExisting不为null,即【5.4 创建叶子Token节点】中分析的 type = LEAF_TYPE_TASK_CONTAINERS(应用leafArea.mExisting = mTaskDisplayAreas.get(i);) 和type = LEAF_TYPE_IME_CONTAINERS(输入法leafArea.mExisting = mImeContainer;)的情况,此时不需要再创建DisplayArea对象,直接用mExisting。

  • mExisting为mTaskDisplayAreas.get(i) mTaskDisplayAreas.get(i)为TaskDisplayArea类型 private final ArrayList<TaskDisplayArea> mTaskDisplayAreas = new ArrayList<>(); 并不是以token的形式保存,因此mExisting.asTokens()为null TaskDisplayArea继承DisplayArea,其中返回的也是null,直接使用mExisting

        /** Cheap way of doing cast and instanceof. */
        DisplayArea.Tokens asTokens() {
            return null;
        }
    
  • mExisting为mImeContainer mImeContainer本身就是Token的形式保存 private DisplayArea.Tokens mImeContainer; 在DisplayArea.Tokens中 final DisplayArea.Tokens asTokens() { return this; } 因此mExisting.asTokens()为true,调用fillAreaForLayers(mExisting.asTokens(), areaForLayer);

            private void fillAreaForLayers(DisplayArea.Tokens leaf, DisplayArea.Tokens[] areaForLayer) {
                for (int i = mMinLayer; i <= mMaxLayer; i++) {
                    areaForLayer[i] = leaf;
                }
            }
    

    输入法的mMinLayer是13,mMaxLayer是14,areaForLayer[i] = leaf也就是将mImeContainer设置给了areaForLayer数组

part 2

           if (mSkipTokens) {
                return null;
            }

mSkipTokens同样只有在【5.4 创建叶子Token节点】中TaskDisplayArea(应用层级)和ImeContainer(输入法层级)设置过,和mExisting在同一逻辑下设置

part 3

            DisplayArea.Type type;
            if (mMinLayer > APPLICATION_LAYER) {
                type = DisplayArea.Type.ABOVE_TASKS;
            } else if (mMaxLayer < APPLICATION_LAYER) {
                type = DisplayArea.Type.BELOW_TASKS;
            } else {
                type = DisplayArea.Type.ANY;
            }

这里根据mMinLayer和mMaxLayer的值与APPLICATION_LAYER(其值为2)的比较关系,将DisplayArea分为三种:

  • mMinLayer大于APPLICATION_LAYER,这类DisplayArea类型为ABOVE_TASKS。
  • mMaxLayer小于APPLICATION_LAYER,这类DisplayArea类型为BELOW_TASKS。
  • 其他情况下的DisplayArea类型为ANY。

part 4

            if (mFeature == null) {
                final DisplayArea.Tokens leaf = new DisplayArea.Tokens(parent.mWmService, type,
                        "Leaf:" + mMinLayer + ":" + mMaxLayer);
                fillAreaForLayers(leaf, areaForLayer);
                return leaf;
            } else {
                return mFeature.mNewDisplayAreaSupplier.create(parent.mWmService, type,
                        mFeature.mName + ":" + mMinLayer + ":" + mMaxLayer, mFeature.mId);
            }

mFeature是我们前面讲过的DisplayAreaPolicyBuilder.PendingArea的成员变量,代表着各个Feature

  • mFeature为null 直接创建一个DisplayArea.Tokens对象,然后把其填充到areaForLayer数组中。 一般来说叶子节点是没有mFeature的,所以这里事实上就是把当前如果是叶子节点,那么创建新的DisplayArea.Tokens对象,并把该叶子的其mMinLayer和mMaxLayer一并给新对象

  • mFeature不为null 调用mFeature.mNewDisplayAreaSupplier.create创建DisplayArea

        interface NewDisplayAreaSupplier {
            DisplayArea create(WindowManagerService wms, DisplayArea.Type type, String name,
                               int featureId);
        }
    

    前面构建Feature时讲过(见4.1),Feature中的mNewDisplayAreaSupplier是通过在Feature.Builder中传递的,其中定义为

    static class Feature {
        	......
            private final NewDisplayAreaSupplier mNewDisplayAreaSupplier;
    		......
            private Feature(String name, int id, boolean[] windowLayers,
                            NewDisplayAreaSupplier newDisplayAreaSupplier) {
                mName = name;
                mId = id;
                mWindowLayers = windowLayers;
                mNewDisplayAreaSupplier = newDisplayAreaSupplier;
            }
    		static class Builder {
    			......
    			private NewDisplayAreaSupplier mNewDisplayAreaSupplier = DisplayArea::new;
    			......
                Feature build() {
                    if (mExcludeRoundedCorner) {
                        // Always put the rounded corner layer to the top most layer.
                        mLayers[mPolicy.getMaxWindowLayer()] = false;
                    }
                    return new Feature(mName, mId, mLayers.clone(), mNewDisplayAreaSupplier);
                }
    

    我们发现Builder中定义为private NewDisplayAreaSupplier mNewDisplayAreaSupplier = DisplayArea::new;,实际上这里mFeature.mNewDisplayAreaSupplier.create()方法调用就是DisplayArea构造方法 补充说明一下:这里的写法用到的是Java 8 的新特性,即方法引用和函数式接口。mNewDisplayAreaSupplier是一个函数式接口的实例,通过使用DisplayArea::new方法引用,使得它的create方法实际上是调用了DisplayArea类的构造函数,并返回一个新的DisplayArea对象。

        DisplayArea(WindowManagerService wms, Type type, String name, int featureId) {
            super(wms);
            // TODO(display-area): move this up to ConfigurationContainer
            mOrientation = SCREEN_ORIENTATION_UNSET;
            mType = type;
            mName = name;
            mFeatureId = featureId;
            mRemoteToken = new RemoteToken(this);
            mOrganizerController =
                    wms.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController;
        }
    

    把当前节点的Feature的mName、mMinLayer、mMaxLayer和mId给新的DisplayArea

createArea方法到此分析完毕,我们再来看看parent.addChild(area, WindowContainer.POSITION_TOP);中的addChild方法

addChild

代码路径:/frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java

	protected final WindowList<E> mChildren = new WindowList<E>();
    /** Adds the input window container has a child of this container at the input index. */
    @CallSuper
    void addChild(E child, int index) {
        ......
		//设置index
        if (index == POSITION_TOP) {
            index = mChildren.size();
        } else if (index == POSITION_BOTTOM) {
            index = 0;
        }
		//添加当前节点到mChildren
        mChildren.add(index, child);

        // Set the parent after we've actually added a child in case a subclass depends on this.
        //设置当前节点的父亲
        child.setParent(this);
    }

mChildren为WindowList对象,而WindowList继承ArrayList。从当前代码来看,index传递的一直是POSITION_TOP,因此index = mChildren.size();。然后再index处插入传递的DisplayArea对象,设置该对象的父亲。 至此,这里就是添加各个节点的核心方法,我们也可以直接在这个方法中加入堆栈来看其详细的添加过程

void addChild(E child, int index) {
	android.util.Log.i("test1:", this + "addChild child = " + child + ", index = " + index, new Exception());
	......
}
构建过程简述

通过实际的例子带入代码讲解流程 在这里插入图片描述三步法走起,把参数带入到实际代码中 root.instantiateChildren(mRoot, displayAreaForLayer, 0, featureAreas); 第一次运行的节点是ROOT,其孩子mChildren是WindowedMagnification:0-31、HideDisplayCutout:32-35、Leaf:36-36

第一步.先根据当前节点的mChildren的mMinLayer(最小层级)进行排序 因此循环顺序为WindowedMagnification:0-31、HideDisplayCutout:32-35、Leaf:36-36,第一次循环的mChildren.get(0)就是WindowedMagnification 第二步.转换,第一次循环

  • final PendingArea child = mChildren.get(0); 获取WindowedMagnification:0-31,child就是WindowedMagnification:0-31

  • final DisplayArea area = child.createArea(mRoot, areaForLayer); WindowedMagnification:0-31进入createArea后,符合其第四个条件中mFeature不为null的情况,因此创建新的DisplayArea对象,并把自己的mName、mMinLayer、mMaxLayer和mId给新的DisplayArea

  • if (area == null) { continue; } area不为null

  • mRoot.addChild(area, WindowContainer.POSITION_TOP); 把转换后的DisplayArea加入到其父节点,我们曾经以ROOT的方式表现为临时根节点,这里正式变成了DisplayContent。 addChild方法中,其中当前index = mChildren.size();里面mChildren是mRoot的,且尚未添加任何内容,因此其size()为0,即index = 0,把WindowedMagnification:0-31插入到第0个位置,这其实也对应了我们dumpsys containers中的编号 在这里插入图片描述

  • if (child.mFeature != null) { featureAreas.get(child.mFeature).add(area); } WindowedMagnification:0-31的mFeature就是WindowedMagnification,把新的DisplayArea对象加入到featureAreas这个Map中key为WindowedMagnification的List中

第三步.最后在递归遍历到每个节点,从而使转换完成 child.instantiateChildren(area, areaForLayer, level + 1, areas);,开始找WindowedMagnification:0-31的孩子。 其递归过程与前面计算mMaxLayer的过程相似,不在赘述

最终生成的结构为

	DisplayContent
		#2 Leaf:36:36
		#1 HideDisplayCutout:32:35
			#2 OneHanded:34:35
				#1 FullscreenMagnification:34:35
					#0 Leaf:34:35
			#1 FullscreenMagnification:33:33
					#0 Leaf:33:33
			#0 OneHanded:32:32
				# 0 Leaf:32:32
		#0 WindowedMagnification:0:31
			#6 HideDisplayCutout:26:31
				#0 OneHanded:26:31
					#2 FullscreenMagnification:29:31
						#0 Leaf:29:31
					#1 Leaf:28:28
					#0 FullscreenMagnification:26:27
						#0 Leaf:26:27
			#5 Leaf:24:25
			#4 HideDisplayCutout:18:23
				#0 OneHanded:18:23
					#0 FullscreenMagnification:18:23
						#0 Leaf:18:23
			#2 HideDisplayCutout:16:16
				#0 OneHanded:16:16
					#0 FullscreenMagnification:16:16
						#0 Leaf:16:16
			#1 OneHanded:15:15
				#0 FullscreenMagnification:15:15
					#0 Leaf:15:15
			#0 HideDisplayCutout:0:14
				#0 OneHanded:0:14
					#1 ImePlaceholder:13:14
						#0 ImeContainer
					#0 FullscreenMagnification:0:12
						#2 Leaf:3:12
						#1 DefaultTaskDisplayArea
						#0 Leaf:0:1

也对应这dump中的信息,大家可以自行对比adb shell dumpsys activity containers,DisplayContent对应着Display。

最终的树形结构图为 在这里插入图片描述

5.7 回调onHierarchyBuilt

	// Notify the root that we have finished attaching all the DisplayAreas. Cache all the
	// feature related collections there for fast access.
	mRoot.onHierarchyBuilt(mFeatures, displayAreaForLayer, featureAreas);

通知显示区域的构建完成,把上一步【5.6生成DisplayArea层级结构】中构建好的参数传递给onHierarchyBuilt

代码路径:/frameworks/base/services/core/java/com/android/server/wm/RootDisplayArea.java

    /** Callback after {@link DisplayArea} hierarchy has been built. */
    void onHierarchyBuilt(ArrayList<Feature> features, DisplayArea.Tokens[] areaForLayer,
            Map<Feature, List<DisplayArea<WindowContainer>>> featureToDisplayAreas) {
        if (mHasBuiltHierarchy) {
            throw new IllegalStateException("Root should only build the hierarchy once");
        }
        mHasBuiltHierarchy = true;
        mFeatures = Collections.unmodifiableList(features);
        mAreaForLayer = areaForLayer;
        mFeatureToDisplayAreas = featureToDisplayAreas;
    }

把传递的参数赋值给RootDisplayArea的成员变量。 至此 层级结构树的构建 完毕。