From d88ee6c69c722d85c133516794481c4c4b410365 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Wed, 5 Oct 2022 16:51:39 +0000 Subject: [PATCH] Make sure that a recents-launch with remote gets its own transition If a remote is attached to an activity-launch, it should be its own transition so that the requester can get the proper transition lifecycle events (handleRequest). Unfortunately, the current startActivity API is synchronous, so we don't know if the caller needs an accurate result or not so normally we have to merge all launches meaning the remote can get lost. Fortunately, for recents, we do know that launcher cares about the transition lifecycle and not the startActivity result. So, in this case, we can defer the activity start if necessary. Bug: 250012839 Test: launch app with dialogactivity on top. Swipe to recents. Change-Id: I715518bf9611b8ad50bbfb5b05dea8002cb5a6e5 --- .../server/wm/ActivityStartController.java | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java index 0707b818f0930..30454d45574eb 100644 --- a/services/core/java/com/android/server/wm/ActivityStartController.java +++ b/services/core/java/com/android/server/wm/ActivityStartController.java @@ -50,6 +50,7 @@ import android.util.Slog; import android.util.SparseArray; import android.view.RemoteAnimationAdapter; import android.view.WindowManager; +import android.window.RemoteTransition; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; @@ -563,14 +564,39 @@ public class ActivityStartController { return false; } mService.mRootWindowContainer.startPowerModeLaunchIfNeeded(true /* forceSend */, r); - final ActivityMetricsLogger.LaunchingState launchingState = - mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent); - final Task task = r.getTask(); - mService.deferWindowLayout(); - try { + final RemoteTransition remote = options.getRemoteTransition(); + if (remote != null && rootTask.mTransitionController.isCollecting()) { + final Transition transition = new Transition(WindowManager.TRANSIT_TO_FRONT, + 0 /* flags */, rootTask.mTransitionController, + mService.mWindowManager.mSyncEngine); + // Special case: we are entering recents while an existing transition is running. In + // this case, we know it's safe to "defer" the activity launch, so lets do so now so + // that it can get its own transition and thus update launcher correctly. + mService.mWindowManager.mSyncEngine.queueSyncSet( + () -> rootTask.mTransitionController.moveToCollecting(transition), + () -> { + final Task task = r.getTask(); + task.mTransitionController.requestStartTransition(transition, + task, remote, null /* displayChange */); + task.mTransitionController.collect(task); + startExistingRecentsIfPossibleInner(intent, options, r, task, rootTask); + }); + } else { + final Task task = r.getTask(); task.mTransitionController.requestTransitionIfNeeded(WindowManager.TRANSIT_TO_FRONT, 0 /* flags */, task, task /* readyGroupRef */, options.getRemoteTransition(), null /* displayChange */); + startExistingRecentsIfPossibleInner(intent, options, r, task, rootTask); + } + return true; + } + + void startExistingRecentsIfPossibleInner(Intent intent, ActivityOptions options, + ActivityRecord r, Task task, Task rootTask) { + final ActivityMetricsLogger.LaunchingState launchingState = + mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent); + mService.deferWindowLayout(); + try { r.mTransitionController.setTransientLaunch(r, TaskDisplayArea.getRootTaskAbove(rootTask)); task.moveToFront("startExistingRecents"); @@ -582,7 +608,6 @@ public class ActivityStartController { task.mInResumeTopActivity = false; mService.continueWindowLayout(); } - return true; } void registerRemoteAnimationForNextActivityStart(String packageName,