Extend taskbar color to entire screen in overview

Only when taskbar is unstashed in apps:
- Scrim workspace with the taskbar color when opening apps and in BackgroundAppState
- Crop opening apps to above the taskbar
- Crop TaskViews to above the taskbar during gestures

If taskbar is stashed in apps, behavior is the same as before, i.e. no scrim over the wallpaper and no cropping of tasks.

Added a field DeviceProfile#taskbkarPresentInApps to distinguish these cases. LauncherTaskbarUIController and TaskbarStashController ensure this value is set appropriately.

Test: Ensure tasks don't appear behind taskbar when it's unstashed; set ENABLE_SCRIM_FOR_APP_LAUNCH = true to test the whole screen scrimming when opening an app

Bug: 196257194
Fixes: 190681228
Change-Id: I481501457a5a6d49c380feea3db3b4058e4cf3f8
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 2da8a45..d41590b 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -85,6 +85,7 @@
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.launcher3.shortcuts.DeepShortcutView;
 import com.android.launcher3.statehandlers.DepthController;
+import com.android.launcher3.taskbar.LauncherTaskbarUIController;
 import com.android.launcher3.util.ActivityOptionsWrapper;
 import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
 import com.android.launcher3.util.RunnableList;
@@ -427,6 +428,10 @@
                         4 - rotationChange);
             }
         }
+        // TODO(b/196637509): don't do this for immersive apps.
+        if (mDeviceProfile.isTaskbarPresentInApps) {
+            bounds.bottom -= mDeviceProfile.taskbarSize;
+        }
         return bounds;
     }
 
@@ -511,7 +516,10 @@
 
             final boolean scrimEnabled = ENABLE_SCRIM_FOR_APP_LAUNCH.get();
             if (scrimEnabled) {
-                int scrimColor = Themes.getAttrColor(mLauncher, R.attr.overviewScrimColor);
+                boolean useTaskbarColor = mDeviceProfile.isTaskbarPresentInApps;
+                int scrimColor = useTaskbarColor
+                        ? mLauncher.getResources().getColor(R.color.taskbar_background)
+                        : Themes.getAttrColor(mLauncher, R.attr.overviewScrimColor);
                 int scrimColorTrans = ColorUtils.setAlphaComponent(scrimColor, 0);
                 int[] colors = isAppOpening
                         ? new int[]{scrimColorTrans, scrimColor}
@@ -524,6 +532,30 @@
                             colors);
                     scrim.setDuration(CONTENT_SCRIM_DURATION);
                     scrim.setInterpolator(DEACCEL_1_5);
+
+                    if (useTaskbarColor) {
+                        // Hide the taskbar background color since it would duplicate the scrim.
+                        scrim.addListener(new AnimatorListenerAdapter() {
+                            @Override
+                            public void onAnimationStart(Animator animation) {
+                                LauncherTaskbarUIController taskbarUIController =
+                                        mLauncher.getTaskbarUIController();
+                                if (taskbarUIController != null) {
+                                    taskbarUIController.forceHideBackground(true);
+                                }
+                            }
+
+                            @Override
+                            public void onAnimationEnd(Animator animation) {
+                                LauncherTaskbarUIController taskbarUIController =
+                                        mLauncher.getTaskbarUIController();
+                                if (taskbarUIController != null) {
+                                    taskbarUIController.forceHideBackground(false);
+                                }
+                            }
+                        });
+                    }
+
                     launcherAnimator.play(scrim);
                 }
             }
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 56c28f0..95c7d62 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -27,6 +27,7 @@
 import androidx.annotation.NonNull;
 
 import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.QuickstepTransitionManager;
 import com.android.launcher3.R;
@@ -58,9 +59,13 @@
     private final AnimatedFloat mIconAlignmentForGestureState =
             new AnimatedFloat(this::onIconAlignmentRatioChanged);
 
+    private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener =
+            this::onStashedInAppChanged;
+
     // Initialized in init.
     private TaskbarControllers mControllers;
     private AnimatedFloat mTaskbarBackgroundAlpha;
+    private AnimatedFloat mTaskbarOverrideBackgroundAlpha;
     private AlphaProperty mIconAlphaForHome;
     private boolean mIsAnimatingToLauncherViaResume;
     private boolean mIsAnimatingToLauncherViaGesture;
@@ -84,6 +89,8 @@
 
         mTaskbarBackgroundAlpha = mControllers.taskbarDragLayerController
                 .getTaskbarBackgroundAlpha();
+        mTaskbarOverrideBackgroundAlpha = mControllers.taskbarDragLayerController
+                .getOverrideBackgroundAlpha();
 
         MultiValueAlpha taskbarIconAlpha = mControllers.taskbarViewController.getTaskbarIconAlpha();
         mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME);
@@ -94,6 +101,9 @@
         onLauncherResumedOrPaused(mLauncher.hasBeenResumed());
         mIconAlignmentForResumedState.finishAnimation();
         onIconAlignmentRatioChanged();
+
+        onStashedInAppChanged(mLauncher.getDeviceProfile());
+        mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
     }
 
     @Override
@@ -102,6 +112,7 @@
         mIconAlignmentForResumedState.finishAnimation();
         mIconAlignmentForGestureState.finishAnimation();
 
+        mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
         mLauncher.getHotseat().setIconsAlpha(1f);
         mLauncher.setTaskbarUIController(null);
     }
@@ -192,7 +203,7 @@
     }
 
     private float getCurrentIconAlignmentRatio() {
-        return  Math.max(mIconAlignmentForResumedState.value, mIconAlignmentForGestureState.value);
+        return Math.max(mIconAlignmentForResumedState.value, mIconAlignmentForGestureState.value);
     }
 
     private void onIconAlignmentRatioChanged() {
@@ -233,6 +244,23 @@
         mLauncher.getHotseat().setIconsAlpha(isVisible ? 0f : 1f);
     }
 
+    @Override
+    protected void onStashedInAppChanged() {
+        onStashedInAppChanged(mLauncher.getDeviceProfile());
+    }
+
+    private void onStashedInAppChanged(DeviceProfile deviceProfile) {
+        boolean taskbarStashedInApps = mControllers.taskbarStashController.isStashedInApp();
+        deviceProfile.isTaskbarPresentInApps = !taskbarStashedInApps;
+    }
+
+    /**
+     * Sets whether the background behind the taskbar/nav bar should be hidden.
+     */
+    public void forceHideBackground(boolean forceHide) {
+        mTaskbarOverrideBackgroundAlpha.updateValue(forceHide ? 0 : 1);
+    }
+
     private final class TaskBarRecentsAnimationListener implements RecentsAnimationListener {
         private final RecentsAnimationCallbacks mCallbacks;
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index df89285..14150b9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -36,10 +36,14 @@
     private final TaskbarActivityContext mActivity;
     private final TaskbarDragLayer mTaskbarDragLayer;
     private final int mFolderMargin;
+
     // Alpha properties for taskbar background.
     private final AnimatedFloat mBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha);
     private final AnimatedFloat mBgNavbar = new AnimatedFloat(this::updateBackgroundAlpha);
     private final AnimatedFloat mKeyguardBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha);
+    // Used to hide our background color when someone else (e.g. ScrimView) is handling it.
+    private final AnimatedFloat mBgOverride = new AnimatedFloat(this::updateBackgroundAlpha);
+
     // Translation property for taskbar background.
     private final AnimatedFloat mBgOffset = new AnimatedFloat(this::updateBackgroundOffset);
 
@@ -58,6 +62,7 @@
         mControllers = controllers;
         mTaskbarDragLayer.init(new TaskbarDragLayerCallbacks());
         mKeyguardBgTaskbar.value = 1;
+        mBgOverride.value = 1;
     }
 
     public void onDestroy() {
@@ -86,13 +91,19 @@
         return mKeyguardBgTaskbar;
     }
 
+    public AnimatedFloat getOverrideBackgroundAlpha() {
+        return mBgOverride;
+    }
+
     public AnimatedFloat getTaskbarBackgroundOffset() {
         return mBgOffset;
     }
 
     private void updateBackgroundAlpha() {
+        final float bgNavbar = mBgNavbar.value;
+        final float bgTaskbar = mBgTaskbar.value * mKeyguardBgTaskbar.value;
         mTaskbarDragLayer.setTaskbarBackgroundAlpha(
-                Math.max(mBgNavbar.value, mBgTaskbar.value * mKeyguardBgTaskbar.value)
+                mBgOverride.value * Math.max(bgNavbar, bgTaskbar)
         );
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 0efec53..949df82 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -197,6 +197,7 @@
             if (wasStashed != isStashed) {
                 SystemUiProxy.INSTANCE.get(mActivity)
                         .notifyTaskbarStatus(/* visible */ true, /* stashed */ isStashed);
+                mControllers.uiController.onStashedInAppChanged();
                 createAnimToIsStashed(isStashed, TASKBAR_STASH_DURATION).start();
                 return true;
             }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 260cedc..df88e02 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -33,4 +33,6 @@
     }
 
     protected void updateContentInsets(Rect outContentInsets) { }
+
+    protected void onStashedInAppChanged() { }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index fe5a347..4984b95 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -23,6 +23,7 @@
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
 import com.android.launcher3.allapps.AllAppsTransitionController;
 import com.android.quickstep.util.LayoutUtils;
 import com.android.quickstep.views.RecentsView;
@@ -89,6 +90,10 @@
 
     @Override
     public int getWorkspaceScrimColor(Launcher launcher) {
+        DeviceProfile dp = launcher.getDeviceProfile();
+        if (dp.isTaskbarPresentInApps) {
+            return launcher.getColor(R.color.taskbar_background);
+        }
         return Color.TRANSPARENT;
     }
 
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 624ade2..571ffc2 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -262,14 +262,14 @@
     public static void getTaskDimension(Context context, DeviceProfile dp, PointF out) {
         if (dp.isMultiWindowMode) {
             WindowBounds bounds = SplitScreenBounds.INSTANCE.getSecondaryWindowBounds(context);
-            if (TaskView.CLIP_STATUS_AND_NAV_BARS) {
+            if (TaskView.clipStatusAndNavBars(dp)) {
                 out.x = bounds.availableSize.x;
                 out.y = bounds.availableSize.y;
             } else {
                 out.x = bounds.availableSize.x + bounds.insets.left + bounds.insets.right;
                 out.y = bounds.availableSize.y + bounds.insets.top + bounds.insets.bottom;
             }
-        } else if (TaskView.CLIP_STATUS_AND_NAV_BARS) {
+        } else if (TaskView.clipStatusAndNavBars(dp)) {
             out.x = dp.availableWidthPx;
             out.y = dp.availableHeightPx;
         } else {
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index 7cfd151..21e0ae8 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -396,7 +396,7 @@
         Rect insets = dp.getInsets();
         float fullWidth = dp.widthPx;
         float fullHeight = dp.heightPx;
-        if (TaskView.CLIP_STATUS_AND_NAV_BARS) {
+        if (TaskView.clipStatusAndNavBars(dp)) {
             fullWidth -= insets.left + insets.right;
             fullHeight -= insets.top + insets.bottom;
         }
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index 35e21ad..0577cce 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -211,7 +211,7 @@
             return Insets.NONE;
         }
 
-        if (!TaskView.CLIP_STATUS_AND_NAV_BARS) {
+        if (!TaskView.clipStatusAndNavBars(mActivity.getDeviceProfile())) {
             return Insets.NONE;
         }
 
@@ -440,7 +440,7 @@
 
             int thumbnailRotation = thumbnailData.rotation;
             int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation);
-            RectF thumbnailClipHint = TaskView.CLIP_STATUS_AND_NAV_BARS
+            RectF thumbnailClipHint = TaskView.clipStatusAndNavBars(dp)
                     ? new RectF(thumbnailData.insets) : new RectF();
 
             float scale = thumbnailData.scale;
@@ -554,7 +554,7 @@
                         -thumbnailClipHint.left * scale,
                         -thumbnailClipHint.top * scale);
             } else {
-                setThumbnailRotation(deltaRotate, thumbnailClipHint, scale, thumbnailBounds);
+                setThumbnailRotation(deltaRotate, thumbnailClipHint, scale, thumbnailBounds, dp);
             }
 
             final float widthWithInsets;
@@ -599,7 +599,7 @@
         }
 
         private void setThumbnailRotation(int deltaRotate, RectF thumbnailInsets, float scale,
-                Rect thumbnailPosition) {
+                Rect thumbnailPosition, DeviceProfile dp) {
             float newLeftInset = 0;
             float newTopInset = 0;
             float translateX = 0;
@@ -626,7 +626,7 @@
             }
             mClippedInsets.offsetTo(newLeftInset * scale, newTopInset * scale);
             mMatrix.postTranslate(translateX, translateY);
-            if (TaskView.FULL_THUMBNAIL) {
+            if (TaskView.useFullThumbnail(dp)) {
                 mMatrix.postTranslate(-mClippedInsets.left, -mClippedInsets.top);
             }
         }
@@ -634,8 +634,8 @@
         /**
          * Insets to used for clipping the thumbnail (in case it is drawing outside its own space)
          */
-        public RectF getInsetsToDrawInFullscreen() {
-            return TaskView.FULL_THUMBNAIL ? mClippedInsets : EMPTY_RECT_F;
+        public RectF getInsetsToDrawInFullscreen(DeviceProfile dp) {
+            return TaskView.useFullThumbnail(dp) ? mClippedInsets : EMPTY_RECT_F;
         }
     }
 }
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 2c33b6d..6ec996d 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -144,12 +144,16 @@
      * Should the TaskView display clip off the status and navigation bars in recents. When this
      * is false the overview shows the whole screen scaled down instead.
      */
-    public static final boolean CLIP_STATUS_AND_NAV_BARS = false;
+    public static boolean clipStatusAndNavBars(DeviceProfile deviceProfile) {
+        return deviceProfile.isTaskbarPresentInApps;
+    }
 
     /**
      * Should the TaskView scale down to fit whole thumbnail in fullscreen.
      */
-    public static final boolean FULL_THUMBNAIL = false;
+    public static boolean useFullThumbnail(DeviceProfile deviceProfile) {
+        return deviceProfile.isTaskbarPresentInApps;
+    };
 
     private static final float EDGE_SCALE_DOWN_FACTOR_CAROUSEL = 0.03f;
     private static final float EDGE_SCALE_DOWN_FACTOR_GRID = 0.00f;
@@ -1489,12 +1493,16 @@
          */
         public void setProgress(float fullscreenProgress, float parentScale, float taskViewScale,
                 int previewWidth, DeviceProfile dp, PreviewPositionHelper pph) {
-            RectF insets = pph.getInsetsToDrawInFullscreen();
+            RectF insets = pph.getInsetsToDrawInFullscreen(dp);
 
             float currentInsetsLeft = insets.left * fullscreenProgress;
             float currentInsetsRight = insets.right * fullscreenProgress;
+            float insetsBottom = insets.bottom;
+            if (dp.isTaskbarPresentInApps) {
+                insetsBottom = Math.max(0, insetsBottom - dp.taskbarSize);
+            }
             mCurrentDrawnInsets.set(currentInsetsLeft, insets.top * fullscreenProgress,
-                    currentInsetsRight, insets.bottom * fullscreenProgress);
+                    currentInsetsRight, insetsBottom * fullscreenProgress);
             float fullscreenCornerRadius = dp.isMultiWindowMode ? 0 : mWindowCornerRadius;
 
             mCurrentDrawnCornerRadius =
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 9fb8167..8b312ee 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -210,6 +210,8 @@
 
      // Taskbar
     public boolean isTaskbarPresent;
+    // Whether Taskbar will inset the bottom of apps by taskbarSize.
+    public boolean isTaskbarPresentInApps;
     public int taskbarSize;
     // How much of the bottom inset is due to Taskbar rather than other system elements.
     public int nonOverlappingTaskbarInset;
@@ -1079,6 +1081,7 @@
         writer.println(prefix + "\tnumShownHotseatIcons: " + numShownHotseatIcons);
 
         writer.println(prefix + "\tisTaskbarPresent:" + isTaskbarPresent);
+        writer.println(prefix + "\tisTaskbarPresentInApps:" + isTaskbarPresentInApps);
 
         writer.println(prefix + pxToDpStr("taskbarSize", taskbarSize));
         writer.println(prefix + pxToDpStr("nonOverlappingTaskbarInset",