Tweak live tile rotation handling

- With ag/15023409, the system will screenshot and cancel the recents
  animation based on the hint provided by launcher when there is a
  global config change. As such, we can remove extra handling of the
  configuration change on the launcher side, and handle the cancel
  with the provided snapshot.

  To handle the snapshot, we need to hook into the gesture state
  recents animation callbacks (which actually are of the lifecycle of
  the animation and not just the gesture).

Bug: 189843542
Test: With live-tile enabled, swipe up to overview and rotate
Change-Id: If74f3fc5d47c327f9f5cca8f1f5d23b48cd3c954
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 4d47ef1..7f38923 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -42,6 +42,7 @@
 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_END_TARGET_SET;
+import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_CANCELED;
 import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED;
 import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
 import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
@@ -378,6 +379,17 @@
             activity.runOnceOnStart(this::onLauncherStart);
         }
 
+        // Set up a entire animation lifecycle callback to notify the current recents view when
+        // the animation is canceled
+        mGestureState.runOnceAtState(STATE_RECENTS_ANIMATION_CANCELED, () -> {
+                ThumbnailData snapshot = mGestureState.getRecentsAnimationCanceledSnapshot();
+                if (snapshot != null) {
+                    RecentsModel.INSTANCE.get(mContext).onTaskSnapshotChanged(
+                            mRecentsView.getRunningTaskId(), snapshot);
+                    mRecentsView.onRecentsAnimationComplete();
+                }
+            });
+
         setupRecentsViewUi();
         linkRecentsViewScroll();
 
@@ -671,6 +683,9 @@
             mRecentsAnimationController.setUseLauncherSystemBarFlags(swipeUpThresholdPassed
                     ||  (quickswitchThresholdPassed && centermostTaskFlags != 0));
             mRecentsAnimationController.setSplitScreenMinimized(swipeUpThresholdPassed);
+            // Provide a hint to WM the direction that we will be settling in case the animation
+            // needs to be canceled
+            mRecentsAnimationController.setWillFinishToHome(swipeUpThresholdPassed);
 
             if (swipeUpThresholdPassed) {
                 mActivity.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0);
@@ -1467,9 +1482,6 @@
             final boolean refreshView = !LIVE_TILE.get() /* refreshView */;
             boolean finishTransitionPosted = false;
             if (mRecentsAnimationController != null) {
-                if (LIVE_TILE.get()) {
-                    mRecentsAnimationController.getController().setWillFinishToHome(true);
-                }
                 // Update the screenshot of the task
                 if (mTaskSnapshot == null) {
                     UI_HELPER_EXECUTOR.execute(() -> {
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 6ad7f55..a302a07 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -142,6 +142,8 @@
     private RemoteAnimationTargetCompat mLastAppearedTaskTarget;
     private Set<Integer> mPreviouslyAppearedTaskIds = new HashSet<>();
     private int mLastStartedTaskId = -1;
+    private RecentsAnimationController mRecentsAnimationController;
+    private ThumbnailData mRecentsAnimationCanceledSnapshot;
 
     /** The time when the swipe up gesture is triggered. */
     private long mSwipeUpStartTimeMs;
@@ -351,13 +353,20 @@
     @Override
     public void onRecentsAnimationStart(RecentsAnimationController controller,
             RecentsAnimationTargets targets) {
+        mRecentsAnimationController = controller;
         mStateCallback.setState(STATE_RECENTS_ANIMATION_STARTED);
     }
 
     @Override
     public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
+        mRecentsAnimationCanceledSnapshot = thumbnailData;
         mStateCallback.setState(STATE_RECENTS_ANIMATION_CANCELED);
         mStateCallback.setState(STATE_RECENTS_ANIMATION_ENDED);
+        if (mRecentsAnimationCanceledSnapshot != null) {
+            // Clean up the screenshot to finalize the recents animation cancel
+            mRecentsAnimationController.cleanupScreenshot();
+            mRecentsAnimationCanceledSnapshot = null;
+        }
     }
 
     @Override
@@ -366,6 +375,14 @@
         mStateCallback.setState(STATE_RECENTS_ANIMATION_ENDED);
     }
 
+    /**
+     * Returns the canceled animation thumbnail data. This call only returns a value while
+     * STATE_RECENTS_ANIMATION_CANCELED state is being set.
+     */
+    ThumbnailData getRecentsAnimationCanceledSnapshot() {
+        return mRecentsAnimationCanceledSnapshot;
+    }
+
     void setSwipeUpStartTimeMs(long uptimeMs) {
         mSwipeUpStartTimeMs = uptimeMs;
     }
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
index 0ebe13b..53b6675 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
@@ -156,6 +156,14 @@
     }
 
     /**
+     * @see IRecentsAnimationController#cleanupScreenshot()
+     */
+    @UiThread
+    public void cleanupScreenshot() {
+        UI_HELPER_EXECUTOR.execute(() -> mController.cleanupScreenshot());
+    }
+
+    /**
      * @see RecentsAnimationControllerCompat#detachNavigationBarFromApp
      */
     @UiThread
@@ -172,6 +180,14 @@
     }
 
     /**
+     * @see IRecentsAnimationController#setWillFinishToHome(boolean)
+     */
+    @UiThread
+    public void setWillFinishToHome(boolean willFinishToHome) {
+        UI_HELPER_EXECUTOR.execute(() -> mController.setWillFinishToHome(willFinishToHome));
+    }
+
+    /**
      * Sets the final surface transaction on a Task. This is used by Launcher to notify the system
      * that animating Activity to PiP has completed and the associated task surface should be
      * updated accordingly. This should be called before `finish`
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 8c3e5b5..a36f2d4 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -392,8 +392,6 @@
 
     private final TaskOverlayFactory mTaskOverlayFactory;
 
-    private int mOrientation;
-
     protected boolean mDisallowScrollToClearAll;
     private boolean mOverlayEnabled;
     protected boolean mFreezeViewVisibility;
@@ -588,7 +586,6 @@
                 .getDimensionPixelSize(R.dimen.recents_fast_fling_velocity);
         mModel = RecentsModel.INSTANCE.get(context);
         mIdp = InvariantDeviceProfile.INSTANCE.get(context);
-        mOrientation = getResources().getConfiguration().orientation;
 
         mClearAllButton = (ClearAllButton) LayoutInflater.from(context)
                 .inflate(R.layout.overview_clear_all_button, this, false);
@@ -2640,15 +2637,7 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        if (LIVE_TILE.get() && mEnableDrawingLiveTile && newConfig.orientation != mOrientation) {
-            switchToScreenshot(
-                    () -> finishRecentsAnimation(true /* toRecents */, false /* showPip */,
-                            this::updateRecentsRotation));
-            mEnableDrawingLiveTile = false;
-        } else {
-            updateRecentsRotation();
-        }
-        mOrientation = newConfig.orientation;
+        updateRecentsRotation();
     }
 
     /**
@@ -3404,16 +3393,26 @@
             if (onFinishComplete != null) {
                 onFinishComplete.run();
             }
-            // After we finish the recents animation, the current task id should be correctly
-            // reset so that when the task is launched from Overview later, it goes through the
-            // flow of starting a new task instead of finishing recents animation to app. A
-            // typical example of this is (1) user swipes up from app to Overview (2) user
-            // taps on QSB (3) user goes back to Overview and launch the most recent task.
-            setCurrentTask(-1);
-            mRecentsAnimationController = null;
+            onRecentsAnimationComplete();
         }, sendUserLeaveHint);
     }
 
+    /**
+     * Called when a running recents animation has finished or canceled.
+     */
+    public void onRecentsAnimationComplete() {
+        // At this point, the recents animation is not running and if the animation was canceled
+        // by a display rotation then reset this state to show the screenshot
+        setRunningTaskViewShowScreenshot(true);
+        // After we finish the recents animation, the current task id should be correctly
+        // reset so that when the task is launched from Overview later, it goes through the
+        // flow of starting a new task instead of finishing recents animation to app. A
+        // typical example of this is (1) user swipes up from app to Overview (2) user
+        // taps on QSB (3) user goes back to Overview and launch the most recent task.
+        setCurrentTask(-1);
+        mRecentsAnimationController = null;
+    }
+
     public void setDisallowScrollToClearAll(boolean disallowScrollToClearAll) {
         if (mDisallowScrollToClearAll != disallowScrollToClearAll) {
             mDisallowScrollToClearAll = disallowScrollToClearAll;