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

Commit 8ec51753 authored by Vinit Nayak's avatar Vinit Nayak Committed by Android (Google) Code Review
Browse files

Merge "Disable recents gesture when split animation running in shell" into main

parents 0474ce60 d46d51a5
Loading
Loading
Loading
Loading
+21 −1
Original line number Diff line number Diff line
@@ -64,7 +64,9 @@ public interface SplitScreen {
        default void onSplitVisibilityChanged(boolean visible) {}
    }

    /** Callback interface for listening to requests to enter split select */
    /**
     * Callback interface for listening to requests to enter split select. Used for desktop -> split
     */
    interface SplitSelectListener {
        default boolean onRequestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo,
                int splitPosition, Rect taskBounds) {
@@ -72,6 +74,15 @@ public interface SplitScreen {
        }
    }

    interface SplitInvocationListener {
        /**
         * Called whenever shell starts or stops the split screen animation
         * @param animationRunning if {@code true} the animation has begun, if {@code false} the
         *                         animation has finished
         */
        default void onSplitAnimationInvoked(boolean animationRunning) { }
    }

    /** Registers listener that gets split screen callback. */
    void registerSplitScreenListener(@NonNull SplitScreenListener listener,
            @NonNull Executor executor);
@@ -79,6 +90,15 @@ public interface SplitScreen {
    /** Unregisters listener that gets split screen callback. */
    void unregisterSplitScreenListener(@NonNull SplitScreenListener listener);

    /**
     * Registers a {@link SplitInvocationListener} to notify when the animation to enter split
     * screen has started and stopped
     *
     * @param executor callbacks to the listener will be executed on this executor
     */
    void registerSplitAnimationListener(@NonNull SplitInvocationListener listener,
            @NonNull Executor executor);

    /** Called when device waking up finished. */
    void onFinishedWakingUp();

+6 −0
Original line number Diff line number Diff line
@@ -1137,6 +1137,12 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
            });
        }

        @Override
        public void registerSplitAnimationListener(@NonNull SplitInvocationListener listener,
                @NonNull Executor executor) {
            mStageCoordinator.registerSplitAnimationListener(listener, executor);
        }

        @Override
        public void onFinishedWakingUp() {
            mMainExecutor.execute(SplitScreenController.this::onFinishedWakingUp);
+13 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import com.android.wm.shell.transition.OneShotRemoteHandler;
import com.android.wm.shell.transition.Transitions;

import java.util.ArrayList;
import java.util.concurrent.Executor;

/** Manages transition animations for split-screen. */
class SplitScreenTransitions {
@@ -79,6 +80,8 @@ class SplitScreenTransitions {

    private Transitions.TransitionFinishCallback mFinishCallback = null;
    private SurfaceControl.Transaction mFinishTransaction;
    private SplitScreen.SplitInvocationListener mSplitInvocationListener;
    private Executor mSplitInvocationListenerExecutor;

    SplitScreenTransitions(@NonNull TransactionPool pool, @NonNull Transitions transitions,
            @NonNull Runnable onFinishCallback, StageCoordinator stageCoordinator) {
@@ -353,6 +356,10 @@ class SplitScreenTransitions {
                    + " skip to start enter split transition since it already exist. ");
            return null;
        }
        if (mSplitInvocationListenerExecutor != null && mSplitInvocationListener != null) {
            mSplitInvocationListenerExecutor.execute(() -> mSplitInvocationListener
                    .onSplitAnimationInvoked(true /*animationRunning*/));
        }
        final IBinder transition = mTransitions.startTransition(transitType, wct, handler);
        setEnterTransition(transition, remoteTransition, extraTransitType, resizeAnim);
        return transition;
@@ -529,6 +536,12 @@ class SplitScreenTransitions {
        mTransitions.getAnimExecutor().execute(va::start);
    }

    public void registerSplitAnimListener(@NonNull SplitScreen.SplitInvocationListener listener,
            @NonNull Executor executor) {
        mSplitInvocationListener = listener;
        mSplitInvocationListenerExecutor = executor;
    }

    /** Calls when the transition got consumed. */
    interface TransitionConsumedCallback {
        void onConsumed(boolean aborted);
+36 −7
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executor;

/**
 * Coordinates the staging (visibility, sizing, ...) of the split-screen {@link MainStage} and
@@ -236,6 +237,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    private DefaultMixedHandler mMixedHandler;
    private final Toast mSplitUnsupportedToast;
    private SplitRequest mSplitRequest;
    /** Used to notify others of when shell is animating into split screen */
    private SplitScreen.SplitInvocationListener mSplitInvocationListener;
    private Executor mSplitInvocationListenerExecutor;

    /**
     * Since StageCoordinator only coordinates MainStage and SideStage, it shouldn't support
@@ -246,6 +250,14 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        return false;
    }

    /** NOTE: Will overwrite any previously set {@link #mSplitInvocationListener} */
    public void registerSplitAnimationListener(
            @NonNull SplitScreen.SplitInvocationListener listener, @NonNull Executor executor) {
        mSplitInvocationListener = listener;
        mSplitInvocationListenerExecutor = executor;
        mSplitTransitions.registerSplitAnimListener(listener, executor);
    }

    class SplitRequest {
        @SplitPosition
        int mActivatePosition;
@@ -529,7 +541,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                            null /* childrenToTop */, EXIT_REASON_UNKNOWN));
                    Log.w(TAG, splitFailureMessage("startShortcut",
                            "side stage was not populated"));
                    mSplitUnsupportedToast.show();
                    handleUnsupportedSplitStart();
                }

                if (finishedCallback != null) {
@@ -660,7 +672,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                            null /* childrenToTop */, EXIT_REASON_UNKNOWN));
                    Log.w(TAG, splitFailureMessage("startIntentLegacy",
                            "side stage was not populated"));
                    mSplitUnsupportedToast.show();
                    handleUnsupportedSplitStart();
                }

                if (apps != null) {
@@ -1213,7 +1225,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                            ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
            Log.w(TAG, splitFailureMessage("onRemoteAnimationFinishedOrCancelled",
                    "main or side stage was not populated."));
            mSplitUnsupportedToast.show();
            handleUnsupportedSplitStart();
        } else {
            mSyncQueue.queue(evictWct);
            mSyncQueue.runInSync(t -> {
@@ -1234,7 +1246,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                    ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
            Log.w(TAG, splitFailureMessage("onRemoteAnimationFinished",
                    "main or side stage was not populated"));
            mSplitUnsupportedToast.show();
            handleUnsupportedSplitStart();
            return;
        }

@@ -2801,6 +2813,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            if (hasEnteringPip) {
                mMixedHandler.animatePendingEnterPipFromSplit(transition, info,
                        startTransaction, finishTransaction, finishCallback);
                notifySplitAnimationFinished();
                return true;
            }

@@ -2835,6 +2848,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                //                    the transition, or synchronize task-org callbacks.
            }
            // Use normal animations.
            notifySplitAnimationFinished();
            return false;
        } else if (mMixedHandler != null && TransitionUtil.hasDisplayChange(info)) {
            // A display-change has been un-expectedly inserted into the transition. Redirect
@@ -2848,6 +2862,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                    mSplitLayout.update(startTransaction, true /* resetImePosition */);
                    startTransaction.apply();
                }
                notifySplitAnimationFinished();
                return true;
            }
        }
@@ -3021,7 +3036,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                    pendingEnter.mRemoteHandler.onTransitionConsumed(transition,
                            false /*aborted*/, finishT);
                }
                mSplitUnsupportedToast.show();
                handleUnsupportedSplitStart();
                return true;
            }
        }
@@ -3050,6 +3065,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        final TransitionInfo.Change finalMainChild = mainChild;
        final TransitionInfo.Change finalSideChild = sideChild;
        enterTransition.setFinishedCallback((callbackWct, callbackT) -> {
            notifySplitAnimationFinished();
            if (finalMainChild != null) {
                if (!mainNotContainOpenTask) {
                    mMainStage.evictOtherChildren(callbackWct, finalMainChild.getTaskInfo().taskId);
@@ -3466,6 +3482,19 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                mSplitLayout.isLeftRightSplit());
    }

    private void handleUnsupportedSplitStart() {
        mSplitUnsupportedToast.show();
        notifySplitAnimationFinished();
    }

    private void notifySplitAnimationFinished() {
        if (mSplitInvocationListener == null || mSplitInvocationListenerExecutor == null) {
            return;
        }
        mSplitInvocationListenerExecutor.execute(() ->
                mSplitInvocationListener.onSplitAnimationInvoked(false /*animationRunning*/));
    }

    /**
     * Logs the exit of splitscreen to a specific stage. This must be called before the exit is
     * executed.
@@ -3528,7 +3557,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                if (!ENABLE_SHELL_TRANSITIONS) {
                    StageCoordinator.this.exitSplitScreen(isMainStage ? mMainStage : mSideStage,
                            EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
                    mSplitUnsupportedToast.show();
                    handleUnsupportedSplitStart();
                    return;
                }

@@ -3548,7 +3577,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                        "app package " + taskInfo.baseActivity.getPackageName()
                        + " does not support splitscreen, or is a controlled activity type"));
                if (splitScreenVisible) {
                    mSplitUnsupportedToast.show();
                    handleUnsupportedSplitStart();
                }
            }
        }
+16 −0
Original line number Diff line number Diff line
@@ -39,10 +39,13 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.annotation.NonNull;
import android.app.ActivityManager;
@@ -63,6 +66,7 @@ import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
@@ -105,6 +109,8 @@ public class SplitTransitionTests extends ShellTestCase {
    @Mock private ShellExecutor mMainExecutor;
    @Mock private LaunchAdjacentController mLaunchAdjacentController;
    @Mock private DefaultMixedHandler mMixedHandler;
    @Mock private SplitScreen.SplitInvocationListener mInvocationListener;
    private final TestShellExecutor mTestShellExecutor = new TestShellExecutor();
    private SplitLayout mSplitLayout;
    private MainStage mMainStage;
    private SideStage mSideStage;
@@ -147,6 +153,7 @@ public class SplitTransitionTests extends ShellTestCase {
                .setParentTaskId(mSideStage.mRootTaskInfo.taskId).build();
        doReturn(mock(SplitDecorManager.class)).when(mMainStage).getSplitDecorManager();
        doReturn(mock(SplitDecorManager.class)).when(mSideStage).getSplitDecorManager();
        mStageCoordinator.registerSplitAnimationListener(mInvocationListener, mTestShellExecutor);
    }

    @Test
@@ -452,6 +459,15 @@ public class SplitTransitionTests extends ShellTestCase {
        mMainStage.activate(new WindowContainerTransaction(), true /* includingTopTask */);
    }

    @Test
    @UiThreadTest
    public void testSplitInvocationCallback() {
        enterSplit();
        mTestShellExecutor.flushAll();
        verify(mInvocationListener, times(1))
                .onSplitAnimationInvoked(eq(true));
    }

    private boolean containsSplitEnter(@NonNull WindowContainerTransaction wct) {
        for (int i = 0; i < wct.getHierarchyOps().size(); ++i) {
            WindowContainerTransaction.HierarchyOp op = wct.getHierarchyOps().get(i);
Loading