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

Commit 15a8232e authored by Gaurav Bhola's avatar Gaurav Bhola Committed by Android (Google) Code Review
Browse files

Merge "Handle alwaysOnTop in DisplayAreas." into tm-qpr-dev

parents ef8f854a ef72f113
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
@@ -693,7 +693,39 @@ public final class WindowContainerTransaction implements Parcelable {
                        .build();
        mHierarchyOps.add(hierarchyOp);
        return this;
    }

    /**
     * Sets/removes the always on top flag for this {@code windowContainer}. See
     * {@link com.android.server.wm.ConfigurationContainer#setAlwaysOnTop(boolean)}.
     * Please note that this method is only intended to be used for a
     * {@link com.android.server.wm.DisplayArea}.
     *
     * <p>
     *     Setting always on top to {@code True} will also make the {@code windowContainer} to move
     *     to the top.
     * </p>
     * <p>
     *     Setting always on top to {@code False} will make this {@code windowContainer} to move
     *     below the other always on top sibling containers.
     * </p>
     *
     * @param windowContainer the container which the flag need to be updated for.
     * @param alwaysOnTop denotes whether or not always on top flag should be set.
     * @hide
     */
    @NonNull
    public WindowContainerTransaction setAlwaysOnTop(
            @NonNull WindowContainerToken windowContainer,
            boolean alwaysOnTop) {
        final HierarchyOp hierarchyOp =
                new HierarchyOp.Builder(
                        HierarchyOp.HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP)
                        .setContainer(windowContainer.asBinder())
                        .setAlwaysOnTop(alwaysOnTop)
                        .build();
        mHierarchyOps.add(hierarchyOp);
        return this;
    }

    /**
@@ -1121,6 +1153,7 @@ public final class WindowContainerTransaction implements Parcelable {
        public static final int HIERARCHY_OP_TYPE_ADD_RECT_INSETS_PROVIDER = 16;
        public static final int HIERARCHY_OP_TYPE_REMOVE_INSETS_PROVIDER = 17;
        public static final int HIERARCHY_OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT = 18;
        public static final int HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP = 19;

        // The following key(s) are for use with mLaunchOptions:
        // When launching a task (eg. from recents), this is the taskId to be launched.
@@ -1171,6 +1204,8 @@ public final class WindowContainerTransaction implements Parcelable {
        @Nullable
        private ShortcutInfo mShortcutInfo;

        private boolean mAlwaysOnTop;

        public static HierarchyOp createForReparent(
                @NonNull IBinder container, @Nullable IBinder reparent, boolean toTop) {
            return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REPARENT)
@@ -1268,6 +1303,7 @@ public final class WindowContainerTransaction implements Parcelable {
            mTaskFragmentCreationOptions = copy.mTaskFragmentCreationOptions;
            mPendingIntent = copy.mPendingIntent;
            mShortcutInfo = copy.mShortcutInfo;
            mAlwaysOnTop = copy.mAlwaysOnTop;
        }

        protected HierarchyOp(Parcel in) {
@@ -1289,6 +1325,7 @@ public final class WindowContainerTransaction implements Parcelable {
            mTaskFragmentCreationOptions = in.readTypedObject(TaskFragmentCreationParams.CREATOR);
            mPendingIntent = in.readTypedObject(PendingIntent.CREATOR);
            mShortcutInfo = in.readTypedObject(ShortcutInfo.CREATOR);
            mAlwaysOnTop = in.readBoolean();
        }

        public int getType() {
@@ -1354,6 +1391,10 @@ public final class WindowContainerTransaction implements Parcelable {
            return mActivityIntent;
        }

        public boolean isAlwaysOnTop() {
            return mAlwaysOnTop;
        }

        @Nullable
        public TaskFragmentCreationParams getTaskFragmentCreationOptions() {
            return mTaskFragmentCreationOptions;
@@ -1422,6 +1463,9 @@ public final class WindowContainerTransaction implements Parcelable {
                            + " insetsType=" + Arrays.toString(mInsetsTypes) + "}";
                case HIERARCHY_OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT:
                    return "{requestFocusOnTaskFragment: container=" + mContainer + "}";
                case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP:
                    return "{setAlwaysOnTop: container=" + mContainer
                            + " alwaysOnTop=" + mAlwaysOnTop + "}";
                default:
                    return "{mType=" + mType + " container=" + mContainer + " reparent=" + mReparent
                            + " mToTop=" + mToTop
@@ -1451,6 +1495,7 @@ public final class WindowContainerTransaction implements Parcelable {
            dest.writeTypedObject(mTaskFragmentCreationOptions, flags);
            dest.writeTypedObject(mPendingIntent, flags);
            dest.writeTypedObject(mShortcutInfo, flags);
            dest.writeBoolean(mAlwaysOnTop);
        }

        @Override
@@ -1509,6 +1554,8 @@ public final class WindowContainerTransaction implements Parcelable {
            @Nullable
            private ShortcutInfo mShortcutInfo;

            private boolean mAlwaysOnTop;

            Builder(int type) {
                mType = type;
            }
@@ -1568,6 +1615,11 @@ public final class WindowContainerTransaction implements Parcelable {
                return this;
            }

            Builder setAlwaysOnTop(boolean alwaysOnTop) {
                mAlwaysOnTop = alwaysOnTop;
                return this;
            }

            Builder setTaskFragmentCreationOptions(
                    @Nullable TaskFragmentCreationParams taskFragmentCreationOptions) {
                mTaskFragmentCreationOptions = taskFragmentCreationOptions;
@@ -1596,6 +1648,7 @@ public final class WindowContainerTransaction implements Parcelable {
                hierarchyOp.mLaunchOptions = mLaunchOptions;
                hierarchyOp.mActivityIntent = mActivityIntent;
                hierarchyOp.mPendingIntent = mPendingIntent;
                hierarchyOp.mAlwaysOnTop = mAlwaysOnTop;
                hierarchyOp.mTaskFragmentCreationOptions = mTaskFragmentCreationOptions;
                hierarchyOp.mShortcutInfo = mShortcutInfo;

+29 −0
Original line number Diff line number Diff line
@@ -207,6 +207,23 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
        return false;
    }

    @Override
    public void setAlwaysOnTop(boolean alwaysOnTop) {
        if (isAlwaysOnTop() == alwaysOnTop) {
            return;
        }
        super.setAlwaysOnTop(alwaysOnTop);
        // positionChildAtTop() must be called even when always on top gets turned off because
        // we need to make sure that the display area is moved from among always on top containers
        // to below other always on top containers. Since the position the display area should be
        // inserted into is calculated properly in {@link DisplayContent#getTopInsertPosition()}
        // in both cases, we can just request that the root task is put at top here.
        if (getParent().asDisplayArea() != null) {
            getParent().asDisplayArea().positionChildAt(POSITION_TOP, this,
                    false /* includingParents */);
        }
    }

    boolean getIgnoreOrientationRequest() {
        // Adding an exception for when ignoreOrientationRequest is overridden at runtime for all
        // DisplayArea-s. For example, this is needed for the Kids Mode since many Kids apps aren't
@@ -234,6 +251,18 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
        // The min possible position we can insert the child at.
        int minPosition = findMinPositionForChildDisplayArea(child);

        // Place all non-always-on-top containers below always-on-top ones.
        int alwaysOnTopCount = 0;
        for (int i = minPosition; i <= maxPosition; i++) {
            if (mChildren.get(i).isAlwaysOnTop()) {
                alwaysOnTopCount++;
            }
        }
        if (child.isAlwaysOnTop()) {
            minPosition = maxPosition - alwaysOnTopCount + 1;
        } else {
            maxPosition -= alwaysOnTopCount;
        }
        return Math.max(Math.min(requestPosition, maxPosition), minPosition);
    }

+13 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT;
@@ -1079,6 +1080,18 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                WindowContainer.fromBinder(hop.getContainer())
                        .removeLocalInsetsSourceProvider(hop.getInsetsTypes());
                break;
            case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP:
                final WindowContainer container = WindowContainer.fromBinder(hop.getContainer());
                if (container == null || container.asDisplayArea() == null
                        || !container.isAttached()) {
                    Slog.e(TAG, "Attempt to operate on unknown or detached display area: "
                            + container);
                    break;
                }
                container.setAlwaysOnTop(hop.isAlwaysOnTop());
                effects |= TRANSACT_EFFECTS_LIFECYCLE;
                break;

        }
        return effects;
    }
+64 −5
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.wm;

import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -399,9 +400,9 @@ public class DisplayAreaTest extends WindowTestsBase {
                parentBounds.right / 2, parentBounds.bottom);
        final Rect childBounds2 = new Rect(parentBounds.right / 2, parentBounds.top,
                parentBounds.right, parentBounds.bottom);
        TestDisplayArea parentDa = new TestDisplayArea(mWm, parentBounds);
        TestDisplayArea childDa1 = new TestDisplayArea(mWm, childBounds1);
        TestDisplayArea childDa2 = new TestDisplayArea(mWm, childBounds2);
        TestDisplayArea parentDa = new TestDisplayArea(mWm, parentBounds, "Parent");
        TestDisplayArea childDa1 = new TestDisplayArea(mWm, childBounds1, "Child1");
        TestDisplayArea childDa2 = new TestDisplayArea(mWm, childBounds2, "Child2");
        parentDa.addChild(childDa1, 0);
        parentDa.addChild(childDa2, 1);

@@ -619,9 +620,67 @@ public class DisplayAreaTest extends WindowTestsBase {
        controller.registerOrganizer(mockDisplayAreaOrganizer, FEATURE_VENDOR_FIRST);
    }

    @Test
    public void testSetAlwaysOnTop_movesDisplayAreaToTop() {
        final Rect bounds = new Rect(0, 0, 100, 100);
        DisplayArea<WindowContainer> parent = new TestDisplayArea(mWm, bounds, "Parent");
        parent.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        DisplayArea<WindowContainer> child1 = new TestDisplayArea(mWm, bounds, "Child1");
        child1.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        DisplayArea<WindowContainer> child2 = new TestDisplayArea(mWm, bounds, "Child2");
        child2.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        parent.addChild(child2, 0);
        parent.addChild(child1, 1);

        child2.setAlwaysOnTop(true);

        assertEquals(parent.getChildAt(1), child2);
        assertThat(child2.isAlwaysOnTop()).isTrue();
    }

    @Test
    public void testDisplayAreaRequestsTopPosition_alwaysOnTopSiblingExists_doesNotMoveToTop() {
        final Rect bounds = new Rect(0, 0, 100, 100);
        DisplayArea<WindowContainer> parent = new TestDisplayArea(mWm, bounds, "Parent");
        parent.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        DisplayArea<WindowContainer> alwaysOnTopChild = new TestDisplayArea(mWm, bounds,
                "AlwaysOnTopChild");
        alwaysOnTopChild.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        DisplayArea<WindowContainer> child = new TestDisplayArea(mWm, bounds, "Child");
        child.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        parent.addChild(alwaysOnTopChild, 0);
        parent.addChild(child, 1);
        alwaysOnTopChild.setAlwaysOnTop(true);

        parent.positionChildAt(POSITION_TOP, child, false /* includingParents */);

        assertEquals(parent.getChildAt(1), alwaysOnTopChild);
        assertEquals(parent.getChildAt(0), child);
    }

    @Test
    public void testAlwaysOnTopDisplayArea_requestsNonTopLocation_doesNotMove() {
        final Rect bounds = new Rect(0, 0, 100, 100);
        DisplayArea<WindowContainer> parent = new TestDisplayArea(mWm, bounds, "Parent");
        parent.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        DisplayArea<WindowContainer> alwaysOnTopChild = new TestDisplayArea(mWm, bounds,
                "AlwaysOnTopChild");
        alwaysOnTopChild.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        DisplayArea<WindowContainer> child = new TestDisplayArea(mWm, bounds, "Child");
        child.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        parent.addChild(alwaysOnTopChild, 0);
        parent.addChild(child, 1);
        alwaysOnTopChild.setAlwaysOnTop(true);

        parent.positionChildAt(POSITION_BOTTOM, alwaysOnTopChild, false /* includingParents */);

        assertEquals(parent.getChildAt(1), alwaysOnTopChild);
        assertEquals(parent.getChildAt(0), child);
    }

    private static class TestDisplayArea<T extends WindowContainer> extends DisplayArea<T> {
        private TestDisplayArea(WindowManagerService wms, Rect bounds) {
            super(wms, ANY, "half display area");
        private TestDisplayArea(WindowManagerService wms, Rect bounds, String name) {
            super(wms, ANY, name);
            setBounds(bounds);
        }