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

Commit 82a602a2 authored by Gustav Sennton's avatar Gustav Sennton
Browse files

[3/N] Report home visibility update on cancelling DragToDesktop transition

When the DragToDesktop START transition gets interrupted (from an unknown
incoming transition) before we've requested an END/CANCEL transition, we
finish the START transition and let it move the user to the Home screen.
In this case we never request an END/CANCEL transition, and before this
CL we would thus never update Home visibility. With this CL we update the
Home visibility when START ends (onTransitionFinished) if we haven't
received an END/CANCEL transition by then.

Bug: 397135730
Test: HomeTransitionObserverTest
Flag: com.android.window.flags.enable_drag_to_desktop_incoming_transitions_bugfix
Change-Id: I7b7c0f40f274210387253a6f02d1eb471b0332b1
parent 5aa2cd3e
Loading
Loading
Loading
Loading
+51 −38
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.wm.shell.transition;

import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.DesktopModeFlags.ENABLE_DRAG_TO_DESKTOP_INCOMING_TRANSITIONS_BUGFIX;
import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;

import static com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP;
@@ -50,6 +51,7 @@ public class HomeTransitionObserver implements TransitionObserver,

    private @NonNull final Context mContext;
    private @NonNull final ShellExecutor mMainExecutor;
    private IBinder mPendingStartDragTransition;
    private Boolean mPendingHomeVisibilityUpdate;

    public HomeTransitionObserver(@NonNull Context context,
@@ -63,31 +65,42 @@ public class HomeTransitionObserver implements TransitionObserver,
            @NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction) {
        if (BubbleAnythingFlagHelper.enableBubbleToFullscreen()) {
            handleTransitionReadyWithBubbleAnything(info);
        } else {
            handleTransitionReady(info);
        }
        Boolean homeVisibilityUpdate = getHomeVisibilityUpdate(info);

        if (info.getType() == TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP) {
            // Do not apply at the start of desktop drag as that updates launcher UI visibility.
            // Store the value and apply with a next transition or when cancelling the
            // desktop-drag transition.
            storePendingHomeVisibilityUpdate(transition, homeVisibilityUpdate);
            return;
        }

    private void handleTransitionReady(@NonNull TransitionInfo info) {
        for (TransitionInfo.Change change : info.getChanges()) {
            final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
            if (taskInfo == null
                    || info.getType() == TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP
                    || taskInfo.displayId != DEFAULT_DISPLAY
                    || taskInfo.taskId == -1
                    || !taskInfo.isRunning) {
                continue;
        if (BubbleAnythingFlagHelper.enableBubbleToFullscreen()
                && info.getType() == TRANSIT_CONVERT_TO_BUBBLE
                && homeVisibilityUpdate == null) {
            // We are converting to bubble and we did not get a change to home visibility in this
            // transition. Apply the value from start of drag.
            homeVisibilityUpdate = mPendingHomeVisibilityUpdate;
        }
            Boolean homeVisibilityUpdate = getHomeVisibilityUpdate(info, change, taskInfo);

        if (homeVisibilityUpdate != null) {
            mPendingHomeVisibilityUpdate = null;
            mPendingStartDragTransition = null;
            notifyHomeVisibilityChanged(homeVisibilityUpdate);
        }
    }

    private void storePendingHomeVisibilityUpdate(
            IBinder transition, Boolean homeVisibilityUpdate) {
        if (!BubbleAnythingFlagHelper.enableBubbleToFullscreen()
                && !ENABLE_DRAG_TO_DESKTOP_INCOMING_TRANSITIONS_BUGFIX.isTrue()) {
            return;
        }
        mPendingHomeVisibilityUpdate = homeVisibilityUpdate;
        mPendingStartDragTransition = transition;
    }

    private void handleTransitionReadyWithBubbleAnything(@NonNull TransitionInfo info) {
    private Boolean getHomeVisibilityUpdate(TransitionInfo info) {
        Boolean homeVisibilityUpdate = null;
        for (TransitionInfo.Change change : info.getChanges()) {
            final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
@@ -97,29 +110,12 @@ public class HomeTransitionObserver implements TransitionObserver,
                    || !taskInfo.isRunning) {
                continue;
            }

            Boolean update = getHomeVisibilityUpdate(info, change, taskInfo);
            if (update != null) {
                homeVisibilityUpdate = update;
            }
        }

        if (info.getType() == TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP) {
            // Do not apply at the start of desktop drag as that updates launcher UI visibility.
            // Store the value and apply with a next transition if needed.
            mPendingHomeVisibilityUpdate = homeVisibilityUpdate;
            return;
        }

        if (info.getType() == TRANSIT_CONVERT_TO_BUBBLE && homeVisibilityUpdate == null) {
            // We are converting to bubble and we did not get a change to home visibility in this
            // transition. Apply the value from start of drag.
            homeVisibilityUpdate = mPendingHomeVisibilityUpdate;
        }
        if (homeVisibilityUpdate != null) {
            mPendingHomeVisibilityUpdate = null;
            notifyHomeVisibilityChanged(homeVisibilityUpdate);
        }
        return homeVisibilityUpdate;
    }

    private Boolean getHomeVisibilityUpdate(TransitionInfo info,
@@ -146,7 +142,24 @@ public class HomeTransitionObserver implements TransitionObserver,

    @Override
    public void onTransitionFinished(@NonNull IBinder transition,
            boolean aborted) {}
            boolean aborted) {
        if (!ENABLE_DRAG_TO_DESKTOP_INCOMING_TRANSITIONS_BUGFIX.isTrue()) {
            return;
        }
        // Handle the case where the DragToDesktop START transition is interrupted and we never
        // receive a CANCEL/END transition.
        if (mPendingStartDragTransition == null
                || mPendingStartDragTransition != transition) {
            return;
        }
        mPendingStartDragTransition = null;
        if (aborted) return;

        if (mPendingHomeVisibilityUpdate != null) {
            notifyHomeVisibilityChanged(mPendingHomeVisibilityUpdate);
            mPendingHomeVisibilityUpdate = null;
        }
    }

    /**
     * Sets the home transition listener that receives any transitions resulting in a change of
+69 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.window.flags.Flags.FLAG_ENABLE_DRAG_TO_DESKTOP_INCOMING_TRANSITIONS_BUGFIX;
import static com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP;
import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE;

@@ -44,6 +45,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
@@ -195,6 +197,73 @@ public class HomeTransitionObserverTest extends ShellTestCase {
        verify(mListener, times(0)).onHomeVisibilityChanged(anyBoolean());
    }

    @Test
    @DisableFlags({FLAG_ENABLE_DRAG_TO_DESKTOP_INCOMING_TRANSITIONS_BUGFIX})
    public void startDragToDesktopFinished_flagDisabled_doesNotTriggerCallback()
            throws RemoteException {
        TransitionInfo info = mock(TransitionInfo.class);
        TransitionInfo.Change change = mock(TransitionInfo.Change.class);
        ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class);
        when(change.getTaskInfo()).thenReturn(taskInfo);
        when(info.getChanges()).thenReturn(new ArrayList<>(List.of(change)));
        when(info.getType()).thenReturn(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP);
        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_OPEN, true);
        IBinder transition = mock(IBinder.class);
        mHomeTransitionObserver.onTransitionReady(
                transition,
                info,
                mock(SurfaceControl.Transaction.class),
                mock(SurfaceControl.Transaction.class));

        mHomeTransitionObserver.onTransitionFinished(transition, /* aborted= */ false);

        verify(mListener, never()).onHomeVisibilityChanged(/* isVisible= */ anyBoolean());
    }

    @Test
    @EnableFlags({FLAG_ENABLE_DRAG_TO_DESKTOP_INCOMING_TRANSITIONS_BUGFIX})
    public void startDragToDesktopAborted_doesNotTriggerCallback() throws RemoteException {
        TransitionInfo info = mock(TransitionInfo.class);
        TransitionInfo.Change change = mock(TransitionInfo.Change.class);
        ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class);
        when(change.getTaskInfo()).thenReturn(taskInfo);
        when(info.getChanges()).thenReturn(new ArrayList<>(List.of(change)));
        when(info.getType()).thenReturn(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP);
        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_OPEN, true);
        IBinder transition = mock(IBinder.class);
        mHomeTransitionObserver.onTransitionReady(
                transition,
                info,
                mock(SurfaceControl.Transaction.class),
                mock(SurfaceControl.Transaction.class));

        mHomeTransitionObserver.onTransitionFinished(transition, /* aborted= */ true);

        verify(mListener, never()).onHomeVisibilityChanged(/* isVisible= */ anyBoolean());
    }

    @Test
    @EnableFlags({FLAG_ENABLE_DRAG_TO_DESKTOP_INCOMING_TRANSITIONS_BUGFIX})
    public void startDragToDesktopFinished_triggersCallback() throws RemoteException {
        TransitionInfo info = mock(TransitionInfo.class);
        TransitionInfo.Change change = mock(TransitionInfo.Change.class);
        ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class);
        when(change.getTaskInfo()).thenReturn(taskInfo);
        when(info.getChanges()).thenReturn(new ArrayList<>(List.of(change)));
        when(info.getType()).thenReturn(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP);
        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_OPEN, true);
        IBinder transition = mock(IBinder.class);
        mHomeTransitionObserver.onTransitionReady(
                transition,
                info,
                mock(SurfaceControl.Transaction.class),
                mock(SurfaceControl.Transaction.class));

        mHomeTransitionObserver.onTransitionFinished(transition, /* aborted= */ false);

        verify(mListener).onHomeVisibilityChanged(/* isVisible= */ true);
    }

    @Test
    @EnableFlags({Flags.FLAG_ENABLE_BUBBLE_TO_FULLSCREEN, Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE})
    public void testDragTaskToBubbleOverHome_notifiesHomeIsVisible() throws RemoteException {