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

Commit 848dac4f authored by Gustav Sennton's avatar Gustav Sennton
Browse files

Windowing: Reparent minimizing-change to keep task behind others

Before this CL, minimizing Tasks would show in front of other Tasks
during the minimize-animation since the animation-leash is shown in
front of other Tasks. With this CL we reparent the minimizing Task to
the root Task to keep it behind other Tasks.

Bug: 335427677
Flag: com.android.window.flags.enable_desktop_windowing_task_limit
Test: minimize a Task -> shows behind other Tasks

Change-Id: I53e4d9ef76f7e291a0c4dacba64ceb71c3e98dd9
parent 7f73178c
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECI
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
import static android.view.WindowManager.TRANSIT_RELAUNCH;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_OWNER_THUMBNAIL;
import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_WORK_THUMBNAIL;
import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS;
@@ -62,6 +63,7 @@ import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITI
import static com.android.wm.shell.transition.TransitionAnimationHelper.edgeExtendWindow;
import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionBackgroundColorIfSet;
import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionTypeFromInfo;
import static com.android.wm.shell.transition.TransitionAnimationHelper.isCoveredByOpaqueFullscreenChange;
import static com.android.wm.shell.transition.TransitionAnimationHelper.loadAttributeAnimation;

import android.animation.Animator;
@@ -352,6 +354,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
                continue;
            }
            final boolean isTask = change.getTaskInfo() != null;
            final boolean isFreeform = isTask && change.getTaskInfo().isFreeform();
            final int mode = change.getMode();
            boolean isSeamlessDisplayChange = false;

@@ -458,6 +461,16 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
                            final int layer = zSplitLine + numChanges - i;
                            startTransaction.setLayer(change.getLeash(), layer);
                        }
                    } else if (!isCoveredByOpaqueFullscreenChange(info, change)
                            && isFreeform
                            && TransitionUtil.isOpeningMode(type)
                            && change.getMode() == TRANSIT_TO_BACK) {
                        // Reparent the minimize-change to the root task so the minimizing Task
                        // isn't shown in front of other Tasks.
                        mRootTDAOrganizer.reparentToDisplayArea(
                                change.getTaskInfo().displayId,
                                change.getLeash(),
                                startTransaction);
                    } else if (isOnlyTranslucent && TransitionUtil.isOpeningType(info.getType())
                                && TransitionUtil.isClosingType(mode)) {
                        // If there is a closing translucent task in an OPENING transition, we will
+1 −1
Original line number Diff line number Diff line
@@ -444,7 +444,7 @@ public class TransitionAnimationHelper {
     * Returns whether there is an opaque fullscreen Change positioned in front of the given Change
     * in the given TransitionInfo.
     */
    private static boolean isCoveredByOpaqueFullscreenChange(
    static boolean isCoveredByOpaqueFullscreenChange(
            TransitionInfo info, TransitionInfo.Change change) {
        // TransitionInfo#getChanges() are ordered from front to back
        for (TransitionInfo.Change coveringChange : info.getChanges()) {
+73 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.wm.shell.transition;

import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_SLEEP;
@@ -185,6 +186,73 @@ public class DefaultTransitionHandlerTest extends ShellTestCase {
        verify(startT, never()).setColor(any(), any());
    }

    @Test
    public void startAnimation_freeformOpenChange_doesntReparentTask() {
        final TransitionInfo.Change openChange = new ChangeBuilder(TRANSIT_OPEN)
                .setTask(createTaskInfo(
                        /* taskId= */ 1, /* windowingMode= */ WINDOWING_MODE_FULLSCREEN))
                .build();
        final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN)
                .addChange(openChange)
                .build();
        final IBinder token = new Binder();
        final SurfaceControl.Transaction startT = MockTransactionPool.create();
        final SurfaceControl.Transaction finishT = MockTransactionPool.create();

        mTransitionHandler.startAnimation(token, info, startT, finishT,
                mock(Transitions.TransitionFinishCallback.class));

        verify(startT, never()).reparent(any(), any());
    }

    @Test
    public void startAnimation_freeformMinimizeChange_underFullscreenChange_doesntReparentTask() {
        final TransitionInfo.Change openChange = new ChangeBuilder(TRANSIT_OPEN)
                .setTask(createTaskInfo(
                        /* taskId= */ 1, /* windowingMode= */ WINDOWING_MODE_FULLSCREEN))
                .build();
        final TransitionInfo.Change toBackChange = new ChangeBuilder(TRANSIT_TO_BACK)
                .setTask(createTaskInfo(
                        /* taskId= */ 2, /* windowingMode= */ WINDOWING_MODE_FREEFORM))
                .build();
        final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN)
                .addChange(openChange)
                .addChange(toBackChange)
                .build();
        final IBinder token = new Binder();
        final SurfaceControl.Transaction startT = MockTransactionPool.create();
        final SurfaceControl.Transaction finishT = MockTransactionPool.create();

        mTransitionHandler.startAnimation(token, info, startT, finishT,
                mock(Transitions.TransitionFinishCallback.class));

        verify(startT, never()).reparent(any(), any());
    }

    @Test
    public void startAnimation_freeform_minimizeAnimation_reparentsTask() {
        final TransitionInfo.Change openChange = new ChangeBuilder(TRANSIT_OPEN)
                .setTask(createTaskInfo(
                        /* taskId= */ 1, /* windowingMode= */ WINDOWING_MODE_FREEFORM))
                .build();
        final TransitionInfo.Change toBackChange = new ChangeBuilder(TRANSIT_TO_BACK)
                .setTask(createTaskInfo(
                        /* taskId= */ 2, /* windowingMode= */ WINDOWING_MODE_FREEFORM))
                .build();
        final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN)
                .addChange(openChange)
                .addChange(toBackChange)
                .build();
        final IBinder token = new Binder();
        final SurfaceControl.Transaction startT = MockTransactionPool.create();
        final SurfaceControl.Transaction finishT = MockTransactionPool.create();

        mTransitionHandler.startAnimation(token, info, startT, finishT,
                mock(Transitions.TransitionFinishCallback.class));

        verify(startT).reparent(any(), any());
    }

    private static void mergeSync(Transitions.TransitionHandler handler, IBinder token) {
        handler.mergeAnimation(
                new Binder(),
@@ -195,10 +263,14 @@ public class DefaultTransitionHandlerTest extends ShellTestCase {
    }

    private static RunningTaskInfo createTaskInfo(int taskId) {
        return createTaskInfo(taskId, WINDOWING_MODE_FULLSCREEN);
    }

    private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
        RunningTaskInfo taskInfo = new RunningTaskInfo();
        taskInfo.taskId = taskId;
        taskInfo.topActivityType = ACTIVITY_TYPE_STANDARD;
        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
        taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
        taskInfo.configuration.windowConfiguration.setActivityType(taskInfo.topActivityType);
        taskInfo.token = mock(WindowContainerToken.class);
        return taskInfo;