From 788821ec4e0b0bc57721aef15d6a7b5a41f6121a Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Wed, 17 Nov 2021 17:34:25 -0800 Subject: [PATCH] Launch GroupedTaskView from thumbnails * Previously when starting the remote animation we were relying on SplitPlaceholderViews to animate into the proper place since we weren't launching from the TaskView itself * Now when launching from a GroupedTaskView, we use the existing animation that handles that animation in addition to showing the new split tasks Fixes: 206608786 Test: Thumbnails animate from home -> overview -> launch Change-Id: I1499ead7d90cd41e285ed0f4df66ea31f0dfbc95 --- .../launcher3/BaseQuickstepLauncher.java | 3 +- .../android/quickstep/RecentsActivity.java | 3 +- .../com/android/quickstep/TaskViewUtils.java | 51 ++++++++++++++++--- .../util/SplitSelectStateController.java | 44 +++++++++++++--- .../quickstep/views/GroupedTaskView.java | 4 +- 5 files changed, 86 insertions(+), 19 deletions(-) diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java index 6e2d2a9cc6..38e8e72cb8 100644 --- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java @@ -301,7 +301,8 @@ public abstract class BaseQuickstepLauncher extends Launcher mActionsView = findViewById(R.id.overview_actions_view); RecentsView overviewPanel = (RecentsView) getOverviewPanel(); SplitSelectStateController controller = - new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this)); + new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this), + getStateManager(), getDepthController()); overviewPanel.init(mActionsView, controller); mActionsView.setDp(getDeviceProfile()); mActionsView.updateVerticalMargin(SysUINavigationMode.getMode(this)); diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java index 09a0b7d387..d6efc7193d 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/src/com/android/quickstep/RecentsActivity.java @@ -128,7 +128,8 @@ public final class RecentsActivity extends StatefulActivity { SYSUI_PROGRESS.set(getRootView().getSysUiScrim(), 0f); SplitSelectStateController controller = - new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this)); + new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this), + getStateManager(), null /*depthController*/); mDragLayer.recreateControllers(); mFallbackRecentsView.init(mActionsView, controller); diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java index 6addfe30f4..142fafe864 100644 --- a/quickstep/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java @@ -56,6 +56,7 @@ import android.view.View; import android.window.TransitionInfo; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; @@ -72,6 +73,7 @@ import com.android.quickstep.util.MultiValueUpdateListener; import com.android.quickstep.util.SurfaceTransactionApplier; import com.android.quickstep.util.TaskViewSimulator; import com.android.quickstep.util.TransformParams; +import com.android.quickstep.views.GroupedTaskView; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskThumbnailView; import com.android.quickstep.views.TaskView; @@ -149,10 +151,12 @@ public final class TaskViewUtils { return taskView; } - public static void createRecentsWindowAnimator(TaskView v, boolean skipViewChanges, - RemoteAnimationTargetCompat[] appTargets, - RemoteAnimationTargetCompat[] wallpaperTargets, - RemoteAnimationTargetCompat[] nonAppTargets, DepthController depthController, + public static void createRecentsWindowAnimator( + @NonNull TaskView v, boolean skipViewChanges, + @NonNull RemoteAnimationTargetCompat[] appTargets, + @NonNull RemoteAnimationTargetCompat[] wallpaperTargets, + @NonNull RemoteAnimationTargetCompat[] nonAppTargets, + @Nullable DepthController depthController, PendingAnimation out) { RecentsView recentsView = v.getRecentsView(); boolean isQuickSwitch = v.isEndQuickswitchCuj(); @@ -418,15 +422,46 @@ public final class TaskViewUtils { finishCallback.run(); } - /** Legacy version (until shell transitions are enabled) */ - public static void composeRecentsSplitLaunchAnimatorLegacy(@NonNull Task initialTask, + /** + * Legacy version (until shell transitions are enabled) + * + * If {@param launchingTaskView} is not null, then this will play the tasks launch animation + * from the position of the GroupedTaskView (when user taps on the TaskView to start it). + * Technically this case should be taken care of by + * {@link #composeRecentsSplitLaunchAnimatorLegacy()} below, but the way we launch tasks whether + * it's a single task or multiple tasks results in different entry-points. + * + * If it is null, then it will simply fade in the starting apps and fade out launcher (for the + * case where launcher handles animating starting split tasks from app icon) */ + public static void composeRecentsSplitLaunchAnimatorLegacy( + @Nullable GroupedTaskView launchingTaskView, + @NonNull Task initialTask, @NonNull Task secondTask, @NonNull RemoteAnimationTargetCompat[] appTargets, @NonNull RemoteAnimationTargetCompat[] wallpaperTargets, @NonNull RemoteAnimationTargetCompat[] nonAppTargets, + @NonNull StateManager stateManager, + @Nullable DepthController depthController, @NonNull Runnable finishCallback) { + if (launchingTaskView != null) { + AnimatorSet animatorSet = new AnimatorSet(); + RecentsView recentsView = launchingTaskView.getRecentsView(); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + finishCallback.run(); + } + }); + composeRecentsLaunchAnimator(animatorSet, launchingTaskView, + appTargets, wallpaperTargets, nonAppTargets, + true, stateManager, + recentsView, depthController); + animatorSet.start(); + return; + } + final ArrayList openingTargets = new ArrayList<>(); final ArrayList closingTargets = new ArrayList<>(); - for (RemoteAnimationTargetCompat appTarget : appTargets) { final int taskId = appTarget.taskInfo != null ? appTarget.taskInfo.taskId : -1; final int mode = appTarget.mode; @@ -490,7 +525,7 @@ public final class TaskViewUtils { @NonNull RemoteAnimationTargetCompat[] wallpaperTargets, @NonNull RemoteAnimationTargetCompat[] nonAppTargets, boolean launcherClosing, @NonNull StateManager stateManager, @NonNull RecentsView recentsView, - @NonNull DepthController depthController) { + @Nullable DepthController depthController) { boolean skipLauncherChanges = !launcherClosing; TaskView taskView = findTaskViewToLaunch(recentsView, v, appTargets); diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java index 41aaa1a80c..c784d82d30 100644 --- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java @@ -30,11 +30,18 @@ import android.view.RemoteAnimationAdapter; import android.view.SurfaceControl; import android.window.TransitionInfo; + +import androidx.annotation.Nullable; + +import com.android.launcher3.statehandlers.DepthController; +import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.util.SplitConfigurationOptions; import com.android.launcher3.util.SplitConfigurationOptions.StagePosition; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.TaskAnimationManager; import com.android.quickstep.TaskViewUtils; +import com.android.quickstep.views.GroupedTaskView; +import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; @@ -52,23 +59,32 @@ public class SplitSelectStateController { private final Handler mHandler; private final SystemUiProxy mSystemUiProxy; + private final StateManager mStateManager; + private final DepthController mDepthController; private @StagePosition int mStagePosition; private Task mInitialTask; private Task mSecondTask; private Rect mInitialBounds; private boolean mRecentsAnimationRunning; + /** If not null, this is the TaskView we want to launch from */ + @Nullable + private GroupedTaskView mLaunchingTaskView; - public SplitSelectStateController(Handler handler, SystemUiProxy systemUiProxy) { + public SplitSelectStateController(Handler handler, SystemUiProxy systemUiProxy, + StateManager stateManager, + DepthController depthController) { mHandler = handler; mSystemUiProxy = systemUiProxy; + mStateManager = stateManager; + mDepthController = depthController; } /** * To be called after first task selected */ - public void setInitialTaskSelect(Task taskView, @StagePosition int stagePosition, + public void setInitialTaskSelect(Task task, @StagePosition int stagePosition, Rect initialBounds) { - mInitialTask = taskView; + mInitialTask = task; mStagePosition = stagePosition; mInitialBounds = initialBounds; } @@ -76,12 +92,24 @@ public class SplitSelectStateController { /** * To be called after second task selected */ - public void setSecondTaskId(Task taskView, Consumer callback) { - mSecondTask = taskView; + public void setSecondTaskId(Task task, Consumer callback) { + mSecondTask = task; launchTasks(mInitialTask, mSecondTask, mStagePosition, callback, false /* freezeTaskList */); } + /** + * To be called when we want to launch split pairs from an existing GroupedTaskView. + */ + public void launchTasks(GroupedTaskView groupedTaskView, + Consumer callback, boolean freezeTaskList) { + mLaunchingTaskView = groupedTaskView; + TaskView.TaskIdAttributeContainer[] taskIdAttributeContainers = + groupedTaskView.getTaskIdAttributeContainers(); + launchTasks(taskIdAttributeContainers[0].getTask(), taskIdAttributeContainers[1].getTask(), + taskIdAttributeContainers[0].getStagePosition(), callback, freezeTaskList); + } + /** * @param stagePosition representing location of task1 */ @@ -169,8 +197,9 @@ public class SplitSelectStateController { RemoteAnimationTargetCompat[] wallpapers, RemoteAnimationTargetCompat[] nonApps, Runnable finishedCallback) { postAsyncCallback(mHandler, - () -> TaskViewUtils.composeRecentsSplitLaunchAnimatorLegacy(mInitialTask, - mSecondTask, apps, wallpapers, nonApps, () -> { + () -> TaskViewUtils.composeRecentsSplitLaunchAnimatorLegacy( + mLaunchingTaskView, mInitialTask, mSecondTask, apps, wallpapers, + nonApps, mStateManager, mDepthController, () -> { finishedCallback.run(); if (mSuccessCallback != null) { mSuccessCallback.accept(true); @@ -201,6 +230,7 @@ public class SplitSelectStateController { mStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED; mInitialBounds = null; mRecentsAnimationRunning = false; + mLaunchingTaskView = null; } /** diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java index ea83b4deaf..bb5728dbf6 100644 --- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java +++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java @@ -156,8 +156,8 @@ public class GroupedTaskView extends TaskView { @Nullable @Override public RunnableList launchTaskAnimated() { - getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask, - STAGE_POSITION_TOP_OR_LEFT, null /*callback*/, + getRecentsView().getSplitPlaceholder().launchTasks(this /*groupedTaskView*/, + null /*callback*/, false /* freezeTaskList */); return null; }