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

Commit a9e39d51 authored by Jerry Chang's avatar Jerry Chang Committed by Android (Google) Code Review
Browse files

Merge "Fix transition when leaving a split pair by home key" into udc-dev

parents 2b02fbd8 e13200ed
Loading
Loading
Loading
Loading
+39 −67
Original line number Diff line number Diff line
@@ -66,13 +66,11 @@ class SplitScreenTransitions {
    private final Transitions mTransitions;
    private final Runnable mOnFinish;

    DismissTransition mPendingDismiss = null;
    DismissSession mPendingDismiss = null;
    TransitSession mPendingEnter = null;
    TransitSession mPendingRecent = null;
    TransitSession mPendingResize = null;

    private IBinder mAnimatingTransition = null;
    OneShotRemoteHandler mPendingRemoteHandler = null;
    private OneShotRemoteHandler mActiveRemoteHandler = null;

    private final Transitions.TransitionFinishCallback mRemoteFinishCB = this::onFinish;
@@ -101,27 +99,30 @@ class SplitScreenTransitions {
        mFinishCallback = finishCallback;
        mAnimatingTransition = transition;
        mFinishTransaction = finishTransaction;
        if (mPendingRemoteHandler != null) {
            mPendingRemoteHandler.startAnimation(transition, info, startTransaction,

        final TransitSession pendingTransition = getPendingTransition(transition);
        if (pendingTransition != null) {
            if (pendingTransition.mCanceled) {
                // The pending transition was canceled, so skip playing animation.
                startTransaction.apply();
                onFinish(null /* wct */, null /* wctCB */);
                return;
            }

            if (pendingTransition.mRemoteHandler != null) {
                pendingTransition.mRemoteHandler.startAnimation(transition, info, startTransaction,
                        finishTransaction, mRemoteFinishCB);
            mActiveRemoteHandler = mPendingRemoteHandler;
            mPendingRemoteHandler = null;
                mActiveRemoteHandler = pendingTransition.mRemoteHandler;
                return;
            }
        }

        playInternalAnimation(transition, info, startTransaction, mainRoot, sideRoot, topRoot);
    }

    private void playInternalAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction t, @NonNull WindowContainerToken mainRoot,
            @NonNull WindowContainerToken sideRoot, @NonNull WindowContainerToken topRoot) {
        final TransitSession pendingTransition = getPendingTransition(transition);
        if (pendingTransition != null && pendingTransition.mCanceled) {
            // The pending transition was canceled, so skip playing animation.
            t.apply();
            onFinish(null /* wct */, null /* wctCB */);
            return;
        }

        // Play some place-holder fade animations
        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
            final TransitionInfo.Change change = info.getChanges().get(i);
@@ -260,10 +261,6 @@ class SplitScreenTransitions {
        return mPendingEnter != null && mPendingEnter.mTransition == transition;
    }

    boolean isPendingRecent(IBinder transition) {
        return mPendingRecent != null && mPendingRecent.mTransition == transition;
    }

    boolean isPendingDismiss(IBinder transition) {
        return mPendingDismiss != null && mPendingDismiss.mTransition == transition;
    }
@@ -276,8 +273,6 @@ class SplitScreenTransitions {
    private TransitSession getPendingTransition(IBinder transition) {
        if (isPendingEnter(transition)) {
            return mPendingEnter;
        } else if (isPendingRecent(transition)) {
            return mPendingRecent;
        } else if (isPendingDismiss(transition)) {
            return mPendingDismiss;
        } else if (isPendingResize(transition)) {
@@ -311,14 +306,8 @@ class SplitScreenTransitions {
            @Nullable RemoteTransition remoteTransition,
            @Nullable TransitionConsumedCallback consumedCallback,
            @Nullable TransitionFinishedCallback finishedCallback) {
        mPendingEnter = new TransitSession(transition, consumedCallback, finishedCallback);

        if (remoteTransition != null) {
            // Wrapping it for ease-of-use (OneShot handles all the binder linking/death stuff)
            mPendingRemoteHandler = new OneShotRemoteHandler(
                    mTransitions.getMainExecutor(), remoteTransition);
            mPendingRemoteHandler.setTransition(transition);
        }
        mPendingEnter = new TransitSession(
                transition, consumedCallback, finishedCallback, remoteTransition);

        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "  splitTransition "
                + " deduced Enter split screen");
@@ -344,7 +333,7 @@ class SplitScreenTransitions {
    /** Sets a transition to dismiss split. */
    void setDismissTransition(@NonNull IBinder transition, @SplitScreen.StageType int dismissTop,
            @SplitScreenController.ExitReason int reason) {
        mPendingDismiss = new DismissTransition(transition, reason, dismissTop);
        mPendingDismiss = new DismissSession(transition, reason, dismissTop);

        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "  splitTransition "
                        + " deduced Dismiss due to %s. toTop=%s",
@@ -372,32 +361,10 @@ class SplitScreenTransitions {
                + " deduced Resize split screen");
    }

    void setRecentTransition(@NonNull IBinder transition,
            @Nullable RemoteTransition remoteTransition,
            @Nullable TransitionFinishedCallback finishCallback) {
        mPendingRecent = new TransitSession(transition, null /* consumedCb */, finishCallback);

        if (remoteTransition != null) {
            // Wrapping it for ease-of-use (OneShot handles all the binder linking/death stuff)
            mPendingRemoteHandler = new OneShotRemoteHandler(
                    mTransitions.getMainExecutor(), remoteTransition);
            mPendingRemoteHandler.setTransition(transition);
        }

        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "  splitTransition "
                + " deduced Enter recent panel");
    }

    void mergeAnimation(IBinder transition, TransitionInfo info, SurfaceControl.Transaction t,
            IBinder mergeTarget, Transitions.TransitionFinishCallback finishCallback) {
        if (mergeTarget != mAnimatingTransition) return;

        if (isPendingEnter(transition) && isPendingRecent(mergeTarget)) {
            // Since there's an entering transition merged, recent transition no longer
            // need to handle entering split screen after the transition finished.
            mPendingRecent.setFinishedCallback(null);
        }

        if (mActiveRemoteHandler != null) {
            mActiveRemoteHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback);
        } else {
@@ -425,19 +392,13 @@ class SplitScreenTransitions {
                // An entering transition got merged, appends the rest operations to finish entering
                // split screen.
                mStageCoordinator.finishEnterSplitScreen(finishT);
                mPendingRemoteHandler = null;
            }

            mPendingEnter.onConsumed(aborted);
            mPendingEnter = null;
            mPendingRemoteHandler = null;
        } else if (isPendingDismiss(transition)) {
            mPendingDismiss.onConsumed(aborted);
            mPendingDismiss = null;
        } else if (isPendingRecent(transition)) {
            mPendingRecent.onConsumed(aborted);
            mPendingRecent = null;
            mPendingRemoteHandler = null;
        } else if (isPendingResize(transition)) {
            mPendingResize.onConsumed(aborted);
            mPendingResize = null;
@@ -451,9 +412,6 @@ class SplitScreenTransitions {
        if (isPendingEnter(mAnimatingTransition)) {
            mPendingEnter.onFinished(wct, mFinishTransaction);
            mPendingEnter = null;
        } else if (isPendingRecent(mAnimatingTransition)) {
            mPendingRecent.onFinished(wct, mFinishTransaction);
            mPendingRecent = null;
        } else if (isPendingDismiss(mAnimatingTransition)) {
            mPendingDismiss.onFinished(wct, mFinishTransaction);
            mPendingDismiss = null;
@@ -462,7 +420,6 @@ class SplitScreenTransitions {
            mPendingResize = null;
        }

        mPendingRemoteHandler = null;
        mActiveRemoteHandler = null;
        mAnimatingTransition = null;

@@ -568,10 +525,11 @@ class SplitScreenTransitions {
    }

    /** Session for a transition and its clean-up callback. */
    static class TransitSession {
    class TransitSession {
        final IBinder mTransition;
        TransitionConsumedCallback mConsumedCallback;
        TransitionFinishedCallback mFinishedCallback;
        OneShotRemoteHandler mRemoteHandler;

        /** Whether the transition was canceled. */
        boolean mCanceled;
@@ -579,10 +537,24 @@ class SplitScreenTransitions {
        TransitSession(IBinder transition,
                @Nullable TransitionConsumedCallback consumedCallback,
                @Nullable TransitionFinishedCallback finishedCallback) {
            this(transition, consumedCallback, finishedCallback, null /* remoteTransition */);
        }

        TransitSession(IBinder transition,
                @Nullable TransitionConsumedCallback consumedCallback,
                @Nullable TransitionFinishedCallback finishedCallback,
                @Nullable RemoteTransition remoteTransition) {
            mTransition = transition;
            mConsumedCallback = consumedCallback;
            mFinishedCallback = finishedCallback;

            if (remoteTransition != null) {
                // Wrapping the remote transition for ease-of-use. (OneShot handles all the binder
                // linking/death stuff)
                mRemoteHandler = new OneShotRemoteHandler(
                        mTransitions.getMainExecutor(), remoteTransition);
                mRemoteHandler.setTransition(transition);
            }
        }

        /** Sets transition consumed callback. */
@@ -621,11 +593,11 @@ class SplitScreenTransitions {
    }

    /** Bundled information of dismiss transition. */
    static class DismissTransition extends TransitSession {
    class DismissSession extends TransitSession {
        final int mReason;
        final @SplitScreen.StageType int mDismissTop;

        DismissTransition(IBinder transition, int reason, int dismissTop) {
        DismissSession(IBinder transition, int reason, int dismissTop) {
            super(transition, null /* consumedCallback */, null /* finishedCallback */);
            this.mReason = reason;
            this.mDismissTop = dismissTop;
+11 −13
Original line number Diff line number Diff line
@@ -2226,16 +2226,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            } else if (isOpening && inFullscreen) {
                final int activityType = triggerTask.getActivityType();
                if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) {
                    if (request.getRemoteTransition() != null) {
                    // starting recents/home, so don't handle this and let it fall-through to
                    // the remote handler.
                    return null;
                }
                    // Need to use the old stuff for non-remote animations, otherwise we don't
                    // exit split-screen.
                    mSplitTransitions.setRecentTransition(transition, null /* remote */,
                            this::onRecentsInSplitAnimationFinish);
                }
            }
        } else {
            if (isOpening && getStageOfTask(triggerTask) != null) {
@@ -2363,8 +2357,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        if (mSplitTransitions.isPendingEnter(transition)) {
            shouldAnimate = startPendingEnterAnimation(
                    transition, info, startTransaction, finishTransaction);
        } else if (mSplitTransitions.isPendingRecent(transition)) {
            onRecentsInSplitAnimationStart(startTransaction);
        } else if (mSplitTransitions.isPendingDismiss(transition)) {
            shouldAnimate = startPendingDismissAnimation(
                    mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction);
@@ -2589,7 +2581,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    }

    private boolean startPendingDismissAnimation(
            @NonNull SplitScreenTransitions.DismissTransition dismissTransition,
            @NonNull SplitScreenTransitions.DismissSession dismissTransition,
            @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t,
            @NonNull SurfaceControl.Transaction finishT) {
        prepareDismissAnimation(dismissTransition.mDismissTop, dismissTransition.mReason, info,
@@ -2626,7 +2618,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,

    /** Call this when the recents animation during split-screen finishes. */
    public void onRecentsInSplitAnimationFinish(WindowContainerTransaction finishWct,
            SurfaceControl.Transaction finishT) {
            SurfaceControl.Transaction finishT, TransitionInfo info) {
        // Check if the recent transition is finished by returning to the current
        // split, so we can restore the divider bar.
        for (int i = 0; i < finishWct.getHierarchyOps().size(); ++i) {
@@ -2643,8 +2635,14 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            }
        }

        // TODO(b/275664132): Remove dismissing split screen here to fit in back-to-split support.
        // Dismiss the split screen if it's not returning to split.
        prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, finishWct);
        for (TransitionInfo.Change change : info.getChanges()) {
            if (change.getTaskInfo() != null && TransitionUtil.isClosingType(change.getMode())) {
                finishT.setCrop(change.getLeash(), null).hide(change.getLeash());
            }
        }
        setSplitsVisible(false);
        setDividerVisibility(false, finishT);
        logExit(EXIT_REASON_UNKNOWN);
+9 −8
Original line number Diff line number Diff line
@@ -187,17 +187,18 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
                && isOpeningType(request.getType())
                && request.getTriggerTask() != null
                && request.getTriggerTask().getWindowingMode() == WINDOWING_MODE_FULLSCREEN
                && (request.getTriggerTask().getActivityType() == ACTIVITY_TYPE_HOME
                        || request.getTriggerTask().getActivityType() == ACTIVITY_TYPE_RECENTS)
                && request.getRemoteTransition() != null) {
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while "
                && request.getTriggerTask().getActivityType() == ACTIVITY_TYPE_HOME) {
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a going-home request while "
                    + "Split-Screen is active, so treat it as Mixed.");
            Pair<Transitions.TransitionHandler, WindowContainerTransaction> handler =
                    mPlayer.dispatchRequest(transition, request, this);
            if (handler == null) {
                android.util.Log.e(Transitions.TAG, "   No handler for remote? This is unexpected"
                        + ", there should at-least be RemoteHandler.");
                return null;
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                        " Lean on the remote transition handler to fetch a proper remote via"
                                + " TransitionFilter");
                handler = new Pair<>(
                        mPlayer.getRemoteTransitionHandler(),
                        new WindowContainerTransaction());
            }
            final MixedTransition mixed = new MixedTransition(
                    MixedTransition.TYPE_RECENTS_DURING_SPLIT, transition);
@@ -515,7 +516,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
            // If pair-to-pair switching, the post-recents clean-up isn't needed.
            if (mixed.mAnimType != MixedTransition.ANIM_TYPE_PAIR_TO_PAIR) {
                wct = wct != null ? wct : new WindowContainerTransaction();
                mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction);
                mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction, info);
            }
            mSplitHandler.onTransitionAnimationComplete();
            finishCallback.onTransitionFinished(wct, wctCB);
+4 −0
Original line number Diff line number Diff line
@@ -324,6 +324,10 @@ public class Transitions implements RemoteCallable<Transitions> {
        mRemoteTransitionHandler.removeFiltered(remoteTransition);
    }

    RemoteTransitionHandler getRemoteTransitionHandler() {
        return mRemoteTransitionHandler;
    }

    /** Registers an observer on the lifecycle of transitions. */
    public void registerObserver(@NonNull TransitionObserver observer) {
        mObservers.add(observer);
+1 −1
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ class DismissSplitScreenByGoHome(flicker: FlickerTest) : SplitScreenBase(flicker
    // TODO(b/245472831): Move back to presubmit after shell transitions landing.
    @FlakyTest(bugId = 245472831)
    @Test
    fun secondaryAppLayerBecomesInvisible() = flicker.layerBecomesInvisible(primaryApp)
    fun secondaryAppLayerBecomesInvisible() = flicker.layerBecomesInvisible(secondaryApp)

    // TODO(b/245472831): Move back to presubmit after shell transitions landing.
    @FlakyTest(bugId = 245472831)
Loading