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

Commit cf508107 authored by Gaurav Bhola's avatar Gaurav Bhola
Browse files

Add an option to reorder a task along with its parents

- This is required when the windowing is structured in multiple
  DisplayAreas and it is desired to have focus (which is tied to
  z-order) on a particular TDA.
- In other words, it is desired to have an API that can move a task
  to the front (along with all its parents DisplayAreas) so that it
  can become the top focused task.

Bug: 344613038
Test: m
Test: used this API in a custom target
Change-Id: I46ef04fd6586492779c0e0d5c5e4e7b5586c1e82
parent 4df011a9
Loading
Loading
Loading
Loading
+48 −2
Original line number Diff line number Diff line
@@ -375,7 +375,23 @@ public final class WindowContainerTransaction implements Parcelable {
     */
    @NonNull
    public WindowContainerTransaction reorder(@NonNull WindowContainerToken child, boolean onTop) {
        mHierarchyOps.add(HierarchyOp.createForReorder(child.asBinder(), onTop));
        return reorder(child, onTop, false /* includingParents */);
    }

    /**
     * Reorders a container within its parent with an option to reorder all the parents in the
     * hierarchy above among their respective siblings.
     *
     * @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
     *              the bottom.
     * @param includingParents When {@code true}, all the parents in the hierarchy above are also
     *                         reordered among their respective siblings.
     * @hide
     */
    @NonNull
    public WindowContainerTransaction reorder(@NonNull WindowContainerToken child, boolean onTop,
            boolean includingParents) {
        mHierarchyOps.add(HierarchyOp.createForReorder(child.asBinder(), onTop, includingParents));
        return this;
    }

@@ -1451,6 +1467,8 @@ public final class WindowContainerTransaction implements Parcelable {
        @Nullable
        private Rect mBounds;

        private boolean mIncludingParents;

        private boolean mAlwaysOnTop;

        private boolean mReparentLeafTaskIfRelaunch;
@@ -1464,11 +1482,22 @@ public final class WindowContainerTransaction implements Parcelable {
                    .build();
        }

        public static HierarchyOp createForReorder(@NonNull IBinder container, boolean toTop) {
        /**
         * Creates the {@link HierarchyOp} for the reorder operation.
         *
         * @param container which needs to be reordered
         * @param toTop if true, the container reorders
         * @param includingParents if true, all the parents in the hierarchy above are also
         *                         reoredered among their respective siblings
         * @return
         */
        public static HierarchyOp createForReorder(@NonNull IBinder container, boolean toTop,
                boolean includingParents) {
            return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REORDER)
                    .setContainer(container)
                    .setReparentContainer(container)
                    .setToTop(toTop)
                    .setIncludingParents(includingParents)
                    .build();
        }

@@ -1555,6 +1584,7 @@ public final class WindowContainerTransaction implements Parcelable {
            mType = copy.mType;
            mContainer = copy.mContainer;
            mBounds = copy.mBounds;
            mIncludingParents = copy.mIncludingParents;
            mReparent = copy.mReparent;
            mInsetsFrameProvider = copy.mInsetsFrameProvider;
            mInsetsFrameOwner = copy.mInsetsFrameOwner;
@@ -1575,6 +1605,7 @@ public final class WindowContainerTransaction implements Parcelable {
            mType = in.readInt();
            mContainer = in.readStrongBinder();
            mBounds = in.readTypedObject(Rect.CREATOR);
            mIncludingParents = in.readBoolean();
            mReparent = in.readStrongBinder();
            mInsetsFrameProvider = in.readTypedObject(InsetsFrameProvider.CREATOR);
            mInsetsFrameOwner = in.readStrongBinder();
@@ -1678,6 +1709,12 @@ public final class WindowContainerTransaction implements Parcelable {
            return mBounds;
        }

        /** Denotes whether the parents should also be included in the op. */
        @NonNull
        public boolean includingParents() {
            return mIncludingParents;
        }

        /** Gets a string representation of a hierarchy-op type. */
        public static String hopToString(int type) {
            switch (type) {
@@ -1789,6 +1826,7 @@ public final class WindowContainerTransaction implements Parcelable {
            dest.writeInt(mType);
            dest.writeStrongBinder(mContainer);
            dest.writeTypedObject(mBounds, flags);
            dest.writeBoolean(mIncludingParents);
            dest.writeStrongBinder(mReparent);
            dest.writeTypedObject(mInsetsFrameProvider, flags);
            dest.writeStrongBinder(mInsetsFrameOwner);
@@ -1866,6 +1904,8 @@ public final class WindowContainerTransaction implements Parcelable {
            @Nullable
            private Rect mBounds;

            private boolean mIncludingParents;

            private boolean mAlwaysOnTop;

            private boolean mReparentLeafTaskIfRelaunch;
@@ -1955,6 +1995,11 @@ public final class WindowContainerTransaction implements Parcelable {
                return this;
            }

            Builder setIncludingParents(boolean value) {
                mIncludingParents = value;
                return this;
            }

            HierarchyOp build() {
                final HierarchyOp hierarchyOp = new HierarchyOp(mType);
                hierarchyOp.mContainer = mContainer;
@@ -1976,6 +2021,7 @@ public final class WindowContainerTransaction implements Parcelable {
                hierarchyOp.mTaskFragmentOperation = mTaskFragmentOperation;
                hierarchyOp.mShortcutInfo = mShortcutInfo;
                hierarchyOp.mBounds = mBounds;
                hierarchyOp.mIncludingParents = mIncludingParents;
                hierarchyOp.mReparentLeafTaskIfRelaunch = mReparentLeafTaskIfRelaunch;

                return hierarchyOp;
+2 −2
Original line number Diff line number Diff line
@@ -23,8 +23,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.TaskFragmentOperation.OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS;
import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_OR_MOVE_TASK_FRAGMENT_DECOR_SURFACE;
import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_DELETE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE;
import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_BOTTOM_OF_TASK;
@@ -1834,7 +1834,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub

            task.getParent().positionChildAt(
                    hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM,
                    task, false /* includingParents */);
                    task, hop.includingParents());
        }
        return TRANSACT_EFFECTS_LIFECYCLE;
    }
+48 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -1454,6 +1455,53 @@ public class WindowOrganizerTests extends WindowTestsBase {
                pendingEvents.get(0).mTask.getTaskInfo().taskDescription.getLabel());
    }

    @Test
    public void testReorderWithParents() {
        /*
                  root
               ____|______
               |         |
           firstTda    secondTda
               |             |
         firstRootTask    secondRootTask

         */
        final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
        final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
                mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea",
                FEATURE_VENDOR_FIRST);
        final Task firstRootTask = firstTaskDisplayArea.createRootTask(
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
        final Task secondRootTask = secondTaskDisplayArea.createRootTask(
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
        final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
                .setTask(firstRootTask).build();
        final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
                .setTask(secondRootTask).build();
        // This assertion is just a defense to ensure that firstRootTask is not the top most
        // by default
        assertThat(mDisplayContent.getTopRootTask()).isEqualTo(secondRootTask);
        WindowContainerTransaction wct = new WindowContainerTransaction();

        // Reorder to top
        wct.reorder(firstRootTask.mRemoteToken.toWindowContainerToken(), true /* onTop */,
                true /* includingParents */);
        mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);

        // firstRootTask can only be on the top if its TDA was also reordered to the Top which
        // in-turn ensures that the reorder happened including the parents.
        assertThat(mDisplayContent.getTopRootTask()).isEqualTo(firstRootTask);

        // Reorder to bottom
        wct.reorder(firstRootTask.mRemoteToken.toWindowContainerToken(), false /* onTop */,
                true /* includingParents */);
        mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);

        // firstRootTask can only be on the bottom if its TDA was also reordered to the bottom
        // which in-turn ensures that the reorder happened including the parents.
        assertThat(mDisplayContent.getBottomMostTask()).isEqualTo(firstRootTask);
    }

    @Test
    public void testAppearDeferThenVanish() {
        final ITaskOrganizer organizer = registerMockOrganizer();