From 53d1bb6e50229dc9c75b1123d17bb299e346dd36 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Fri, 23 Apr 2021 13:14:41 -0700 Subject: [PATCH] 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 --- .../shared/system/RemoteTransitionCompat.java | 86 ++++++++++++++++--- 1 file changed, 75 insertions(+), 11 deletions(-) diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java index 351dfd5b10c4c..5708855b0a4f9 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java @@ -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) {