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

Commit fb61358b authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Always use a DisplayArea for WindowingLayer

This fixes the case if FEATURE_WINDOWED_MAGNIFICATION is supported:
 Correct hierarchy
  Display 0
   > WindowedMagnification:0:31 (WindowingLayer)
   > HideDisplayCutout:32:35
   > Leaf:36:36
   > Overlays

 Wrong hierarchy after calling migrateToNewSurfaceControl
 (The DisplayArea 32~36 should not belong to 0~31)
  Display 0
   > WindowedMagnification:0:31 (WindowingLayer)
     >> HideDisplayCutout:32:35
     >> Leaf:36:36
   > Overlays

There are various assumptions that the real parent surface should be
used as the target of reparent except display. Such as onParentChanged
and animation leash management. So it might not be appropriate to be a
general override in WindowContainer.

To reduce confusing of WindowingLayer, this change makes the layer
name consistent with its purpose and window hierarchy. There will
be a real DisplayArea for WindowingLayer, so the exception case of
relationship between surface and container is gone.

Before:
 RootWrapper (DisplayContent#mSurfaceControl)
  > Display 1 (WindowingLayer)
    >> TaskDisplayArea
  > Overlays

After:
 Display 1 (DisplayContent#mSurfaceControl)
  > WindowingLayer
    >> TaskDisplayArea
  > Overlays

Bug: 326975721
Test: atest DisplayContentTests#testValidWindowingLayer
            DisplayAreaPolicyBuilderTest
Test: Kill systemui (which triggers setOrganizer ->
      sendDisplayAreaVanished -> migrateToNewSurfaceControl)
      and check surface hierarchy.

Change-Id: Id4c2723a67738827be81ffb6fd4f47cf3a094634
parent 96fd8a65
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -111,6 +111,15 @@ public class DisplayAreaOrganizer extends WindowOrganizer {
     */
    public static final int FEATURE_IME = FEATURE_SYSTEM_FIRST + 8;

    /**
     * Display area that includes all areas which can have windows. It is used to separate the
     * window content to provide the ability of display level animation and display recording.
     * It is usually only a placeholder that organizer should not control it. This only exists
     * if {@link #FEATURE_WINDOWED_MAGNIFICATION} is not available to be the windowing layer.
     * @hide
     */
    public static final int FEATURE_WINDOWING_LAYER = FEATURE_SYSTEM_FIRST + 9;

    /**
     * The last boundary of display area for system features
     */
+5 −0
Original line number Diff line number Diff line
@@ -83,6 +83,11 @@ public abstract class DisplayAreaPolicy {
     */
    public abstract List<DisplayArea<? extends WindowContainer>> getDisplayAreas(int featureId);

    /**
     * Returns the {@link DisplayArea} that is used to put all window content.
     */
    public abstract DisplayArea<? extends WindowContainer> getWindowingArea();

    /**
     * @return the default/fallback {@link TaskDisplayArea} on the display.
     */
+39 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER;
import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_LAST;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWING_LAYER;
import static android.window.DisplayAreaOrganizer.KEY_ROOT_DISPLAY_AREA_ID;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
@@ -254,6 +256,10 @@ class DisplayAreaPolicyBuilder {
            throw new IllegalStateException("There must be a default TaskDisplayArea with id of "
                    + "FEATURE_DEFAULT_TASK_CONTAINER.");
        }

        if (!mRootHierarchyBuilder.hasValidWindowingLayer()) {
            throw new IllegalStateException("WindowingLayer must exist at the top level index");
        }
    }

    /** Checks if the given hierarchy contains the default {@link TaskDisplayArea}. */
@@ -267,6 +273,11 @@ class DisplayAreaPolicyBuilder {
        return false;
    }

    /** Returns {@code true} if the feature id can be used to put all window content. */
    static boolean canBeWindowingLayer(int featureId) {
        return featureId == FEATURE_WINDOWED_MAGNIFICATION || featureId == FEATURE_WINDOWING_LAYER;
    }

    /**
     * Makes sure that ids meet requirement.
     * {@link RootDisplayArea} and {@link TaskDisplayArea} must have unique ids.
@@ -329,6 +340,12 @@ class DisplayAreaPolicyBuilder {
    }

    Result build(WindowManagerService wmService) {
        if (mRootHierarchyBuilder != null && !mRootHierarchyBuilder.hasValidWindowingLayer()) {
            // Need an additional top layer for screen level animation.
            mRootHierarchyBuilder.mFeatures.add(0 /* top level index */, new Feature.Builder(
                    wmService.mPolicy, "WindowingLayer", FEATURE_WINDOWING_LAYER)
                    .setExcludeRoundedCornerOverlay(false).all().build());
        }
        validate();

        // Attach DA group roots to screen hierarchy before adding windows to group hierarchies.
@@ -624,6 +641,11 @@ class DisplayAreaPolicyBuilder {
            }
        }

        boolean hasValidWindowingLayer() {
            // The windowing layer feature can only be the first one as the top hierarchy.
            return !mFeatures.isEmpty() && canBeWindowingLayer(mFeatures.get(0).mId);
        }

        private static int typeOfLayer(WindowManagerPolicy policy, int layer) {
            if (layer == APPLICATION_LAYER) {
                return LEAF_TYPE_TASK_CONTAINERS;
@@ -865,6 +887,23 @@ class DisplayAreaPolicyBuilder {
            }
        }

        @Override
        public DisplayArea<? extends WindowContainer> getWindowingArea() {
            if (mRoot.mFeatures.isEmpty()) {
                throw new IllegalStateException("There must be at least one feature.");
            }
            final Feature feature = mRoot.mFeatures.get(0);
            if (canBeWindowingLayer(feature.mId)) {
                final List<DisplayArea<WindowContainer>> areas =
                        mRoot.mFeatureToDisplayAreas.get(feature);
                if (areas.size() == 1) {
                    return areas.get(0);
                }
            }
            throw new IllegalStateException("There must be exactly one DisplayArea at top for the "
                    + "FEATURE_WINDOWED_MAGNIFICATION or FEATURE_WINDOWING_LAYER");
        }

        @Override
        public TaskDisplayArea getDefaultTaskDisplayArea() {
            return mDefaultTaskDisplayArea;
+13 −58
Original line number Diff line number Diff line
@@ -87,7 +87,6 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.inputmethod.ImeTracker.DEBUG_IME_VISIBILITY;
import static android.window.DisplayAreaOrganizer.FEATURE_IME;
import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
@@ -339,12 +338,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    /** A surfaceControl specifically for accessibility overlays. */
    private SurfaceControl mA11yOverlayLayer;

    /**
     * The direct child layer of the display to put all non-overlay windows. This is also used for
     * screen rotation animation so that there is a parent layer to put the animation leash.
     */
    private SurfaceControl mWindowingLayer;

    /**
     * Delegate for handling all logic around content recording; decides if this DisplayContent is
     * recording, and if so, applies necessary updates to SurfaceFlinger.
@@ -365,7 +358,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    private final ImeContainer mImeWindowsContainer = new ImeContainer(mWmService);

    @VisibleForTesting
    DisplayAreaPolicy mDisplayAreaPolicy;
    final DisplayAreaPolicy mDisplayAreaPolicy;

    private WindowState mTmpWindow;
    private boolean mUpdateImeTarget;
@@ -1245,6 +1238,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        mWindowCornerRadius = mDisplayPolicy.getWindowCornerRadius();
        mPinnedTaskController = new PinnedTaskController(mWmService, this);

        // Set up 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);
        final Transaction pendingTransaction = getPendingTransaction();
        configureSurfaces(pendingTransaction);
        pendingTransaction.apply();
@@ -1315,14 +1312,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        mLastDeltaRotation = Surface.ROTATION_0;

        configureSurfaces(t);

        for (int i = 0; i < mChildren.size(); i++)  {
            SurfaceControl sc = mChildren.get(i).getSurfaceControl();
            if (sc != null) {
                t.reparent(sc, getParentingSurfaceControl());
            }
        }

        scheduleAnimation();
    }

@@ -1338,31 +1327,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
                .setContainerLayer()
                .setCallsite("DisplayContent");
        mSurfaceControl = b.setName(getName()).setContainerLayer().build();

        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);
        for (int i = getChildCount() - 1; i >= 0; i--)  {
            final SurfaceControl sc = getChildAt(i).mSurfaceControl;
            if (sc != null) {
                transaction.reparent(sc, mSurfaceControl);
            }

        final List<DisplayArea<? extends WindowContainer>> areas =
                mDisplayAreaPolicy.getDisplayAreas(FEATURE_WINDOWED_MAGNIFICATION);
        final DisplayArea<?> area = areas.size() == 1 ? areas.get(0) : null;

        if (area != null && area.getParent() == this) {
            // The windowed magnification area should contain all non-overlay windows, so just use
            // it as the windowing layer.
            mWindowingLayer = area.mSurfaceControl;
            transaction.reparent(mWindowingLayer, mSurfaceControl);
        } else {
            // Need an additional layer for screen level animation, so move the layer containing
            // the windows to the new root.
            mWindowingLayer = mSurfaceControl;
            mSurfaceControl = b.setName("RootWrapper").build();
            transaction.reparent(mWindowingLayer, mSurfaceControl)
                    .show(mWindowingLayer);
        }

        if (mOverlayLayer == null) {
@@ -1385,7 +1354,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        }

        transaction
                .setLayer(mSurfaceControl, 0)
                .setLayerStack(mSurfaceControl, mDisplayId)
                .show(mSurfaceControl)
                .setLayer(mOverlayLayer, Integer.MAX_VALUE)
@@ -3455,7 +3423,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            mOverlayLayer.release();
            mInputOverlayLayer.release();
            mA11yOverlayLayer.release();
            mWindowingLayer.release();
            mInputMonitor.onDisplayRemoved();
            mWmService.mDisplayNotificationController.dispatchDisplayRemoved(this);
            mDisplayRotation.onDisplayRemoved();
@@ -5829,22 +5796,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    }

    /**
     * Returns the {@link SurfaceControl} where all the children should be parented on.
     *
     * <p> {@link DisplayContent} inserts a RootWrapper leash in the hierarchy above its original
     * {@link #mSurfaceControl} and then overrides the {@link #mSurfaceControl} to point to the
     * RootWrapper.
     * <p> To prevent inconsistent state later where the DAs might get re-parented to the
     * RootWrapper, this method should be used which returns the correct surface where the
     * re-parenting should happen.
     * The direct child layer of the display to put all non-overlay windows. This is also used for
     * screen rotation animation so that there is a parent layer to put the animation leash.
     */
    @Override
    SurfaceControl getParentingSurfaceControl() {
        return mWindowingLayer;
    }

    SurfaceControl getWindowingLayer() {
        return mWindowingLayer;
        return mDisplayAreaPolicy.getWindowingArea().mSurfaceControl;
    }

    DisplayArea.Tokens getImeContainer() {
@@ -7238,7 +7194,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp

    public void replaceContent(SurfaceControl sc) {
        new Transaction().reparent(sc, getSurfaceControl())
                .reparent(mWindowingLayer, null)
                .reparent(mOverlayLayer, null)
                .reparent(mInputOverlayLayer, null)
                .reparent(mA11yOverlayLayer, null)
+1 −12
Original line number Diff line number Diff line
@@ -716,7 +716,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<

        // If parent is null, the layer should be placed offscreen so reparent to null. Otherwise,
        // set to the available parent.
        t.reparent(mSurfaceControl, mParent == null ? null : mParent.getParentingSurfaceControl());
        t.reparent(mSurfaceControl, mParent == null ? null : mParent.mSurfaceControl);

        if (mLastRelativeToLayer != null) {
            t.setRelativeLayer(mSurfaceControl, mLastRelativeToLayer, mLastLayer);
@@ -2906,17 +2906,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
        return mSurfaceControl;
    }

    /**
     * Returns the {@link SurfaceControl} where all the children should be parented on.
     *
     * A {@link WindowContainer} might insert intermediate leashes in the hierarchy and hence
     * {@link #getSurfaceControl} won't return the correct surface where the children should be
     * re-parented on.
     */
    SurfaceControl getParentingSurfaceControl() {
        return getSurfaceControl();
    }

    /**
     * Use this method instead of {@link #getPendingTransaction()} if the Transaction should be
     * synchronized with the client.
Loading