Merge "Increase REORDER_TIMEOUT to make it easier for users to create/add to folder." into ub-launcher3-edmonton
diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar
index 398bd3c..11d5694 100644
--- a/quickstep/libs/sysui_shared.jar
+++ b/quickstep/libs/sysui_shared.jar
Binary files differ
diff --git a/quickstep/res/layout/scrim_view.xml b/quickstep/res/layout/scrim_view.xml
new file mode 100644
index 0000000..2cc37f9
--- /dev/null
+++ b/quickstep/res/layout/scrim_view.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.quickstep.views.ShelfScrimView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/scrim_view" />
\ No newline at end of file
diff --git a/quickstep/src/com/android/launcher3/uioverrides/AllAppsScrim.java b/quickstep/src/com/android/launcher3/uioverrides/AllAppsScrim.java
deleted file mode 100644
index 3c741b3..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/AllAppsScrim.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.uioverrides;
-
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.support.v4.graphics.ColorUtils;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.allapps.AllAppsContainerView;
-import com.android.launcher3.graphics.ViewScrim;
-import com.android.launcher3.util.Themes;
-
-/**
- * Scrim used for all-apps and shelf in Overview
- * In transposed layout, it behaves as a simple color scrim.
- * In portrait layout, it draws a rounded rect such that
- *    From normal state to overview state, the shelf just fades in and does not move
- *    From overview state to all-apps state the self moves up and fades in to cover the screen
- */
-public class AllAppsScrim extends ViewScrim<AllAppsContainerView> {
-
-    private static final int THRESHOLD_ALPHA_DARK = 102;
-    private static final int THRESHOLD_ALPHA_LIGHT = 46;
-
-    private final Launcher mLauncher;
-    private final int mEndColor;
-
-    private int mProgressColor;
-
-    // In transposed layout, we simply draw a flat color.
-    private boolean mDrawingFlatColor;
-
-    private final Paint mVerticalPaint;
-    private float mVerticalProgress;
-
-    private final int mEndAlpha;
-    private final int mThresholdAlpha;
-    private final float mRadius;
-    private final float mTopPadding;
-
-    // Max vertical progress after which the scrim stops moving.
-    private float mMoveThreshold;
-    // Minimum visible size of the scrim.
-    private int mMinSize;
-    private float mDrawFactor = 0;
-
-    public AllAppsScrim(AllAppsContainerView view) {
-        super(view);
-        mLauncher = Launcher.getLauncher(view.getContext());
-        mEndColor = Themes.getAttrColor(mLauncher, R.attr.allAppsScrimColor);
-        mProgressColor = mEndColor;
-
-        mEndAlpha = Color.alpha(mEndColor);
-        mThresholdAlpha = Themes.getAttrBoolean(mLauncher, R.attr.isMainColorDark)
-                ? THRESHOLD_ALPHA_DARK : THRESHOLD_ALPHA_LIGHT;
-        mRadius = mLauncher.getResources().getDimension(R.dimen.shelf_surface_radius);
-        mTopPadding = mLauncher.getResources().getDimension(R.dimen.shelf_surface_top_padding);
-
-        mVerticalPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-        mVerticalPaint.setColor(ColorUtils.setAlphaComponent(mEndColor, 255));
-
-        // Just assume the easiest UI for now, until we have the proper layout information.
-        mDrawingFlatColor = true;
-    }
-
-    @Override
-    protected void onProgressChanged() {
-        mProgressColor = ColorUtils.setAlphaComponent(mEndColor,
-                Math.round(DEACCEL_2.getInterpolation(mProgress) * Color.alpha(mEndColor)));
-    }
-
-    @Override
-    public void draw(Canvas canvas, int width, int height) {
-        if (mDrawingFlatColor) {
-            if (mProgress > 0) {
-                canvas.drawColor(mProgressColor);
-            }
-            return;
-        }
-
-        if (mVerticalPaint.getAlpha() == 0) {
-            return;
-        } else if (mDrawFactor <= 0) {
-            canvas.drawPaint(mVerticalPaint);
-        } else {
-            float top = (height - mMinSize) * mDrawFactor - mTopPadding;
-            canvas.drawRoundRect(0, top - mRadius, width, height + mRadius,
-                    mRadius, mRadius, mVerticalPaint);
-        }
-    }
-
-    public void reInitUi() {
-        DeviceProfile dp = mLauncher.getDeviceProfile();
-        mDrawingFlatColor = dp.isVerticalBarLayout();
-
-        if (!mDrawingFlatColor) {
-            float swipeLength = OverviewState.getDefaultSwipeHeight(mLauncher);
-            mMoveThreshold = 1 - swipeLength / mLauncher.getAllAppsController().getShiftRange();
-            mMinSize = dp.hotseatBarSizePx + dp.getInsets().bottom;
-            onVerticalProgress(mVerticalProgress);
-        }
-        invalidate();
-    }
-
-    public void onVerticalProgress(float progress) {
-        mVerticalProgress = progress;
-        if (mDrawingFlatColor) {
-            return;
-        }
-
-        float drawFactor;
-        int alpha;
-        if (mVerticalProgress >= mMoveThreshold) {
-            drawFactor = 1;
-            alpha = mVerticalProgress >= 1 ? 0 : Math.round(mThresholdAlpha
-                    * ACCEL_2.getInterpolation((1 - mVerticalProgress) / (1 - mMoveThreshold)));
-        } else if (mVerticalProgress <= 0) {
-            drawFactor = 0;
-            alpha = mEndAlpha;
-        } else {
-            drawFactor = mVerticalProgress / mMoveThreshold;
-            alpha = mEndAlpha - Math.round((mEndAlpha - mThresholdAlpha) * drawFactor);
-        }
-        alpha = Utilities.boundToRange(alpha, 0, 255);
-        if (alpha != mVerticalPaint.getAlpha() || drawFactor != mDrawFactor) {
-            mVerticalPaint.setAlpha(alpha);
-            mDrawFactor = drawFactor;
-            invalidate();
-        }
-    }
-
-}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
index 5a216f6..e31805c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
@@ -31,7 +31,7 @@
  */
 public class AllAppsState extends LauncherState {
 
-    private static final int STATE_FLAGS = FLAG_DISABLE_ACCESSIBILITY | FLAG_ALL_APPS_SCRIM;
+    private static final int STATE_FLAGS = FLAG_DISABLE_ACCESSIBILITY;
 
     private static final PageAlphaProvider PAGE_ALPHA_PROVIDER = new PageAlphaProvider(DEACCEL_2) {
         @Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/DisplayRotationListener.java b/quickstep/src/com/android/launcher3/uioverrides/DisplayRotationListener.java
new file mode 100644
index 0000000..2d9a161
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/DisplayRotationListener.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.uioverrides;
+
+import android.content.Context;
+import android.os.Handler;
+
+import com.android.systemui.shared.system.RotationWatcher;
+
+/**
+ * Utility class for listening for rotation changes
+ */
+public class DisplayRotationListener extends RotationWatcher {
+
+    private final Runnable mCallback;
+    private Handler mHandler;
+
+    public DisplayRotationListener(Context context, Runnable callback) {
+        super(context);
+        mCallback = callback;
+    }
+
+    @Override
+    public void enable() {
+        if (mHandler == null) {
+            mHandler = new Handler();
+        }
+        super.enable();
+    }
+
+    @Override
+    protected void onRotationChanged(int i) {
+        mHandler.post(mCallback);
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
index 89dd879..0451653 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
@@ -24,9 +24,8 @@
  */
 public class FastOverviewState extends OverviewState {
 
-    private static final int STATE_FLAGS = FLAG_SHOW_SCRIM | FLAG_DISABLE_RESTORE
-            | FLAG_DISABLE_INTERACTION | FLAG_OVERVIEW_UI | FLAG_HIDE_BACK_BUTTON
-            | FLAG_DISABLE_ACCESSIBILITY;
+    private static final int STATE_FLAGS = FLAG_DISABLE_RESTORE | FLAG_DISABLE_INTERACTION
+            | FLAG_OVERVIEW_UI | FLAG_HIDE_BACK_BUTTON | FLAG_DISABLE_ACCESSIBILITY;
 
     public FastOverviewState(int id) {
         super(id, QuickScrubController.QUICK_SCRUB_START_DURATION, STATE_FLAGS);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 5bdf1b5..91e1e7f 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -34,7 +34,7 @@
  */
 public class OverviewState extends LauncherState {
 
-    private static final int STATE_FLAGS = FLAG_SHOW_SCRIM | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED
+    private static final int STATE_FLAGS = FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED
             | FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_DISABLE_ACCESSIBILITY;
 
     public OverviewState(int id) {
@@ -101,6 +101,11 @@
     }
 
     @Override
+    public float getWorkspaceScrimAlpha(Launcher launcher) {
+        return 0.5f;
+    }
+
+    @Override
     public float getVerticalProgress(Launcher launcher) {
         if ((getVisibleElements(launcher) & ALL_APPS_HEADER_EXTRA) == 0) {
             // We have no all apps content, so we're still at the fully down progress.
diff --git a/quickstep/src/com/android/quickstep/OverviewInteractionState.java b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
index 8923608..9416a29 100644
--- a/quickstep/src/com/android/quickstep/OverviewInteractionState.java
+++ b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
@@ -21,9 +21,12 @@
 import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
 import static com.android.systemui.shared.system.SettingsCompat.SWIPE_UP_SETTING_NAME;
 
+import static com.android.launcher3.Utilities.getSystemProperty;
+
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -33,6 +36,8 @@
 import android.util.Log;
 
 import com.android.launcher3.MainThreadExecutor;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.allapps.DiscoveryBounce;
 import com.android.launcher3.util.UiThreadHelper;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 
@@ -52,6 +57,8 @@
 
     private static final String TAG = "OverviewFlags";
 
+    private static final String HAS_ENABLED_QUICKSTEP_ONCE = "launcher.has_enabled_quickstep_once";
+
     // We do not need any synchronization for this variable as its only written on UI thread.
     private static OverviewInteractionState INSTANCE;
 
@@ -77,6 +84,7 @@
 
     private final SwipeUpGestureEnabledSettingObserver mSwipeUpSettingObserver;
 
+    private final Context mContext;
     private final Handler mUiHandler;
     private final Handler mBgHandler;
 
@@ -88,12 +96,18 @@
     private Runnable mOnSwipeUpSettingChangedListener;
 
     private OverviewInteractionState(Context context) {
+        mContext = context;
         mUiHandler = new Handler(this::handleUiMessage);
         mBgHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleBgMessage);
 
-        mSwipeUpSettingObserver = new SwipeUpGestureEnabledSettingObserver(mUiHandler,
-                context.getContentResolver());
-        mSwipeUpSettingObserver.register();
+        if (shouldIgnoreSwipeUpEnabledSettings()) {
+            mSwipeUpSettingObserver = null;
+            mSwipeUpEnabled = true;
+        } else {
+            mSwipeUpSettingObserver = new SwipeUpGestureEnabledSettingObserver(mUiHandler,
+                    context.getContentResolver());
+            mSwipeUpSettingObserver.register();
+        }
     }
 
     public boolean isSwipeUpGestureEnabled() {
@@ -125,6 +139,8 @@
                 break;
             case MSG_SET_SWIPE_UP_ENABLED:
                 mSwipeUpEnabled = msg.arg1 != 0;
+                resetHomeBounceSeenOnQuickstepEnabledFirstTime();
+
                 if (mOnSwipeUpSettingChangedListener != null) {
                     mOnSwipeUpSettingChangedListener.run();
                 }
@@ -171,6 +187,7 @@
             mResolver.registerContentObserver(Settings.Secure.getUriFor(SWIPE_UP_SETTING_NAME),
                     false, this);
             mSwipeUpEnabled = getValue();
+            resetHomeBounceSeenOnQuickstepEnabledFirstTime();
         }
 
         @Override
@@ -184,4 +201,23 @@
             return Settings.Secure.getInt(mResolver, SWIPE_UP_SETTING_NAME, 0) == 1;
         }
     }
+
+    private boolean shouldIgnoreSwipeUpEnabledSettings() {
+        String sdkInt = getSystemProperty("ro.product.first_api_level", "0");
+        try {
+            return Integer.parseInt(sdkInt) >= Build.VERSION_CODES.P;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
+        if (mSwipeUpEnabled && !Utilities.getPrefs(mContext).getBoolean(
+                HAS_ENABLED_QUICKSTEP_ONCE, true)) {
+            Utilities.getPrefs(mContext).edit()
+                    .putBoolean(HAS_ENABLED_QUICKSTEP_ONCE, true)
+                    .putBoolean(DiscoveryBounce.HOME_BOUNCE_SEEN, false)
+                    .apply();
+        }
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 1359b3a..20ecde9 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -121,6 +121,11 @@
         dispatchDeviceProfileChanged();
 
         mRecentsRootView.setup();
+        reapplyUi();
+    }
+
+    @Override
+    protected void reapplyUi() {
         mRecentsRootView.dispatchInsets();
     }
 
@@ -140,6 +145,7 @@
                     ? new InvariantDeviceProfile(this).getDeviceProfile(this)
                     : appState.getInvariantDeviceProfile().getDeviceProfile(this).copy(this);
         }
+        onDeviceProfileInitiated();
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 2fa3875..2f7aef8 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -43,6 +43,7 @@
 import android.util.Log;
 import android.view.View;
 import android.view.ViewTreeObserver.OnDrawListener;
+import android.view.WindowManager;
 import android.view.animation.Interpolator;
 
 import com.android.launcher3.AbstractFloatingView;
@@ -541,6 +542,7 @@
             dp = dp.copy(mContext);
             dp.updateInsets(insets);
         }
+        dp.updateIsSeascape(mContext.getSystemService(WindowManager.class));
 
         if (runningTaskTarget != null) {
             mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 82a5bdc..8c3e1a2 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -406,7 +406,6 @@
             taskView.bind(task);
         }
         resetTaskVisuals();
-        applyIconScale(false /* animate */);
 
         if (oldChildCount != getChildCount()) {
             mQuickScrubController.snapToNextTaskIfAvailable();
@@ -426,6 +425,7 @@
         if (mRunningTaskTileHidden) {
             setRunningTaskHidden(mRunningTaskTileHidden);
         }
+        applyIconScale(false /* animate */);
 
         updateCurveProperties();
         // Update the set of visible task's data
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
new file mode 100644
index 0000000..aa04672
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.views;
+
+import static android.support.v4.graphics.ColorUtils.compositeColors;
+import static android.support.v4.graphics.ColorUtils.setAlphaComponent;
+
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.anim.Interpolators.ACCEL_2;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Path.Direction;
+import android.graphics.Path.Op;
+import android.util.AttributeSet;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.uioverrides.OverviewState;
+import com.android.launcher3.util.Themes;
+import com.android.launcher3.views.ScrimView;
+
+/**
+ * Scrim used for all-apps and shelf in Overview
+ * In transposed layout, it behaves as a simple color scrim.
+ * In portrait layout, it draws a rounded rect such that
+ *    From normal state to overview state, the shelf just fades in and does not move
+ *    From overview state to all-apps state the shelf moves up and fades in to cover the screen
+ */
+public class ShelfScrimView extends ScrimView {
+
+    private static final int THRESHOLD_ALPHA_DARK = 102;
+    private static final int THRESHOLD_ALPHA_LIGHT = 46;
+
+    private final Launcher mLauncher;
+
+    // In transposed layout, we simply draw a flat color.
+    private boolean mDrawingFlatColor;
+
+    // For shelf mode
+    private final int mEndAlpha;
+    private final int mThresholdAlpha;
+    private final float mRadius;
+    private final float mTopPadding;
+    private final float mMaxScrimAlpha;
+    private final Paint mPaint;
+
+    // Max vertical progress after which the scrim stops moving.
+    private float mMoveThreshold;
+    // Minimum visible size of the scrim.
+    private int mMinSize;
+
+    private float mScrimMoveFactor = 0;
+    private int mShelfColor;
+    private int mRemainingScreenColor;
+
+    private final Path mTempPath = new Path();
+    private final Path mRemainingScreenPath = new Path();
+    private boolean mRemainingScreenPathValid = false;
+
+    public ShelfScrimView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        mLauncher = Launcher.getLauncher(context);
+        mMaxScrimAlpha = OVERVIEW.getWorkspaceScrimAlpha(mLauncher);
+
+        mEndAlpha = Color.alpha(mEndScrim);
+        mThresholdAlpha = Themes.getAttrBoolean(mLauncher, R.attr.isMainColorDark)
+                ? THRESHOLD_ALPHA_DARK : THRESHOLD_ALPHA_LIGHT;
+        mRadius = mLauncher.getResources().getDimension(R.dimen.shelf_surface_radius);
+        mTopPadding = mLauncher.getResources().getDimension(R.dimen.shelf_surface_top_padding);
+        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+        // Just assume the easiest UI for now, until we have the proper layout information.
+        mDrawingFlatColor = true;
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        mRemainingScreenPathValid = false;
+    }
+
+    @Override
+    public void reInitUi() {
+        DeviceProfile dp = mLauncher.getDeviceProfile();
+        mDrawingFlatColor = dp.isVerticalBarLayout();
+
+        if (!mDrawingFlatColor) {
+            float swipeLength = OverviewState.getDefaultSwipeHeight(mLauncher);
+            mMoveThreshold = 1 - swipeLength / mLauncher.getAllAppsController().getShiftRange();
+            mMinSize = dp.hotseatBarSizePx + dp.getInsets().bottom;
+            mRemainingScreenPathValid = false;
+            updateColors();
+        }
+        invalidate();
+    }
+
+
+    @Override
+    public void updateColors() {
+        super.updateColors();
+        if (mDrawingFlatColor) {
+            return;
+        }
+
+        if (mProgress >= mMoveThreshold) {
+            mScrimMoveFactor = 1;
+
+            if (mProgress >= 1) {
+                mShelfColor = 0;
+            } else {
+                int alpha = Math.round(mThresholdAlpha * ACCEL_2.getInterpolation(
+                        (1 - mProgress) / (1 - mMoveThreshold)));
+                mShelfColor = setAlphaComponent(mEndScrim, alpha);
+            }
+            mRemainingScreenColor = 0;
+        } else if (mProgress <= 0) {
+            mScrimMoveFactor = 0;
+            mShelfColor = mCurrentFlatColor;
+            mRemainingScreenColor = 0;
+
+        } else {
+            mScrimMoveFactor = mProgress / mMoveThreshold;
+            mRemainingScreenColor = setAlphaComponent(mScrimColor,
+                    Math.round((1 - mScrimMoveFactor) * mMaxScrimAlpha * 255));
+
+            // Merge the remainingScreenColor and shelfColor in one to avoid overdraw.
+            int alpha = mEndAlpha - Math.round((mEndAlpha - mThresholdAlpha) * mScrimMoveFactor);
+            mShelfColor = compositeColors(setAlphaComponent(mEndScrim, alpha),
+                    mRemainingScreenColor);
+        }
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mDrawingFlatColor) {
+            if (mCurrentFlatColor != 0) {
+                canvas.drawColor(mCurrentFlatColor);
+            }
+            return;
+        }
+
+        if (mShelfColor == 0) {
+            return;
+        } else if (mScrimMoveFactor <= 0) {
+            canvas.drawColor(mShelfColor);
+            return;
+        }
+
+        float minTop = getHeight() - mMinSize;
+        float top = minTop * mScrimMoveFactor - mTopPadding - mRadius;
+
+        // Draw the scrim over the remaining screen if needed.
+        if (mRemainingScreenColor != 0) {
+            if (!mRemainingScreenPathValid) {
+                mTempPath.reset();
+                // Using a arbitrary '+10' in the bottom to avoid any left-overs at the
+                // corners due to rounding issues.
+                mTempPath.addRoundRect(0, minTop, getWidth(), getHeight() + mRadius + 10,
+                        mRadius, mRadius, Direction.CW);
+
+                mRemainingScreenPath.reset();
+                mRemainingScreenPath.addRect(0, 0, getWidth(), getHeight(), Direction.CW);
+                mRemainingScreenPath.op(mTempPath, Op.DIFFERENCE);
+            }
+
+            float offset = minTop - top;
+            canvas.translate(0, -offset);
+            mPaint.setColor(mRemainingScreenColor);
+            canvas.drawPath(mRemainingScreenPath, mPaint);
+            canvas.translate(0, offset);
+        }
+
+        mPaint.setColor(mShelfColor);
+        canvas.drawRoundRect(0, top, getWidth(), getHeight() + mRadius,
+                mRadius, mRadius, mPaint);
+    }
+}
diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml
index 6556adf..cd8a425 100644
--- a/res/layout/launcher.xml
+++ b/res/layout/launcher.xml
@@ -57,6 +57,9 @@
             android:id="@+id/drop_target_bar"
             layout="@layout/drop_target_bar" />
 
+        <include android:id="@+id/scrim_view"
+            layout="@layout/scrim_view" />
+
         <include
             android:id="@+id/apps_view"
             layout="@layout/all_apps"
diff --git a/res/layout/scrim_view.xml b/res/layout/scrim_view.xml
new file mode 100644
index 0000000..a604d56
--- /dev/null
+++ b/res/layout/scrim_view.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.launcher3.views.ScrimView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/scrim_view" />
\ No newline at end of file
diff --git a/res/values/config.xml b/res/values/config.xml
index 6158f29..d5bb131 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -41,9 +41,6 @@
     <item type="id" name="drag_event_parity" />
 
 <!-- AllApps & Launcher transitions -->
-    <!-- The alpha of the AppsCustomize bg in spring loaded mode -->
-    <integer name="config_workspaceScrimAlpha">76</integer>
-
     <!-- Out of 100, the percent to shrink the workspace during spring loaded mode. -->
     <integer name="config_workspaceSpringLoadShrinkPercentage">90</integer>
 
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index a41edc0..bd38bf0 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -213,19 +213,6 @@
         return mForceInvisible != 0;
     }
 
-    /**
-     * Sets the device profile, adjusting it accordingly in case of multi-window
-     */
-    protected void setDeviceProfile(DeviceProfile dp) {
-        mDeviceProfile = dp;
-        if (isInMultiWindowModeCompat()) {
-            Display display = getWindowManager().getDefaultDisplay();
-            Point mwSize = new Point();
-            display.getSize(mwSize);
-            mDeviceProfile = mDeviceProfile.getMultiWindowProfile(this, mwSize);
-        }
-    }
-
     public interface MultiWindowModeChangedListener {
         void onMultiWindowModeChanged(boolean isInMultiWindowMode);
     }
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index 1400432..e47dbe5 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -28,12 +28,14 @@
 import android.os.UserHandle;
 import android.util.Log;
 import android.view.ActionMode;
+import android.view.Surface;
 import android.view.View;
 import android.widget.Toast;
 
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.badge.BadgeInfo;
 import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.uioverrides.DisplayRotationListener;
 import com.android.launcher3.uioverrides.WallpaperColorInfo;
 import com.android.launcher3.shortcuts.DeepShortcutManager;
 import com.android.launcher3.views.BaseDragLayer;
@@ -61,10 +63,13 @@
 
     private int mThemeRes = R.style.LauncherTheme;
 
+    private DisplayRotationListener mRotationListener;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mIsSafeModeEnabled = getPackageManager().isSafeMode();
+        mRotationListener = new DisplayRotationListener(this, this::onDeviceRotationChanged);
 
         // Update theme
         WallpaperColorInfo wallpaperColorInfo = WallpaperColorInfo.getInstance(this);
@@ -237,12 +242,30 @@
     protected void onDestroy() {
         super.onDestroy();
         WallpaperColorInfo.getInstance(this).removeOnChangeListener(this);
+        mRotationListener.disable();
     }
 
     public <T extends BaseDraggingActivity> void setOnStartCallback(OnStartCallback<T> callback) {
         mOnStartCallback = callback;
     }
 
+    protected void onDeviceProfileInitiated() {
+        if (mDeviceProfile.isVerticalBarLayout()) {
+            mRotationListener.enable();
+            mDeviceProfile.updateIsSeascape(getWindowManager());
+        } else {
+            mRotationListener.disable();
+        }
+    }
+
+    private void onDeviceRotationChanged() {
+        if (mDeviceProfile.updateIsSeascape(getWindowManager())) {
+            reapplyUi();
+        }
+    }
+
+    protected abstract void reapplyUi();
+
     /**
      * Callback for listening for onStart
      */
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 4deed73..4f9920c 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -25,6 +25,8 @@
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.util.DisplayMetrics;
+import android.view.Surface;
+import android.view.WindowManager;
 
 import com.android.launcher3.CellLayout.ContainerType;
 import com.android.launcher3.badge.BadgeRenderer;
@@ -118,6 +120,7 @@
     private final Rect mInsets = new Rect();
     public final Rect workspacePadding = new Rect();
     private final Rect mHotseatPadding = new Rect();
+    private boolean mIsSeascape;
 
     // Icon badges
     public BadgeRenderer mBadgeRenderer;
@@ -519,9 +522,22 @@
         return isLandscape && transposeLayoutWithOrientation;
     }
 
+    /**
+     * Updates orientation information and returns true if it has changed from the previous value.
+     */
+    public boolean updateIsSeascape(WindowManager wm) {
+        if (isVerticalBarLayout()) {
+            boolean isSeascape = wm.getDefaultDisplay().getRotation() == Surface.ROTATION_270;
+            if (mIsSeascape != isSeascape) {
+                mIsSeascape = isSeascape;
+                return true;
+            }
+        }
+        return false;
+    }
+
     public boolean isSeascape() {
-        // TODO: This might not hold true for multi window mode, use configuration insead.
-        return isVerticalBarLayout() && mInsets.left > mInsets.right;
+        return isVerticalBarLayout() && mIsSeascape;
     }
 
     public boolean shouldFadeAdjacentWorkspaceScreens() {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index d8bb90a..8088f64 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -45,6 +45,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Point;
 import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
@@ -57,6 +58,7 @@
 import android.text.method.TextKeyListener;
 import android.util.Log;
 import android.util.SparseArray;
+import android.view.Display;
 import android.view.KeyEvent;
 import android.view.KeyboardShortcutGroup;
 import android.view.KeyboardShortcutInfo;
@@ -359,9 +361,7 @@
             mUserEventDispatcher = null;
             initDeviceProfile(mDeviceProfile.inv);
             dispatchDeviceProfileChanged();
-
-            getRootView().dispatchInsets();
-            getStateManager().reapplyState(true /* cancelCurrentAnimation */);
+            reapplyUi();
 
             // Recreate touch controllers
             mDragLayer.setup(mDragController);
@@ -376,6 +376,12 @@
     }
 
     @Override
+    protected void reapplyUi() {
+        getRootView().dispatchInsets();
+        getStateManager().reapplyState(true /* cancelCurrentAnimation */);
+    }
+
+    @Override
     public void rebindModel() {
         int currentPage = mWorkspace.getNextPage();
         if (mModel.startLoader(currentPage)) {
@@ -386,7 +392,14 @@
 
     private void initDeviceProfile(InvariantDeviceProfile idp) {
         // Load configuration-specific DeviceProfile
-        setDeviceProfile(idp.getDeviceProfile(this));
+        mDeviceProfile = idp.getDeviceProfile(this);
+        if (isInMultiWindowModeCompat()) {
+            Display display = getWindowManager().getDefaultDisplay();
+            Point mwSize = new Point();
+            display.getSize(mwSize);
+            mDeviceProfile = mDeviceProfile.getMultiWindowProfile(this, mwSize);
+        }
+        onDeviceProfileInitiated();
         mModelWriter = mModel.getWriter(mDeviceProfile.isVerticalBarLayout(), true);
     }
 
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index ad1456a2..ae0e7a7 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -21,12 +21,9 @@
     private final Launcher mLauncher;
 
     private final Paint mOpaquePaint;
+
     @ViewDebug.ExportedProperty(category = "launcher")
-    private boolean mDrawSideInsetBar;
-    @ViewDebug.ExportedProperty(category = "launcher")
-    private int mLeftInsetBarWidth;
-    @ViewDebug.ExportedProperty(category = "launcher")
-    private int mRightInsetBarWidth;
+    private final Rect mConsumedInsets = new Rect();
 
     private View mAlignedView;
     private WindowStateListener mWindowStateListener;
@@ -54,18 +51,26 @@
     @TargetApi(23)
     @Override
     protected boolean fitSystemWindows(Rect insets) {
-        mDrawSideInsetBar = (insets.right > 0 || insets.left > 0) &&
+        mConsumedInsets.setEmpty();
+        boolean drawInsetBar = false;
+        if (mLauncher.isInMultiWindowModeCompat()
+                && (insets.left > 0 || insets.right > 0 || insets.bottom > 0)) {
+            mConsumedInsets.left = insets.left;
+            mConsumedInsets.right = insets.right;
+            mConsumedInsets.bottom = insets.bottom;
+            insets = new Rect(0, insets.top, 0, 0);
+            drawInsetBar = true;
+        } else  if ((insets.right > 0 || insets.left > 0) &&
                 (!Utilities.ATLEAST_MARSHMALLOW ||
-                        getContext().getSystemService(ActivityManager.class).isLowRamDevice());
-        if (mDrawSideInsetBar) {
-            mLeftInsetBarWidth = insets.left;
-            mRightInsetBarWidth = insets.right;
+                        getContext().getSystemService(ActivityManager.class).isLowRamDevice())) {
+            mConsumedInsets.left = insets.left;
+            mConsumedInsets.right = insets.right;
             insets = new Rect(0, insets.top, 0, insets.bottom);
-        } else {
-            mLeftInsetBarWidth = mRightInsetBarWidth = 0;
+            drawInsetBar = true;
         }
+
         mLauncher.getSystemUiController().updateUiState(
-                UI_STATE_ROOT_VIEW, mDrawSideInsetBar ? FLAG_DARK_NAV : 0);
+                UI_STATE_ROOT_VIEW, drawInsetBar ? FLAG_DARK_NAV : 0);
 
         // Update device profile before notifying th children.
         mLauncher.getDeviceProfile().updateInsets(insets);
@@ -73,11 +78,14 @@
         setInsets(insets);
 
         if (mAlignedView != null) {
-            // Apply margins on aligned view to handle left/right insets.
+            // Apply margins on aligned view to handle consumed insets.
             MarginLayoutParams lp = (MarginLayoutParams) mAlignedView.getLayoutParams();
-            if (lp.leftMargin != mLeftInsetBarWidth || lp.rightMargin != mRightInsetBarWidth) {
-                lp.leftMargin = mLeftInsetBarWidth;
-                lp.rightMargin = mRightInsetBarWidth;
+            if (lp.leftMargin != mConsumedInsets.left || lp.rightMargin != mConsumedInsets.right ||
+                    lp.bottomMargin != mConsumedInsets.bottom) {
+                lp.leftMargin = mConsumedInsets.left;
+                lp.rightMargin = mConsumedInsets.right;
+                lp.topMargin = mConsumedInsets.top;
+                lp.bottomMargin = mConsumedInsets.bottom;
                 mAlignedView.setLayoutParams(lp);
             }
         }
@@ -109,14 +117,16 @@
         super.dispatchDraw(canvas);
 
         // If the right inset is opaque, draw a black rectangle to ensure that is stays opaque.
-        if (mDrawSideInsetBar) {
-            if (mRightInsetBarWidth > 0) {
-                int width = getWidth();
-                canvas.drawRect(width - mRightInsetBarWidth, 0, width, getHeight(), mOpaquePaint);
-            }
-            if (mLeftInsetBarWidth > 0) {
-                canvas.drawRect(0, 0, mLeftInsetBarWidth, getHeight(), mOpaquePaint);
-            }
+        if (mConsumedInsets.right > 0) {
+            int width = getWidth();
+            canvas.drawRect(width - mConsumedInsets.right, 0, width, getHeight(), mOpaquePaint);
+        }
+        if (mConsumedInsets.left > 0) {
+            canvas.drawRect(0, 0, mConsumedInsets.left, getHeight(), mOpaquePaint);
+        }
+        if (mConsumedInsets.bottom > 0) {
+            int height = getHeight();
+            canvas.drawRect(0, height - mConsumedInsets.bottom, getWidth(), height, mOpaquePaint);
         }
     }
 
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 4697b82..f548095 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -52,17 +52,15 @@
     public static final int ALL_APPS_CONTENT = 1 << 4;
     public static final int DRAG_HANDLE_INDICATOR = 1 << 5;
 
-    protected static final int FLAG_SHOW_SCRIM = 1 << 0;
-    protected static final int FLAG_MULTI_PAGE = 1 << 1;
-    protected static final int FLAG_DISABLE_ACCESSIBILITY = 1 << 2;
-    protected static final int FLAG_DISABLE_RESTORE = 1 << 3;
-    protected static final int FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED = 1 << 4;
-    protected static final int FLAG_DISABLE_PAGE_CLIPPING = 1 << 5;
-    protected static final int FLAG_PAGE_BACKGROUNDS = 1 << 6;
-    protected static final int FLAG_ALL_APPS_SCRIM = 1 << 7;
-    protected static final int FLAG_DISABLE_INTERACTION = 1 << 8;
-    protected static final int FLAG_OVERVIEW_UI = 1 << 9;
-    protected static final int FLAG_HIDE_BACK_BUTTON = 1 << 10;
+    protected static final int FLAG_MULTI_PAGE = 1 << 0;
+    protected static final int FLAG_DISABLE_ACCESSIBILITY = 1 << 1;
+    protected static final int FLAG_DISABLE_RESTORE = 1 << 2;
+    protected static final int FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED = 1 << 3;
+    protected static final int FLAG_DISABLE_PAGE_CLIPPING = 1 << 4;
+    protected static final int FLAG_PAGE_BACKGROUNDS = 1 << 5;
+    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 PageAlphaProvider DEFAULT_ALPHA_PROVIDER =
             new PageAlphaProvider(ACCEL_2) {
@@ -116,9 +114,7 @@
      *
      * @see WorkspaceStateTransitionAnimation
      */
-    public final boolean hasScrim;
     public final boolean hasWorkspacePageBackground;
-    public final boolean hasAllAppsScrim;
 
     public final int transitionDuration;
 
@@ -153,10 +149,7 @@
         this.containerType = containerType;
         this.transitionDuration = transitionDuration;
 
-        this.hasScrim = (flags & FLAG_SHOW_SCRIM) != 0;
         this.hasWorkspacePageBackground = (flags & FLAG_PAGE_BACKGROUNDS) != 0;
-        this.hasAllAppsScrim = (flags & FLAG_ALL_APPS_SCRIM) != 0;
-
         this.hasMultipleVisiblePages = (flags & FLAG_MULTI_PAGE) != 0;
         this.workspaceAccessibilityFlag = (flags & FLAG_DISABLE_ACCESSIBILITY) != 0
                 ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
@@ -215,6 +208,10 @@
         return 1f;
     }
 
+    public float getWorkspaceScrimAlpha(Launcher launcher) {
+        return 0;
+    }
+
     public String getDescription(Launcher launcher) {
         return launcher.getWorkspace().getCurrentPageDescription();
     }
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 77a45bf..8d3d459 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -96,9 +96,7 @@
 
         // Set scrim
         propertySetter.setFloat(ViewScrim.get(mWorkspace), ViewScrim.PROGRESS,
-                state.hasScrim ? 1 : 0, Interpolators.LINEAR);
-        propertySetter.setFloat(ViewScrim.get(mLauncher.getAppsView()), ViewScrim.PROGRESS,
-                state.hasAllAppsScrim ? 1 : 0, Interpolators.LINEAR);
+                state.getWorkspaceScrimAlpha(mLauncher), Interpolators.LINEAR);
     }
 
     public void applyChildState(LauncherState state, CellLayout cl, int childIndex) {
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 211d98f..f8648bb 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -47,7 +47,6 @@
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.uioverrides.AllAppsScrim;
 import com.android.launcher3.keyboard.FocusedItemDecorator;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
 import com.android.launcher3.util.ItemInfoMatcher;
@@ -110,9 +109,6 @@
 
         mAllAppsStore.addUpdateListener(this::onAppsUpdated);
 
-        // Attach a scrim to be drawn behind all-apps and hotseat
-        new AllAppsScrim(this).attach();
-
         addSpringView(R.id.all_apps_header);
         addSpringView(R.id.apps_list_view);
         addSpringView(R.id.all_apps_tabs_view_pager);
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 53d3da6..6d70a08 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -26,9 +26,8 @@
 import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.anim.AnimatorSetBuilder;
 import com.android.launcher3.anim.PropertySetter;
-import com.android.launcher3.uioverrides.AllAppsScrim;
-import com.android.launcher3.graphics.ViewScrim;
 import com.android.launcher3.util.Themes;
+import com.android.launcher3.views.ScrimView;
 
 /**
  * Handles AllApps view transition.
@@ -57,7 +56,7 @@
     };
 
     private AllAppsContainerView mAppsView;
-    private AllAppsScrim mAllAppsScrim;
+    private ScrimView mScrimView;
 
     private final Launcher mLauncher;
     private final boolean mIsDarkTheme;
@@ -117,7 +116,7 @@
      */
     public void setProgress(float progress) {
         mProgress = progress;
-        mAllAppsScrim.onVerticalProgress(progress);
+        mScrimView.setProgress(progress);
         float shiftCurrent = progress * mShiftRange;
 
         mAppsView.setTranslationY(shiftCurrent);
@@ -209,8 +208,7 @@
 
     public void setupViews(AllAppsContainerView appsView) {
         mAppsView = appsView;
-        mAllAppsScrim = (AllAppsScrim) ViewScrim.get(mAppsView);
-        mAllAppsScrim.reInitUi();
+        mScrimView = mLauncher.findViewById(R.id.scrim_view);
     }
 
     /**
@@ -220,8 +218,8 @@
         mScrollRangeDelta = delta;
         mShiftRange = mLauncher.getDeviceProfile().heightPx - mScrollRangeDelta;
 
-        if (mAllAppsScrim != null) {
-            mAllAppsScrim.reInitUi();
+        if (mScrimView != null) {
+            mScrimView.reInitUi();
         }
     }
 
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index 8e729e8..84085cb 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -206,6 +206,10 @@
         mOnCancelRunnable = runnable;
     }
 
+    public Runnable getOnCancelRunnable() {
+        return mOnCancelRunnable;
+    }
+
     public static class AnimatorPlaybackControllerVL extends AnimatorPlaybackController {
 
         private final ValueAnimator[] mChildAnimations;
diff --git a/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java b/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java
index 5c991e9..136528d 100644
--- a/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java
+++ b/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java
@@ -61,7 +61,6 @@
 
     private int mFullScrimColor;
 
-    private final int mMaxAlpha;
     private int mAlpha = 0;
 
     public WorkspaceAndHotseatScrim(Workspace view) {
@@ -69,7 +68,6 @@
         mLauncher = Launcher.getLauncher(view.getContext());
         mWallpaperColorInfo = WallpaperColorInfo.getInstance(mLauncher);
 
-        mMaxAlpha = mLauncher.getResources().getInteger(R.integer.config_workspaceScrimAlpha);
         mMaskHeight = Utilities.pxFromDp(ALPHA_MASK_BITMAP_DP,
                 view.getResources().getDisplayMetrics());
 
@@ -108,7 +106,7 @@
 
     @Override
     protected void onProgressChanged() {
-        mAlpha = Math.round(mMaxAlpha * mProgress);
+        mAlpha = Math.round(255 * mProgress);
     }
 
     @Override
@@ -126,9 +124,9 @@
     public void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo) {
         // for super light wallpaper it needs to be darken for contrast to workspace
         // for dark wallpapers the text is white so darkening works as well
-        mFullScrimColor = ColorUtils.compositeColors(DARK_SCRIM_COLOR,
-                wallpaperColorInfo.getMainColor());
-        mBottomMaskPaint.setColor(mFullScrimColor);
+        mBottomMaskPaint.setColor(ColorUtils.compositeColors(DARK_SCRIM_COLOR,
+                wallpaperColorInfo.getMainColor()));
+        mFullScrimColor = wallpaperColorInfo.getMainColor();
     }
 
     public Bitmap createDitheredAlphaMask() {
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index 90d3821..aa7d0d5 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -33,7 +33,7 @@
  */
 public class SpringLoadedState extends LauncherState {
 
-    private static final int STATE_FLAGS = FLAG_SHOW_SCRIM | FLAG_MULTI_PAGE |
+    private static final int STATE_FLAGS = FLAG_MULTI_PAGE |
             FLAG_DISABLE_ACCESSIBILITY | FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED |
             FLAG_DISABLE_PAGE_CLIPPING | FLAG_PAGE_BACKGROUNDS | FLAG_HIDE_BACK_BUTTON;
 
@@ -86,6 +86,11 @@
     }
 
     @Override
+    public float getWorkspaceScrimAlpha(Launcher launcher) {
+        return 0.3f;
+    }
+
+    @Override
     public void onStateDisabled(final Launcher launcher) {
         launcher.getWorkspace().getPageIndicator().setShouldAutoHide(true);
 
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 658af95..bad4976 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -244,8 +244,13 @@
                         endProgress - Math.max(progress, 0));
             }
         } else {
+            // Let the state manager know that the animation didn't go to the target state,
+            // but don't cancel ourselves (we already clean up when the animation completes).
+            Runnable onCancel = mCurrentAnimation.getOnCancelRunnable();
             mCurrentAnimation.setOnCancelRunnable(null);
             mCurrentAnimation.dispatchOnCancel();
+            mCurrentAnimation.setOnCancelRunnable(onCancel);
+
             endProgress = 0;
             if (progress <= 0) {
                 duration = 0;
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
new file mode 100644
index 0000000..b49b565
--- /dev/null
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.views;
+
+import static android.support.v4.graphics.ColorUtils.compositeColors;
+import static android.support.v4.graphics.ColorUtils.setAlphaComponent;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.launcher3.Insettable;
+import com.android.launcher3.R;
+import com.android.launcher3.uioverrides.WallpaperColorInfo;
+import com.android.launcher3.uioverrides.WallpaperColorInfo.OnChangeListener;
+import com.android.launcher3.util.Themes;
+
+/**
+ * Simple scrim which draws a flat color
+ */
+public class ScrimView extends View implements Insettable, OnChangeListener {
+
+    private final WallpaperColorInfo mWallpaperColorInfo;
+    protected final int mEndScrim;
+
+    protected float mMaxScrimAlpha;
+
+    protected float mProgress = 1;
+    protected int mScrimColor;
+
+    protected int mCurrentFlatColor;
+    protected int mEndFlatColor;
+    protected int mEndFlatColorAlpha;
+
+    public ScrimView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mWallpaperColorInfo = WallpaperColorInfo.getInstance(context);
+        mEndScrim = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
+
+        mMaxScrimAlpha = 0.7f;
+    }
+
+    @Override
+    public void setInsets(Rect insets) { }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mWallpaperColorInfo.addOnChangeListener(this);
+        onExtractedColorsChanged(mWallpaperColorInfo);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mWallpaperColorInfo.removeOnChangeListener(this);
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+
+    @Override
+    public void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo) {
+        mScrimColor = wallpaperColorInfo.getMainColor();
+        mEndFlatColor = compositeColors(mEndScrim, setAlphaComponent(
+                mScrimColor, Math.round(mMaxScrimAlpha * 255)));
+        mEndFlatColorAlpha = Color.alpha(mEndFlatColor);
+        updateColors();
+        invalidate();
+    }
+
+    public void setProgress(float progress) {
+        if (mProgress != progress) {
+            mProgress = progress;
+            updateColors();
+            invalidate();
+        }
+    }
+
+    public void reInitUi() { }
+
+    protected void updateColors() {
+        mCurrentFlatColor = mProgress >= 1 ? 0 : setAlphaComponent(
+                mEndFlatColor, Math.round((1 - mProgress) * mEndFlatColorAlpha));
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mCurrentFlatColor != 0) {
+            canvas.drawColor(mCurrentFlatColor);
+        }
+    }
+}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsScrim.java b/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsScrim.java
deleted file mode 100644
index e970c5b..0000000
--- a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsScrim.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.uioverrides;
-
-import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
-
-import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
-import com.android.launcher3.graphics.ColorScrim;
-import com.android.launcher3.util.Themes;
-
-public class AllAppsScrim extends ColorScrim {
-
-    public AllAppsScrim(AllAppsContainerView view) {
-        super(view, Themes.getAttrColor(view.getContext(), R.attr.allAppsScrimColor), ACCEL_1_5);
-    }
-
-    public void reInitUi() {
-        // No op
-    }
-
-    public void onVerticalProgress(float progress) {
-        // No op
-    }
-}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsState.java
index 6366b2d..4a2f544 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsState.java
@@ -34,7 +34,7 @@
 
     private static final float PARALLAX_COEFFICIENT = .125f;
 
-    private static final int STATE_FLAGS = FLAG_DISABLE_ACCESSIBILITY | FLAG_ALL_APPS_SCRIM;
+    private static final int STATE_FLAGS = FLAG_DISABLE_ACCESSIBILITY;
 
     private static final PageAlphaProvider PAGE_ALPHA_PROVIDER = new PageAlphaProvider(DEACCEL_2) {
         @Override
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/DisplayRotationListener.java b/src_ui_overrides/com/android/launcher3/uioverrides/DisplayRotationListener.java
new file mode 100644
index 0000000..b1a67e9
--- /dev/null
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/DisplayRotationListener.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.uioverrides;
+
+import android.content.Context;
+import android.view.OrientationEventListener;
+
+/**
+ * Utility class for listening for rotation changes
+ */
+public class DisplayRotationListener extends OrientationEventListener {
+
+    private final Runnable mCallback;
+
+    public DisplayRotationListener(Context context, Runnable callback) {
+        super(context);
+        mCallback = callback;
+    }
+
+    @Override
+    public void onOrientationChanged(int i) {
+        mCallback.run();
+    }
+}