Removing scrim overdraw

> Moving all the scrims to draglayer to avoid creating multiple layers during
  various animations
> Removing sys-ui scrim in various states which alread have a background scrim

Bug: 74556464
Bug: 78585335
Change-Id: I8a3fd34ed440f3c7d2e19b3cdb4b72723c535602
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 2f83f45..521ad48 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -25,9 +25,7 @@
 import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
 
 import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.annotation.TargetApi;
 import android.app.ActivityOptions;
@@ -220,9 +218,6 @@
     private IconCache mIconCache;
     private LauncherAccessibilityDelegate mAccessibilityDelegate;
 
-    private ObjectAnimator mScrimAnimator;
-    private boolean mShouldFadeInScrim;
-
     private PopupDataProvider mPopupDataProvider;
 
     private int mSynchronouslyBoundPage = PagedView.INVALID_PAGE;
@@ -244,12 +239,6 @@
 
     private RotationHelper mRotationHelper;
 
-    // Used to keep track of the swipe up state
-    private SharedPreferences.OnSharedPreferenceChangeListener mSharedPrefsListener =
-            (sharedPreferences, s) -> {
-                mDragLayer.setup(mDragController);
-            };
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         if (DEBUG_STRICT_MODE) {
@@ -277,7 +266,6 @@
         initDeviceProfile(app.getInvariantDeviceProfile());
 
         mSharedPrefs = Utilities.getPrefs(this);
-        mSharedPrefs.registerOnSharedPreferenceChangeListener(mSharedPrefsListener);
         mIconCache = app.getIconCache();
         mAccessibilityDelegate = new LauncherAccessibilityDelegate(this);
 
@@ -336,11 +324,7 @@
         getRootView().dispatchInsets();
 
         // Listen for broadcasts
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_SCREEN_OFF);
-        filter.addAction(Intent.ACTION_USER_PRESENT); // When the device wakes up + keyguard is gone
-        registerReceiver(mReceiver, filter);
-        mShouldFadeInScrim = true;
+        registerReceiver(mScreenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
 
         getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
                 Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
@@ -361,9 +345,7 @@
             initDeviceProfile(mDeviceProfile.inv);
             dispatchDeviceProfileChanged();
             reapplyUi();
-
-            // Recreate touch controllers
-            mDragLayer.setup(mDragController);
+            mDragLayer.recreateControllers();
 
             // TODO: We can probably avoid rebind when only screen size changed.
             rebindModel();
@@ -764,25 +746,6 @@
         }
         mAppWidgetHost.setListenIfResumed(true);
         NotificationListener.setNotificationsChangedListener(mPopupDataProvider);
-
-        if (mShouldFadeInScrim && mLauncherView.getBackground() != null) {
-            if (mScrimAnimator != null) {
-                mScrimAnimator.cancel();
-            }
-            mLauncherView.getBackground().setAlpha(0);
-            mScrimAnimator = ObjectAnimator.ofInt(mLauncherView.getBackground(),
-                    LauncherAnimUtils.DRAWABLE_ALPHA, 0, 255);
-            mScrimAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mScrimAnimator = null;
-                }
-            });
-            mScrimAnimator.setDuration(600);
-            mScrimAnimator.setStartDelay(getWindow().getTransitionBackgroundFadeDuration());
-            mScrimAnimator.start();
-        }
-        mShouldFadeInScrim = false;
         UiFactory.onStart(this);
     }
 
@@ -939,9 +902,8 @@
                 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
 
         // Setup the drag layer
-        Runnable setupDragLayer = () -> mDragLayer.setup(mDragController);
-        UiFactory.setOnTouchControllersChangedListener(this, setupDragLayer);
-        setupDragLayer.run();
+        mDragLayer.setup(mDragController, mWorkspace);
+        UiFactory.setOnTouchControllersChangedListener(this, mDragLayer::recreateControllers);
 
         mWorkspace.setup(mDragController);
         // Until the workspace is bound, ensure that we keep the wallpaper offset locked to the
@@ -1118,21 +1080,13 @@
         hostView.setOnFocusChangeListener(mFocusHandler);
     }
 
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+    private final BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            if (Intent.ACTION_SCREEN_OFF.equals(action)) {
-                // Reset AllApps to its initial state only if we are not in the middle of
-                // processing a multi-step drop
-                if (mAppsView != null && mPendingRequestArgs == null) {
-                    mStateManager.goToState(NORMAL);
-                }
-                mShouldFadeInScrim = true;
-            } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
-                // ACTION_USER_PRESENT is sent after onStart/onResume. This covers the case where
-                // the user unlocked and the Launcher is not in the foreground.
-                mShouldFadeInScrim = false;
+            // Reset AllApps to its initial state only if we are not in the middle of
+            // processing a multi-step drop
+            if (mPendingRequestArgs == null) {
+                mStateManager.goToState(NORMAL);
             }
         }
     };
@@ -1267,7 +1221,7 @@
                 }
 
                 // Reset the apps view
-                if (!alreadyOnHome && mAppsView != null) {
+                if (!alreadyOnHome) {
                     mAppsView.reset(isStarted() /* animate */);
                 }
 
@@ -1336,7 +1290,7 @@
     public void onDestroy() {
         super.onDestroy();
 
-        unregisterReceiver(mReceiver);
+        unregisterReceiver(mScreenOffReceiver);
         mWorkspace.removeFolderListeners();
 
         UiFactory.setOnTouchControllersChangedListener(this, null);
@@ -1349,7 +1303,6 @@
             LauncherAppState.getInstance(this).setLauncher(null);
         }
         mRotationHelper.destroy();
-        mSharedPrefs.unregisterOnSharedPreferenceChangeListener(mSharedPrefsListener);
 
         try {
             mAppWidgetHost.stopListening();
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index ae0e7a7..3cf6d62 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -14,8 +14,6 @@
 import android.view.View;
 import android.view.ViewDebug;
 
-import com.android.launcher3.util.Themes;
-
 public class LauncherRootView extends InsettableFrameLayout {
 
     private final Launcher mLauncher;
@@ -103,8 +101,6 @@
         if (!insets.equals(mInsets)) {
             super.setInsets(insets);
         }
-        setBackground(insets.top == 0 ? null
-                : Themes.getAttrDrawable(getContext(), R.attr.workspaceStatusBarScrim));
     }
 
     public void dispatchInsets() {
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 4e10ab6..5052674 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -61,6 +61,7 @@
     protected static final int FLAG_DISABLE_INTERACTION = 1 << 6;
     protected static final int FLAG_OVERVIEW_UI = 1 << 7;
     protected static final int FLAG_HIDE_BACK_BUTTON = 1 << 8;
+    protected static final int FLAG_HAS_SYS_UI_SCRIM = 1 << 9;
 
     protected static final PageAlphaProvider DEFAULT_ALPHA_PROVIDER =
             new PageAlphaProvider(ACCEL_2) {
@@ -75,8 +76,9 @@
     /**
      * TODO: Create a separate class for NORMAL state.
      */
-    public static final LauncherState NORMAL = new LauncherState(0, ContainerType.WORKSPACE,
-            0, FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_HIDE_BACK_BUTTON);
+    public static final LauncherState NORMAL = new LauncherState(0, ContainerType.WORKSPACE, 0,
+            FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_HIDE_BACK_BUTTON |
+            FLAG_HAS_SYS_UI_SCRIM);
 
     /**
      * Various Launcher states arranged in the increasing order of UI layers
@@ -147,6 +149,8 @@
      */
     public final boolean hideBackButton;
 
+    public final boolean hasSysUiScrim;
+
     public LauncherState(int id, int containerType, int transitionDuration, int flags) {
         this.containerType = containerType;
         this.transitionDuration = transitionDuration;
@@ -162,6 +166,7 @@
         this.disableInteraction = (flags & FLAG_DISABLE_INTERACTION) != 0;
         this.overviewUi = (flags & FLAG_OVERVIEW_UI) != 0;
         this.hideBackButton = (flags & FLAG_HIDE_BACK_BUTTON) != 0;
+        this.hasSysUiScrim = (flags & FLAG_HAS_SYS_UI_SCRIM) != 0;
 
         this.ordinal = id;
         sAllStates[id] = this;
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index d870109..223fa97 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -75,8 +75,6 @@
 import com.android.launcher3.folder.PreviewBackground;
 import com.android.launcher3.graphics.DragPreviewProvider;
 import com.android.launcher3.graphics.PreloadIconDrawable;
-import com.android.launcher3.graphics.ViewScrim;
-import com.android.launcher3.graphics.WorkspaceAndHotseatScrim;
 import com.android.launcher3.pageindicators.WorkspacePageIndicator;
 import com.android.launcher3.popup.PopupContainerWithArrow;
 import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
@@ -279,9 +277,6 @@
 
         // Disable multitouch across the workspace/all apps/customize tray
         setMotionEventSplittingEnabled(true);
-
-        // Attach a scrim
-        new WorkspaceAndHotseatScrim(this).attach();
         setOnTouchListener(new WorkspaceTouchListener(mLauncher, this));
     }
 
@@ -2152,7 +2147,7 @@
         }
         // Invalidating the scrim will also force this CellLayout
         // to be invalidated so that it is highlighted if necessary.
-        ViewScrim.get(this).invalidate();
+        mLauncher.getDragLayer().getScrim().invalidate();
     }
 
     public CellLayout getCurrentDragOverlappingLayout() {
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index d6b2349..9f26e4a 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -21,6 +21,8 @@
 import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
 import static com.android.launcher3.LauncherState.HOTSEAT_SEARCH_BOX;
 import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
+import static com.android.launcher3.graphics.WorkspaceAndHotseatScrim.SCRIM_PROGRESS;
+import static com.android.launcher3.graphics.WorkspaceAndHotseatScrim.SYSUI_PROGRESS;
 
 import android.view.View;
 import android.view.animation.Interpolator;
@@ -30,7 +32,7 @@
 import com.android.launcher3.anim.AnimatorSetBuilder;
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PropertySetter;
-import com.android.launcher3.graphics.ViewScrim;
+import com.android.launcher3.graphics.WorkspaceAndHotseatScrim;
 
 /**
  * Manages the animations between each of the workspace states.
@@ -103,8 +105,11 @@
                 pageAlphaProvider.interpolator);
 
         // Set scrim
-        propertySetter.setFloat(ViewScrim.get(mWorkspace), ViewScrim.PROGRESS,
-                state.getWorkspaceScrimAlpha(mLauncher), Interpolators.LINEAR);
+        WorkspaceAndHotseatScrim scrim = mLauncher.getDragLayer().getScrim();
+        propertySetter.setFloat(scrim, SCRIM_PROGRESS, state.getWorkspaceScrimAlpha(mLauncher),
+                Interpolators.LINEAR);
+        propertySetter.setFloat(scrim, SYSUI_PROGRESS, state.hasSysUiScrim ? 1 : 0,
+                Interpolators.LINEAR);
     }
 
     public void applyChildState(LauncherState state, CellLayout cl, int childIndex) {
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 8519365..aad1e5a 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -27,6 +27,8 @@
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -42,10 +44,12 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.ShortcutAndWidgetContainer;
+import com.android.launcher3.Workspace;
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.folder.FolderIcon;
 import com.android.launcher3.graphics.ViewScrim;
+import com.android.launcher3.graphics.WorkspaceAndHotseatScrim;
 import com.android.launcher3.keyboard.ViewGroupFocusHelper;
 import com.android.launcher3.uioverrides.UiFactory;
 import com.android.launcher3.util.Thunk;
@@ -77,6 +81,7 @@
 
     // Related to adjacent page hints
     private final ViewGroupFocusHelper mFocusIndicatorHelper;
+    private final WorkspaceAndHotseatScrim mScrim;
 
     /**
      * Used to create a new DragLayer from XML.
@@ -92,10 +97,16 @@
         setChildrenDrawingOrderEnabled(true);
 
         mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
+        mScrim = new WorkspaceAndHotseatScrim(this);
     }
 
-    public void setup(DragController dragController) {
+    public void setup(DragController dragController, Workspace workspace) {
         mDragController = dragController;
+        mScrim.setWorkspace(workspace);
+        recreateControllers();
+    }
+
+    public void recreateControllers() {
         mControllers = UiFactory.createTouchControllers(mActivity);
     }
 
@@ -542,7 +553,24 @@
     @Override
     protected void dispatchDraw(Canvas canvas) {
         // Draw the background below children.
+        mScrim.draw(canvas);
         mFocusIndicatorHelper.draw(canvas);
         super.dispatchDraw(canvas);
     }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        mScrim.setSize(w, h);
+    }
+
+    @Override
+    public void setInsets(Rect insets) {
+        super.setInsets(insets);
+        mScrim.onInsetsChanged(insets);
+    }
+
+    public WorkspaceAndHotseatScrim getScrim() {
+        return mScrim;
+    }
 }
diff --git a/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java b/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java
index 136528d..9d847d6 100644
--- a/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java
+++ b/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java
@@ -16,6 +16,14 @@
 
 package com.android.launcher3.graphics;
 
+import static android.content.Intent.ACTION_SCREEN_OFF;
+import static android.content.Intent.ACTION_USER_PRESENT;
+
+import android.animation.ObjectAnimator;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -25,8 +33,11 @@
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.graphics.Shader;
+import android.graphics.drawable.Drawable;
 import android.support.v4.graphics.ColorUtils;
 import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.Property;
 import android.view.View;
 
 import com.android.launcher3.CellLayout;
@@ -35,13 +46,68 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.uioverrides.WallpaperColorInfo;
+import com.android.launcher3.util.Themes;
 
 /**
  * View scrim which draws behind hotseat and workspace
  */
-public class WorkspaceAndHotseatScrim extends ViewScrim<Workspace> implements
+public class WorkspaceAndHotseatScrim implements
         View.OnAttachStateChangeListener, WallpaperColorInfo.OnChangeListener {
 
+    public static Property<WorkspaceAndHotseatScrim, Float> SCRIM_PROGRESS =
+            new Property<WorkspaceAndHotseatScrim, Float>(Float.TYPE, "scrimProgress") {
+                @Override
+                public Float get(WorkspaceAndHotseatScrim scrim) {
+                    return scrim.mScrimProgress;
+                }
+
+                @Override
+                public void set(WorkspaceAndHotseatScrim scrim, Float value) {
+                    scrim.setScrimProgress(value);
+                }
+            };
+
+    public static Property<WorkspaceAndHotseatScrim, Float> SYSUI_PROGRESS =
+            new Property<WorkspaceAndHotseatScrim, Float>(Float.TYPE, "sysUiProgress") {
+                @Override
+                public Float get(WorkspaceAndHotseatScrim scrim) {
+                    return scrim.mSysUiProgress;
+                }
+
+                @Override
+                public void set(WorkspaceAndHotseatScrim scrim, Float value) {
+                    scrim.setSysUiProgress(value);
+                }
+            };
+
+    private static Property<WorkspaceAndHotseatScrim, Float> SYSUI_ANIM_MULTIPLIER =
+            new Property<WorkspaceAndHotseatScrim, Float>(Float.TYPE, "sysUiAnimMultiplier") {
+                @Override
+                public Float get(WorkspaceAndHotseatScrim scrim) {
+                    return scrim.mSysUiAnimMultiplier;
+                }
+
+                @Override
+                public void set(WorkspaceAndHotseatScrim scrim, Float value) {
+                    scrim.mSysUiAnimMultiplier = value;
+                    scrim.reapplySysUiAlpha();
+                }
+            };
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (ACTION_SCREEN_OFF.equals(action)) {
+                mAnimateScrimOnNextDraw = true;
+            } else if (ACTION_USER_PRESENT.equals(action)) {
+                // ACTION_USER_PRESENT is sent after onStart/onResume. This covers the case where
+                // the user unlocked and the Launcher is not in the foreground.
+                mAnimateScrimOnNextDraw = false;
+            }
+        }
+    };
+
     private static final int DARK_SCRIM_COLOR = 0x55000000;
     private static final int MAX_HOTSEAT_SCRIM_ALPHA = 100;
     private static final int ALPHA_MASK_HEIGHT_DP = 500;
@@ -51,40 +117,61 @@
     private final Rect mHighlightRect = new Rect();
     private final Launcher mLauncher;
     private final WallpaperColorInfo mWallpaperColorInfo;
+    private final View mRoot;
 
-    private final boolean mHasHotseatScrim;
+    private Workspace mWorkspace;
+
+    private final boolean mHasSysUiScrim;
+    private boolean mDrawTopScrim, mDrawBottomScrim;
+
     private final RectF mFinalMaskRect = new RectF();
     private final Paint mBottomMaskPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
-
     private final Bitmap mBottomMask;
     private final int mMaskHeight;
 
+    private final Drawable mTopScrim;
+
     private int mFullScrimColor;
 
-    private int mAlpha = 0;
+    private float mScrimProgress;
+    private int mScrimAlpha = 0;
 
-    public WorkspaceAndHotseatScrim(Workspace view) {
-        super(view);
+    private float mSysUiProgress = 1;
+
+    private boolean mAnimateScrimOnNextDraw = false;
+    private float mSysUiAnimMultiplier = 1;
+
+    public WorkspaceAndHotseatScrim(View view) {
+        mRoot = view;
         mLauncher = Launcher.getLauncher(view.getContext());
         mWallpaperColorInfo = WallpaperColorInfo.getInstance(mLauncher);
 
         mMaskHeight = Utilities.pxFromDp(ALPHA_MASK_BITMAP_DP,
                 view.getResources().getDisplayMetrics());
 
-        mHasHotseatScrim = !mWallpaperColorInfo.supportsDarkText();
-        mBottomMask = mHasHotseatScrim ? createDitheredAlphaMask() : null;
+        mHasSysUiScrim = !mWallpaperColorInfo.supportsDarkText();
+        if (mHasSysUiScrim) {
+            mTopScrim = Themes.getAttrDrawable(view.getContext(), R.attr.workspaceStatusBarScrim);
+            mBottomMask = createDitheredAlphaMask();
+        } else {
+            mTopScrim = null;
+            mBottomMask = null;
+        }
 
         view.addOnAttachStateChangeListener(this);
         onExtractedColorsChanged(mWallpaperColorInfo);
     }
 
-    @Override
-    public void draw(Canvas canvas, int width, int height) {
+    public void setWorkspace(Workspace workspace)  {
+        mWorkspace = workspace;
+    }
+
+    public void draw(Canvas canvas) {
         // Draw the background below children.
-        if (mAlpha > 0) {
+        if (mScrimAlpha > 0) {
             // Update the scroll position first to ensure scrim cutout is in the right place.
-            mView.computeScrollWithoutInvalidation();
-            CellLayout currCellLayout = mView.getCurrentDragOverlappingLayout();
+            mWorkspace.computeScrollWithoutInvalidation();
+            CellLayout currCellLayout = mWorkspace.getCurrentDragOverlappingLayout();
             canvas.save();
             if (currCellLayout != null && currCellLayout != mLauncher.getHotseat().getLayout()) {
                 // Cut a hole in the darkening scrim on the page that should be highlighted, if any.
@@ -93,31 +180,68 @@
                 canvas.clipRect(mHighlightRect, Region.Op.DIFFERENCE);
             }
 
-            canvas.drawColor(ColorUtils.setAlphaComponent(mFullScrimColor, mAlpha));
+            canvas.drawColor(ColorUtils.setAlphaComponent(mFullScrimColor, mScrimAlpha));
             canvas.restore();
         }
 
-        if (mHasHotseatScrim && !mLauncher.getDeviceProfile().isVerticalBarLayout()) {
-            mFinalMaskRect.set(0, height - mMaskHeight, width, height);
-            mBottomMaskPaint.setAlpha(Math.round(MAX_HOTSEAT_SCRIM_ALPHA * (1 - mProgress)));
-            canvas.drawBitmap(mBottomMask, null, mFinalMaskRect, mBottomMaskPaint);
+        if (mHasSysUiScrim) {
+            if (mSysUiProgress <= 0) {
+                mAnimateScrimOnNextDraw = false;
+                return;
+            }
+
+            if (mAnimateScrimOnNextDraw) {
+                mSysUiAnimMultiplier = 0;
+                reapplySysUiAlphaNoInvalidate();
+
+                ObjectAnimator anim = ObjectAnimator.ofFloat(this, SYSUI_ANIM_MULTIPLIER, 1);
+                anim.setAutoCancel(true);
+                anim.setDuration(600);
+                anim.setStartDelay(mLauncher.getWindow().getTransitionBackgroundFadeDuration());
+                anim.start();
+                mAnimateScrimOnNextDraw = false;
+            }
+
+            if (mDrawTopScrim) {
+                mTopScrim.draw(canvas);
+            }
+            if (mDrawBottomScrim) {
+                canvas.drawBitmap(mBottomMask, null, mFinalMaskRect, mBottomMaskPaint);
+            }
         }
     }
 
-    @Override
-    protected void onProgressChanged() {
-        mAlpha = Math.round(255 * mProgress);
+    public void onInsetsChanged(Rect insets) {
+        mDrawTopScrim = insets.top > 0;
+        mDrawBottomScrim = !mLauncher.getDeviceProfile().isVerticalBarLayout();
+    }
+
+    private void setScrimProgress(float progress) {
+        if (mScrimProgress != progress) {
+            mScrimProgress = progress;
+            mScrimAlpha = Math.round(255 * mScrimProgress);
+            invalidate();
+        }
     }
 
     @Override
     public void onViewAttachedToWindow(View view) {
         mWallpaperColorInfo.addOnChangeListener(this);
         onExtractedColorsChanged(mWallpaperColorInfo);
+
+        if (mHasSysUiScrim) {
+            IntentFilter filter = new IntentFilter(ACTION_SCREEN_OFF);
+            filter.addAction(ACTION_USER_PRESENT); // When the device wakes up + keyguard is gone
+            mRoot.getContext().registerReceiver(mReceiver, filter);
+        }
     }
 
     @Override
     public void onViewDetachedFromWindow(View view) {
         mWallpaperColorInfo.removeOnChangeListener(this);
+        if (mHasSysUiScrim) {
+            mRoot.getContext().unregisterReceiver(mReceiver);
+        }
     }
 
     @Override
@@ -126,7 +250,42 @@
         // for dark wallpapers the text is white so darkening works as well
         mBottomMaskPaint.setColor(ColorUtils.compositeColors(DARK_SCRIM_COLOR,
                 wallpaperColorInfo.getMainColor()));
+        reapplySysUiAlpha();
         mFullScrimColor = wallpaperColorInfo.getMainColor();
+        if (mScrimAlpha > 0) {
+            invalidate();
+        }
+    }
+
+    public void setSize(int w, int h) {
+        if (mHasSysUiScrim) {
+            mTopScrim.setBounds(0, 0, w, h);
+            mFinalMaskRect.set(0, h - mMaskHeight, w, h);
+        }
+    }
+
+    private void setSysUiProgress(float progress) {
+        if (progress != mSysUiProgress) {
+            mSysUiProgress = progress;
+            reapplySysUiAlpha();
+        }
+    }
+
+    private void reapplySysUiAlpha() {
+        if (mHasSysUiScrim) {
+            reapplySysUiAlphaNoInvalidate();
+            invalidate();
+        }
+    }
+
+    private void reapplySysUiAlphaNoInvalidate() {
+        float factor = mSysUiProgress * mSysUiAnimMultiplier;
+        mBottomMaskPaint.setAlpha(Math.round(MAX_HOTSEAT_SCRIM_ALPHA * factor));
+        mTopScrim.setAlpha(Math.round(255 * factor));
+    }
+
+    public void invalidate() {
+        mRoot.invalidate();
     }
 
     public Bitmap createDitheredAlphaMask() {