Window层级树构建

Post on Feb 12, 2023 by Wei Lin

窗口层级树的构建

SystemServer.startOtherServices()

开始WMS的创建流程。

t.traceBegin("StartWindowManagerService");
// WMS needs sensor service ready
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
        new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
        DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
        /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
t.traceEnd();

t.traceBegin("SetWindowManagerService");
mActivityManagerService.setWindowManager(wm);
t.traceEnd();

setWindowManager()

调用AMS等服务的setWindowManager(),将WMS相关属性赋予内部成员(初始化)。

ActivityManagerService.java
public void setWindowManager(WindowManagerService wm) {
    synchronized (this) {
        mWindowManager = wm;
        mWmInternal = LocalServices.getService(WindowManagerInternal.class);
        mActivityTaskManager.setWindowManager(wm);
    }
}

ActivityTaskManagerService.java
public void setWindowManager(WindowManagerService wm) {
    synchronized (mGlobalLock) {
        mWindowManager = wm;
        mRootWindowContainer = wm.mRoot;
        mWindowOrganizerController.setWindowManager(wm);
        mTempConfig.setToDefaults();
        mTempConfig.setLocales(LocaleList.getDefault());
        mConfigurationSeq = mTempConfig.seq = 1;
        mRootWindowContainer.onConfigurationChanged(mTempConfig);
        mLockTaskController.setWindowManager(wm);
        mTaskSupervisor.setWindowManager(wm);
        mRootWindowContainer.setWindowManager(wm);
        if (mBackNavigationController != null) {
            mBackNavigationController.setWindowManager(wm);
        }
    }
}

RootWindowContainer.java

说明:获取全部可用的物理屏幕mDisplayManager.getDisplays(),并为每个物理屏幕构造窗口层级树new DisplayContent()。

void setWindowManager(WindowManagerService wm) {
    mWindowManager = wm;
    mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
    mDisplayManager.registerDisplayListener(this, mService.mUiHandler);
    mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);

    final Display[] displays = mDisplayManager.getDisplays();
    for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) {
        final Display display = displays[displayNdx];
        final DisplayContent displayContent = new DisplayContent(display, this);
        addChild(displayContent, POSITION_BOTTOM);
        if (displayContent.mDisplayId == DEFAULT_DISPLAY) {
            mDefaultDisplay = displayContent;
        }
    }

    final TaskDisplayArea defaultTaskDisplayArea = getDefaultTaskDisplayArea();
    defaultTaskDisplayArea.getOrCreateRootHomeTask(ON_TOP);
    positionChildAt(POSITION_TOP, defaultTaskDisplayArea.mDisplayContent,
            false /* includingParents */);
}

以上调用详细情况暂时略过,在RootWindowContainer.setWindowManager()创建DisplayContent对象,便真正进入到了Android窗口层级树的创建过程。

new DisplayContent()

// 需要用Surfaceflinger绘制,所以需要进行surface相关配置
final Transaction pendingTransaction = getPendingTransaction();
configureSurfaces(pendingTransaction);
pendingTransaction.apply();

DisplayContent.configureSurfaces()

/**
 * Configures the surfaces hierarchy for DisplayContent
 * This method always recreates the main surface control but reparents the children
 * if they are already created.
 * @param transaction as part of which to perform the configuration
 */
private void configureSurfaces(Transaction transaction) {...}

说明:为DisplayContent(表示物理屏对象)构建surfaces层级。

// 首先构建DisplayAreaPolicy
// 这里的mDisplayAreaPolicy实际上是一个DisplayAreaPolicyBuilder.Result对象,static class Result extends DisplayAreaPolicy {...}
if (mDisplayAreaPolicy == null) {
    // Setup the policy and build the display area hierarchy.
    // Build the hierarchy only after creating the surface so it is reparented correctly
    mDisplayAreaPolicy = mWmService.getDisplayAreaPolicyProvider().instantiate(
            mWmService, this /* content */, this /* root */,
            mImeWindowsContainer);
}

mWmService.getDisplayAreaPolicyProvider()实际调用到了DisplayAreaPolicy.DefaultProvider类中。

DAP.DefaultProvider.instantiate()

DAP=DisplayAreaPolicy

DefaultProvider是DisplayAreaPolicy的静态内部类。

在DefaultProvider.instantiate()中主要执行以下操作:

  • 准备TaskDisplayArea,这里是名为DefaultTaskDisplayArea的TaskDisplayArea容器,也就是用来放Activity的;
  • 初始化HierarchyBuilder rootHierarchy对象;
  • 设置ImeContainer和TaskDisplayArea;
  • 执行configureTrustedHierarchyBuilder(),设置rootHierarchy相关数据(即窗口层级树);
  • 配置完成执行DisplayAreaPolicyBuilder.build(),通过rootHierarchy构造窗口层级树。
/** Provider for platform-default display area policy. */
static final class DefaultProvider implements DisplayAreaPolicy.Provider {
    @Override
    public DisplayAreaPolicy instantiate(WindowManagerService wmService,
            DisplayContent content, RootDisplayArea root,
            DisplayArea.Tokens imeContainer) {
        final TaskDisplayArea defaultTaskDisplayArea = new TaskDisplayArea(content, wmService,
                "DefaultTaskDisplayArea", FEATURE_DEFAULT_TASK_CONTAINER);
        final List<TaskDisplayArea> tdaList = new ArrayList<>();
        tdaList.add(defaultTaskDisplayArea);

        // Define the features that will be supported under the root of the whole logical
        // display. The policy will build the DisplayArea hierarchy based on this.
        final HierarchyBuilder rootHierarchy = new HierarchyBuilder(root);
        // Set the essential containers (even if the display doesn't support IME).
        rootHierarchy.setImeContainer(imeContainer).setTaskDisplayAreas(tdaList);
        if (content.isTrusted()) {
            // Only trusted display can have system decorations.
            configureTrustedHierarchyBuilder(rootHierarchy, wmService, content);
        }

        // Instantiate the policy with the hierarchy defined above. This will create and attach
        // all the necessary DisplayAreas to the root.
        return new DisplayAreaPolicyBuilder().setRootHierarchy(rootHierarchy).build(wmService);
    }
    // …
}

DefaultProvider.configureTrustedHierarchyBuilder()

构造各个窗口层级的Feature,然后将构造好的Feature添加到HierarchyBuilder.mFeatures成员中。

private void configureTrustedHierarchyBuilder(HierarchyBuilder rootHierarchy,
        WindowManagerService wmService, DisplayContent content) {
    // WindowedMagnification should be on the top so that there is only one surface
    // to be magnified.
    rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "WindowedMagnification",
            FEATURE_WINDOWED_MAGNIFICATION)
            .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
            .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
            // Make the DA dimmable so that the magnify window also mirrors the dim layer.
            .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new)
            .build());
    if (content.isDefaultDisplay) {
        // Only default display can have cutout.
        // See LocalDisplayAdapter.LocalDisplayDevice#getDisplayDeviceInfoLocked.
        rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "HideDisplayCutout",
                FEATURE_HIDE_DISPLAY_CUTOUT)
                .all()
                .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, TYPE_STATUS_BAR,
                        TYPE_NOTIFICATION_SHADE)
                .build())
                .addFeature(new Feature.Builder(wmService.mPolicy, "OneHanded",
                        FEATURE_ONE_HANDED)
                        .all()
                        .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL,
                                TYPE_SECURE_SYSTEM_OVERLAY)
                        .build());
    }
    rootHierarchy
            .addFeature(new Feature.Builder(wmService.mPolicy, "FullscreenMagnification",
                    FEATURE_FULLSCREEN_MAGNIFICATION)
                    .all()
                    .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, TYPE_INPUT_METHOD,
                            TYPE_INPUT_METHOD_DIALOG, TYPE_MAGNIFICATION_OVERLAY,
                            TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL)
                    .build())
            .addFeature(new Feature.Builder(wmService.mPolicy, "ImePlaceholder",
                    FEATURE_IME_PLACEHOLDER)
                    .and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG)
                    .build());
}

以”WindowedMagnification”这个Feature为例:

rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "WindowedMagnification",
        FEATURE_WINDOWED_MAGNIFICATION)
        .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
        .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
        // Make the DA dimmable so that the magnify window also mirrors the dim layer.
        .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new)
        .build());

Builder.upTo()

作用:添加WindowLayer到当前Feature。

根据传入的WindowType,调用getWindowLayerFromTypeLw()获取到对应的窗口层级。

/**
 * Set that the feature applies window types that are layerd at or below the layer of
 * the given window type.
 */
Builder upTo(int typeInclusive) {
    final int max = layerFromType(typeInclusive, false);
    for (int i = 0; i < max; i++) {
        mLayers[i] = true;
    }
    set(typeInclusive, true);
    return this;
}

private int layerFromType(int type, boolean internalWindows) {
    return mPolicy.getWindowLayerFromTypeLw(type, internalWindows);
}

将值保存在数值mLayers中,mLayers定义如下:

mLayers = new boolean[mPolicy.getMaxWindowLayer() + 1];
default int getMaxWindowLayer() {
    return 36;
}

mLayers是一个大小为37的boolean类型数组,对当前Feature对象,传入Type为TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,则返回Layer为32,则mLayers[0~31]=true,表示该Feature支持max=32以下的Layer。之后通过set(typeInclusive, true)设置mLayers[32]=true。

所以这一步Feature对象WindowedMagnification:0:32

Builder.except()

作用:排除WindowLayer到当前Feature。

/**
 * Set that the feature does not apply to the given window types.
 */
Builder except(int... types) {
    for (int i = 0; i < types.length; i++) {
        int type = types[i];
        set(type, false);
    }
    return this;
}

对WindowedMagnification,这里又排除了TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,所以这一步Feature对象WindowedMagnification:0:31。

Builder.setNewDisplayAreaSupplier()

/**
 * Sets the function to create new {@link DisplayArea} for this feature. By default, it
 * uses {@link DisplayArea}'s constructor.
 */
Builder setNewDisplayAreaSupplier(NewDisplayAreaSupplier newDisplayAreaSupplier) {
    mNewDisplayAreaSupplier = newDisplayAreaSupplier;
    return this;
}

所有Feature

// Only default display can have cutout.
// See LocalDisplayAdapter.LocalDisplayDevice#getDisplayDeviceInfoLocked.
rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "HideDisplayCutout",
        FEATURE_HIDE_DISPLAY_CUTOUT)
        .all()  // 添加[0,36]
        .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, TYPE_STATUS_BAR,
                TYPE_NOTIFICATION_SHADE)  // 排除24,25,15,17
        .build())  // 排除36
        .addFeature(new Feature.Builder(wmService.mPolicy, "OneHanded",
                FEATURE_ONE_HANDED)
                .all()  // 添加[0,36]
                .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL,
                        TYPE_SECURE_SYSTEM_OVERLAY)  // 排除24,25,33
                .build());  // 排除36


rootHierarchy
        .addFeature(new Feature.Builder(wmService.mPolicy, "FullscreenMagnification",
                FEATURE_FULLSCREEN_MAGNIFICATION)
                .all()  // 添加[0,36]
                .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, TYPE_INPUT_METHOD,
                        TYPE_INPUT_METHOD_DIALOG, TYPE_MAGNIFICATION_OVERLAY,
                        TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL)
                .build())  // 排除32,13,14,28,24,25,36
        .addFeature(new Feature.Builder(wmService.mPolicy, "ImePlaceholder",
                FEATURE_IME_PLACEHOLDER)
                .and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG)  // 添加13,14
                .build());

最后所有的窗口层级如下:

WindowedMagnification 0-31
HideDisplayCutout 0-14 16 18-23 26-35
OneHanded 0-23 26-32 34-35
FullscreenMagnification 0-12 15-23 26-27 29-31 33-35
ImePlaceholder 13-14

可以发现这些层级与dumpsys activity containers中是可以对应上的,接下来看一下怎么通过以上数据构建出dumpsys activity containers中的窗口层级树。

DisplayAreaPolicyBuilder.build()

由DisplayAreaPolicy.DefaultProvider.instantiate()调用而来。

说明:返回DisplayAreaPolicyBuilder.Result对象。Result是DisplayAreaPolicy的子类。static class Result extends DisplayAreaPolicy {…},用于在DisplayContent.configureSurfaces()中构建surfaces层级。

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);
}

HierarchyBuilder.build()

说明:HierarchyBuilder是DisplayAreaPolicyBuilder的内部类,其作用就是构建一个以RootDisplayArea mRoot为根的树,build()则是在初始化之后开始进行构建。

HierarchyBuilder.build()关键步骤如下:

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<>());
}

// PendingArea是构造DisplayArea的暂时状态,这里37个
PendingArea[] areaForLayer = new PendingArea[maxWindowLayerCount];
// 设置root
final PendingArea root = new PendingArea(null, 0, null);
// areaForLayer全部用PendingArea root填充
Arrays.fill(areaForLayer, root);

// 这里的size就是configureTrustedHierarchyBuilder()中的5个
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);  // 取出一个Feature
    PendingArea featureArea = null;  // 即将要设置的节点
    for (int layer = 0; layer < maxWindowLayerCount; layer++) {  // 按顺序依次设置
        if (feature.mWindowLayers[layer]) {  // 如果该feature包含第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).
            // 如果当前节点为null,第1次设置时才为null
            // 如果当前节点不为null,
            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;
        }
    }
}

Feature: WindowedMagnification

注:PendingArea构造时只有minLayer。

以第1个Feature为例,其名为WindowedMagnification,层级为0~31,所以其feature.mWindowLayers[0~31]=true,feature[0]=WindowedMagnification:0:31。

layer=0时, areaForLayer[0]=root,featureArea=WindowedMagnification:0,如下:
    root:0(areaForLayer[0])
      \
       \
WindowedMagnification:0(featureArea)

然后areaForLayer[0]=WindowedMagnification:0,如下:
    root:0
      \
       \
WindowedMagnification:0(areaForLayer[0])

layer=1时,areaForLayer[0]=WindowedMagnification:0,areaForLayer[1]=root,featureArea=WindowedMagnification:1,featureArea的父节点root= areaForLayer[1],然后areaForLayer[1]=WindowedMagnification:1
    root:0
      \
       \
WindowedMagnification:1(areaForLayer[0])

于是WindowedMagnification:0和WindowedMagnification:1的父节点都为areaForLayer[0],可以记为WindowedMagnification:0:1,areaForLayer[0]记为root:0:0

所以第1个feature从0~31层,都是共用一个父节点,第1个feature执行完,最后为:
    root:0:0
      \
       \
WindowedMagnification:0:31

image-20240226230155335

Feature: HideDisplayCutout

第2个feature为HideDisplayCutout:0-14 16 18-23 26-35

对HideDisplayCutout:0:14,其父节点为WindowedMagnification:0:14

对HideDisplayCutout:16:16,其父节点为WindowedMagnification:16:16

对HideDisplayCutout:18:23,其父节点为WindowedMagnification:18:23

对HideDisplayCutout:26:35,其父节点为WindowedMagnification:26:31和HideDisplayCutout:32:35(因为WindowedMagnification最大Layer为31)

表示为树如下:

image-20240226230236257

Feature: OneHanded

第3个feature为OneHanded 0-23 26-32 34-35

按照以上方法挂载后,树形如下:

image-20240226230258823

Feature: FullscreenMagnification

第4个feature为FullscreenMagnification:0-12 15-23 26-27 29-31 33-35

按照以上方法挂载后,树形如下:

image-20240226230334865

Feature: ImePlaceholder

第5个feature为ImePlaceholder 13-14

image-20240226230358702

这就是5个feature加载完成之后,初步形成的窗口层级树,另外还要包含一些未赋值的null节点,如下:

image-20240226230424810

接下来还要对这棵树作进一步的配置。

配置子节点

接下来执行以下步骤:

  • 为每个叶子节点后面都新增一个子节点,子节点的Feature name为空,记为Leaf:min:max;
  • 对TaskDisplayArea(即Layer 2)和ImeContainer(即Layer 13:14)作特殊处理。

注:为什么是Layer 2和Layer 13:14,是在typeOfLayer()中确定的。

// Create Tokens as leaf for every layer.
PendingArea leafArea = null;
int leafType = LEAF_TYPE_TOKENS;
for (int layer = 0; layer < maxWindowLayerCount; layer++) {  // 遍历每个节点
    // 获取每个节点的类型,除了TaskDisplayArea和ImeContainer外,其它的type都为LEAF_TYPE_TOKENS,详见typeOfLayer()函数
    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.
        // 创建子节点,设置父节点
        // 给每一个叶子节点都挂载一个PendingArea
        leafArea = new PendingArea(null /* feature */, layer, areaForLayer[layer]);
        areaForLayer[layer].mChildren.add(leafArea);
        leafType = type;
        // 针对TYPE_TASK_CONTAINERS作特殊处理,即Layer 2
        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.
            // 设置叶子节点Layer 2设置为一个APPLICATION_LAYER类型的节点
            addTaskDisplayAreasToApplicationLayer(areaForLayer[layer]);
            addDisplayAreaGroupsToApplicationLayer(areaForLayer[layer],
                    displayAreaGroupHierarchyBuilders);
            leafArea.mSkipTokens = true;  // 跳过,不添加Tokens
        // 针对TYPE_IME_CONTAINERS作特殊处理,即Layer 13:14
        } 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.
            // 将叶子节点Layer13:14设置为ImeContainer类型
            leafArea.mExisting = mImeContainer;
            leafArea.mSkipTokens = true;
        }
    }
    leafArea.mMaxLayer = layer;
}

// 返回类型
private static int typeOfLayer(WindowManagerPolicy policy, int layer) {
    // 设置areaForLayer[2]为TYPE_TASK_CONTAINERS,作为Activity的容器
    if (layer == APPLICATION_LAYER) {
        return LEAF_TYPE_TASK_CONTAINERS;
    } else if (layer == policy.getWindowLayerFromTypeLw(TYPE_INPUT_METHOD)
            || layer == policy.getWindowLayerFromTypeLw(TYPE_INPUT_METHOD_DIALOG)) {
        // 设置areaForLayer[13]和设置areaForLayer[14]为TYPE_IME_CONTAINERS,作为输入法的容器
        return LEAF_TYPE_IME_CONTAINERS;
    } else {
        // 其它都标记为TYPE_TOKENS,之后会添加一个Tokens子节点
        return LEAF_TYPE_TOKENS;
    }
}

注:APPLICATION_LAYER定义于WindowManagerPolicyConstants.APPLICATION_LAYER,表示层级树中显示APP的Activity的层级。

经过这一次配置之后的层级树如下:

image-20240226230517531

上述执行完成后,PendingArea[] areaForLayer = new PendingArea[37]这颗树基本配置完了,但它只是个PendingArea[],并不是DisplayArea,并且根节点Root:0:0也不是DisplayContent(表示一个显示屏)。

Attach to DisplayAreas

说明:开始实例化上面构建的areaForLayer[37]这颗树,该树根节点为root。

// 以根节点root开始,递归计算每个节点的最大Layer
root.computeMaxLayer();

// 根据areaForLayer[37]建立DisplayArea
// mRoot作为窗口树的根节点,实际上是一个DisplayContent
// displayAreaForLayer[37]只是在上面构造了,接下来才会赋值
// 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);

// 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);

PendingArea.instantiateChildren()

注:PendingArea是DisplayAreaPolicyBuilder的静态内部类。

说明:在这一步主要将之前构建的areaForLayer[37]实例化,将其中的PendingArea转换为DisplayArea。并逐个添加到以mRoot(DisplayContent对象)为根节点的树中。

void instantiateChildren(DisplayArea<DisplayArea> parent, DisplayArea.Tokens[] areaForLayer,
        int level, Map<Feature, List<DisplayArea<WindowContainer>>> areas) {
    mChildren.sort(Comparator.comparingInt(pendingArea -> pendingArea.mMinLayer));
    for (int i = 0; i < mChildren.size(); i++) {
        // 将PendingArea转换为DisplayArea
        final PendingArea child = mChildren.get(i);
        final DisplayArea area = child.createArea(parent, areaForLayer);
        if (area == null) {  // TaskDisplayArea and ImeContainer为null
            // TaskDisplayArea and ImeContainer can be set at different hierarchy, so it can
            // be null.
            continue;
        }
        // 以mRoot开始,逐个添加子节点
        parent.addChild(area, WindowContainer.POSITION_TOP);
        if (child.mFeature != null) {
            areas.get(child.mFeature).add(area);
        }
        // 子节点继续递归,直到构建整个树
        child.instantiateChildren(area, areaForLayer, level + 1, areas);
    }
}

image-20240226230624302