Don't draw taskbar background during gestures

In this case, the ScrimView for BackgroundAppState will handle drawing behind the whole screen, and prevents taskbar from drawing the rounded corners on top of TaskViews.

Added a hack to defer resuming last task by a frame to ensure taskbar is drawing first.

Test: Quick switch to an app, ensure it isn't covered by the taskbar's rounded corner
Bug: 196257194
Change-Id: Ibc81d80bc3bf1d908e6912b179cbcafbdcc56c0f
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 4c96fba..da10bfb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -23,6 +23,7 @@
 import android.animation.ObjectAnimator;
 import android.graphics.Rect;
 import android.view.MotionEvent;
+import android.view.View;
 
 import androidx.annotation.NonNull;
 
@@ -241,7 +242,11 @@
         return mContext.getDragController().isDragging();
     }
 
-    void setTaskbarViewVisible(boolean isVisible) {
+    public View getRootView() {
+        return mTaskbarDragLayer;
+    }
+
+    private void setTaskbarViewVisible(boolean isVisible) {
         mIconAlphaForHome.setValue(isVisible ? 1 : 0);
         mLauncher.getHotseat().setIconsAlpha(isVisible ? 0f : 1f);
     }
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 42c89fd..6797fbb 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -655,8 +655,13 @@
 
     private void onAnimatorPlaybackControllerCreated(AnimatorControllerWithResistance anim) {
         mLauncherTransitionController = anim;
-        mLauncherTransitionController.getNormalController().dispatchOnStart();
-        updateLauncherTransitionProgress();
+        mStateCallback.runOnceAtState(STATE_GESTURE_STARTED, () -> {
+            // Wait until the gesture is started (touch slop was passed) to start in sync with
+            // mWindowTransitionController. This ensures we don't hide the taskbar background when
+            // long pressing to stash it, for instance.
+            mLauncherTransitionController.getNormalController().dispatchOnStart();
+            updateLauncherTransitionProgress();
+        });
     }
 
     public Intent getLaunchIntent() {
@@ -885,6 +890,9 @@
         // Fast-finish the attaching animation if it's still running.
         maybeUpdateRecentsAttachedState(false);
         final GestureEndTarget endTarget = mGestureState.getEndTarget();
+        // Wait until the given View (if supplied) draws before resuming the last task.
+        View postResumeLastTask = mActivityInterface.onSettledOnEndTarget(endTarget);
+
         if (endTarget != NEW_TASK) {
             InteractionJankMonitorWrapper.cancel(
                     InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
@@ -893,6 +901,7 @@
             InteractionJankMonitorWrapper.cancel(
                     InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME);
         }
+
         switch (endTarget) {
             case HOME:
                 mStateCallback.setState(STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT);
@@ -907,7 +916,12 @@
                 mStateCallback.setState(STATE_START_NEW_TASK | STATE_CAPTURE_SCREENSHOT);
                 break;
             case LAST_TASK:
-                mStateCallback.setState(STATE_RESUME_LAST_TASK);
+                if (postResumeLastTask != null) {
+                    ViewUtils.postFrameDrawn(postResumeLastTask,
+                            () -> mStateCallback.setState(STATE_RESUME_LAST_TASK));
+                } else {
+                    mStateCallback.setState(STATE_RESUME_LAST_TASK);
+                }
                 TaskViewUtils.setDividerBarShown(mRecentsAnimationTargets.nonApps, true);
                 break;
         }
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 571ffc2..29a069c 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -40,6 +40,7 @@
 import android.os.Build;
 import android.view.Gravity;
 import android.view.MotionEvent;
+import android.view.View;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
@@ -385,6 +386,15 @@
      */
     public abstract STATE_TYPE stateFromGestureEndTarget(GestureState.GestureEndTarget endTarget);
 
+    /**
+     * Called when the animation to the target has finished, but right before updating the state.
+     * @return A View that needs to draw before ending the recents animation to LAST_TASK.
+     * (This is a hack to ensure Taskbar draws its background first to avoid flickering.)
+     */
+    public @Nullable View onSettledOnEndTarget(GestureState.GestureEndTarget endTarget) {
+        return null;
+    }
+
     public interface AnimationFactory {
 
         void createActivityInterface(long transitionLength);
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index f84f377..1b796e9 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -25,10 +25,12 @@
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.content.Context;
 import android.graphics.Rect;
 import android.view.MotionEvent;
+import android.view.View;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
@@ -131,6 +133,18 @@
                         new ClampedDepthProperty(fromDepthRatio, toDepthRatio),
                         fromDepthRatio, toDepthRatio, LINEAR);
 
+                pa.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationStart(Animator animation) {
+                        LauncherTaskbarUIController taskbarUIController =
+                                activity.getTaskbarUIController();
+                        if (taskbarUIController != null) {
+                            // Launcher's ScrimView will draw the background throughout the gesture.
+                            taskbarUIController.forceHideBackground(true);
+                        }
+                    }
+                });
+
             }
         };
 
@@ -358,4 +372,16 @@
                 return NORMAL;
         }
     }
+
+    @Override
+    public View onSettledOnEndTarget(@Nullable GestureEndTarget endTarget) {
+        View superRet = super.onSettledOnEndTarget(endTarget);
+        LauncherTaskbarUIController taskbarUIController = getTaskbarController();
+        if (taskbarUIController != null) {
+            // Start drawing taskbar's background again since launcher might stop drawing.
+            taskbarUIController.forceHideBackground(false);
+            return taskbarUIController.getRootView();
+        }
+        return superRet;
+    }
 }