Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 32e3b065 authored by Chris Li's avatar Chris Li Committed by Android (Google) Code Review
Browse files

Merge "Introduce DisplayAreaGroup"

parents cb431f96 416269ee
Loading
Loading
Loading
Loading
+149 −24
Original line number Original line Diff line number Diff line
@@ -23,20 +23,24 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER;
import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER;
import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;


import android.annotation.Nullable;
import android.annotation.Nullable;
import android.os.Bundle;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.ArraySet;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.policy.WindowManagerPolicy;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Comparator;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiFunction;


/**
/**
 * A builder for instantiating a complex {@link DisplayAreaPolicy}
 * A builder for instantiating a complex {@link DisplayAreaPolicy}
@@ -70,22 +74,93 @@ import java.util.Objects;
 */
 */
class DisplayAreaPolicyBuilder {
class DisplayAreaPolicyBuilder {
    @Nullable private HierarchyBuilder mRootHierarchyBuilder;
    @Nullable private HierarchyBuilder mRootHierarchyBuilder;
    private ArrayList<HierarchyBuilder> mDisplayAreaGroupHierarchyBuilders = new ArrayList<>();


    /** Defines the root hierarchy. */
    /**
     * When a window is created, the policy will use this function to select the
     * {@link RootDisplayArea} to place that window in. The selected root can be either the one of
     * the {@link #mRootHierarchyBuilder} or the one of any of the
     * {@link #mDisplayAreaGroupHierarchyBuilders}.
     **/
    @Nullable private BiFunction<WindowToken, Bundle, RootDisplayArea> mSelectRootForWindowFunc;

    /** Defines the root hierarchy for the whole logical display. */
    DisplayAreaPolicyBuilder setRootHierarchy(HierarchyBuilder rootHierarchyBuilder) {
    DisplayAreaPolicyBuilder setRootHierarchy(HierarchyBuilder rootHierarchyBuilder) {
        // TODO(b/157683117): Add method to add sub root and root choosing func.
        mRootHierarchyBuilder = rootHierarchyBuilder;
        mRootHierarchyBuilder = rootHierarchyBuilder;
        return this;
        return this;
    }
    }


    /**
     * Defines a DisplayAreaGroup hierarchy. Its root will be added as a child of the root
     * hierarchy.
     */
    DisplayAreaPolicyBuilder addDisplayAreaGroupHierarchy(
            HierarchyBuilder displayAreaGroupHierarchy) {
        mDisplayAreaGroupHierarchyBuilders.add(displayAreaGroupHierarchy);
        return this;
    }

    /** The policy will use this function to find the root to place windows in. */
    DisplayAreaPolicyBuilder setSelectRootForWindowFunc(
            BiFunction<WindowToken, Bundle, RootDisplayArea> selectRootForWindowFunc) {
        mSelectRootForWindowFunc = selectRootForWindowFunc;
        return this;
    }

    /** Makes sure the setting meets the requirement. */
    private void validate() {
        if (mRootHierarchyBuilder == null) {
            throw new IllegalStateException("Root must be set for the display area policy.");
        }

        boolean containsImeContainer = mRootHierarchyBuilder.mImeContainer != null;
        boolean containsDefaultTda = containsDefaultTaskDisplayArea(mRootHierarchyBuilder);
        for (int i = 0; i < mDisplayAreaGroupHierarchyBuilders.size(); i++) {
            HierarchyBuilder hierarchyBuilder = mDisplayAreaGroupHierarchyBuilders.get(i);
            if (hierarchyBuilder.mTaskDisplayAreas.isEmpty()) {
                throw new IllegalStateException(
                        "DisplayAreaGroup must contain at least one TaskDisplayArea.");
            }

            containsImeContainer = containsImeContainer || hierarchyBuilder.mImeContainer != null;
            containsDefaultTda = containsDefaultTda
                    || containsDefaultTaskDisplayArea(hierarchyBuilder);
        }

        if (!containsImeContainer) {
            throw new IllegalStateException("IME container must be set.");
        }

        if (!containsDefaultTda) {
            throw new IllegalStateException("There must be a default TaskDisplayArea.");
        }
    }

    /** Checks if the given hierarchy contains the default {@link TaskDisplayArea}. */
    private static boolean containsDefaultTaskDisplayArea(HierarchyBuilder displayAreaHierarchy) {
        for (int i = 0; i < displayAreaHierarchy.mTaskDisplayAreas.size(); i++) {
            if (displayAreaHierarchy.mTaskDisplayAreas.get(i).mFeatureId
                    == FEATURE_DEFAULT_TASK_CONTAINER) {
                return true;
            }
        }
        return false;
    }

    Result build(WindowManagerService wmService) {
    Result build(WindowManagerService wmService) {
        Objects.requireNonNull(mRootHierarchyBuilder,
        validate();
                "Root must be set for the display area policy.");

        Objects.requireNonNull(mRootHierarchyBuilder.mImeContainer, "Ime must not be null");
        // Attach DA group roots to screen hierarchy before adding windows to group hierarchies.
        Preconditions.checkCollectionNotEmpty(mRootHierarchyBuilder.mTaskDisplayAreas,
        mRootHierarchyBuilder.build(mDisplayAreaGroupHierarchyBuilders);
                "TaskDisplayAreas must not be empty");
        List<RootDisplayArea> displayAreaGroupRoots = new ArrayList<>(
        mRootHierarchyBuilder.build();
                mDisplayAreaGroupHierarchyBuilders.size());
        return new Result(wmService, mRootHierarchyBuilder.mRoot);
        for (int i = 0; i < mDisplayAreaGroupHierarchyBuilders.size(); i++) {
            HierarchyBuilder hierarchyBuilder = mDisplayAreaGroupHierarchyBuilders.get(i);
            hierarchyBuilder.build();
            displayAreaGroupRoots.add(hierarchyBuilder.mRoot);
        }
        return new Result(wmService, mRootHierarchyBuilder.mRoot, displayAreaGroupRoots,
                mSelectRootForWindowFunc);
    }
    }


    /**
    /**
@@ -131,6 +206,14 @@ class DisplayAreaPolicyBuilder {


        /** Builds the {@link DisplayArea} hierarchy below root. */
        /** Builds the {@link DisplayArea} hierarchy below root. */
        private void build() {
        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) {
            final WindowManagerPolicy policy = mRoot.mWmService.mPolicy;
            final WindowManagerPolicy policy = mRoot.mWmService.mPolicy;
            final int maxWindowLayerCount = policy.getMaxWindowLayer();
            final int maxWindowLayerCount = policy.getMaxWindowLayer();
            final DisplayArea.Tokens[] displayAreaForLayer =
            final DisplayArea.Tokens[] displayAreaForLayer =
@@ -215,7 +298,9 @@ class DisplayAreaPolicyBuilder {
                    if (leafType == LEAF_TYPE_TASK_CONTAINERS) {
                    if (leafType == LEAF_TYPE_TASK_CONTAINERS) {
                        // We use the passed in TaskDisplayAreas for task container type of layer.
                        // We use the passed in TaskDisplayAreas for task container type of layer.
                        // Skip creating Tokens even if there is no TDA.
                        // Skip creating Tokens even if there is no TDA.
                        addTaskDisplayAreasToLayer(areaForLayer[layer]);
                        addTaskDisplayAreasToApplicationLayer(areaForLayer[layer]);
                        addDisplayAreaGroupsToApplicationLayer(areaForLayer[layer],
                                displayAreaGroupHierarchyBuilders);
                        leafArea.mSkipTokens = true;
                        leafArea.mSkipTokens = true;
                    } else if (leafType == LEAF_TYPE_IME_CONTAINERS) {
                    } else if (leafType == LEAF_TYPE_IME_CONTAINERS) {
                        // We use the passed in ImeContainer for ime container type of layer.
                        // We use the passed in ImeContainer for ime container type of layer.
@@ -234,11 +319,11 @@ class DisplayAreaPolicyBuilder {


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


        /** Adds all {@link TaskDisplayArea} to the specified layer */
        /** Adds all {@link TaskDisplayArea} to the application layer. */
        private void addTaskDisplayAreasToLayer(PendingArea parentPendingArea) {
        private void addTaskDisplayAreasToApplicationLayer(PendingArea parentPendingArea) {
            final int count = mTaskDisplayAreas.size();
            final int count = mTaskDisplayAreas.size();
            for (int i = 0; i < count; i++) {
            for (int i = 0; i < count; i++) {
                PendingArea leafArea =
                PendingArea leafArea =
@@ -249,6 +334,24 @@ class DisplayAreaPolicyBuilder {
            }
            }
        }
        }


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

        private static int typeOfLayer(WindowManagerPolicy policy, int layer) {
        private static int typeOfLayer(WindowManagerPolicy policy, int layer) {
            if (layer == APPLICATION_LAYER) {
            if (layer == APPLICATION_LAYER) {
                return LEAF_TYPE_TASK_CONTAINERS;
                return LEAF_TYPE_TASK_CONTAINERS;
@@ -401,9 +504,20 @@ class DisplayAreaPolicyBuilder {
    }
    }


    static class Result extends DisplayAreaPolicy {
    static class Result extends DisplayAreaPolicy {
        final List<RootDisplayArea> mDisplayAreaGroupRoots;
        final BiFunction<WindowToken, Bundle, RootDisplayArea> mSelectRootForWindowFunc;


        Result(WindowManagerService wmService, RootDisplayArea root) {
        Result(WindowManagerService wmService, RootDisplayArea root,
                List<RootDisplayArea> displayAreaGroupRoots,
                @Nullable BiFunction<WindowToken, Bundle, RootDisplayArea>
                        selectRootForWindowFunc) {
            super(wmService, root);
            super(wmService, root);
            mDisplayAreaGroupRoots = Collections.unmodifiableList(displayAreaGroupRoots);
            mSelectRootForWindowFunc = selectRootForWindowFunc == null
                    // Always return the highest level root of the logical display when the func is
                    // not specified.
                    ? (window, options) -> mRoot
                    : selectRootForWindowFunc;
        }
        }


        @Override
        @Override
@@ -414,27 +528,38 @@ class DisplayAreaPolicyBuilder {


        @VisibleForTesting
        @VisibleForTesting
        DisplayArea.Tokens findAreaForToken(WindowToken token) {
        DisplayArea.Tokens findAreaForToken(WindowToken token) {
            // TODO(b/157683117): Choose root/sub root from OEM provided func.
            return mSelectRootForWindowFunc.apply(token, token.mOptions).findAreaForToken(token);
            return mRoot.findAreaForToken(token);
        }
        }


        @VisibleForTesting
        @VisibleForTesting
        List<Feature> getFeatures() {
        List<Feature> getFeatures() {
            // TODO(b/157683117): Also get feature from sub root.
            Set<Feature> features = new ArraySet<>();
            return new ArrayList<>(mRoot.mFeatures);
            features.addAll(mRoot.mFeatures);
            for (int i = 0; i < mDisplayAreaGroupRoots.size(); i++) {
                features.addAll(mDisplayAreaGroupRoots.get(i).mFeatures);
            }
            return new ArrayList<>(features);
        }
        }


        @Override
        @Override
        public List<DisplayArea<? extends WindowContainer>> getDisplayAreas(int featureId) {
        public List<DisplayArea<? extends WindowContainer>> getDisplayAreas(int featureId) {
            // TODO(b/157683117): Also get display areas from sub root.
            List<DisplayArea<? extends WindowContainer>> displayAreas = new ArrayList<>();
            List<Feature> features = getFeatures();
            getDisplayAreas(mRoot, featureId, displayAreas);
            for (int i = 0; i < mDisplayAreaGroupRoots.size(); i++) {
                getDisplayAreas(mDisplayAreaGroupRoots.get(i), featureId, displayAreas);
            }
            return displayAreas;
        }

        private static void getDisplayAreas(RootDisplayArea root, int featureId,
                List<DisplayArea<? extends WindowContainer>> displayAreas) {
            List<Feature> features = root.mFeatures;
            for (int i = 0; i < features.size(); i++) {
            for (int i = 0; i < features.size(); i++) {
                Feature feature = features.get(i);
                Feature feature = features.get(i);
                if (feature.mId == featureId) {
                if (feature.mId == featureId) {
                    return new ArrayList<>(mRoot.mFeatureToDisplayAreas.get(feature));
                    displayAreas.addAll(root.mFeatureToDisplayAreas.get(feature));
                }
                }
            }
            }
            return new ArrayList<>();
        }
        }
    }
    }


+2 −1
Original line number Original line Diff line number Diff line
@@ -71,6 +71,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;


import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
@@ -910,7 +911,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
     * @param root {@link RootWindowContainer}
     * @param root {@link RootWindowContainer}
     */
     */
    DisplayContent(Display display, RootWindowContainer root) {
    DisplayContent(Display display, RootWindowContainer root) {
        super(root.mWindowManager);
        super(root.mWindowManager, "DisplayContent", FEATURE_ROOT);
        if (mWmService.mRoot.getDisplayContent(display.getDisplayId()) != null) {
        if (mWmService.mRoot.getDisplayContent(display.getDisplayId()) != null) {
            throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
            throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
                    + " already exists="
                    + " already exists="
+3 −14
Original line number Original line Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.server.wm;
package com.android.server.wm;


import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER;
import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER;
import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;


import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature;
import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature;


@@ -44,19 +43,11 @@ class RootDisplayArea extends DisplayArea<DisplayArea> {
    /** Mapping from window layer to {@link DisplayArea.Tokens} that holds windows on that layer. */
    /** Mapping from window layer to {@link DisplayArea.Tokens} that holds windows on that layer. */
    private DisplayArea.Tokens[] mAreaForLayer;
    private DisplayArea.Tokens[] mAreaForLayer;


    /**
     * List of {@link TaskDisplayArea} that are attached to this {@link DisplayArea} hierarchy. The
     * order is the same as their z-order.
     *
     * TODO(b/157683117): Instead of caching the TDAs, always traverse the hierarchy to get them.
     */
    ArrayList<TaskDisplayArea> mTaskDisplayAreas;

    /** Whether the hierarchy has been built. */
    /** Whether the hierarchy has been built. */
    private boolean mHasBuiltHierarchy;
    private boolean mHasBuiltHierarchy;


    RootDisplayArea(WindowManagerService wms) {
    RootDisplayArea(WindowManagerService wms, String name, int featureId) {
        super(wms, Type.ANY, "RootDisplayArea", FEATURE_ROOT);
        super(wms, Type.ANY, name, featureId);
    }
    }


    /** Finds the {@link DisplayArea.Tokens} that this type of window should be attached to. */
    /** Finds the {@link DisplayArea.Tokens} that this type of window should be attached to. */
@@ -73,15 +64,13 @@ class RootDisplayArea extends DisplayArea<DisplayArea> {


    /** Callback after {@link DisplayArea} hierarchy has been built. */
    /** Callback after {@link DisplayArea} hierarchy has been built. */
    void onHierarchyBuilt(ArrayList<Feature> features, DisplayArea.Tokens[] areaForLayer,
    void onHierarchyBuilt(ArrayList<Feature> features, DisplayArea.Tokens[] areaForLayer,
            Map<Feature, List<DisplayArea<? extends WindowContainer>>> featureToDisplayAreas,
            Map<Feature, List<DisplayArea<? extends WindowContainer>>> featureToDisplayAreas) {
            ArrayList<TaskDisplayArea> taskDisplayAreas) {
        if (mHasBuiltHierarchy) {
        if (mHasBuiltHierarchy) {
            throw new IllegalStateException("Root should only build the hierarchy once");
            throw new IllegalStateException("Root should only build the hierarchy once");
        }
        }
        mHasBuiltHierarchy = true;
        mHasBuiltHierarchy = true;
        mFeatures = Collections.unmodifiableList(features);
        mFeatures = Collections.unmodifiableList(features);
        mAreaForLayer = areaForLayer;
        mAreaForLayer = areaForLayer;
        mTaskDisplayAreas = taskDisplayAreas;
        mFeatureToDisplayAreas = featureToDisplayAreas;
        mFeatureToDisplayAreas = featureToDisplayAreas;
    }
    }
}
}
+9 −1
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.wm;
package com.android.server.wm;


import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.os.Process.INVALID_UID;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;


import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
@@ -24,6 +25,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIG
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;


import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.RemoteException;
@@ -44,7 +46,13 @@ class WallpaperWindowToken extends WindowToken {


    WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit,
    WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit,
            DisplayContent dc, boolean ownerCanManageAppTokens) {
            DisplayContent dc, boolean ownerCanManageAppTokens) {
        super(service, token, TYPE_WALLPAPER, explicit, dc, ownerCanManageAppTokens);
        this(service, token, explicit, dc, ownerCanManageAppTokens, null /* options */);
    }

    WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit,
            DisplayContent dc, boolean ownerCanManageAppTokens, @Nullable Bundle options) {
        super(service, token, TYPE_WALLPAPER, explicit, dc, ownerCanManageAppTokens, INVALID_UID,
                false /* roundedCornerOverlay */, false /* fromClientToken */, options);
        dc.mWallpaperController.addWallpaperToken(this);
        dc.mWallpaperController.addWallpaperToken(this);
        setWindowingMode(WINDOWING_MODE_FULLSCREEN);
        setWindowingMode(WINDOWING_MODE_FULLSCREEN);
    }
    }
+3 −2
Original line number Original line Diff line number Diff line
@@ -2670,10 +2670,11 @@ public class WindowManagerService extends IWindowManager.Stub
                }
                }
                // TODO(window-container): Clean up dead tokens
                // TODO(window-container): Clean up dead tokens
                if (type == TYPE_WALLPAPER) {
                if (type == TYPE_WALLPAPER) {
                    new WallpaperWindowToken(this, binder, true, dc, callerCanManageAppTokens);
                    new WallpaperWindowToken(this, binder, true, dc, callerCanManageAppTokens,
                            options);
                } else {
                } else {
                    new WindowToken(this, binder, type, true, dc, callerCanManageAppTokens,
                    new WindowToken(this, binder, type, true, dc, callerCanManageAppTokens,
                            callingUid, false /* roundedCornerOverlay */, fromClientToken);
                            callingUid, false /* roundedCornerOverlay */, fromClientToken, options);
                }
                }
            }
            }
        } finally {
        } finally {
Loading