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

Commit 9b27cdf8 authored by Tony Huang's avatar Tony Huang
Browse files

Improve drag divider dismiss transition.

Before this CL, the split root task will not include in tansition
when drag to dismiss. It leads to users could see flicker when
the top task bounds changed due to no animation on it.

On this CL, it add update bounds too on dismiss transition then
split root could be included in transition. And we could use decor
to do fade-out animation.

Fix: 245472831
Fix: 283045645
Test: manual
Test: pass existing tests
Change-Id: Ie6be85173d9a5b71603aa89858df117be08ea484
parent f05dac69
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -293,6 +293,9 @@ public class SplitDecorManager extends WindowlessWindowManager {
        }

        if (mResizingIconView == null) {
            if (mRunningAnimationCount == 0 && animFinishedCallback != null) {
                animFinishedCallback.accept(false);
            }
            return;
        }

@@ -311,6 +314,9 @@ public class SplitDecorManager extends WindowlessWindowManager {
                        releaseDecor(finishT);
                        finishT.apply();
                        finishT.close();
                        if (mRunningAnimationCount == 0 && animFinishedCallback != null) {
                            animFinishedCallback.accept(true);
                        }
                    }
                });
                return;
+49 −6
Original line number Diff line number Diff line
@@ -87,6 +87,14 @@ class SplitScreenTransitions {
        mStageCoordinator = stageCoordinator;
    }

    private void initTransition(@NonNull IBinder transition,
            @NonNull SurfaceControl.Transaction finishTransaction,
            @NonNull Transitions.TransitionFinishCallback finishCallback) {
        mAnimatingTransition = transition;
        mFinishTransaction = finishTransaction;
        mFinishCallback = finishCallback;
    }

    /** Play animation for enter transition or dismiss transition. */
    void playAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startTransaction,
@@ -94,9 +102,7 @@ class SplitScreenTransitions {
            @NonNull Transitions.TransitionFinishCallback finishCallback,
            @NonNull WindowContainerToken mainRoot, @NonNull WindowContainerToken sideRoot,
            @NonNull WindowContainerToken topRoot) {
        mFinishCallback = finishCallback;
        mAnimatingTransition = transition;
        mFinishTransaction = finishTransaction;
        initTransition(transition, finishTransaction, finishCallback);

        final TransitSession pendingTransition = getPendingTransition(transition);
        if (pendingTransition != null) {
@@ -220,6 +226,45 @@ class SplitScreenTransitions {
        onFinish(null /* wct */, null /* wctCB */);
    }

    /** Play animation for drag divider dismiss transition. */
    void playDragDismissAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction,
            @NonNull Transitions.TransitionFinishCallback finishCallback,
            @NonNull WindowContainerToken toTopRoot, @NonNull SplitDecorManager toTopDecor,
            @NonNull WindowContainerToken topRoot) {
        initTransition(transition, finishTransaction, finishCallback);

        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
            final TransitionInfo.Change change = info.getChanges().get(i);
            final SurfaceControl leash = change.getLeash();

            if (toTopRoot.equals(change.getContainer())) {
                startTransaction.setAlpha(leash, 1.f);
                startTransaction.show(leash);

                ValueAnimator va = new ValueAnimator();
                mAnimations.add(va);

                toTopDecor.onResized(startTransaction, animated -> {
                    mAnimations.remove(va);
                    if (animated) {
                        mTransitions.getMainExecutor().execute(() -> {
                            onFinish(null /* wct */, null /* wctCB */);
                        });
                    }
                });
            } else if (topRoot.equals(change.getContainer())) {
                // Ensure it on top of all changes in transition.
                startTransaction.setLayer(leash, Integer.MAX_VALUE);
                startTransaction.setAlpha(leash, 1.f);
                startTransaction.show(leash);
            }
        }
        startTransaction.apply();
        onFinish(null /* wct */, null /* wctCB */);
    }

    /** Play animation for resize transition. */
    void playResizeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startTransaction,
@@ -227,9 +272,7 @@ class SplitScreenTransitions {
            @NonNull Transitions.TransitionFinishCallback finishCallback,
            @NonNull WindowContainerToken mainRoot, @NonNull WindowContainerToken sideRoot,
            @NonNull SplitDecorManager mainDecor, @NonNull SplitDecorManager sideDecor) {
        mFinishCallback = finishCallback;
        mAnimatingTransition = transition;
        mFinishTransaction = finishTransaction;
        initTransition(transition, finishTransaction, finishCallback);

        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
            final TransitionInfo.Change change = info.getChanges().get(i);
+21 −4
Original line number Diff line number Diff line
@@ -1328,8 +1328,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            mIsExiting = true;
            childrenToTop.resetBounds(wct);
            wct.reorder(childrenToTop.mRootTaskInfo.token, true);
            wct.setSmallestScreenWidthDp(childrenToTop.mRootTaskInfo.token,
                    SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
        }
        wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
                false /* reparentLeafTaskIfRelaunch */);
@@ -1517,6 +1515,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,

    void finishEnterSplitScreen(SurfaceControl.Transaction t) {
        mSplitLayout.update(t);
        mMainStage.getSplitDecorManager().inflate(mContext, mMainStage.mRootLeash,
                getMainStageBounds());
        mSideStage.getSplitDecorManager().inflate(mContext, mSideStage.mRootLeash,
                getSideStageBounds());
        setDividerVisibility(true, t);
        // Ensure divider surface are re-parented back into the hierarchy at the end of the
        // transition. See Transition#buildFinishTransaction for more detail.
@@ -1989,13 +1991,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        final boolean mainStageToTop =
                bottomOrRight ? mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT
                        : mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT;
        final StageTaskListener toTopStage = mainStageToTop ? mMainStage : mSideStage;
        if (!ENABLE_SHELL_TRANSITIONS) {
            exitSplitScreen(mainStageToTop ? mMainStage : mSideStage, reason);
            exitSplitScreen(toTopStage, reason);
            return;
        }

        final int dismissTop = mainStageToTop ? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE;
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        toTopStage.resetBounds(wct);
        prepareExitSplitScreen(dismissTop, wct);
        if (mRootTaskInfo != null) {
            wct.setDoNotPip(mRootTaskInfo.token);
@@ -2531,8 +2535,17 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            shouldAnimate = startPendingEnterAnimation(
                    mSplitTransitions.mPendingEnter, info, startTransaction, finishTransaction);
        } else if (mSplitTransitions.isPendingDismiss(transition)) {
            final SplitScreenTransitions.DismissSession dismiss = mSplitTransitions.mPendingDismiss;
            shouldAnimate = startPendingDismissAnimation(
                    mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction);
                    dismiss, info, startTransaction, finishTransaction);
            if (shouldAnimate && dismiss.mReason == EXIT_REASON_DRAG_DIVIDER) {
                final StageTaskListener toTopStage =
                        dismiss.mDismissTop == STAGE_TYPE_MAIN ? mMainStage : mSideStage;
                mSplitTransitions.playDragDismissAnimation(transition, info, startTransaction,
                        finishTransaction, finishCallback, toTopStage.mRootTaskInfo.token,
                        toTopStage.getSplitDecorManager(), mRootTaskInfo.token);
                return true;
            }
        } else if (mSplitTransitions.isPendingResize(transition)) {
            mSplitTransitions.playResizeAnimation(transition, info, startTransaction,
                    finishTransaction, finishCallback, mMainStage.mRootTaskInfo.token,
@@ -2787,6 +2800,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            mSplitTransitions.mPendingDismiss = null;
            return false;
        }
        dismissTransition.setFinishedCallback((callbackWct, callbackT) -> {
            mMainStage.getSplitDecorManager().release(callbackT);
            mSideStage.getSplitDecorManager().release(callbackT);
        });

        addDividerBarToTransition(info, false /* show */);
        return true;
+3 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.wm.shell.splitscreen;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
import static android.view.RemoteAnimationTarget.MODE_OPENING;

import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
@@ -201,7 +202,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
    public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
        if (mRootTaskInfo.taskId == taskInfo.taskId) {
            // Inflates split decor view only when the root task is visible.
            if (mRootTaskInfo.isVisible != taskInfo.isVisible) {
            if (!ENABLE_SHELL_TRANSITIONS && mRootTaskInfo.isVisible != taskInfo.isVisible) {
                if (taskInfo.isVisible) {
                    mSplitDecorManager.inflate(mContext, mRootLeash,
                            taskInfo.configuration.windowConfiguration.getBounds());
@@ -385,6 +386,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
    void resetBounds(WindowContainerTransaction wct) {
        wct.setBounds(mRootTaskInfo.token, null);
        wct.setAppBounds(mRootTaskInfo.token, null);
        wct.setSmallestScreenWidthDp(mRootTaskInfo.token, SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
    }

    void onSplitScreenListenerRegistered(SplitScreen.SplitScreenListener listener,
+4 −0
Original line number Diff line number Diff line
@@ -44,11 +44,15 @@ public class SplitTestUtils {

    static SplitLayout createMockSplitLayout() {
        final Rect dividerBounds = new Rect(48, 0, 52, 100);
        final Rect bounds1 = new Rect(0, 0, 40, 100);
        final Rect bounds2 = new Rect(60, 0, 100, 100);
        final SurfaceControl leash = createMockSurface();
        SplitLayout out = mock(SplitLayout.class);
        doReturn(dividerBounds).when(out).getDividerBounds();
        doReturn(dividerBounds).when(out).getRefDividerBounds();
        doReturn(leash).when(out).getDividerLeash();
        doReturn(bounds1).when(out).getBounds1();
        doReturn(bounds2).when(out).getBounds2();
        return out;
    }

Loading