Fallback recents activity fixes:

> Always deferring the start activity call
> Fixing quickscrub when start activtiy is deferred
> Preventing finish() call on the activity
> Fixing initTrack to work when the activity already exists

Bug: 75979063
Change-Id: Id6038c1f6c2680ec920222fb6a85c0ecc0172ed4
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 5841285..95947d7 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -19,6 +19,7 @@
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
 
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
@@ -46,9 +47,6 @@
 import com.android.quickstep.views.LauncherRecentsView;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.AssistDataReceiver;
-import com.android.systemui.shared.system.RecentsAnimationListener;
 
 import java.util.function.BiPredicate;
 
@@ -85,9 +83,6 @@
 
     ActivityInitListener createActivityInitListener(BiPredicate<T, Boolean> onInitListener);
 
-    void startRecentsFromSwipe(Intent intent, AssistDataReceiver assistDataReceiver,
-            final RecentsAnimationListener remoteAnimationListener);
-
     @Nullable
     T getCreatedActivity();
 
@@ -98,6 +93,12 @@
     @UiThread
     boolean switchToRecentsIfVisible();
 
+    /**
+     * @return {@code true} if recents activity should be started immediately on touchDown,
+     *         {@code false} if it should deferred until some threshold is crossed.
+     */
+    boolean deferStartingActivity(int downHitTarget);
+
     class LauncherActivityControllerHelper implements ActivityControlHelper<Launcher> {
 
         @Override
@@ -220,13 +221,6 @@
             return new LauncherInitListener(onInitListener);
         }
 
-        @Override
-        public void startRecentsFromSwipe(Intent intent, AssistDataReceiver assistDataReceiver,
-                final RecentsAnimationListener remoteAnimationListener) {
-            ActivityManagerWrapper.getInstance().startRecentsActivity(
-                    intent, assistDataReceiver, remoteAnimationListener, null, null);
-        }
-
         @Nullable
         @Override
         public Launcher getCreatedActivity() {
@@ -262,6 +256,11 @@
             }
             return false;
         }
+
+        @Override
+        public boolean deferStartingActivity(int downHitTarget) {
+            return downHitTarget == HIT_TARGET_BACK;
+        }
     }
 
     class FallbackActivityControllerHelper implements ActivityControlHelper<RecentsActivity> {
@@ -353,14 +352,6 @@
             return new RecentsActivityTracker(onInitListener);
         }
 
-        @Override
-        public void startRecentsFromSwipe(Intent intent, AssistDataReceiver assistDataReceiver,
-                final RecentsAnimationListener remoteAnimationListener) {
-            // We can use the normal recents animation for swipe up
-            ActivityManagerWrapper.getInstance().startRecentsActivity(
-                    intent, assistDataReceiver, remoteAnimationListener, null, null);
-        }
-
         @Nullable
         @Override
         public RecentsActivity getCreatedActivity() {
@@ -381,6 +372,12 @@
         public boolean switchToRecentsIfVisible() {
             return false;
         }
+
+        @Override
+        public boolean deferStartingActivity(int downHitTarget) {
+            // Always defer starting the activity when using fallback
+            return true;
+        }
     }
 
     interface LayoutListener {
diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
index 4d695de..28c950b 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
@@ -21,8 +21,7 @@
 import static android.view.MotionEvent.ACTION_POINTER_UP;
 import static android.view.MotionEvent.ACTION_UP;
 import static android.view.MotionEvent.INVALID_POINTER_ID;
-import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
-import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
+
 import static com.android.systemui.shared.system.NavigationBarCompat.QUICK_STEP_DRAG_SLOP_PX;
 
 import android.annotation.TargetApi;
@@ -55,7 +54,6 @@
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 import com.android.systemui.shared.system.WindowManagerWrapper;
 
-import java.util.Arrays;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -66,8 +64,6 @@
 public class OtherActivityTouchConsumer extends ContextWrapper implements TouchConsumer {
 
     private static final long LAUNCHER_DRAW_TIMEOUT_MS = 150;
-    private static final int[] DEFERRED_HIT_TARGETS = false
-            ? new int[] {HIT_TARGET_BACK, HIT_TARGET_OVERVIEW} : new int[] {HIT_TARGET_BACK};
 
     private final RunningTaskInfo mRunningTask;
     private final RecentsModel mRecentsModel;
@@ -102,7 +98,7 @@
         mActivityControlHelper = activityControl;
         mMainThreadExecutor = mainThreadExecutor;
         mBackgroundThreadChoreographer = backgroundThreadChoreographer;
-        mIsDeferredDownTarget = Arrays.binarySearch(DEFERRED_HIT_TARGETS, downHitTarget) >= 0;
+        mIsDeferredDownTarget = activityControl.deferStartingActivity(downHitTarget);
     }
 
     @Override
@@ -218,7 +214,8 @@
         handler.initWhenReady();
 
         TraceHelper.beginSection("RecentsController");
-        Runnable startActivity = () -> mActivityControlHelper.startRecentsFromSwipe(mHomeIntent,
+        Runnable startActivity = () -> ActivityManagerWrapper.getInstance().startRecentsActivity(
+                mHomeIntent,
                 new AssistDataReceiver() {
                     @Override
                     public void onHandleAssistData(Bundle bundle) {
@@ -247,7 +244,7 @@
                             handler.onRecentsAnimationCanceled();
                         }
                     }
-                });
+                }, null, null);
 
         if (Looper.myLooper() != Looper.getMainLooper()) {
             startActivity.run();
@@ -305,6 +302,13 @@
 
     @Override
     public void updateTouchTracking(int interactionType) {
+        if (!mPassedInitialSlop && mIsDeferredDownTarget && mInteractionHandler == null) {
+            // If we deferred starting the window animation on touch down, then
+            // start tracking now
+            startTouchTrackingForWindowAnimation(SystemClock.uptimeMillis());
+            mPassedInitialSlop = true;
+        }
+
         notifyGestureStarted();
         if (mInteractionHandler != null) {
             mInteractionHandler.updateInteractionType(interactionType);
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index cf60fdf..19ef8ab 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -16,6 +16,7 @@
 package com.android.quickstep;
 
 import android.app.ActivityOptions;
+import android.content.Intent;
 import android.os.Bundle;
 import android.view.View;
 
@@ -103,8 +104,26 @@
     }
 
     @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        RecentsActivityTracker.onRecentsActivityNewIntent(this);
+    }
+
+    @Override
     protected void onDestroy() {
         super.onDestroy();
         RecentsActivityTracker.onRecentsActivityDestroy(this);
     }
+
+    @Override
+    public void onBackPressed() {
+        // TODO: Launch the task we came from
+        startHome();
+    }
+
+    public void startHome() {
+        startActivity(new Intent(Intent.ACTION_MAIN)
+                .addCategory(Intent.CATEGORY_HOME)
+                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java
index 77f0e7a..fb6090e 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java
@@ -22,6 +22,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 
+import com.android.launcher3.MainThreadExecutor;
 import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
 import com.android.quickstep.util.RemoteAnimationProvider;
 
@@ -34,9 +35,8 @@
 @TargetApi(Build.VERSION_CODES.P)
 public class RecentsActivityTracker implements ActivityInitListener {
 
-    private static final Object LOCK = new Object();
-    private static WeakReference<RecentsActivityTracker> sTracker = new WeakReference<>(null);
     private static WeakReference<RecentsActivity> sCurrentActivity = new WeakReference<>(null);
+    private static final Scheduler sScheduler = new Scheduler();
 
     private final BiPredicate<RecentsActivity, Boolean> mOnInitListener;
 
@@ -46,42 +46,20 @@
 
     @Override
     public void register() {
-        synchronized (LOCK) {
-            sTracker = new WeakReference<>(this);
-        }
+        sScheduler.schedule(this);
     }
 
     @Override
     public void unregister() {
-        synchronized (LOCK) {
-            if (sTracker.get() == this) {
-                sTracker.clear();
-            }
-        }
+        sScheduler.clearReference(this);
     }
 
-    public static void onRecentsActivityCreate(RecentsActivity activity) {
-        synchronized (LOCK) {
-            RecentsActivityTracker tracker = sTracker.get();
-            if (tracker != null && tracker.mOnInitListener.test(activity, false)) {
-                sTracker.clear();
-            }
-            sCurrentActivity = new WeakReference<>(activity);
-        }
-    }
-
-    public static void onRecentsActivityDestroy(RecentsActivity activity) {
-        synchronized (LOCK) {
-            if (sCurrentActivity.get() == activity) {
-                sCurrentActivity.clear();
-            }
-        }
+    private boolean init(RecentsActivity activity, boolean visible) {
+        return mOnInitListener.test(activity, visible);
     }
 
     public static RecentsActivity getCurrentActivity() {
-        synchronized (LOCK) {
-            return sCurrentActivity.get();
-        }
+        return sCurrentActivity.get();
     }
 
     @Override
@@ -92,4 +70,62 @@
         Bundle options = animProvider.toActivityOptions(handler, duration).toBundle();
         context.startActivity(intent, options);
     }
+
+    public static void onRecentsActivityCreate(RecentsActivity activity) {
+        sCurrentActivity = new WeakReference<>(activity);
+        sScheduler.initIfPending(activity, false);
+    }
+
+
+    public static void onRecentsActivityNewIntent(RecentsActivity activity) {
+        sScheduler.initIfPending(activity, activity.isStarted());
+    }
+
+    public static void onRecentsActivityDestroy(RecentsActivity activity) {
+        if (sCurrentActivity.get() == activity) {
+            sCurrentActivity.clear();
+        }
+    }
+
+
+    private static class Scheduler implements Runnable {
+
+        private WeakReference<RecentsActivityTracker> mPendingTracker = new WeakReference<>(null);
+        private MainThreadExecutor mMainThreadExecutor;
+
+        public synchronized void schedule(RecentsActivityTracker tracker) {
+            mPendingTracker = new WeakReference<>(tracker);
+            if (mMainThreadExecutor == null) {
+                mMainThreadExecutor = new MainThreadExecutor();
+            }
+            mMainThreadExecutor.execute(this);
+        }
+
+        @Override
+        public void run() {
+            RecentsActivity activity = sCurrentActivity.get();
+            if (activity != null) {
+                initIfPending(activity, activity.isStarted());
+            }
+        }
+
+        public synchronized boolean initIfPending(RecentsActivity activity, boolean alreadyOnHome) {
+            RecentsActivityTracker tracker = mPendingTracker.get();
+            if (tracker != null) {
+                if (!tracker.init(activity, alreadyOnHome)) {
+                    mPendingTracker.clear();
+                }
+                return true;
+            }
+            return false;
+        }
+
+        public synchronized boolean clearReference(RecentsActivityTracker tracker) {
+            if (mPendingTracker.get() == tracker) {
+                mPendingTracker.clear();
+                return true;
+            }
+            return false;
+        }
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index d4c35e0..fb061d0 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -164,6 +164,7 @@
     private float mCurrentDisplacement;
     private boolean mGestureStarted;
     private int mLogAction = Touch.SWIPE;
+    private float mCurrentQuickScrubProgress;
 
     private @InteractionType int mInteractionType = INTERACTION_NORMAL;
 
@@ -228,11 +229,11 @@
         mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
                 this::invalidateHandlerWithLauncher);
 
-        mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_QUICK_SCRUB_START,
+        mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_QUICK_SCRUB_START,
                 this::onQuickScrubStart);
-        mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_QUICK_SCRUB_START
+        mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_QUICK_SCRUB_START
                 | STATE_SCALED_CONTROLLER_RECENTS, this::onFinishedTransitionToQuickScrub);
-        mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_SWITCH_TO_SCREENSHOT_COMPLETE
+        mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_SWITCH_TO_SCREENSHOT_COMPLETE
                 | STATE_QUICK_SCRUB_END, this::switchToFinalAppAfterQuickScrub);
     }
 
@@ -308,7 +309,6 @@
             return;
         }
 
-        mStateCallback.setState(STATE_LAUNCHER_STARTED);
         mActivityControlHelper.prepareRecentsUI(mActivity, mWasLauncherAlreadyVisible);
         AbstractFloatingView.closeAllOpenViews(activity, mWasLauncherAlreadyVisible);
 
@@ -343,6 +343,7 @@
         mRecentsView.showTask(mRunningTaskId);
         mRecentsView.setFirstTaskIconScaledDown(true /* isScaledDown */, false /* animate */);
         mLayoutListener.open();
+        mStateCallback.setState(STATE_LAUNCHER_STARTED);
     }
 
     public void setLauncherOnDrawCallback(Runnable callback) {
@@ -684,6 +685,9 @@
     private void onQuickScrubStart() {
         mActivityControlHelper.onQuickInteractionStart(mActivity, mWasLauncherAlreadyVisible);
         mQuickScrubController.onQuickScrubStart(false);
+
+        // Inform the last progress in case we skipped before.
+        mQuickScrubController.onQuickScrubProgress(mCurrentQuickScrubProgress);
     }
 
     private void onFinishedTransitionToQuickScrub() {
@@ -691,10 +695,8 @@
     }
 
     public void onQuickScrubProgress(float progress) {
+        mCurrentQuickScrubProgress = progress;
         if (Looper.myLooper() != Looper.getMainLooper() || mQuickScrubController == null) {
-            // TODO: We can still get progress events while launcher is not ready on the worker
-            // thread. Keep track of last received progress and apply that progress when launcher
-            // is ready
             return;
         }
         mQuickScrubController.onQuickScrubProgress(progress);
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 4ed1656..89422af 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -41,7 +41,7 @@
 
     @Override
     protected void onAllTasksRemoved() {
-        mActivity.finish();
+        mActivity.startHome();
     }
 
     @Override