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

Commit ab14e55a authored by Chilun Huang's avatar Chilun Huang Committed by Android (Google) Code Review
Browse files

Merge "Improve shell transition of dismiss by divider"

parents a38206b2 1e8a9711
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;

import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreen.stageTypeToString;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER;
import static com.android.wm.shell.splitscreen.SplitScreenController.exitReasonToString;
@@ -179,6 +181,33 @@ class SplitScreenTransitions {
        onFinish(null /* wct */, null /* wctCB */);
    }

    void applyDismissTransition(@NonNull IBinder transition, @NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction,
            @NonNull Transitions.TransitionFinishCallback finishCallback,
            @NonNull WindowContainerToken topRoot,
            @NonNull WindowContainerToken mainRoot, @NonNull WindowContainerToken sideRoot,
            @NonNull SplitDecorManager mainDecor, @NonNull SplitDecorManager sideDecor) {
        if (mPendingDismiss.mDismissTop != STAGE_TYPE_UNDEFINED) {
            mFinishCallback = finishCallback;
            mAnimatingTransition = transition;
            mFinishTransaction = finishTransaction;

            final SplitDecorManager topDecor = mPendingDismiss.mDismissTop == STAGE_TYPE_MAIN
                    ? mainDecor : sideDecor;
            topDecor.fadeOutDecor(() -> {
                mTransitions.getMainExecutor().execute(() -> {
                    onFinish(null /* wct */, null /* wctCB */);
                });
            });

            startTransaction.apply();
        } else {
            playAnimation(transition, info, startTransaction, finishTransaction,
                    finishCallback, mainRoot, sideRoot, topRoot);
        }
    }

    void applyResizeTransition(@NonNull IBinder transition, @NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction,
@@ -200,8 +229,11 @@ class SplitScreenTransitions {

                SplitDecorManager decor = mainRoot.equals(change.getContainer())
                        ? mainDecor : sideDecor;

                // This is to ensure onFinished be called after all animations ended.
                ValueAnimator va = new ValueAnimator();
                mAnimations.add(va);

                decor.setScreenshotIfNeeded(change.getSnapshot(), startTransaction);
                decor.onResized(startTransaction, () -> {
                    mTransitions.getMainExecutor().execute(() -> {
+66 −24
Original line number Diff line number Diff line
@@ -1354,8 +1354,18 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    private void prepareExitSplitScreen(@StageType int stageToTop,
            @NonNull WindowContainerTransaction wct) {
        if (!mMainStage.isActive()) return;
        mSideStage.removeAllTasks(wct, stageToTop == STAGE_TYPE_SIDE);
        mMainStage.deactivate(wct, stageToTop == STAGE_TYPE_MAIN);
        // Set the dismiss-to-top side to fullscreen for dismiss transition.
        // Reparent the non-dismiss-to-top side to properly update its visibility.
        if (stageToTop == STAGE_TYPE_MAIN) {
            wct.setBounds(mMainStage.mRootTaskInfo.token, null /* bounds */);
            mSideStage.removeAllTasks(wct, false /* toTop */);
        } else if (stageToTop == STAGE_TYPE_SIDE) {
            wct.setBounds(mSideStage.mRootTaskInfo.token, null /* bounds */);
            mMainStage.deactivate(wct, false /* toTop */);
        } else {
            mSideStage.removeAllTasks(wct, false /* toTop */);
            mMainStage.deactivate(wct, false /* toTop */);
        }
    }

    private void prepareEnterSplitScreen(WindowContainerTransaction wct) {
@@ -2273,6 +2283,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        } else if (mSplitTransitions.isPendingDismiss(transition)) {
            shouldAnimate = startPendingDismissAnimation(
                    mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction);
            if (shouldAnimate) {
                mSplitTransitions.applyDismissTransition(transition, info,
                        startTransaction, finishTransaction, finishCallback, mRootTaskInfo.token,
                        mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token,
                        mMainStage.getSplitDecorManager(), mSideStage.getSplitDecorManager());
                return true;
            }
        } else if (mSplitTransitions.isPendingResize(transition)) {
            mSplitTransitions.applyResizeTransition(transition, info, startTransaction,
                    finishTransaction, finishCallback, mMainStage.mRootTaskInfo.token,
@@ -2403,6 +2420,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        // aren't serialized with transition callbacks.
        // TODO(b/184679596): Find a way to either include task-org information in
        //                    the transition, or synchronize task-org callbacks.
        if (toStage == STAGE_TYPE_UNDEFINED) {
            if (mMainStage.getChildCount() != 0) {
                final StringBuilder tasksLeft = new StringBuilder();
                for (int i = 0; i < mMainStage.getChildCount(); ++i) {
@@ -2423,11 +2441,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                        + " to have been called with [" + tasksLeft.toString()
                        + "] before startAnimation().");
            }
        }

        mRecentTasks.ifPresent(recentTasks -> {
            // Notify recents if we are exiting in a way that breaks the pair, and disable further
            // updates to splits in the recents until we enter split again
            if (shouldBreakPairedTaskInRecents(dismissReason) && mShouldUpdateRecents) {
                if (toStage == STAGE_TYPE_UNDEFINED) {
                    for (TransitionInfo.Change change : info.getChanges()) {
                        final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
                        if (taskInfo != null
@@ -2435,6 +2455,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                            recentTasks.removeSplitPair(taskInfo.taskId);
                        }
                    }
                } else {
                    recentTasks.removeSplitPair(mMainStage.getTopVisibleChildTaskId());
                    recentTasks.removeSplitPair(mSideStage.getTopVisibleChildTaskId());
                }
            }
        });
        mShouldUpdateRecents = false;
@@ -2446,6 +2470,12 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        // Reset crops so they don't interfere with subsequent launches
        t.setCrop(mMainStage.mRootLeash, null);
        t.setCrop(mSideStage.mRootLeash, null);
        // Hide the non-top stage and set the top one to the fullscreen position.
        if (toStage != STAGE_TYPE_UNDEFINED) {
            t.hide(toStage == STAGE_TYPE_MAIN ? mSideStage.mRootLeash : mMainStage.mRootLeash);
            t.setPosition(toStage == STAGE_TYPE_MAIN
                    ? mMainStage.mRootLeash : mSideStage.mRootLeash, 0, 0);
        }

        if (toStage == STAGE_TYPE_UNDEFINED) {
            logExit(dismissReason);
@@ -2472,6 +2502,18 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            mSplitLayout.release(t);
            mSplitTransitions.mPendingDismiss = null;
            return false;
        } else {
            final @SplitScreen.StageType int dismissTop = dismissTransition.mDismissTop;
            // Reparent all tasks after dismiss transition finished.
            dismissTransition.setFinishedCallback(
                    new SplitScreenTransitions.TransitionFinishedCallback() {
                        @Override
                        public void onFinished(WindowContainerTransaction wct,
                                SurfaceControl.Transaction t) {
                            mSideStage.removeAllTasks(wct, dismissTop == STAGE_TYPE_SIDE);
                            mMainStage.deactivate(wct, dismissTop == STAGE_TYPE_MAIN);
                        }
                    });
        }

        addDividerBarToTransition(info, finishT, false /* show */);
+2 −1
Original line number Diff line number Diff line
@@ -371,7 +371,8 @@ public class SplitTransitionTests extends ShellTestCase {
        IBinder transition = mock(IBinder.class);
        WindowContainerTransaction result = mStageCoordinator.handleRequest(transition, request);

        assertTrue(containsSplitExit(result));
        // Don't reparent tasks until the animation is complete.
        assertFalse(containsSplitExit(result));

        // make sure we haven't made any local changes yet (need to wait until transition is ready)
        assertTrue(mStageCoordinator.isSplitScreenVisible());