Relaunch app that is restarted mid-gesture

Bug: 156692295
Test: Swipe up from an app that has a HUN and ensure tapping on the
      HUN (or anything that can restart the activity) will start the
      activity while the recents animation is still running
Change-Id: Ia1fbd9cfb21aa64b3c8a0d431ba2d9824ee4c0a1
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
index 92e10b1..e7a3d9a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
@@ -41,6 +41,7 @@
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
 import android.annotation.TargetApi;
+import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.PointF;
@@ -78,9 +79,11 @@
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.InputConsumerController;
 import com.android.systemui.shared.system.LatencyTrackerCompat;
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import com.android.systemui.shared.system.TaskStackChangeListener;
 
 /**
  * Handles the navigation gestures when Launcher is the default home activity.
@@ -900,6 +903,21 @@
 
     protected abstract HomeAnimationFactory createHomeAnimationFactory(long duration);
 
+    private TaskStackChangeListener mActivityRestartListener = new TaskStackChangeListener() {
+        @Override
+        public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
+                boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
+            if (task.taskId == mGestureState.getRunningTaskId()) {
+                // Since this is an edge case, just cancel and relaunch with default activity
+                // options (since we don't know if there's an associated app icon to launch from)
+                endRunningWindowAnim(true /* cancel */);
+                ActivityManagerWrapper.getInstance().unregisterTaskStackListener(
+                        mActivityRestartListener);
+                ActivityManagerWrapper.getInstance().startActivityFromRecents(task.taskId, null);
+            }
+        }
+    };
+
     @UiThread
     private void animateToProgressInternal(float start, float end, long duration,
             Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) {
@@ -907,6 +925,13 @@
         mGestureState.setEndTarget(target, false /* isAtomic */);
         maybeUpdateRecentsAttachedState();
 
+        // If we are transitioning to launcher, then listen for the activity to be restarted while
+        // the transition is in progress
+        if (mGestureState.getEndTarget().isLauncher) {
+            ActivityManagerWrapper.getInstance().registerTaskStackListener(
+                    mActivityRestartListener);
+        }
+
         if (mGestureState.getEndTarget() == HOME) {
             HomeAnimationFactory homeAnimFactory = createHomeAnimationFactory(duration);
             RectFSpringAnim windowAnim = createWindowAnimationToHome(start, homeAnimFactory);
@@ -1127,6 +1152,7 @@
         }
 
         mActivityInitListener.unregister();
+        ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mActivityRestartListener);
         mTaskSnapshot = null;
     }