Merge "Removing unused SplitScreen bounds notification from systemUI" into tm-qpr-dev
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 5cc5f10..7e4c2f6 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -48,7 +48,7 @@
 import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED;
 import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.CANCEL_RECENTS_ANIMATION;
-import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.FINISH_RECENTS_ANIMATION;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.EXPECTING_TASK_APPEARED;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.ON_SETTLED_ON_END_TARGET;
 import static com.android.quickstep.util.VibratorWrapper.OVERVIEW_HAPTIC;
 import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
@@ -1704,10 +1704,6 @@
     private void resumeLastTask() {
         if (mRecentsAnimationController != null) {
             mRecentsAnimationController.finish(false /* toRecents */, null);
-            ActiveGestureLog.INSTANCE.addLog(
-                    /* event= */ "finishRecentsAnimation",
-                    /* extras= */ false,
-                    /* gestureEvent= */ FINISH_RECENTS_ANIMATION);
         }
         doLogGesture(LAST_TASK, null);
         reset();
@@ -1916,10 +1912,6 @@
                 mRecentsAnimationController.detachNavigationBarFromApp(true);
             }
         }
-        ActiveGestureLog.INSTANCE.addLog(
-                /* event= */ "finishRecentsAnimation",
-                /* extras= */ true,
-                /* gestureEvent= */ FINISH_RECENTS_ANIMATION);
     }
 
     private void finishCurrentTransitionToHome() {
@@ -1931,10 +1923,6 @@
             finishRecentsControllerToHome(
                     () -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
         }
-        ActiveGestureLog.INSTANCE.addLog(
-                /* event= */ "finishRecentsAnimation",
-                /* extras= */ true,
-                /* gestureEvent= */ FINISH_RECENTS_ANIMATION);
         doLogGesture(HOME, mRecentsView == null ? null : mRecentsView.getCurrentPageTaskView());
     }
 
@@ -2045,6 +2033,9 @@
                 mGestureState.updateLastStartedTaskId(taskId);
                 boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds()
                         .contains(taskId);
+                if (!hasTaskPreviouslyAppeared) {
+                    ActiveGestureLog.INSTANCE.trackEvent(EXPECTING_TASK_APPEARED);
+                }
                 nextTask.launchTask(success -> {
                     resultCallback.accept(success);
                     if (success) {
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 3c4ee75..31b78b3 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -21,7 +21,6 @@
 import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.SET_END_TARGET;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.SET_END_TARGET_HOME;
-import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.SET_END_TARGET_LAST_TASK;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.SET_END_TARGET_NEW_TASK;
 
 import android.annotation.Nullable;
@@ -341,8 +340,6 @@
                 ActiveGestureLog.INSTANCE.trackEvent(SET_END_TARGET_NEW_TASK);
                 break;
             case LAST_TASK:
-                ActiveGestureLog.INSTANCE.trackEvent(SET_END_TARGET_LAST_TASK);
-                break;
             case RECENTS:
             default:
                 // No-Op
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
index 2451ad8..b82ff03 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
@@ -130,7 +130,7 @@
     public final void onAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas) {
         Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
             ActiveGestureLog.INSTANCE.addLog(
-                    /* event= */ "onRecentsAnimationCancelled",
+                    /* event= */ "RecentsAnimationCallbacks.onAnimationCanceled",
                     /* gestureEvent= */ CANCEL_RECENTS_ANIMATION);
             for (RecentsAnimationListener listener : getListeners()) {
                 listener.onRecentsAnimationCanceled(thumbnailDatas);
@@ -142,7 +142,7 @@
     @Override
     public void onTasksAppeared(RemoteAnimationTarget[] apps) {
         Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
-            ActiveGestureLog.INSTANCE.addLog("onTasksAppeared",
+            ActiveGestureLog.INSTANCE.addLog("RecentsAnimationCallbacks.onTasksAppeared",
                     ActiveGestureErrorDetector.GestureEvent.TASK_APPEARED);
             for (RecentsAnimationListener listener : getListeners()) {
                 listener.onTasksAppeared(apps);
@@ -164,6 +164,8 @@
 
     private final void onAnimationFinished(RecentsAnimationController controller) {
         Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
+            ActiveGestureLog.INSTANCE.addLog(
+                    /* event= */ "RecentsAnimationCallbacks.onAnimationFinished");
             for (RecentsAnimationListener listener : getListeners()) {
                 listener.onRecentsAnimationFinished(controller);
             }
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
index 81e3782..cf1c137 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
@@ -18,6 +18,7 @@
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.FINISH_RECENTS_ANIMATION;
 
 import android.content.Context;
 import android.os.RemoteException;
@@ -155,6 +156,10 @@
             mPendingFinishCallbacks.add(callback);
             return;
         }
+        ActiveGestureLog.INSTANCE.addLog(
+                /* event= */ "finishRecentsAnimation",
+                /* extras= */ toRecents,
+                /* gestureEvent= */ FINISH_RECENTS_ANIMATION);
 
         // Finish not yet requested
         mFinishRequested = true;
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 90e8091..c45b2f0 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -21,6 +21,7 @@
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
 import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION;
 import static com.android.systemui.shared.system.RemoteTransitionCompat.newRemoteTransition;
 
 import android.app.ActivityManager;
@@ -38,6 +39,7 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
+import com.android.quickstep.util.ActiveGestureLog;
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -101,6 +103,9 @@
     @UiThread
     public RecentsAnimationCallbacks startRecentsAnimation(GestureState gestureState,
             Intent intent, RecentsAnimationCallbacks.RecentsAnimationListener listener) {
+        ActiveGestureLog.INSTANCE.addLog(
+                /* event= */ "startRecentsAnimation",
+                /* gestureEvent= */ START_RECENTS_ANIMATION);
         // Notify if recents animation is still running
         if (mController != null) {
             String msg = "New recents animation started before old animation completed";
@@ -250,6 +255,7 @@
      * Continues the existing running recents animation for a new gesture.
      */
     public RecentsAnimationCallbacks continueRecentsAnimation(GestureState gestureState) {
+        ActiveGestureLog.INSTANCE.addLog(/* event= */ "continueRecentsAnimation");
         mCallbacks.removeListener(mLastGestureState);
         mLastGestureState = gestureState;
         mCallbacks.addListener(gestureState);
@@ -288,6 +294,8 @@
      */
     public void finishRunningRecentsAnimation(boolean toHome) {
         if (mController != null) {
+            ActiveGestureLog.INSTANCE.addLog(
+                    /* event= */ "finishRunningRecentsAnimation", toHome);
             mCallbacks.notifyAnimationCanceled();
             Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), toHome
                     ? mController::finishAnimationToHome
@@ -320,6 +328,7 @@
      * Cleans up the recents animation entirely.
      */
     private void cleanUpRecentsAnimation() {
+        ActiveGestureLog.INSTANCE.addLog(/* event= */ "cleanUpRecentsAnimation");
         if (mLiveTileCleanUpHandler != null) {
             mLiveTileCleanUpHandler.run();
             mLiveTileCleanUpHandler = null;
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index b33ef25..4cdb5f8 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -23,6 +23,7 @@
 import static com.android.launcher3.config.FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.quickstep.GestureState.DEFAULT_STATE;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_DOWN;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_UP;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -906,6 +907,9 @@
                 .append(consumer.getName())
                 .append(". reason(s):")
                 .append(reasonString));
+        if ((consumer.getType() & InputConsumer.TYPE_OTHER_ACTIVITY) != 0) {
+            ActiveGestureLog.INSTANCE.trackEvent(FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER);
+        }
     }
 
     private void handleOrientationSetup(InputConsumer baseInputConsumer) {
@@ -1230,12 +1234,22 @@
     }
 
     private void onCommand(PrintWriter pw, LinkedList<String> args) {
-        switch (args.pollFirst()) {
+        String cmd = args.pollFirst();
+        if (cmd == null) {
+            pw.println("Command missing");
+            printAvailableCommands(pw);
+            return;
+        }
+        switch (cmd) {
             case "clear-touch-log":
                 ActiveGestureLog.INSTANCE.clear();
                 break;
             case "print-gesture-log":
                 ActiveGestureLog.INSTANCE.dump("", pw);
+                break;
+            default:
+                pw.println("Command does not exist: " + cmd);
+                printAvailableCommands(pw);
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 9d269fb..b3d3c3d 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -30,7 +30,6 @@
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS;
 import static com.android.launcher3.util.VelocityUtils.PX_PER_MS;
-import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION;
 import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
 
 import android.annotation.TargetApi;
@@ -67,7 +66,6 @@
 import com.android.quickstep.RecentsAnimationTargets;
 import com.android.quickstep.RotationTouchHelper;
 import com.android.quickstep.TaskAnimationManager;
-import com.android.quickstep.util.ActiveGestureLog;
 import com.android.quickstep.util.CachedEventDispatcher;
 import com.android.quickstep.util.MotionPauseDetector;
 import com.android.quickstep.util.NavBarPosition;
@@ -387,10 +385,6 @@
     }
 
     private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
-        ActiveGestureLog.INSTANCE.addLog(
-                /* event= */ "startRecentsAnimation",
-                /* gestureEvent= */ START_RECENTS_ANIMATION);
-
         mInteractionHandler = mHandlerFactory.newHandler(mGestureState, touchTimeMs);
         mInteractionHandler.setGestureEndCallback(this::onInteractionGestureFinished);
         mMotionPauseDetector.setOnMotionPauseListener(mInteractionHandler.getMotionPauseListener());
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
index b9b5e7c..2462394 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
@@ -28,8 +28,6 @@
 import android.graphics.Point;
 import android.view.MotionEvent;
 
-import androidx.annotation.Nullable;
-
 import com.android.launcher3.anim.AnimatorListeners;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
@@ -43,7 +41,6 @@
 import com.android.quickstep.RecentsAnimationController;
 import com.android.quickstep.RecentsAnimationTargets;
 import com.android.quickstep.TaskAnimationManager;
-import com.android.quickstep.util.ActiveGestureErrorDetector;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.InputMonitorCompat;
 
@@ -102,8 +99,7 @@
         mDisplaySize = DisplayController.INSTANCE.get(context).getInfo().currentSize;
 
         // Init states
-        mStateCallback = new MultiStateCallback(
-                STATE_NAMES, ProgressDelegateInputConsumer::getTrackedEventForState);
+        mStateCallback = new MultiStateCallback(STATE_NAMES);
         mStateCallback.runOnceAtState(STATE_TARGET_RECEIVED | STATE_HANDLER_INVALIDATED,
                 this::endRemoteAnimation);
         mStateCallback.runOnceAtState(STATE_TARGET_RECEIVED | STATE_FLING_FINISHED,
@@ -113,14 +109,6 @@
         mSwipeDetector.setDetectableScrollConditions(DIRECTION_POSITIVE, false);
     }
 
-    @Nullable
-    private static ActiveGestureErrorDetector.GestureEvent getTrackedEventForState(int stateFlag) {
-        if (stateFlag == STATE_HANDLER_INVALIDATED) {
-            return ActiveGestureErrorDetector.GestureEvent.STATE_HANDLER_INVALIDATED;
-        }
-        return null;
-    }
-
     @Override
     public int getType() {
         return TYPE_PROGRESS_DELEGATE;
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
index 53e0c2b..60065fb 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
@@ -33,10 +33,11 @@
      * Enums associated to gesture navigation events.
      */
     public enum GestureEvent {
-        MOTION_DOWN, MOTION_UP, SET_END_TARGET, SET_END_TARGET_HOME, SET_END_TARGET_LAST_TASK,
-        SET_END_TARGET_NEW_TASK, ON_SETTLED_ON_END_TARGET, START_RECENTS_ANIMATION,
-        FINISH_RECENTS_ANIMATION, CANCEL_RECENTS_ANIMATION, SET_ON_PAGE_TRANSITION_END_CALLBACK,
-        CANCEL_CURRENT_ANIMATION, CLEANUP_SCREENSHOT, SCROLLER_ANIMATION_ABORTED, TASK_APPEARED,
+        MOTION_DOWN, MOTION_UP, SET_END_TARGET, SET_END_TARGET_HOME, SET_END_TARGET_NEW_TASK,
+        ON_SETTLED_ON_END_TARGET, START_RECENTS_ANIMATION, FINISH_RECENTS_ANIMATION,
+        CANCEL_RECENTS_ANIMATION, SET_ON_PAGE_TRANSITION_END_CALLBACK, CANCEL_CURRENT_ANIMATION,
+        CLEANUP_SCREENSHOT, SCROLLER_ANIMATION_ABORTED, TASK_APPEARED, EXPECTING_TASK_APPEARED,
+        FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER,
 
         /**
          * These GestureEvents are specifically associated to state flags that get set in
@@ -91,35 +92,40 @@
                     case MOTION_UP:
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(GestureEvent.MOTION_DOWN),
-                                /* errorMessage= */ prefix + "\t\tMotion up detected before/without"
+                                prefix,
+                                /* errorMessage= */ "Motion up detected before/without"
                                         + " motion down.",
                                 writer);
                         break;
                     case ON_SETTLED_ON_END_TARGET:
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(GestureEvent.SET_END_TARGET),
-                                /* errorMessage= */ prefix + "\t\tonSettledOnEndTarget called "
+                                prefix,
+                                /* errorMessage= */ "onSettledOnEndTarget called "
                                         + "before/without setEndTarget.",
                                 writer);
                         break;
                     case FINISH_RECENTS_ANIMATION:
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(GestureEvent.START_RECENTS_ANIMATION),
-                                /* errorMessage= */ prefix + "\t\tfinishRecentsAnimation called "
+                                prefix,
+                                /* errorMessage= */ "finishRecentsAnimation called "
                                         + "before/without startRecentsAnimation.",
                                 writer);
                         break;
                     case CANCEL_RECENTS_ANIMATION:
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(GestureEvent.START_RECENTS_ANIMATION),
-                                /* errorMessage= */ prefix + "\t\tcancelRecentsAnimation called "
+                                prefix,
+                                /* errorMessage= */ "cancelRecentsAnimation called "
                                         + "before/without startRecentsAnimation.",
                                 writer);
                         break;
                     case CLEANUP_SCREENSHOT:
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(GestureEvent.STATE_SCREENSHOT_CAPTURED),
-                                /* errorMessage= */ prefix + "\t\trecents activity screenshot was "
+                                prefix,
+                                /* errorMessage= */ "recents activity screenshot was "
                                         + "cleaned up before/without STATE_SCREENSHOT_CAPTURED "
                                         + "being set.",
                                 writer);
@@ -129,48 +135,66 @@
                                 encounteredEvents.contains(GestureEvent.SET_END_TARGET_HOME)
                                         && !encounteredEvents.contains(
                                                 GestureEvent.ON_SETTLED_ON_END_TARGET),
-                                /* errorMessage= */ prefix + "\t\trecents view scroller animation "
+                                prefix,
+                                /* errorMessage= */ "recents view scroller animation "
                                         + "aborted after setting end target HOME, but before"
                                         + " settling on end target.",
                                 writer);
                         break;
                     case TASK_APPEARED:
                         errorDetected |= printErrorIfTrue(
-                                !encounteredEvents.contains(GestureEvent.SET_END_TARGET_LAST_TASK)
-                                        && !encounteredEvents.contains(
-                                        GestureEvent.SET_END_TARGET_NEW_TASK),
-                                /* errorMessage= */ prefix + "\t\tonTasksAppeared called "
-                                        + "before/without setting end target to last or new task",
+                                !encounteredEvents.contains(GestureEvent.SET_END_TARGET_NEW_TASK),
+                                prefix,
+                                /* errorMessage= */ "onTasksAppeared called "
+                                        + "before/without setting end target to new task",
+                                writer);
+                        errorDetected |= printErrorIfTrue(
+                                !encounteredEvents.contains(GestureEvent.EXPECTING_TASK_APPEARED),
+                                prefix,
+                                /* errorMessage= */ "onTasksAppeared was not expected to be called",
+                                writer);
+                        break;
+                    case EXPECTING_TASK_APPEARED:
+                        errorDetected |= printErrorIfTrue(
+                                !encounteredEvents.contains(GestureEvent.SET_END_TARGET_NEW_TASK),
+                                prefix,
+                                /* errorMessage= */ "expecting onTasksAppeared to be called "
+                                        + "before/without setting end target to new task",
                                 writer);
                         break;
                     case STATE_GESTURE_COMPLETED:
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(GestureEvent.MOTION_UP),
-                                /* errorMessage= */ prefix + "\t\tSTATE_GESTURE_COMPLETED set "
+                                prefix,
+                                /* errorMessage= */ "STATE_GESTURE_COMPLETED set "
                                         + "before/without motion up.",
                                 writer);
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(GestureEvent.STATE_GESTURE_STARTED),
-                                /* errorMessage= */ prefix + "\t\tSTATE_GESTURE_COMPLETED set "
+                                prefix,
+                                /* errorMessage= */ "STATE_GESTURE_COMPLETED set "
                                         + "before/without STATE_GESTURE_STARTED.",
                                 writer);
                         break;
                     case STATE_GESTURE_CANCELLED:
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(GestureEvent.MOTION_UP),
-                                /* errorMessage= */ prefix + "\t\tSTATE_GESTURE_CANCELLED set "
+                                prefix,
+                                /* errorMessage= */ "STATE_GESTURE_CANCELLED set "
                                         + "before/without motion up.",
                                 writer);
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(GestureEvent.STATE_GESTURE_STARTED),
-                                /* errorMessage= */ prefix + "\t\tSTATE_GESTURE_CANCELLED set "
+                                prefix,
+                                /* errorMessage= */ "STATE_GESTURE_CANCELLED set "
                                         + "before/without STATE_GESTURE_STARTED.",
                                 writer);
                         break;
                     case STATE_SCREENSHOT_CAPTURED:
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(GestureEvent.STATE_CAPTURE_SCREENSHOT),
-                                /* errorMessage= */ prefix + "\t\tSTATE_SCREENSHOT_CAPTURED set "
+                                prefix,
+                                /* errorMessage= */ "STATE_SCREENSHOT_CAPTURED set "
                                         + "before/without STATE_CAPTURE_SCREENSHOT.",
                                 writer);
                         break;
@@ -178,7 +202,8 @@
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(
                                         GestureEvent.SET_ON_PAGE_TRANSITION_END_CALLBACK),
-                                /* errorMessage= */ prefix + "\t\tSTATE_RECENTS_SCROLLING_FINISHED "
+                                prefix,
+                                /* errorMessage= */ "STATE_RECENTS_SCROLLING_FINISHED "
                                         + "set before/without calling "
                                         + "setOnPageTransitionEndCallback.",
                                 writer);
@@ -187,16 +212,19 @@
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(
                                         GestureEvent.START_RECENTS_ANIMATION),
-                                /* errorMessage= */ prefix + "\t\tSTATE_RECENTS_ANIMATION_CANCELED "
+                                prefix,
+                                /* errorMessage= */ "STATE_RECENTS_ANIMATION_CANCELED "
                                         + "set before/without startRecentsAnimation.",
                                 writer);
                         break;
                     case MOTION_DOWN:
                     case SET_END_TARGET:
                     case SET_END_TARGET_HOME:
+                    case SET_END_TARGET_NEW_TASK:
                     case START_RECENTS_ANIMATION:
                     case SET_ON_PAGE_TRANSITION_END_CALLBACK:
                     case CANCEL_CURRENT_ANIMATION:
+                    case FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER:
                     case STATE_GESTURE_STARTED:
                     case STATE_END_TARGET_ANIMATION_FINISHED:
                     case STATE_CAPTURE_SCREENSHOT:
@@ -210,31 +238,36 @@
             // Check that all required events were found.
             errorDetected |= printErrorIfTrue(
                     !encounteredEvents.contains(GestureEvent.MOTION_DOWN),
-                    /* errorMessage= */ prefix + "\t\tMotion down never detected.",
+                    prefix,
+                    /* errorMessage= */ "Motion down never detected.",
                     writer);
             errorDetected |= printErrorIfTrue(
                     !encounteredEvents.contains(GestureEvent.MOTION_UP),
-                    /* errorMessage= */ prefix + "\t\tMotion up never detected.",
+                    prefix,
+                    /* errorMessage= */ "Motion up never detected.",
                     writer);
 
             errorDetected |= printErrorIfTrue(
                     /* condition= */ encounteredEvents.contains(GestureEvent.SET_END_TARGET)
                             && !encounteredEvents.contains(GestureEvent.ON_SETTLED_ON_END_TARGET),
-                    /* errorMessage= */ prefix + "\t\tsetEndTarget was called, but "
+                    prefix,
+                    /* errorMessage= */ "setEndTarget was called, but "
                             + "onSettledOnEndTarget wasn't.",
                     writer);
             errorDetected |= printErrorIfTrue(
                     /* condition= */ encounteredEvents.contains(GestureEvent.SET_END_TARGET)
                             && !encounteredEvents.contains(
                                     GestureEvent.STATE_END_TARGET_ANIMATION_FINISHED),
-                    /* errorMessage= */ prefix + "\t\tsetEndTarget was called, but "
+                    prefix,
+                    /* errorMessage= */ "setEndTarget was called, but "
                             + "STATE_END_TARGET_ANIMATION_FINISHED was never set.",
                     writer);
             errorDetected |= printErrorIfTrue(
                     /* condition= */ encounteredEvents.contains(GestureEvent.SET_END_TARGET)
                             && !encounteredEvents.contains(
                                     GestureEvent.STATE_RECENTS_SCROLLING_FINISHED),
-                    /* errorMessage= */ prefix + "\t\tsetEndTarget was called, but "
+                    prefix,
+                    /* errorMessage= */ "setEndTarget was called, but "
                             + "STATE_RECENTS_SCROLLING_FINISHED was never set.",
                     writer);
             errorDetected |= printErrorIfTrue(
@@ -243,7 +276,8 @@
                             && encounteredEvents.contains(
                                     GestureEvent.STATE_RECENTS_SCROLLING_FINISHED)
                             && !encounteredEvents.contains(GestureEvent.ON_SETTLED_ON_END_TARGET),
-                    /* errorMessage= */ prefix + "\t\tSTATE_END_TARGET_ANIMATION_FINISHED and "
+                    prefix,
+                    /* errorMessage= */ "STATE_END_TARGET_ANIMATION_FINISHED and "
                             + "STATE_RECENTS_SCROLLING_FINISHED were set, but onSettledOnEndTarget "
                             + "wasn't called.",
                     writer);
@@ -253,7 +287,8 @@
                             GestureEvent.START_RECENTS_ANIMATION)
                             && !encounteredEvents.contains(GestureEvent.FINISH_RECENTS_ANIMATION)
                             && !encounteredEvents.contains(GestureEvent.CANCEL_RECENTS_ANIMATION),
-                    /* errorMessage= */ prefix + "\t\tstartRecentsAnimation was called, but "
+                    prefix,
+                    /* errorMessage= */ "startRecentsAnimation was called, but "
                             + "finishRecentsAnimation and cancelRecentsAnimation weren't.",
                     writer);
 
@@ -261,7 +296,8 @@
                     /* condition= */ encounteredEvents.contains(GestureEvent.STATE_GESTURE_STARTED)
                             && !encounteredEvents.contains(GestureEvent.STATE_GESTURE_COMPLETED)
                             && !encounteredEvents.contains(GestureEvent.STATE_GESTURE_CANCELLED),
-                    /* errorMessage= */ prefix + "\t\tSTATE_GESTURE_STARTED was set, but "
+                    prefix,
+                    /* errorMessage= */ "STATE_GESTURE_STARTED was set, but "
                             + "STATE_GESTURE_COMPLETED and STATE_GESTURE_CANCELLED weren't.",
                     writer);
 
@@ -269,7 +305,8 @@
                     /* condition= */ encounteredEvents.contains(
                             GestureEvent.STATE_CAPTURE_SCREENSHOT)
                             && !encounteredEvents.contains(GestureEvent.STATE_SCREENSHOT_CAPTURED),
-                    /* errorMessage= */ prefix + "\t\tSTATE_CAPTURE_SCREENSHOT was set, but "
+                    prefix,
+                    /* errorMessage= */ "STATE_CAPTURE_SCREENSHOT was set, but "
                             + "STATE_SCREENSHOT_CAPTURED wasn't.",
                     writer);
 
@@ -278,15 +315,18 @@
                             GestureEvent.SET_ON_PAGE_TRANSITION_END_CALLBACK)
                             && !encounteredEvents.contains(
                                     GestureEvent.STATE_RECENTS_SCROLLING_FINISHED),
-                    /* errorMessage= */ prefix + "\t\tsetOnPageTransitionEndCallback called, but "
+                    prefix,
+                    /* errorMessage= */ "setOnPageTransitionEndCallback called, but "
                             + "STATE_RECENTS_SCROLLING_FINISHED wasn't set.",
                     writer);
 
             errorDetected |= printErrorIfTrue(
-                    /* condition= */ !encounteredEvents.contains(
-                            GestureEvent.CANCEL_CURRENT_ANIMATION)
+                    /* condition= */ encounteredEvents.contains(
+                            GestureEvent.FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER)
+                            && !encounteredEvents.contains(GestureEvent.CANCEL_CURRENT_ANIMATION)
                             && !encounteredEvents.contains(GestureEvent.STATE_HANDLER_INVALIDATED),
-                    /* errorMessage= */ prefix + "\t\tAbsSwipeUpHandler.cancelCurrentAnimation "
+                    prefix,
+                    /* errorMessage= */ "AbsSwipeUpHandler.cancelCurrentAnimation "
                             + "wasn't called and STATE_HANDLER_INVALIDATED wasn't set.",
                     writer);
 
@@ -294,23 +334,17 @@
                     /* condition= */ encounteredEvents.contains(
                             GestureEvent.STATE_RECENTS_ANIMATION_CANCELED)
                             && !encounteredEvents.contains(GestureEvent.CLEANUP_SCREENSHOT),
-                    /* errorMessage= */ prefix + "\t\tSTATE_RECENTS_ANIMATION_CANCELED was set but "
+                    prefix,
+                    /* errorMessage= */ "STATE_RECENTS_ANIMATION_CANCELED was set but "
                             + "the task screenshot wasn't cleaned up.",
                     writer);
 
             errorDetected |= printErrorIfTrue(
                     /* condition= */ encounteredEvents.contains(
-                            GestureEvent.SET_END_TARGET_LAST_TASK)
+                            GestureEvent.EXPECTING_TASK_APPEARED)
                             && !encounteredEvents.contains(GestureEvent.TASK_APPEARED),
-                    /* errorMessage= */ prefix + "\t\tend target set to last task, but "
-                            + "onTaskAppeared wasn't called.",
-                    writer);
-            errorDetected |= printErrorIfTrue(
-                    /* condition= */ encounteredEvents.contains(
-                            GestureEvent.SET_END_TARGET_NEW_TASK)
-                            && !encounteredEvents.contains(GestureEvent.TASK_APPEARED),
-                    /* errorMessage= */ prefix + "\t\tend target set to new task, but "
-                            + "onTaskAppeared wasn't called.",
+                    prefix,
+                    /* errorMessage= */ "onTaskAppeared was expected to be called but wasn't.",
                     writer);
 
             if (!errorDetected) {
@@ -320,11 +354,11 @@
     }
 
     private static boolean printErrorIfTrue(
-            boolean condition, String errorMessage, PrintWriter writer) {
+            boolean condition, String prefix, String errorMessage, PrintWriter writer) {
         if (!condition) {
             return false;
         }
-        writer.println(errorMessage);
+        writer.println(prefix + "\t\t- " + errorMessage);
         return true;
     }
 }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 4479be8..35414a6 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -2897,6 +2897,19 @@
 
         InteractionJankMonitorWrapper.begin(this,
                 InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "First tile selected");
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                if (mSplitHiddenTaskView == getRunningTaskView()) {
+                    finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
+                            null /* onFinishComplete */);
+                } else {
+                    switchToScreenshot(
+                            () -> finishRecentsAnimation(true /* toRecents */,
+                                    false /* shouldPip */, null /* onFinishComplete */));
+                }
+            }
+        });
         anim.addEndListener(success -> {
             if (success) {
                 InteractionJankMonitorWrapper.end(
@@ -4187,8 +4200,6 @@
         mSplitSelectStateController.setInitialTaskSelect(taskView.getTask(),
                 stagePosition, splitEvent, taskView.getItemInfo());
         mSplitHiddenTaskViewIndex = indexOfChild(taskView);
-        finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
-                null /* onFinishComplete */);
     }
 
     /**
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index 2ff992e..da86d98 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -107,8 +107,7 @@
             new RecyclerView.OnScrollListener() {
                 @Override
                 public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
-                    updateHeaderScroll(
-                            ((AllAppsRecyclerView) recyclerView).computeVerticalScrollOffset());
+                    updateHeaderScroll(recyclerView.computeVerticalScrollOffset());
                 }
             };
 
@@ -192,7 +191,6 @@
                 reset(true);
             }
         }
-
     }
 
     @Override
@@ -815,6 +813,10 @@
         }
     }
 
+    protected void onInitializeRecyclerView(RecyclerView rv) {
+        rv.addOnScrollListener(mScrollListener);
+    }
+
     /** Holds a {@link BaseAllAppsAdapter} and related fields. */
     public class AdapterHolder {
         public static final int MAIN = 0;
@@ -851,7 +853,7 @@
             mRecyclerView.setHasFixedSize(true);
             // No animations will occur when changes occur to the items in this RecyclerView.
             mRecyclerView.setItemAnimator(null);
-            mRecyclerView.addOnScrollListener(mScrollListener);
+            onInitializeRecyclerView(mRecyclerView);
             FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(mRecyclerView);
             mRecyclerView.addItemDecoration(focusedItemDecorator);
             mAdapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
diff --git a/src/com/android/launcher3/allapps/BaseSearchConfig.java b/src/com/android/launcher3/allapps/BaseSearchConfig.java
index 9f47e8d..3900954 100644
--- a/src/com/android/launcher3/allapps/BaseSearchConfig.java
+++ b/src/com/android/launcher3/allapps/BaseSearchConfig.java
@@ -25,4 +25,11 @@
     public boolean isKeyboardSyncEnabled() {
         return false;
     }
+
+    /**
+     * Returns whether IME is enabled on swipe up.
+     */
+    public boolean isImeEnabledOnSwipeUp() {
+        return false;
+    }
 }
diff --git a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
index 20f5e74..92e29bb 100644
--- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
@@ -16,19 +16,50 @@
 package com.android.launcher3.allapps;
 
 import android.content.Context;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.WindowInsets;
 
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.launcher3.ExtendedEditText;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
 
 /**
  * AllAppsContainerView with launcher specific callbacks
  */
 public class LauncherAllAppsContainerView extends ActivityAllAppsContainerView<Launcher> {
 
+    private final RecyclerView.OnScrollListener mActivityScrollListener =
+            new RecyclerView.OnScrollListener() {
+                @Override
+                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+                    int scrolledOffset = recyclerView.computeVerticalScrollOffset();
+                    ExtendedEditText input = mSearchUiManager.getEditText();
+                    // Scroll up and scroll to top
+                    if (dy < 0 && scrolledOffset == 0 && input != null) {
+                        boolean isImeEnabledOnSwipeUp = Launcher.getLauncher(mActivityContext)
+                                .getSearchConfig().isImeEnabledOnSwipeUp();
+                        if (isImeEnabledOnSwipeUp || !TextUtils.isEmpty(input.getText())) {
+                            input.showKeyboard();
+                        }
+                    }
+                }
+            };
+
+    @Override
+    protected void onInitializeRecyclerView(RecyclerView rv) {
+        super.onInitializeRecyclerView(rv);
+        if (FeatureFlags.SCROLL_TOP_TO_RESET.get()) {
+            rv.addOnScrollListener(mActivityScrollListener);
+        }
+    }
+
     public LauncherAllAppsContainerView(Context context) {
         this(context, null);
     }
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 32463a5..91c9929 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -290,6 +290,10 @@
     public static final BooleanFlag ENABLE_WIDGET_PICKER_DEPTH = new DeviceFlag(
             "ENABLE_WIDGET_PICKER_DEPTH", true, "Enable changing depth in widget picker.");
 
+    public static final BooleanFlag SCROLL_TOP_TO_RESET = new DeviceFlag(
+            "SCROLL_TOP_TO_RESET", false, "Bring up IME and focus on "
+            + "input when scroll to top if 'Always show keyboard' is enabled or in prefix state");
+
     public static final BooleanFlag SHOW_DELIGHTFUL_PAGINATION = getDebugFlag(
             "SHOW_DELIGHTFUL_PAGINATION", false,
             "Enable showing the new 'delightful pagination' which is a brand"
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
index 2846cae..9ba3f7b 100644
--- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
+++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
@@ -116,7 +116,7 @@
         FavoriteItemsTransaction transaction =
                 new FavoriteItemsTransaction(mTargetContext, this);
         mWorkspaceBuilder.buildFromBoard(testCase.mStart, transaction).commit();
-
+        waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading());
         Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.x,
                 mainWidgetCellPos.y);
         assertNotNull(widget);