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

Commit b9c28dc9 authored by Eric Lin's avatar Eric Lin
Browse files

Add WCT API for excluding individual tasks from recents.

Introduces a new WindowContainerTransaction (WCT) API,
setTaskForceExcludedFromRecents(), which allows clients to explicitly
exclude individual tasks from the Recents list. This provides a more
direct and flexible way to control task visibility in Recents.

Bug: 404726350
Flag: com.android.window.flags.exclude_task_from_recents
Test: atest WmTests:WindowContainerTransactionTests
Test: atest WmTests:WindowOrganizerTests
Change-Id: Id561740dc225860905ffc28524db083633b4685b
parent 850e122f
Loading
Loading
Loading
Loading
+44 −1
Original line number Diff line number Diff line
@@ -469,6 +469,28 @@ public final class WindowContainerTransaction implements Parcelable {
        return this;
    }

    /**
     * Sets whether the task should be forcibly excluded from Recents.
     *
     * @param container The window container of the task that the exclusion state is set on.
     * @param forceExcluded  {@code true} to force exclude the task, {@code false} otherwise.
     * @throws IllegalStateException if the flag {@link Flags.FLAG_EXCLUDE_TASK_FROM_RECENTS} is
     *                               not enabled.
     * @hide
     */
    @NonNull
    public WindowContainerTransaction setTaskForceExcludedFromRecents(
            @NonNull WindowContainerToken container, boolean forceExcluded) {
        if (!Flags.excludeTaskFromRecents()) {
            throw new IllegalStateException(
                    "Flag " + Flags.FLAG_EXCLUDE_TASK_FROM_RECENTS + " is not enabled");
        }
        final Change chg = getOrCreateChange(container.asBinder());
        chg.mChangeMask |= Change.CHANGE_FORCE_EXCLUDED_FROM_RECENTS;
        chg.mForceExcludedFromRecents = forceExcluded;
        return this;
    }

    /*
     * ===========================================================================================
     * Hierarchy updates (create/destroy/reorder/reparent containers)
@@ -1292,6 +1314,7 @@ public final class WindowContainerTransaction implements Parcelable {
        public static final int CHANGE_FORCE_TRANSLUCENT = 1 << 6;
        public static final int CHANGE_DRAG_RESIZING = 1 << 7;
        public static final int CHANGE_RELATIVE_BOUNDS = 1 << 8;
        public static final int CHANGE_FORCE_EXCLUDED_FROM_RECENTS = 1 << 9;

        @IntDef(flag = true, prefix = { "CHANGE_" }, value = {
                CHANGE_FOCUSABLE,
@@ -1302,7 +1325,8 @@ public final class WindowContainerTransaction implements Parcelable {
                CHANGE_FORCE_NO_PIP,
                CHANGE_FORCE_TRANSLUCENT,
                CHANGE_DRAG_RESIZING,
                CHANGE_RELATIVE_BOUNDS
                CHANGE_RELATIVE_BOUNDS,
                CHANGE_FORCE_EXCLUDED_FROM_RECENTS,
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface ChangeMask {}
@@ -1313,6 +1337,7 @@ public final class WindowContainerTransaction implements Parcelable {
        private boolean mIgnoreOrientationRequest = false;
        private boolean mForceTranslucent = false;
        private boolean mDragResizing = false;
        private boolean mForceExcludedFromRecents = false;

        private @ChangeMask int mChangeMask = 0;
        private @ActivityInfo.Config int mConfigSetMask = 0;
@@ -1336,6 +1361,7 @@ public final class WindowContainerTransaction implements Parcelable {
            mIgnoreOrientationRequest = in.readBoolean();
            mForceTranslucent = in.readBoolean();
            mDragResizing = in.readBoolean();
            mForceExcludedFromRecents = in.readBoolean();
            mChangeMask = in.readInt();
            mConfigSetMask = in.readInt();
            mWindowSetMask = in.readInt();
@@ -1388,6 +1414,9 @@ public final class WindowContainerTransaction implements Parcelable {
            if ((other.mChangeMask & CHANGE_DRAG_RESIZING) != 0) {
                mDragResizing = other.mDragResizing;
            }
            if ((other.mChangeMask & CHANGE_FORCE_EXCLUDED_FROM_RECENTS) != 0) {
                mForceExcludedFromRecents = other.mForceExcludedFromRecents;
            }
            mChangeMask |= other.mChangeMask;
            if (other.mActivityWindowingMode >= WINDOWING_MODE_UNDEFINED) {
                mActivityWindowingMode = other.mActivityWindowingMode;
@@ -1460,6 +1489,15 @@ public final class WindowContainerTransaction implements Parcelable {
            return mDragResizing;
        }

        /** Gets whether the task is force excluded from recents. */
        public boolean getForceExcludedFromRecents() {
            if (!Flags.excludeTaskFromRecents()) {
                throw new IllegalStateException(
                        "Flag " + Flags.FLAG_EXCLUDE_TASK_FROM_RECENTS + " is not enabled");
            }
            return mForceExcludedFromRecents;
        }

        /** Gets whether the config should be sent to the client at the end of the transition. */
        public boolean getConfigAtTransitionEnd() {
            return mConfigAtTransitionEnd;
@@ -1539,6 +1577,9 @@ public final class WindowContainerTransaction implements Parcelable {
            if ((mChangeMask & CHANGE_DRAG_RESIZING) != 0) {
                sb.append("dragResizing:" + mDragResizing + ",");
            }
            if ((mChangeMask & CHANGE_FORCE_EXCLUDED_FROM_RECENTS) != 0) {
                sb.append("forceExcludedFromRecents:" + mForceExcludedFromRecents + ",");
            }
            if (mBoundsChangeTransaction != null) {
                sb.append("hasBoundsTransaction,");
            }
@@ -1563,6 +1604,7 @@ public final class WindowContainerTransaction implements Parcelable {
            dest.writeBoolean(mIgnoreOrientationRequest);
            dest.writeBoolean(mForceTranslucent);
            dest.writeBoolean(mDragResizing);
            dest.writeBoolean(mForceExcludedFromRecents);
            dest.writeInt(mChangeMask);
            dest.writeInt(mConfigSetMask);
            dest.writeInt(mWindowSetMask);
@@ -2250,6 +2292,7 @@ public final class WindowContainerTransaction implements Parcelable {
                    sb.append("container= ").append(mContainer)
                            .append(" safeRegionBounds= ")
                            .append(mSafeRegionBounds);
                    break;
                default:
                    sb.append("container=").append(mContainer)
                            .append(" reparent=").append(mReparent)
+6 −1
Original line number Diff line number Diff line
@@ -121,7 +121,6 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
import android.view.RemoteAnimationAdapter;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.IDisplayAreaOrganizerController;
@@ -892,6 +891,11 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
            tr.setDragResizing(c.getDragResizing());
        }

        if ((c.getChangeMask()
                & WindowContainerTransaction.Change.CHANGE_FORCE_EXCLUDED_FROM_RECENTS) != 0) {
            tr.setForceExcludedFromRecents(c.getForceExcludedFromRecents());
        }

        final int childWindowingMode = c.getActivityWindowingMode();
        if (!ActivityTaskManagerService.isPip2ExperimentEnabled()
                && tr.getWindowingMode() == WINDOWING_MODE_PINNED) {
@@ -1528,6 +1532,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                }
                container.setSafeRegionBounds(hop.getSafeRegionBounds());
                effects |= TRANSACT_EFFECTS_CLIENT_CONFIG;
                break;
            }
        }
        return effects;
+32 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
@@ -360,6 +361,37 @@ public class WindowContainerTransactionTests extends WindowTestsBase {
        assertNull(taskDisplayArea.getSafeRegionBounds());
    }

    @Test
    @EnableFlags(Flags.FLAG_EXCLUDE_TASK_FROM_RECENTS)
    public void testSetTaskForceExcludedFromRecents() {
        final Task rootTask = createTask(mDisplayContent);
        final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        final WindowContainerToken token = task.mRemoteToken.toWindowContainerToken();

        wct.setTaskForceExcludedFromRecents(token, true /* forceExcluded */);
        applyTransaction(wct);

        assertTrue(task.isForceExcludedFromRecents());
    }

    @Test
    @EnableFlags(Flags.FLAG_EXCLUDE_TASK_FROM_RECENTS)
    public void testSetTaskForceExcludedFromRecents_resetsTaskForceExcludedFromRecents() {
        final Task rootTask = createTask(mDisplayContent);
        final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        final WindowContainerToken token = task.mRemoteToken.toWindowContainerToken();
        wct.setTaskForceExcludedFromRecents(token, true /* forceExcluded */);
        applyTransaction(wct);

        // Re-include the task using WCT.
        wct.setTaskForceExcludedFromRecents(token, false /* forceExcluded */);
        applyTransaction(wct);

        assertFalse(task.isForceExcludedFromRecents());
    }

    @Test
    public void testDesktopMode_moveTaskToFront() {
        final TestDesktopOrganizer desktopOrganizer = new TestDesktopOrganizer(mAtm);
+31 −0
Original line number Diff line number Diff line
@@ -1613,6 +1613,37 @@ public class WindowOrganizerTests extends WindowTestsBase {
        assertNull(task1.getSafeRegionBounds());
    }

    @Test
    @EnableFlags(Flags.FLAG_EXCLUDE_TASK_FROM_RECENTS)
    public void testSetTaskForceExcludedFromRecents() {
        final Task rootTask = createRootTask();
        final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        final WindowContainerToken token = task.mRemoteToken.toWindowContainerToken();

        wct.setTaskForceExcludedFromRecents(token, true /* forceExcluded */);
        mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);

        assertTrue(task.isForceExcludedFromRecents());
    }

    @Test
    @EnableFlags(Flags.FLAG_EXCLUDE_TASK_FROM_RECENTS)
    public void testSetTaskForceExcludedFromRecents_resetsTaskForceExcludedFromRecents() {
        final Task rootTask = createRootTask();
        final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        final WindowContainerToken token = task.mRemoteToken.toWindowContainerToken();
        wct.setTaskForceExcludedFromRecents(token, true /* forceExcluded */);
        mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);

        // Reset excludedFromRecents on the task.
        wct.setTaskForceExcludedFromRecents(token, false /* forceExcluded */);
        mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);

        assertFalse(task.isForceExcludedFromRecents());
    }

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