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

Commit 53d1bb6e authored by Evan Rosky's avatar Evan Rosky
Browse files

Adapt transition merge during recents into onTaskAppeared.

If an incoming transition merge request contains only a task
open, this will be converted into the existing onTaskAppeared
callback that recents expects.

Bug: 186132704
Test: open app, swipe to overview, scroll to another app, launch.
Change-Id: Ifd288fbb73e2b4ea7011066bda5c3694b5f579d9
parent 08d64fbc
Loading
Loading
Loading
Loading
+75 −11
Original line number Diff line number Diff line
@@ -101,6 +101,9 @@ public class RemoteTransitionCompat implements Parcelable {
    public RemoteTransitionCompat(RecentsAnimationListener recents,
            RecentsAnimationControllerCompat controller) {
        mTransition = new IRemoteTransition.Stub() {
            final RecentsControllerWrap mRecentsSession = new RecentsControllerWrap();
            IBinder mToken = null;

            @Override
            public void startAnimation(IBinder transition, TransitionInfo info,
                    SurfaceControl.Transaction t,
@@ -110,6 +113,7 @@ public class RemoteTransitionCompat implements Parcelable {
                final RemoteAnimationTargetCompat[] wallpapers =
                        RemoteAnimationTargetCompat.wrap(info, true /* wallpapers */);
                // TODO(b/177438007): Move this set-up logic into launcher's animation impl.
                mToken = transition;
                // This transition is for opening recents, so recents is on-top. We want to draw
                // the current going-away task on top of recents, though, so move it to front
                WindowContainerToken pausingTask = null;
@@ -127,9 +131,8 @@ public class RemoteTransitionCompat implements Parcelable {
                    t.setAlpha(wallpapers[i].leash.mSurfaceControl, 1);
                }
                t.apply();
                final RecentsAnimationControllerCompat wrapControl =
                        new RecentsControllerWrap(controller, info, finishedCallback, pausingTask);
                recents.onAnimationStart(wrapControl, apps, wallpapers, new Rect(0, 0, 0, 0),
                mRecentsSession.setup(controller, info, finishedCallback, pausingTask);
                recents.onAnimationStart(mRecentsSession, apps, wallpapers, new Rect(0, 0, 0, 0),
                        new Rect());
            }

@@ -137,7 +140,13 @@ public class RemoteTransitionCompat implements Parcelable {
            public void mergeAnimation(IBinder transition, TransitionInfo info,
                    SurfaceControl.Transaction t, IBinder mergeTarget,
                    IRemoteTransitionFinishedCallback finishedCallback) {
                // TODO: hook up merge to onTaskAppeared. Until then, just ignore incoming merges.
                if (!mergeTarget.equals(mToken)) return;
                if (!mRecentsSession.merge(info, t, recents)) return;
                try {
                    finishedCallback.onTransitionFinished(null /* wct */);
                } catch (RemoteException e) {
                    Log.e(TAG, "Error merging transition.", e);
                }
            }
        };
    }
@@ -159,19 +168,57 @@ public class RemoteTransitionCompat implements Parcelable {
     */
    @VisibleForTesting
    static class RecentsControllerWrap extends RecentsAnimationControllerCompat {
        private final RecentsAnimationControllerCompat mWrapped;
        private final IRemoteTransitionFinishedCallback mFinishCB;
        private final WindowContainerToken mPausingTask;
        private final TransitionInfo mInfo;
        private RecentsAnimationControllerCompat mWrapped = null;
        private IRemoteTransitionFinishedCallback mFinishCB = null;
        private WindowContainerToken mPausingTask = null;
        private TransitionInfo mInfo = null;
        private SurfaceControl mOpeningLeash = null;

        RecentsControllerWrap(RecentsAnimationControllerCompat wrapped, TransitionInfo info,
        void setup(RecentsAnimationControllerCompat wrapped, TransitionInfo info,
                IRemoteTransitionFinishedCallback finishCB, WindowContainerToken pausingTask) {
            if (mInfo != null) {
                throw new IllegalStateException("Trying to run a new recents animation while"
                        + " recents is already active.");
            }
            mWrapped = wrapped;
            mInfo = info;
            mFinishCB = finishCB;
            mPausingTask = pausingTask;
        }

        @SuppressLint("NewApi")
        boolean merge(TransitionInfo info, SurfaceControl.Transaction t,
                RecentsAnimationListener recents) {
            TransitionInfo.Change openingTask = null;
            for (int i = info.getChanges().size() - 1; i >= 0; --i) {
                final TransitionInfo.Change change = info.getChanges().get(i);
                if (change.getMode() == TRANSIT_OPEN || change.getMode() == TRANSIT_TO_FRONT) {
                    if (change.getTaskInfo() != null) {
                        if (openingTask != null) {
                            Log.w(TAG, " Expecting to merge a task-open, but got >1 opening "
                                    + "tasks");
                        }
                        openingTask = change;
                    }
                }
            }
            if (openingTask == null) return false;
            mOpeningLeash = openingTask.getLeash();
            if (openingTask.getContainer().equals(mPausingTask)) {
                // In this case, we are "returning" to the already running app, so just consume
                // the merge and do nothing.
                return true;
            }
            // We are receiving a new opening task, so convert to onTaskAppeared.
            final int layer = mInfo.getChanges().size() * 3;
            t.reparent(mOpeningLeash, mInfo.getRootLeash());
            t.setLayer(mOpeningLeash, layer);
            t.hide(mOpeningLeash);
            t.apply();
            recents.onTaskAppeared(new RemoteAnimationTargetCompat(openingTask, layer));
            return true;
        }

        @Override public ThumbnailData screenshotTask(int taskId) {
            return mWrapped != null ? mWrapped.screenshotTask(taskId) : null;
        }
@@ -198,25 +245,42 @@ public class RemoteTransitionCompat implements Parcelable {
        @Override
        @SuppressLint("NewApi")
        public void finish(boolean toHome, boolean sendUserLeaveHint) {
            if (mFinishCB == null) {
                Log.e(TAG, "Duplicate call to finish", new RuntimeException());
                return;
            }
            if (mWrapped != null) mWrapped.finish(toHome, sendUserLeaveHint);
            try {
                if (!toHome && mPausingTask != null) {
                if (!toHome && mPausingTask != null && mOpeningLeash == null) {
                    // The gesture went back to opening the app rather than continuing with
                    // recents, so end the transition by moving the app back to the top.
                    final WindowContainerTransaction wct = new WindowContainerTransaction();
                    wct.reorder(mPausingTask, true /* onTop */);
                    mFinishCB.onTransitionFinished(wct);
                } else {
                    if (mOpeningLeash != null) {
                        // TODO: the launcher animation should handle this
                        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
                        t.show(mOpeningLeash);
                        t.setAlpha(mOpeningLeash, 1.f);
                        t.apply();
                    }
                    mFinishCB.onTransitionFinished(null /* wct */);
                }
            } catch (RemoteException e) {
                Log.e("RemoteTransitionCompat", "Failed to call animation finish callback", e);
            }
            if (mWrapped != null) mWrapped.finish(toHome, sendUserLeaveHint);
            // Release surface references now. This is apparently to free GPU
            // memory while doing quick operations (eg. during CTS).
            for (int i = 0; i < mInfo.getChanges().size(); ++i) {
                mInfo.getChanges().get(i).getLeash().release();
            }
            // Reset all members.
            mWrapped = null;
            mFinishCB = null;
            mPausingTask = null;
            mInfo = null;
            mOpeningLeash = null;
        }

        @Override public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) {