From bec41bc5b9ffec54b77b034dee2a2255c40ff377 Mon Sep 17 00:00:00 2001 From: lumark Date: Sat, 7 Mar 2020 00:09:21 +0800 Subject: [PATCH] Trigger onTaskAppeared when a task started from recents becomes ready. Launcher can now receive onTaskAppeared callback from RecentsAnimationController to get remote animation target when in quick switch mode. Note: This CL just demonstrates how to receive callback and then calling removeTask & finish recents animation, in order to really improve quick switch flicking, launcher side needs to implement the rest of logic to animate task's remote animation target to make task switching more smoothly. Bug: 152480470 Test: WIP Change-Id: Id0371db7339cfe84942cc905a89b0a2c1fab62ec --- .../android/quickstep/BaseSwipeUpHandler.java | 45 +++++++------------ .../quickstep/LauncherSwipeHandler.java | 19 ++++++++ .../com/android/quickstep/GestureState.java | 19 ++++++++ .../quickstep/RecentsAnimationCallbacks.java | 15 +++++++ .../quickstep/RecentsAnimationController.java | 11 +++++ 5 files changed, 80 insertions(+), 29 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java index 5abeae4653..f81c56fc34 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java @@ -212,36 +212,23 @@ public abstract class BaseSwipeUpHandler { - if (TestProtocol.sDebugTracing) { - Log.d(TestProtocol.NO_START_FROM_RECENTS, "onFinishComplete1"); + if (!mCanceled) { + TaskView nextTask = mRecentsView.getTaskView(taskId); + if (nextTask != null) { + nextTask.launchTask(false /* animate */, true /* freezeTaskList */, + success -> { + resultCallback.accept(success); + if (!success) { + mActivityInterface.onLaunchTaskFailed(); + nextTask.notifyTaskLaunchFailed(TAG); + } else { + mActivityInterface.onLaunchTaskSuccess(); + } + }, MAIN_EXECUTOR.getHandler()); } - if (!mCanceled) { - if (TestProtocol.sDebugTracing) { - Log.d(TestProtocol.NO_START_FROM_RECENTS, "onFinishComplete2"); - } - TaskView nextTask = mRecentsView.getTaskView(taskId); - if (nextTask != null) { - if (TestProtocol.sDebugTracing) { - Log.d(TestProtocol.NO_START_FROM_RECENTS, "onFinishComplete3"); - } - nextTask.launchTask(false /* animate */, true /* freezeTaskList */, - success -> { - resultCallback.accept(success); - if (!success) { - mActivityInterface.onLaunchTaskFailed(); - nextTask.notifyTaskLaunchFailed(TAG); - } else { - mActivityInterface.onLaunchTaskSuccess(); - } - }, MAIN_EXECUTOR.getHandler()); - } - mStateCallback.setStateOnUiThread(successStateFlag); - } - mCanceled = false; - mFinishingRecentsAnimationForNewTaskId = -1; - }); + mStateCallback.setStateOnUiThread(successStateFlag); + } + mCanceled = false; } ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java index 1bd03330fe..4cfa6f1617 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java @@ -30,6 +30,7 @@ import static com.android.quickstep.GestureState.GestureEndTarget.NEW_TASK; import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS; import static com.android.quickstep.GestureState.STATE_END_TARGET_ANIMATION_FINISHED; import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED; +import static com.android.quickstep.GestureState.STATE_TASK_APPEARED_DURING_SWITCH; import static com.android.quickstep.MultiStateCallback.DEBUG_STATES; import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS; import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE; @@ -253,6 +254,8 @@ public class LauncherSwipeHandler | STATE_RECENTS_SCROLLING_FINISHED, this::onSettledOnEndTarget); + mGestureState.runOnceAtState(STATE_TASK_APPEARED_DURING_SWITCH, this::onTaskAppeared); + mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED, this::invalidateHandler); mStateCallback.runOnceAtState(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED, this::invalidateHandlerWithLauncher); @@ -727,6 +730,22 @@ public class LauncherSwipeHandler } } + private void onTaskAppeared() { + RemoteAnimationTargetCompat app = mGestureState.getAnimationTarget(); + if (mRecentsAnimationController != null && app != null) { + + // TODO(b/152480470): Update Task target animation after onTaskAppeared holistically. + /* android.util.Log.d("LauncherSwipeHandler", "onTaskAppeared"); + + final boolean result = mRecentsAnimationController.removeTaskTarget(app); + mGestureState.setAnimationTarget(null); + android.util.Log.d("LauncherSwipeHandler", "removeTask, result=" + result); */ + + mRecentsAnimationController.finish(false /* toRecents */, + null /* onFinishComplete */); + } + } + private GestureEndTarget calculateEndTarget(PointF velocity, float endVelocity, boolean isFling, boolean isCancel) { final GestureEndTarget endTarget; diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java index 5118906b28..544f420811 100644 --- a/quickstep/src/com/android/quickstep/GestureState.java +++ b/quickstep/src/com/android/quickstep/GestureState.java @@ -23,6 +23,7 @@ import android.content.Intent; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.systemui.shared.recents.model.ThumbnailData; +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import java.io.PrintWriter; import java.util.ArrayList; @@ -109,6 +110,9 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL public static final int STATE_RECENTS_SCROLLING_FINISHED = getFlagForIndex("STATE_RECENTS_SCROLLING_FINISHED"); + // Called when the new task appeared from quick switching. + public static final int STATE_TASK_APPEARED_DURING_SWITCH = + getFlagForIndex("STATE_TASK_APPEARED_DURING_SWITCH"); // Needed to interact with the current activity private final Intent mHomeIntent; @@ -119,6 +123,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL private ActivityManager.RunningTaskInfo mRunningTask; private GestureEndTarget mEndTarget; + private RemoteAnimationTargetCompat mAnimationTarget; // TODO: This can be removed once we stop finishing the animation when starting a new task private int mFinishingRecentsAnimationTaskId = -1; @@ -227,6 +232,14 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL return mEndTarget; } + public void setAnimationTarget(RemoteAnimationTargetCompat target) { + mAnimationTarget = target; + } + + public RemoteAnimationTargetCompat getAnimationTarget() { + return mAnimationTarget; + } + /** * Sets the end target of this gesture and immediately notifies the state changes. */ @@ -301,6 +314,12 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL mStateCallback.setState(STATE_RECENTS_ANIMATION_ENDED); } + @Override + public void onTaskAppeared(RemoteAnimationTargetCompat app) { + mAnimationTarget = app; + mStateCallback.setState(STATE_TASK_APPEARED_DURING_SWITCH); + } + public void dump(PrintWriter pw) { pw.println("GestureState:"); pw.println(" gestureID=" + mGestureId); diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java index 783978d6a8..566a701985 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java @@ -121,6 +121,16 @@ public class RecentsAnimationCallbacks implements }); } + @BinderThread + @Override + public void onTaskAppeared(RemoteAnimationTargetCompat app) { + Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> { + for (RecentsAnimationListener listener : getListeners()) { + listener.onTaskAppeared(app); + } + }); + } + private final void onAnimationFinished(RecentsAnimationController controller) { Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> { for (RecentsAnimationListener listener : getListeners()) { @@ -150,5 +160,10 @@ public class RecentsAnimationCallbacks implements * Callback made whenever the recents animation is finished. */ default void onRecentsAnimationFinished(RecentsAnimationController controller) {} + + /** + * Callback made when a task started from the recents is ready for an app transition. + */ + default void onTaskAppeared(RemoteAnimationTargetCompat app) {} } } diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java index 8dd4aa4cab..268e5645bd 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java @@ -22,6 +22,7 @@ import static android.view.MotionEvent.ACTION_UP; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; +import android.annotation.NonNull; import android.os.SystemClock; import android.util.Log; import android.view.InputEvent; @@ -34,6 +35,7 @@ import com.android.launcher3.util.Preconditions; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import java.util.function.Consumer; import java.util.function.Supplier; @@ -107,6 +109,15 @@ public class RecentsAnimationController { UI_HELPER_EXECUTOR.execute(() -> mController.cleanupScreenshot()); } + /** + * Remove task remote animation target from + * {@link RecentsAnimationCallbacks#onTaskAppeared(RemoteAnimationTargetCompat)}}. + */ + @UiThread + public boolean removeTaskTarget(@NonNull RemoteAnimationTargetCompat target) { + return mController.removeTask(target.taskId); + } + @UiThread public void finishAnimationToHome() { finishAndClear(true /* toRecents */, null, false /* sendUserLeaveHint */);