Merge "Import translations. DO NOT MERGE ANYWHERE"
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
index 79e50ef..67e9d89 100644
--- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -49,6 +49,7 @@
     public static final String ACTION_SEARCH = "com.android.quickstep.ACTION_SEARCH";
     public static final String ELAPSED_NANOS = "niu_actions_elapsed_realtime_nanos";
     public static final String ACTIONS_URL = "niu_actions_app_url";
+    public static final String ACTIONS_APP_PACKAGE = "niu_actions_app_package";
     public static final String ACTIONS_ERROR_CODE = "niu_actions_app_error_code";
     public static final int ERROR_PERMISSIONS = 1;
     private static final String TAG = "TaskOverlayFactoryGo";
@@ -72,6 +73,7 @@
      */
     public static final class TaskOverlayGo<T extends OverviewActionsView> extends TaskOverlay {
         private String mNIUPackageName;
+        private String mTaskPackageName;
         private String mWebUrl;
         private boolean mAssistPermissionsEnabled;
 
@@ -87,7 +89,7 @@
                 boolean rotated) {
             getActionsView().updateDisabledFlags(DISABLED_NO_THUMBNAIL, thumbnail == null);
             mNIUPackageName =
-                    mApplicationContext.getResources().getString(R.string.niu_actions_package);
+                    mApplicationContext.getString(R.string.niu_actions_package);
 
             if (thumbnail == null || TextUtils.isEmpty(mNIUPackageName)) {
                 return;
@@ -96,6 +98,7 @@
             getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated);
             boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot();
             getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
+            mTaskPackageName = task.key.getPackageName();
 
             checkPermissions();
             if (!mAssistPermissionsEnabled) {
@@ -150,6 +153,7 @@
                     .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
                     .addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
                     .setPackage(mNIUPackageName)
+                    .putExtra(ACTIONS_APP_PACKAGE, mTaskPackageName)
                     .putExtra(ELAPSED_NANOS, SystemClock.elapsedRealtimeNanos());
 
             if (mWebUrl != null) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index f09d9e0..d07cc35 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -26,6 +26,7 @@
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
 import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_WIDGET_APP_START;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
 import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL;
 import static com.android.launcher3.testing.TestProtocol.HINT_STATE_TWO_BUTTON_ORDINAL;
@@ -36,7 +37,6 @@
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
-import android.os.SystemProperties;
 import android.view.HapticFeedbackConstants;
 import android.view.View;
 
@@ -90,9 +90,6 @@
 
 public class QuickstepLauncher extends BaseQuickstepLauncher {
 
-    private static final boolean ENABLE_APP_WIDGET_LAUNCH_ANIMATION =
-            SystemProperties.getBoolean("persist.debug.quickstep_app_widget_launch", false);
-
     public static final boolean GO_LOW_RAM_RECENTS_ENABLED = false;
     /**
      * Reusable command for applying the shelf height on the background thread.
@@ -327,7 +324,7 @@
 
     protected LauncherAppWidgetHost createAppWidgetHost() {
         LauncherAppWidgetHost appWidgetHost = super.createAppWidgetHost();
-        if (ENABLE_APP_WIDGET_LAUNCH_ANIMATION) {
+        if (ENABLE_QUICKSTEP_WIDGET_APP_START.get()) {
             appWidgetHost.setInteractionHandler(new QuickstepInteractionHandler(this));
         }
         return appWidgetHost;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index ba61923..3ac7866 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -77,6 +77,7 @@
     @Override
     public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState,
             StateAnimationConfig config) {
+        RecentsView overview = mActivity.getOverviewPanel();
         if (toState == NORMAL && fromState == OVERVIEW) {
             config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
             config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
@@ -85,7 +86,12 @@
             config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL_DEACCEL);
 
             if (SysUINavigationMode.getMode(mActivity) == NO_BUTTON) {
-                config.setInterpolator(ANIM_OVERVIEW_FADE, FINAL_FRAME);
+                // Scrolling in tasks, so make visible straight away
+                if (overview.getTaskViewCount() > 0) {
+                    config.setInterpolator(ANIM_OVERVIEW_FADE, FINAL_FRAME);
+                } else {
+                    config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
+                }
             } else {
                 config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
             }
@@ -122,13 +128,18 @@
                 config.setInterpolator(ANIM_WORKSPACE_SCALE,
                         fromState == NORMAL ? ACCEL : OVERSHOOT_1_2);
                 config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
-                config.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
+
+                // Scrolling in tasks, so show straight away
+                if (overview.getTaskViewCount() > 0) {
+                    config.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
+                } else {
+                    config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
+                }
             } else {
                 config.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
                 config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
 
                 // Scale up the recents, if it is not coming from the side
-                RecentsView overview = mActivity.getOverviewPanel();
                 if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) {
                     RECENTS_SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
                 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index 2d95ce2..729e2cb 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -18,20 +18,11 @@
 
 import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
 import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
-import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.HINT_STATE;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
 import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_HEADER_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
 import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
 
@@ -45,7 +36,6 @@
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.states.StateAnimationConfig;
 import com.android.launcher3.util.VibratorWrapper;
 import com.android.quickstep.SystemUiProxy;
@@ -269,39 +259,4 @@
     private float dpiFromPx(float pixels) {
         return Utilities.dpiFromPx(pixels, mLauncher.getResources().getDisplayMetrics().densityDpi);
     }
-
-    @Override
-    protected StateAnimationConfig getConfigForStates(
-            LauncherState fromState, LauncherState toState) {
-        if (fromState == NORMAL && toState == ALL_APPS) {
-            StateAnimationConfig builder = new StateAnimationConfig();
-            builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
-                    ACCEL,
-                    0,
-                    ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD));
-            builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
-                    ACCEL,
-                    ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD,
-                    ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD));
-
-            // Get workspace out of the way quickly, to prepare for potential pause.
-            builder.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL_3);
-            builder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, DEACCEL_3);
-            builder.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_3);
-            return builder;
-        } else if (fromState == ALL_APPS && toState == NORMAL) {
-            StateAnimationConfig builder = new StateAnimationConfig();
-
-            builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
-                    DEACCEL,
-                    1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
-                    1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD));
-            builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
-                    DEACCEL,
-                    1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
-                    1));
-            return builder;
-        }
-        return super.getConfigForStates(fromState, toState);
-    }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index b8f9452..3c83d25 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -24,6 +24,7 @@
 import static com.android.launcher3.anim.Interpolators.ACCEL;
 import static com.android.launcher3.anim.Interpolators.DEACCEL;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
 
 import android.view.MotionEvent;
 
@@ -56,13 +57,17 @@
     /**
      * Minimum clamping progress for fading in all apps content
      */
-    protected static final float ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD = 0.4f;
-
+    protected static final float ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD = 0.5f;
 
     /**
-     * The progress at which recents will begin fading out when swiping up from overview.
+     * Minimum clamping progress for fading in all apps scrim
      */
-    private static final float RECENTS_FADE_THRESHOLD = 0.88f;
+    protected static final float ALL_APPS_SCRIM_VISIBLE_THRESHOLD = .1f;
+
+    /**
+     * Maximum clamping progress for opaque all apps scrim
+     */
+    protected static final float ALL_APPS_SCRIM_OPAQUE_THRESHOLD = .5f;
 
     private final PortraitOverviewStateTouchHelper mOverviewPortraitStateTouchHelper;
 
@@ -122,14 +127,22 @@
     private StateAnimationConfig getNormalToAllAppsAnimation() {
         StateAnimationConfig builder = new StateAnimationConfig();
         builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(ACCEL,
-                0, ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD));
+                ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD,
+                ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD));
+        builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(ACCEL,
+                ALL_APPS_SCRIM_VISIBLE_THRESHOLD,
+                ALL_APPS_SCRIM_OPAQUE_THRESHOLD));
         return builder;
     }
 
     private StateAnimationConfig getAllAppsToNormalAnimation() {
         StateAnimationConfig builder = new StateAnimationConfig();
         builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL,
-                1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD, 1));
+                1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
+                1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD));
+        builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(DEACCEL,
+                1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD,
+                1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
         return builder;
     }
 
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 7067dbc..e4d148c 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -20,7 +20,7 @@
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCRIM_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
 import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
 import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
@@ -98,6 +98,6 @@
                 state.displayOverviewTasksAsGrid(mActivity.getDeviceProfile()) ? 1f : 0f, LINEAR);
 
         setter.setViewBackgroundColor(mActivity.getScrimView(), state.getScrimColor(mActivity),
-                config.getInterpolator(ANIM_WORKSPACE_SCRIM_FADE, LINEAR));
+                config.getInterpolator(ANIM_SCRIM_FADE, LINEAR));
     }
 }
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
index c396eec..14c3a92 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -20,9 +20,7 @@
 import static com.android.quickstep.interaction.TutorialController.TutorialType.RIGHT_EDGE_BACK_NAVIGATION;
 
 import android.graphics.PointF;
-import android.view.View;
 
-import androidx.annotation.Nullable;
 import androidx.appcompat.content.res.AppCompatResources;
 
 import com.android.launcher3.R;
@@ -36,11 +34,6 @@
         super(fragment, tutorialType);
     }
 
-    @Nullable
-    public View getMockLauncherView() {
-        return null;
-    }
-
     @Override
     public Integer getIntroductionTitle() {
         return mTutorialType == LEFT_EDGE_BACK_NAVIGATION
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
index 3c59ed3..06610e6 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -16,15 +16,11 @@
 package com.android.quickstep.interaction;
 
 import static com.android.launcher3.anim.Interpolators.ACCEL;
-import static com.android.quickstep.interaction.TutorialController.TutorialType.OVERVIEW_NAVIGATION_COMPLETE;
 
 import android.animation.AnimatorSet;
 import android.annotation.TargetApi;
 import android.graphics.PointF;
 import android.os.Build;
-import android.view.View;
-
-import androidx.annotation.Nullable;
 
 import com.android.launcher3.R;
 import com.android.launcher3.anim.PendingAnimation;
@@ -52,12 +48,6 @@
         return R.string.overview_gesture_intro_subtitle;
     }
 
-    @Nullable
-    @Override
-    public View getMockLauncherView() {
-        return null;
-    }
-
     @Override
     public void onBackGestureAttempted(BackGestureResult result) {
         switch (mTutorialType) {
diff --git a/quickstep/src/com/android/quickstep/interaction/SandboxLauncherRenderer.java b/quickstep/src/com/android/quickstep/interaction/SandboxLauncherRenderer.java
deleted file mode 100644
index 80ffe66..0000000
--- a/quickstep/src/com/android/quickstep/interaction/SandboxLauncherRenderer.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2020 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.interaction;
-
-import android.content.Context;
-import android.view.View;
-
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.graphics.LauncherPreviewRenderer;
-
-/** Renders a fake Launcher for use in the Sandbox. */
-class SandboxLauncherRenderer extends LauncherPreviewRenderer {
-    SandboxLauncherRenderer(Context context, InvariantDeviceProfile idp, boolean migrated) {
-        super(context, idp, migrated);
-    }
-
-    @Override
-    public boolean shouldShowRealLauncherPreview() {
-        return false;
-    }
-
-    @Override
-    public boolean shouldShowQsb() {
-        return false;
-    }
-
-    @Override
-    public View.OnLongClickListener getWorkspaceChildOnLongClickListener() {
-        return null;
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 6f82f85..55972ad 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -37,7 +37,6 @@
 import androidx.appcompat.app.AlertDialog;
 import androidx.appcompat.content.res.AppCompatResources;
 
-import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.views.ClipIconView;
@@ -129,13 +128,6 @@
         return R.drawable.default_sandbox_app_previous_task_thumbnail;
     }
 
-    @Nullable
-    public View getMockLauncherView() {
-        InvariantDeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext);
-
-        return new SandboxLauncherRenderer(mContext, dp, true).getRenderedView();
-    }
-
     @DrawableRes
     public int getMockAppIconResId() {
         return R.drawable.default_sandbox_app_icon;
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index 88f1850..f93d87c 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -61,6 +61,7 @@
 import com.android.launcher3.util.rule.FailureWatcher;
 import com.android.quickstep.views.RecentsView;
 
+import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.RuleChain;
@@ -141,6 +142,12 @@
         }
     }
 
+    @After
+    public void verifyLauncherState() {
+        // Limits UI tests affecting tests running after them.
+        AbstractQuickStepTest.checkDetectedLeaks(mLauncher);
+    }
+
     // b/143488140
     //@NavigationModeSwitch
     @Test
diff --git a/res/color/cell_layout_bg_color_active.xml b/res/color/cell_layout_bg_color_active.xml
index e826489..d1a3d7c 100644
--- a/res/color/cell_layout_bg_color_active.xml
+++ b/res/color/cell_layout_bg_color_active.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="0.4"
+    <item android:alpha="0.3"
       android:color="?android:attr/colorAccent"/>
 </selector>
diff --git a/res/color/cell_layout_bg_color_inactive.xml b/res/color/cell_layout_bg_color_inactive.xml
index d60a27a..0632100 100644
--- a/res/color/cell_layout_bg_color_inactive.xml
+++ b/res/color/cell_layout_bg_color_inactive.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="0.3"
+    <item android:alpha="0.25"
         android:color="?android:attr/colorAccent"/>
 </selector>
\ No newline at end of file
diff --git a/res/values/config.xml b/res/values/config.xml
index f8a517d..1e78373 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -35,7 +35,7 @@
     <!-- Workspace -->
     <!-- The duration (in ms) of the fade animation on the object outlines, used when
          we are dragging objects around on the home screen. -->
-    <integer name="config_dragOutlineFadeTime">900</integer>
+    <integer name="config_dragOutlineFadeTime">500</integer>
 
     <!-- The alpha value at which to show the most recent drop visualization outline. -->
     <integer name="config_dragOutlineMaxAlpha">255</integer>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index dd14eaa..a57ccde 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -293,7 +293,7 @@
     <dimen name="overview_task_margin">0dp</dimen>
 
 <!-- Workspace grid visualization parameters -->
-    <dimen name="grid_visualization_rounding_radius">28dp</dimen>
+    <dimen name="grid_visualization_rounding_radius">22dp</dimen>
     <dimen name="grid_visualization_cell_spacing">6dp</dimen>
 
 </resources>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 2ace796..3d044d6 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -317,7 +317,8 @@
 
     @UiThread
     protected void applyIconAndLabel(ItemInfoWithIcon info) {
-        FastBitmapDrawable iconDrawable = info.newIcon(getContext());
+        boolean useTheme = mDisplay == DISPLAY_WORKSPACE || mDisplay == DISPLAY_FOLDER;
+        FastBitmapDrawable iconDrawable = info.newIcon(getContext(), useTheme);
         mDotParams.color = IconPalette.getMutedColor(info.bitmap.color, 0.54f);
 
         setIcon(iconDrawable);
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index a037675..2f755e1 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -18,7 +18,6 @@
 
 import static android.animation.ValueAnimator.areAnimatorsEnabled;
 
-import static com.android.launcher3.Utilities.getBoundsForViewInDragLayer;
 import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
 
 import android.animation.Animator;
@@ -194,7 +193,6 @@
     private static final int INVALID_DIRECTION = -100;
 
     private final Rect mTempRect = new Rect();
-    private final RectF mTempRectF = new RectF();
 
     private static final Paint sPaint = new Paint();
 
@@ -504,7 +502,7 @@
     }
 
     private void updateBgAlpha() {
-        mBackground.setAlpha((int) (mSpringLoadedProgress * mScrollProgress * 255));
+        mBackground.setAlpha((int) (mSpringLoadedProgress * 255));
     }
 
     /**
@@ -527,9 +525,12 @@
     }
 
     protected void visualizeGrid(Canvas canvas) {
-        mVisualizeGridRect.set(mGridVisualizationPadding, mGridVisualizationPadding,
-                mCellWidth - mGridVisualizationPadding,
-                mCellHeight - mGridVisualizationPadding);
+        DeviceProfile dp = mActivity.getDeviceProfile();
+        int paddingX = (int) Math.min((mCellWidth - dp.iconSizePx) / 2, mGridVisualizationPadding);
+        int paddingY = (int) Math.min((mCellHeight - dp.iconSizePx) / 2, mGridVisualizationPadding);
+        mVisualizeGridRect.set(paddingX, paddingY,
+                mCellWidth - paddingX,
+                mCellHeight - paddingY);
 
         mVisualizeGridPaint.setStrokeWidth(8);
         int paintAlpha = (int) (120 * mGridAlpha);
@@ -539,9 +540,9 @@
             for (int i = 0; i < mCountX; i++) {
                 for (int j = 0; j < mCountY; j++) {
                     int transX = i * mCellWidth + (i * mBorderSpacing) + getPaddingLeft()
-                            + mGridVisualizationPadding;
+                            + paddingX;
                     int transY = j * mCellHeight + (j * mBorderSpacing) + getPaddingTop()
-                            + mGridVisualizationPadding;
+                            + paddingY;
 
                     mVisualizeGridRect.offsetTo(transX, transY);
                     mVisualizeGridPaint.setStyle(Paint.Style.FILL);
@@ -562,14 +563,14 @@
                 int spanX = mDragOutlines[i].cellHSpan;
                 int spanY = mDragOutlines[i].cellVSpan;
 
-                mVisualizeGridRect.set(mGridVisualizationPadding, mGridVisualizationPadding,
-                        mCellWidth * spanX - mGridVisualizationPadding,
-                        mCellHeight * spanY - mGridVisualizationPadding);
+                mVisualizeGridRect.set(paddingX, paddingY,
+                        mCellWidth * spanX - paddingX,
+                        mCellHeight * spanY - paddingY);
 
                 int transX = x * mCellWidth + (x * mBorderSpacing)
-                        + getPaddingLeft() + mGridVisualizationPadding;
+                        + getPaddingLeft() + paddingX;
                 int transY = y * mCellHeight + (y * mBorderSpacing)
-                        + getPaddingTop() + mGridVisualizationPadding;
+                        + getPaddingTop() + paddingY;
 
                 mVisualizeGridRect.offsetTo(transX, transY);
 
@@ -1069,16 +1070,11 @@
         // Apply local extracted color if the DragView is an AppWidgetHostViewDrawable.
         View view = dragObject.dragView.getContentView();
         if (view instanceof LauncherAppWidgetHostView) {
-            Launcher launcher = Launcher.getLauncher(dragObject.dragView.getContext());
-            Workspace workspace = launcher.getWorkspace();
+            Workspace workspace =
+                    Launcher.getLauncher(dragObject.dragView.getContext()).getWorkspace();
             int screenId = workspace.getIdForScreen(this);
             int pageId = workspace.getPageIndexForScreenId(screenId);
             cellToRect(targetCell[0], targetCell[1], spanX, spanY, mTempRect);
-
-            // Now get the rect in drag layer coordinates.
-            getBoundsForViewInDragLayer(launcher.getDragLayer(), workspace, mTempRect, false,
-                    mTempRectF);
-            Utilities.setRect(mTempRectF, mTempRect);
             ((LauncherAppWidgetHostView) view).handleDrag(mTempRect, pageId);
         }
     }
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 073a46c..be5463e 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -33,7 +33,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ShortcutInfo;
-import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
@@ -75,9 +74,9 @@
 import com.android.launcher3.graphics.GridCustomizationsProvider;
 import com.android.launcher3.graphics.TintedDrawableSpan;
 import com.android.launcher3.icons.FastBitmapDrawable;
-import com.android.launcher3.icons.IconProvider;
 import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.icons.ShortcutCachingLogic;
+import com.android.launcher3.icons.ThemedIconDrawable.ThemedAdaptiveIcon;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.pm.ShortcutConfigActivityInfo;
@@ -85,7 +84,6 @@
 import com.android.launcher3.shortcuts.ShortcutRequest;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.PackageManagerHelper;
-import com.android.launcher3.views.BaseDragLayer;
 import com.android.launcher3.widget.PendingAddShortcutInfo;
 
 import java.lang.reflect.Method;
@@ -106,8 +104,6 @@
     private static final Pattern sTrimPattern =
             Pattern.compile("^[\\s|\\p{javaSpaceChar}]*(.*)[\\s|\\p{javaSpaceChar}]*$");
 
-    private static final float[] sTmpFloatArray = new float[4];
-
     private static final int[] sLoc0 = new int[2];
     private static final int[] sLoc1 = new int[2];
     private static final Matrix sMatrix = new Matrix();
@@ -137,15 +133,6 @@
             Build.TYPE.toLowerCase(Locale.ROOT).contains("debug") ||
             Build.TYPE.toLowerCase(Locale.ROOT).equals("eng");
 
-    /**
-     * Returns true if theme is dark.
-     */
-    public static boolean isDarkTheme(Context context) {
-        Configuration configuration = context.getResources().getConfiguration();
-        int nightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
-        return nightMode == Configuration.UI_MODE_NIGHT_YES;
-    }
-
     public static boolean isDevelopersOptionsEnabled(Context context) {
         return Settings.Global.getInt(context.getApplicationContext().getContentResolver(),
                         Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
@@ -232,33 +219,6 @@
     }
 
     /**
-     * Returns bounds for a child view of DragLayer, in drag layer coordinates.
-     *
-     * see {@link com.android.launcher3.dragndrop.DragLayer}.
-     *
-     * @param viewBounds Bounds of the view wanted in drag layer coordinates, relative to the view
-     *                   itself. eg. (0, 0, view.getWidth, view.getHeight)
-     * @param ignoreTransform If true, view transform is ignored
-     * @param outRect The out rect where we return the bounds of {@param view} in drag layer coords.
-     */
-    public static void getBoundsForViewInDragLayer(BaseDragLayer dragLayer, View view,
-            Rect viewBounds, boolean ignoreTransform, RectF outRect) {
-        float[] points = sTmpFloatArray;
-        points[0] = viewBounds.left;
-        points[1] = viewBounds.top;
-        points[2] = viewBounds.right;
-        points[3] = viewBounds.bottom;
-
-        Utilities.getDescendantCoordRelativeToAncestor(view, dragLayer, points,
-                false, ignoreTransform);
-        outRect.set(
-                Math.min(points[0], points[2]),
-                Math.min(points[1], points[3]),
-                Math.max(points[0], points[2]),
-                Math.max(points[1], points[3]));
-    }
-
-    /**
      * Inverse of {@link #getDescendantCoordRelativeToAncestor(View, View, float[], boolean)}.
      */
     public static void mapCoordInSelfToDescendant(View descendant, View root, float[] coord) {
@@ -313,16 +273,6 @@
         return new int[] {sLoc1[0] - sLoc0[0], sLoc1[1] - sLoc0[1]};
     }
 
-    /**
-     * Helper method to set rectOut with rectFSrc.
-     */
-    public static void setRect(RectF rectFSrc, Rect rectOut) {
-        rectOut.left = (int) rectFSrc.left;
-        rectOut.top = (int) rectFSrc.top;
-        rectOut.right = (int) rectFSrc.right;
-        rectOut.bottom = (int) rectFSrc.bottom;
-    }
-
     public static void scaleRectFAboutCenter(RectF r, float scale) {
         if (scale != 1.0f) {
             float cx = r.centerX();
@@ -646,13 +596,23 @@
      */
     public static Drawable getFullDrawable(Launcher launcher, ItemInfo info, int width, int height,
             Object[] outObj) {
+        Drawable icon = loadFullDrawableWithoutTheme(launcher, info, width, height, outObj);
+        if (icon instanceof ThemedAdaptiveIcon) {
+            icon = ((ThemedAdaptiveIcon) icon).getThemedDrawable(launcher);
+        }
+        return icon;
+    }
+
+    private static Drawable loadFullDrawableWithoutTheme(Launcher launcher, ItemInfo info,
+            int width, int height, Object[] outObj) {
         LauncherAppState appState = LauncherAppState.getInstance(launcher);
         if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
             LauncherActivityInfo activityInfo = launcher.getSystemService(LauncherApps.class)
                     .resolveActivity(info.getIntent(), info.user);
             outObj[0] = activityInfo;
-            return activityInfo == null ? null : new IconProvider(launcher).getIcon(
-                    activityInfo, launcher.getDeviceProfile().inv.fillResIconDpi);
+            return activityInfo == null ? null : LauncherAppState.getInstance(launcher)
+                    .getIconCache().getIconProvider().getIcon(
+                            activityInfo, launcher.getDeviceProfile().inv.fillResIconDpi);
         } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
             if (info instanceof PendingAddShortcutInfo) {
                 ShortcutConfigActivityInfo activityInfo =
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index aa99d52..c771e3e 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -34,9 +34,9 @@
 import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCRIM_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
 import static com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM;
 
@@ -166,10 +166,9 @@
         propertySetter.setFloat(sysUiScrim, SYSUI_PROGRESS,
                 state.hasFlag(FLAG_HAS_SYS_UI_SCRIM) ? 1 : 0, LINEAR);
 
-
         propertySetter.setViewBackgroundColor(mLauncher.getScrimView(),
                 state.getWorkspaceScrimColor(mLauncher),
-                config.getInterpolator(ANIM_WORKSPACE_SCRIM_FADE, LINEAR));
+                config.getInterpolator(ANIM_SCRIM_FADE, LINEAR));
     }
 
     public void applyChildState(LauncherState state, CellLayout cl, int childIndex) {
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index bad8704..d935032 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -87,6 +87,10 @@
     public static final BooleanFlag ENABLE_QUICKSTEP_LIVE_TILE = getDebugFlag(
             "ENABLE_QUICKSTEP_LIVE_TILE", true, "Enable live tile in Quickstep overview");
 
+    public static final BooleanFlag ENABLE_QUICKSTEP_WIDGET_APP_START = getDebugFlag(
+            "ENABLE_QUICKSTEP_WIDGET_APP_START", false,
+            "Enable Quickstep animation when launching activities from an app widget");
+
     // Keep as DeviceFlag to allow remote disable in emergency.
     public static final BooleanFlag ENABLE_SUGGESTED_ACTIONS_OVERVIEW = new DeviceFlag(
             "ENABLE_SUGGESTED_ACTIONS_OVERVIEW", true, "Show chip hints on the overview screen");
@@ -137,8 +141,8 @@
     public static final BooleanFlag MULTI_DB_GRID_MIRATION_ALGO = getDebugFlag(
             "MULTI_DB_GRID_MIRATION_ALGO", true, "Use the multi-db grid migration algorithm");
 
-    public static final BooleanFlag ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER = getDebugFlag(
-            "ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER", true, "Show launcher preview in grid picker");
+    public static final BooleanFlag ENABLE_THEMED_ICONS = getDebugFlag(
+            "ENABLE_THEMED_ICONS", false, "Enable themed icons on workspace");
 
     // Keep as DeviceFlag for remote disable in emergency.
     public static final BooleanFlag ENABLE_OVERVIEW_SELECTIONS = new DeviceFlag(
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index d7f6cdb..575b8fd 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -22,7 +22,6 @@
 import static com.android.launcher3.Utilities.ATLEAST_Q;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 
-import android.animation.ValueAnimator;
 import android.content.ComponentName;
 import android.content.res.Resources;
 import android.graphics.Point;
@@ -307,17 +306,12 @@
             mOptions.preDragCondition.onPreDragEnd(mDragObject, true /* dragStarted*/);
         }
         mIsInPreDrag = false;
+        mDragObject.dragView.onDragStart();
         for (DragListener listener : new ArrayList<>(mListeners)) {
             listener.onDragStart(mDragObject, mOptions);
         }
     }
 
-    public void addFirstFrameAnimationHelper(ValueAnimator anim) {
-        if (mDragObject != null && mDragObject.dragView != null) {
-            mDragObject.dragView.mFirstFrameAnimatorHelper.addTo(anim);
-        }
-    }
-
     public Optional<InstanceId> getLogInstanceId() {
         return Optional.ofNullable(mDragObject)
                 .map(dragObject -> dragObject.logInstanceId);
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 68a8af2..30ee9ec 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -51,7 +51,6 @@
 import androidx.dynamicanimation.animation.SpringAnimation;
 import androidx.dynamicanimation.animation.SpringForce;
 
-import com.android.launcher3.FirstFrameAnimatorHelper;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.LauncherState;
@@ -62,6 +61,7 @@
 import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.statemanager.StateManager.StateListener;
+import com.android.launcher3.util.RunnableList;
 import com.android.launcher3.util.Thunk;
 import com.android.launcher3.views.BaseDragLayer;
 
@@ -85,12 +85,13 @@
     private final float mScaleOnDrop;
     private final int[] mTempLoc = new int[2];
 
+    private final RunnableList mOnDragStartCallback = new RunnableList();
+
     private Point mDragVisualizeOffset = null;
     private Rect mDragRegion = null;
     private final Launcher mLauncher;
     private final DragLayer mDragLayer;
     @Thunk final DragController mDragController;
-    final FirstFrameAnimatorHelper mFirstFrameAnimatorHelper;
     private boolean mHasDrawn = false;
 
     final ValueAnimator mAnim;
@@ -136,7 +137,6 @@
         mLauncher = launcher;
         mDragLayer = launcher.getDragLayer();
         mDragController = launcher.getDragController();
-        mFirstFrameAnimatorHelper = new FirstFrameAnimatorHelper(this);
 
         mContent = content;
         mWidth = width;
@@ -276,7 +276,8 @@
                 }
                 mFgSpringDrawable.setBounds(bounds);
 
-                new Handler(Looper.getMainLooper()).post(() -> {
+                new Handler(Looper.getMainLooper()).post(() -> mOnDragStartCallback.add(() -> {
+                    // TODO: Consider fade-in animation
                     // Assign the variable on the UI thread to avoid race conditions.
                     mScaledMaskPath = mask;
                     // Avoid relayout as we do not care about children affecting layout
@@ -290,11 +291,18 @@
                         mBadge.setColorFilter(d.getColorFilter());
                     }
                     invalidate();
-                });
+                }));
             }
         });
     }
 
+    /**
+     * Called when pre-drag finishes for an icon
+     */
+    public void onDragStart() {
+        mOnDragStartCallback.executeAllAndDestroy();
+    }
+
     // TODO(b/183609936): This is only for LauncherAppWidgetHostView that is rendered in a drawable.
     // Once LauncherAppWidgetHostView is directly rendered in this view, removes this method.
     @Override
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
index 8244f01..6adef01 100644
--- a/src/com/android/launcher3/folder/PreviewItemManager.java
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -400,7 +400,7 @@
             drawable.setLevel(item.getProgressLevel());
             p.drawable = drawable;
         } else {
-            p.drawable = item.newIcon(mContext);
+            p.drawable = item.newIcon(mContext, true);
         }
         p.drawable.setBounds(0, 0, mIconSize, mIconSize);
         p.item = item;
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 31764c5..acfeeac 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -20,7 +20,6 @@
 import static android.view.View.VISIBLE;
 
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER;
 import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
 import static com.android.launcher3.model.ModelUtils.getMissingHotseatRanks;
 import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially;
@@ -118,7 +117,7 @@
  *   4) Measure and draw the view on a canvas
  */
 @TargetApi(Build.VERSION_CODES.O)
-public class LauncherPreviewRenderer extends ContextThemeWrapper
+public class LauncherPreviewRenderer extends ContextWrapper
         implements ActivityContext, WorkspaceLayoutManager, LayoutInflater.Factory2 {
 
     private static final String TAG = "LauncherPreviewRenderer";
@@ -220,7 +219,7 @@
     private final CellLayout mWorkspace;
 
     public LauncherPreviewRenderer(Context context, InvariantDeviceProfile idp, boolean migrated) {
-        super(context, R.style.AppTheme);
+        super(context);
         mUiHandler = new Handler(Looper.getMainLooper());
         mContext = context;
         mIdp = idp;
@@ -271,14 +270,6 @@
         return mRootView;
     }
 
-    public boolean shouldShowRealLauncherPreview() {
-        return ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER.get();
-    }
-
-    public boolean shouldShowQsb() {
-        return FeatureFlags.QSB_ON_FIRST_SCREEN;
-    }
-
     @Override
     public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
         if ("TextClock".equals(name)) {
@@ -402,107 +393,88 @@
     }
 
     private void populate() {
-        if (shouldShowRealLauncherPreview()) {
-            WorkspaceFetcher fetcher;
-            PreviewContext previewContext = null;
-            if (mMigrated) {
-                previewContext = new PreviewContext(mContext, mIdp);
-                LauncherAppState appForPreview = new LauncherAppState(
-                        previewContext, null /* iconCacheFileName */);
-                fetcher = new WorkspaceItemsInfoFromPreviewFetcher(appForPreview);
-                MODEL_EXECUTOR.execute(fetcher);
-            } else {
-                fetcher = new WorkspaceItemsInfoFetcher();
-                LauncherAppState.getInstance(mContext).getModel().enqueueModelUpdateTask(
-                        (LauncherModel.ModelUpdateTask) fetcher);
-            }
-            WorkspaceResult workspaceResult = fetcher.get();
-            if (previewContext != null) {
-                previewContext.onDestroy();
-            }
-
-            if (workspaceResult == null) {
-                return;
-            }
-
-            // Separate the items that are on the current screen, and the other remaining items.
-            ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<>();
-            ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<>();
-            ArrayList<LauncherAppWidgetInfo> currentAppWidgets = new ArrayList<>();
-            ArrayList<LauncherAppWidgetInfo> otherAppWidgets = new ArrayList<>();
-            filterCurrentWorkspaceItems(0 /* currentScreenId */,
-                    workspaceResult.mWorkspaceItems, currentWorkspaceItems,
-                    otherWorkspaceItems);
-            filterCurrentWorkspaceItems(0 /* currentScreenId */, workspaceResult.mAppWidgets,
-                    currentAppWidgets, otherAppWidgets);
-            sortWorkspaceItemsSpatially(mIdp, currentWorkspaceItems);
-            for (ItemInfo itemInfo : currentWorkspaceItems) {
-                switch (itemInfo.itemType) {
-                    case Favorites.ITEM_TYPE_APPLICATION:
-                    case Favorites.ITEM_TYPE_SHORTCUT:
-                    case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
-                        inflateAndAddIcon((WorkspaceItemInfo) itemInfo);
-                        break;
-                    case Favorites.ITEM_TYPE_FOLDER:
-                        inflateAndAddFolder((FolderInfo) itemInfo);
-                        break;
-                    default:
-                        break;
-                }
-            }
-            for (ItemInfo itemInfo : currentAppWidgets) {
-                switch (itemInfo.itemType) {
-                    case Favorites.ITEM_TYPE_APPWIDGET:
-                    case Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
-                        if (mMigrated) {
-                            inflateAndAddWidgets((LauncherAppWidgetInfo) itemInfo,
-                                    workspaceResult.mWidgetProvidersMap);
-                        } else {
-                            inflateAndAddWidgets((LauncherAppWidgetInfo) itemInfo,
-                                    workspaceResult.mWidgetsModel);
-                        }
-                        break;
-                    default:
-                        break;
-                }
-            }
-            IntArray ranks = getMissingHotseatRanks(currentWorkspaceItems,
-                    mDp.numShownHotseatIcons);
-            List<ItemInfo> predictions = workspaceResult.mHotseatPredictions == null
-                    ? Collections.emptyList() : workspaceResult.mHotseatPredictions.items;
-            int count = Math.min(ranks.size(), predictions.size());
-            for (int i = 0; i < count; i++) {
-                int rank = ranks.get(i);
-                WorkspaceItemInfo itemInfo =
-                        new WorkspaceItemInfo((WorkspaceItemInfo) predictions.get(i));
-                itemInfo.container = CONTAINER_HOTSEAT_PREDICTION;
-                itemInfo.rank = rank;
-                itemInfo.cellX = mHotseat.getCellXFromOrder(rank);
-                itemInfo.cellY = mHotseat.getCellYFromOrder(rank);
-                itemInfo.screenId = rank;
-                inflateAndAddPredictedIcon(itemInfo);
-            }
+        WorkspaceFetcher fetcher;
+        PreviewContext previewContext = null;
+        if (mMigrated) {
+            previewContext = new PreviewContext(mContext, mIdp);
+            LauncherAppState appForPreview = new LauncherAppState(
+                    previewContext, null /* iconCacheFileName */);
+            fetcher = new WorkspaceItemsInfoFromPreviewFetcher(appForPreview);
+            MODEL_EXECUTOR.execute(fetcher);
         } else {
-            // Add hotseat icons
-            for (int i = 0; i < mDp.numShownHotseatIcons; i++) {
-                WorkspaceItemInfo info = new WorkspaceItemInfo(mWorkspaceItemInfo);
-                info.container = Favorites.CONTAINER_HOTSEAT;
-                info.screenId = i;
-                inflateAndAddIcon(info);
+            fetcher = new WorkspaceItemsInfoFetcher();
+            LauncherAppState.getInstance(mContext).getModel().enqueueModelUpdateTask(
+                    (LauncherModel.ModelUpdateTask) fetcher);
+        }
+        WorkspaceResult workspaceResult = fetcher.get();
+        if (previewContext != null) {
+            previewContext.onDestroy();
+        }
+
+        if (workspaceResult == null) {
+            return;
+        }
+
+        // Separate the items that are on the current screen, and the other remaining items.
+        ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<>();
+        ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<>();
+        ArrayList<LauncherAppWidgetInfo> currentAppWidgets = new ArrayList<>();
+        ArrayList<LauncherAppWidgetInfo> otherAppWidgets = new ArrayList<>();
+        filterCurrentWorkspaceItems(0 /* currentScreenId */,
+                workspaceResult.mWorkspaceItems, currentWorkspaceItems,
+                otherWorkspaceItems);
+        filterCurrentWorkspaceItems(0 /* currentScreenId */, workspaceResult.mAppWidgets,
+                currentAppWidgets, otherAppWidgets);
+        sortWorkspaceItemsSpatially(mIdp, currentWorkspaceItems);
+        for (ItemInfo itemInfo : currentWorkspaceItems) {
+            switch (itemInfo.itemType) {
+                case Favorites.ITEM_TYPE_APPLICATION:
+                case Favorites.ITEM_TYPE_SHORTCUT:
+                case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
+                    inflateAndAddIcon((WorkspaceItemInfo) itemInfo);
+                    break;
+                case Favorites.ITEM_TYPE_FOLDER:
+                    inflateAndAddFolder((FolderInfo) itemInfo);
+                    break;
+                default:
+                    break;
             }
-            // Add workspace icons
-            for (int i = 0; i < mIdp.numColumns; i++) {
-                WorkspaceItemInfo info = new WorkspaceItemInfo(mWorkspaceItemInfo);
-                info.container = Favorites.CONTAINER_DESKTOP;
-                info.screenId = 0;
-                info.cellX = i;
-                info.cellY = mIdp.numRows - 1;
-                inflateAndAddIcon(info);
+        }
+        for (ItemInfo itemInfo : currentAppWidgets) {
+            switch (itemInfo.itemType) {
+                case Favorites.ITEM_TYPE_APPWIDGET:
+                case Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
+                    if (mMigrated) {
+                        inflateAndAddWidgets((LauncherAppWidgetInfo) itemInfo,
+                                workspaceResult.mWidgetProvidersMap);
+                    } else {
+                        inflateAndAddWidgets((LauncherAppWidgetInfo) itemInfo,
+                                workspaceResult.mWidgetsModel);
+                    }
+                    break;
+                default:
+                    break;
             }
         }
+        IntArray ranks = getMissingHotseatRanks(currentWorkspaceItems,
+                mDp.numShownHotseatIcons);
+        List<ItemInfo> predictions = workspaceResult.mHotseatPredictions == null
+                ? Collections.emptyList() : workspaceResult.mHotseatPredictions.items;
+        int count = Math.min(ranks.size(), predictions.size());
+        for (int i = 0; i < count; i++) {
+            int rank = ranks.get(i);
+            WorkspaceItemInfo itemInfo =
+                    new WorkspaceItemInfo((WorkspaceItemInfo) predictions.get(i));
+            itemInfo.container = CONTAINER_HOTSEAT_PREDICTION;
+            itemInfo.rank = rank;
+            itemInfo.cellX = mHotseat.getCellXFromOrder(rank);
+            itemInfo.cellY = mHotseat.getCellYFromOrder(rank);
+            itemInfo.screenId = rank;
+            inflateAndAddPredictedIcon(itemInfo);
+        }
 
         // Add first page QSB
-        if (shouldShowQsb()) {
+        if (FeatureFlags.QSB_ON_FIRST_SCREEN) {
             View qsb = mHomeElementInflater.inflate(
                     R.layout.search_container_workspace, mWorkspace, false);
             CellLayout.LayoutParams lp =
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index e45b8f7..13ae866 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -21,6 +21,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
@@ -33,7 +34,6 @@
 import android.util.SparseArray;
 import android.view.ContextThemeWrapper;
 
-import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.launcher3.icons.GraphicsUtils;
@@ -119,7 +119,9 @@
                 info,
                 IconPalette.getPreloadProgressColor(context, info.bitmap.color),
                 getPreloadColors(context),
-                Utilities.isDarkTheme(context));
+            (context.getResources().getConfiguration().uiMode
+                    & Configuration.UI_MODE_NIGHT_MASK
+                    & Configuration.UI_MODE_NIGHT_YES) != 0) /* isDarkMode */;
     }
 
     public PreloadIconDrawable(
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
index fdc3a94..6193570 100644
--- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -20,6 +20,7 @@
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 
+import android.app.WallpaperColors;
 import android.content.Context;
 import android.hardware.display.DisplayManager;
 import android.os.Bundle;
@@ -28,18 +29,23 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
+import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.SurfaceControlViewHost;
 import android.view.View;
 import android.view.animation.AccelerateDecelerateInterpolator;
 
 import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.R;
 import com.android.launcher3.model.GridSizeMigrationTask;
 import com.android.launcher3.model.GridSizeMigrationTaskV2;
+import com.android.launcher3.util.Themes;
+import com.android.launcher3.widget.LocalColorExtractor;
 
 import java.util.concurrent.TimeUnit;
 
 /** Render preview using surface view. */
+@SuppressWarnings("NewApi")
 public class PreviewSurfaceRenderer implements IBinder.DeathRecipient {
 
     private static final int FADE_IN_ANIMATION_DURATION = 200;
@@ -50,6 +56,7 @@
     private static final String KEY_DISPLAY_ID = "display_id";
     private static final String KEY_SURFACE_PACKAGE = "surface_package";
     private static final String KEY_CALLBACK = "callback";
+    private static final String KEY_COLORS = "wallpaper_colors";
 
     private final Context mContext;
     private final InvariantDeviceProfile mIdp;
@@ -57,6 +64,7 @@
     private final int mWidth;
     private final int mHeight;
     private final Display mDisplay;
+    private final WallpaperColors mWallpaperColors;
 
     private SurfaceControlViewHost mSurfaceControlViewHost;
 
@@ -68,6 +76,8 @@
         if (gridName == null) {
             gridName = InvariantDeviceProfile.getCurrentGridName(context);
         }
+        mWallpaperColors = bundle.getParcelable(KEY_COLORS);
+
         mIdp = new InvariantDeviceProfile(context, gridName);
 
         mHostToken = bundle.getBinder(KEY_HOST_TOKEN);
@@ -100,6 +110,19 @@
         MODEL_EXECUTOR.post(() -> {
             final boolean success = doGridMigrationIfNecessary();
 
+            final Context inflationContext;
+            if (mWallpaperColors != null) {
+                // Workaround to create a themed context
+                Context context = mContext.createDisplayContext(mDisplay);
+                LocalColorExtractor.newInstance(mContext)
+                        .applyColorsOverride(context, mWallpaperColors);
+
+                inflationContext = new ContextThemeWrapper(context,
+                        Themes.getActivityThemeRes(context, mWallpaperColors.getColorHints()));
+            } else {
+                inflationContext = new ContextThemeWrapper(mContext,  R.style.AppTheme);
+            }
+
             MAIN_EXECUTOR.post(() -> {
                 // If mSurfaceControlViewHost is null due to any reason (e.g. binder died,
                 // happening when user leaves the preview screen before preview rendering finishes),
@@ -109,7 +132,8 @@
                     return;
                 }
 
-                View view = new LauncherPreviewRenderer(mContext, mIdp, success).getRenderedView();
+                View view = new LauncherPreviewRenderer(inflationContext, mIdp, success)
+                        .getRenderedView();
                 // This aspect scales the view to fit in the surface and centers it
                 final float scale = Math.min(mWidth / (float) view.getMeasuredWidth(),
                         mHeight / (float) view.getMeasuredHeight());
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index a2c0f5c..bc93a1e 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -52,7 +52,6 @@
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.shortcuts.ShortcutKey;
-import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.InstantAppResolver;
 import com.android.launcher3.util.PackageUserKey;
 import com.android.launcher3.util.Preconditions;
@@ -94,7 +93,7 @@
         mLauncherApps = mContext.getSystemService(LauncherApps.class);
         mUserManager = UserCache.INSTANCE.get(mContext);
         mInstantAppResolver = InstantAppResolver.newInstance(mContext);
-        mIconProvider = new IconProvider(context);
+        mIconProvider = new IconProvider(context, true /* supportsIconTheme */);
     }
 
     @Override
@@ -107,8 +106,12 @@
         return mInstantAppResolver.isInstantApp(info);
     }
 
+    public IconProvider getIconProvider() {
+        return mIconProvider;
+    }
+
     @Override
-    protected BaseIconFactory getIconFactory() {
+    public BaseIconFactory getIconFactory() {
         return LauncherIcons.obtain(mContext);
     }
 
@@ -333,15 +336,6 @@
                 + ",flags_asi:" + FeatureFlags.APP_SEARCH_IMPROVEMENTS.get();
     }
 
-    @Override
-    protected boolean getEntryFromDB(ComponentKey cacheKey, CacheEntry entry, boolean lowRes) {
-        if (mIconProvider.isClockIcon(cacheKey)) {
-            // For clock icon, we always load the dynamic icon
-            return false;
-        }
-        return super.getEntryFromDB(cacheKey, entry, lowRes);
-    }
-
     /**
      * Interface for receiving itemInfo with high-res icon.
      */
diff --git a/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java b/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java
index 93de35a..8fc3977 100644
--- a/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java
+++ b/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java
@@ -20,6 +20,7 @@
 import android.content.pm.LauncherActivityInfo;
 import android.os.UserHandle;
 
+import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
 import com.android.launcher3.icons.cache.CachingLogic;
 import com.android.launcher3.util.ResourceBasedOverride;
@@ -56,8 +57,8 @@
     @Override
     public BitmapInfo loadIcon(Context context, LauncherActivityInfo object) {
         try (LauncherIcons li = LauncherIcons.obtain(context)) {
-            return li.createBadgedIconBitmap(new IconProvider(context)
-                            .getIcon(object, li.mFillResIconDpi),
+            return li.createBadgedIconBitmap(LauncherAppState.getInstance(context)
+                            .getIconCache().getIconProvider().getIcon(object, li.mFillResIconDpi),
                     object.getUser(), object.getApplicationInfo().targetSdkVersion);
         }
     }
diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
index 76b2ab0..0754c29 100644
--- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
@@ -16,6 +16,8 @@
 
 package com.android.launcher3.model.data;
 
+import static com.android.launcher3.config.FeatureFlags.ENABLE_THEMED_ICONS;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -223,7 +225,15 @@
      * Returns a FastBitmapDrawable with the icon.
      */
     public FastBitmapDrawable newIcon(Context context) {
-        FastBitmapDrawable drawable = bitmap.newIcon(context);
+        return newIcon(context, false);
+    }
+
+    /**
+     * Returns a FastBitmapDrawable with the icon and context theme applied
+     */
+    public FastBitmapDrawable newIcon(Context context, boolean applyTheme) {
+        FastBitmapDrawable drawable = applyTheme && ENABLE_THEMED_ICONS.get()
+                ? bitmap.newThemedIcon(context) : bitmap.newIcon(context);
         drawable.setIsDisabled(isDisabled());
         return drawable;
     }
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 48c5d0a..c19dfe9 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -16,9 +16,9 @@
 
 package com.android.launcher3.popup;
 
+import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
 import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
 import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS;
-import static com.android.launcher3.util.ColorExtractionUtils.getColorExtractionRect;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -31,7 +31,6 @@
 import android.content.res.Resources;
 import android.graphics.Outline;
 import android.graphics.Rect;
-import android.graphics.RectF;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.GradientDrawable;
@@ -42,21 +41,17 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewOutlineProvider;
-import android.view.ViewTreeObserver;
 import android.widget.FrameLayout;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.InsettableFrameLayout;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAnimUtils;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.Workspace;
 import com.android.launcher3.anim.RevealOutlineAnimation;
 import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
 import com.android.launcher3.dragndrop.DragLayer;
@@ -64,11 +59,9 @@
 import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.BaseDragLayer;
-import com.android.launcher3.widget.LocalColorExtractor;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 
 /**
  * A container for shortcuts to deep links and notifications associated with an app.
@@ -80,9 +73,6 @@
 
     // +1 for system shortcut view
     private static final int MAX_NUM_CHILDREN = MAX_SHORTCUTS + 1;
-    // Index used to get background color when using local wallpaper color extraction,
-    private static final int LIGHT_COLOR_EXTRACTION_INDEX = android.R.color.system_accent2_50;
-    private static final int DARK_COLOR_EXTRACTION_INDEX = android.R.color.system_accent2_800;
 
     private final Rect mTempRect = new Rect();
 
@@ -114,14 +104,8 @@
 
     private Runnable mOnCloseCallback = () -> { };
 
-    // The rect string of the view that the arrow is attached to, in screen reference frame.
-    private String mArrowColorRectString;
     private int mArrowColor;
     private final int[] mColors;
-    private final HashMap<String, View> mViewForRect = new HashMap<>();
-
-    private final int mColorExtractionIndex;
-    @Nullable private LocalColorExtractor mColorExtractor;
 
     public ArrowPopup(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
@@ -129,9 +113,7 @@
         mOutlineRadius = Themes.getDialogCornerRadius(context);
         mLauncher = BaseDraggingActivity.fromContext(context);
         mIsRtl = Utilities.isRtl(getResources());
-        mColorExtractionIndex = Utilities.isDarkTheme(context)
-                ? DARK_COLOR_EXTRACTION_INDEX
-                : LIGHT_COLOR_EXTRACTION_INDEX;
+
         setClipToOutline(true);
         setOutlineProvider(new ViewOutlineProvider() {
             @Override
@@ -176,10 +158,6 @@
                 mColors[i] =
                         (int) argb.evaluate((i + 1) * step, primaryColor, secondaryColor);
             }
-
-            if (Utilities.ATLEAST_S) {
-                setupColorExtraction();
-            }
         }
     }
 
@@ -364,15 +342,6 @@
             // so we centered it instead. In that case we don't want to showDefaultOptions the arrow.
             mArrow.setVisibility(INVISIBLE);
         } else {
-            updateArrowColor();
-        }
-
-        mArrow.setPivotX(mArrowWidth / 2.0f);
-        mArrow.setPivotY(mIsAboveIcon ? mArrowHeight : 0);
-    }
-
-    private void updateArrowColor() {
-        if (!Gravity.isVertical(mGravity)) {
             mArrow.setBackground(new RoundedArrowDrawable(
                     mArrowWidth, mArrowHeight, mArrowPointRadius,
                     mOutlineRadius, getMeasuredWidth(), getMeasuredHeight(),
@@ -381,6 +350,9 @@
                     mArrowColor));
             mArrow.setElevation(getElevation());
         }
+
+        mArrow.setPivotX(mArrowWidth / 2.0f);
+        mArrow.setPivotY(mIsAboveIcon ? mArrowHeight : 0);
     }
 
     /**
@@ -699,11 +671,6 @@
         getPopupContainer().removeView(this);
         getPopupContainer().removeView(mArrow);
         mOnCloseCallback.run();
-        mArrowColorRectString = null;
-        mViewForRect.clear();
-        if (mColorExtractor != null) {
-            mColorExtractor.removeLocations();
-        }
     }
 
     /**
@@ -713,68 +680,6 @@
         mOnCloseCallback = callback;
     }
 
-    private void setupColorExtraction() {
-        Workspace workspace = mLauncher.findViewById(R.id.workspace);
-        if (workspace == null) {
-            return;
-        }
-
-        mColorExtractor = LocalColorExtractor.newInstance(mLauncher);
-        mColorExtractor.setListener((rect, extractedColors) -> {
-            String rectString = rect.toShortString();
-            View v = mViewForRect.get(rectString);
-            if (v != null) {
-                int newColor = extractedColors.get(mColorExtractionIndex);
-                setChildColor(v, newColor);
-                if (rectString.equals(mArrowColorRectString)) {
-                    mArrowColor = newColor;
-                    updateArrowColor();
-                }
-            }
-        });
-
-        getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
-            @Override
-            public boolean onPreDraw() {
-                getViewTreeObserver().removeOnPreDrawListener(this);
-
-                ArrayList<RectF> locations = new ArrayList<>();
-                Rect r = new Rect();
-
-                int count = getChildCount();
-                int numVisibleChild = 0;
-                for (int i = 0; i < count; i++) {
-                    View view = getChildAt(i);
-                    if (view.getVisibility() == VISIBLE) {
-                        RectF rf = new RectF();
-                        getColorExtractionRect(Launcher.getLauncher(getContext()),
-                                workspace.getCurrentPage(), view, rf);
-                        if (rf.isEmpty()) {
-                            numVisibleChild++;
-                            continue;
-                        }
-
-                        locations.add(rf);
-                        String rectString = rf.toShortString();
-                        mViewForRect.put(rectString, view);
-
-                        // Arrow color matches the first child or the last child.
-                        if (!mIsAboveIcon && numVisibleChild == 0) {
-                            mArrowColorRectString = rectString;
-                        } else if (mIsAboveIcon) {
-                            mArrowColorRectString = rectString;
-                        }
-
-                        numVisibleChild++;
-                    }
-                }
-
-                mColorExtractor.addLocation(locations);
-                return false;
-            }
-        });
-    }
-
     protected BaseDragLayer getPopupContainer() {
         return mLauncher.getDragLayer();
     }
diff --git a/src/com/android/launcher3/states/StateAnimationConfig.java b/src/com/android/launcher3/states/StateAnimationConfig.java
index 2f26b4f..bd6f7d3 100644
--- a/src/com/android/launcher3/states/StateAnimationConfig.java
+++ b/src/com/android/launcher3/states/StateAnimationConfig.java
@@ -58,8 +58,7 @@
             ANIM_OVERVIEW_TRANSLATE_Y,
             ANIM_OVERVIEW_FADE,
             ANIM_ALL_APPS_FADE,
-            ANIM_WORKSPACE_SCRIM_FADE,
-            ANIM_ALL_APPS_HEADER_FADE,
+            ANIM_SCRIM_FADE,
             ANIM_OVERVIEW_MODAL,
             ANIM_DEPTH,
             ANIM_OVERVIEW_ACTIONS_FADE,
@@ -77,13 +76,12 @@
     public static final int ANIM_OVERVIEW_TRANSLATE_Y = 8;
     public static final int ANIM_OVERVIEW_FADE = 9;
     public static final int ANIM_ALL_APPS_FADE = 10;
-    public static final int ANIM_WORKSPACE_SCRIM_FADE = 11;
-    public static final int ANIM_ALL_APPS_HEADER_FADE = 12; // e.g. predictions
-    public static final int ANIM_OVERVIEW_MODAL = 13;
-    public static final int ANIM_DEPTH = 14;
-    public static final int ANIM_OVERVIEW_ACTIONS_FADE = 15;
+    public static final int ANIM_SCRIM_FADE = 11;
+    public static final int ANIM_OVERVIEW_MODAL = 12;
+    public static final int ANIM_DEPTH = 13;
+    public static final int ANIM_OVERVIEW_ACTIONS_FADE = 14;
 
-    private static final int ANIM_TYPES_COUNT = 16;
+    private static final int ANIM_TYPES_COUNT = 15;
 
     protected final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT];
 
diff --git a/src/com/android/launcher3/util/ColorExtractionUtils.java b/src/com/android/launcher3/util/ColorExtractionUtils.java
deleted file mode 100644
index b377ded..0000000
--- a/src/com/android/launcher3/util/ColorExtractionUtils.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2021 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.util;
-
-import android.content.res.Resources;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.view.View;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.Utilities;
-
-/**
- * Utility class used to map launcher views to wallpaper rect.
- */
-public class ColorExtractionUtils {
-
-    public static final String TAG = "ColorExtractionUtils";
-
-    private static final Rect sTempRect = new Rect();
-    private static final RectF sTempRectF = new RectF();
-
-    /**
-     * Takes a view and returns its rect that can be used by the wallpaper local color extractor.
-     *
-     * @param launcher Launcher class class.
-     * @param pageId The page the workspace item is on.
-     * @param v The view.
-     * @param colorExtractionRectOut The location rect, but converted to a format expected by the
-     *                               wallpaper local color extractor.
-     */
-    public static void getColorExtractionRect(Launcher launcher, int pageId, View v,
-            RectF colorExtractionRectOut) {
-        Rect viewRect = sTempRect;
-        viewRect.set(0, 0, v.getWidth(), v.getHeight());
-        Utilities.getBoundsForViewInDragLayer(launcher.getDragLayer(), v, viewRect, false,
-                sTempRectF);
-        Utilities.setRect(sTempRectF, viewRect);
-        getColorExtractionRect(launcher, pageId, viewRect, colorExtractionRectOut);
-    }
-
-    /**
-     * Takes a rect in drag layer coordinates and returns the rect that can be used by the wallpaper
-     * local color extractor.
-     *
-     * @param launcher Launcher class.
-     * @param pageId The page the workspace item is on.
-     * @param rectInDragLayer The relevant bounds of the view in drag layer coordinates.
-     * @param colorExtractionRectOut The location rect, but converted to a format expected by the
-     *                               wallpaper local color extractor.
-     */
-    public static void getColorExtractionRect(Launcher launcher, int pageId, Rect rectInDragLayer,
-            RectF colorExtractionRectOut) {
-        // If the view hasn't been measured and laid out, we cannot do this.
-        if (rectInDragLayer.isEmpty()) {
-            colorExtractionRectOut.setEmpty();
-            return;
-        }
-
-        Resources res = launcher.getResources();
-        DeviceProfile dp = launcher.getDeviceProfile().inv.getDeviceProfile(launcher);
-        float screenWidth = dp.widthPx;
-        float screenHeight = dp.heightPx;
-        int numScreens = launcher.getWorkspace().getNumPagesForWallpaperParallax();
-        pageId = Utilities.isRtl(res) ? numScreens - pageId - 1 : pageId;
-        float relativeScreenWidth = 1f / numScreens;
-
-        int[] dragLayerBounds = new int[2];
-        launcher.getDragLayer().getLocationOnScreen(dragLayerBounds);
-        // Translate from drag layer coordinates to screen coordinates.
-        int screenLeft = rectInDragLayer.left + dragLayerBounds[0];
-        int screenTop = rectInDragLayer.top + dragLayerBounds[1];
-        int screenRight = rectInDragLayer.right + dragLayerBounds[0];
-        int screenBottom = rectInDragLayer.bottom + dragLayerBounds[1];
-
-        // This is the position of the view relative to the wallpaper, as expected by the
-        // local color extraction of the WallpaperManager.
-        // The coordinate system is such that, on the horizontal axis, each screen has a
-        // distinct range on the [0,1] segment. So if there are 3 screens, they will have the
-        // ranges [0, 1/3], [1/3, 2/3] and [2/3, 1]. The position on the subrange should be
-        // the position of the view relative to the screen. For the vertical axis, this is
-        // simply the location of the view relative to the screen.
-        // Translate from drag layer coordinates to screen coordinates
-        colorExtractionRectOut.left = (screenLeft / screenWidth + pageId) * relativeScreenWidth;
-        colorExtractionRectOut.right = (screenRight / screenWidth + pageId) * relativeScreenWidth;
-        colorExtractionRectOut.top = screenTop / screenHeight;
-        colorExtractionRectOut.bottom = screenBottom / screenHeight;
-
-        if (colorExtractionRectOut.left < 0
-                || colorExtractionRectOut.right > 1
-                || colorExtractionRectOut.top < 0
-                || colorExtractionRectOut.bottom > 1) {
-            colorExtractionRectOut.setEmpty();
-        }
-    }
-}
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
index 06cac08..99942aa 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -22,6 +22,7 @@
 import android.app.WallpaperColors;
 import android.app.WallpaperManager;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.ColorMatrix;
@@ -53,12 +54,16 @@
     }
 
     public static int getActivityThemeRes(Context context, int wallpaperColorHints) {
+        Configuration configuration = context.getResources().getConfiguration();
+        int nightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
+        boolean darkTheme = nightMode == Configuration.UI_MODE_NIGHT_YES;
+
         boolean supportsDarkText = Utilities.ATLEAST_S
                 && (wallpaperColorHints & HINT_SUPPORTS_DARK_TEXT) != 0;
         boolean isMainColorDark = Utilities.ATLEAST_S
                 && (wallpaperColorHints & HINT_SUPPORTS_DARK_THEME) != 0;
 
-        if (Utilities.isDarkTheme(context)) {
+        if (darkTheme) {
             return supportsDarkText ? R.style.AppTheme_Dark_DarkText
                     : isMainColorDark ? R.style.AppTheme_Dark_DarkMainColor : R.style.AppTheme_Dark;
         } else {
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 1ddd1ba..d49320b 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -233,8 +233,15 @@
             outViewBounds.set(0, 0, v.getWidth(), v.getHeight());
         }
 
-        Utilities.getBoundsForViewInDragLayer(launcher.getDragLayer(), v, outViewBounds,
-                ignoreTransform, outRect);
+        float[] points = new float[] {outViewBounds.left, outViewBounds.top, outViewBounds.right,
+                outViewBounds.bottom};
+        Utilities.getDescendantCoordRelativeToAncestor(v, launcher.getDragLayer(), points,
+                false, ignoreTransform);
+        outRect.set(
+                Math.min(points[0], points[2]),
+                Math.min(points[1], points[3]),
+                Math.max(points[0], points[2]),
+                Math.max(points[1], points[3]));
     }
 
     /**
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index 697c453..620604a 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -16,10 +16,6 @@
 
 package com.android.launcher3.widget;
 
-import static com.android.launcher3.Utilities.getBoundsForViewInDragLayer;
-import static com.android.launcher3.Utilities.setRect;
-import static com.android.launcher3.util.ColorExtractionUtils.getColorExtractionRect;
-
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -29,6 +25,7 @@
 import android.graphics.RectF;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.util.Log;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 import android.view.LayoutInflater;
@@ -98,11 +95,11 @@
     private RectF mLastLocationRegistered = null;
     @Nullable private AppWidgetHostViewDragListener mDragListener;
 
-    // Used to store the widget sizes in drag layer coordinates.
+    // Used to store the widget size during onLayout.
     private final Rect mCurrentWidgetSize = new Rect();
     private final Rect mWidgetSizeAtDrag = new Rect();
-
     private final RectF mTempRectF = new RectF();
+    private final boolean mIsRtl;
     private final Rect mEnforcedRectangle = new Rect();
     private final float mEnforcedCornerRadius;
     private final ViewOutlineProvider mCornerRadiusEnforcementOutline = new ViewOutlineProvider() {
@@ -132,6 +129,7 @@
         if (Utilities.ATLEAST_Q && Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText)) {
             setOnLightBackground(true);
         }
+        mIsRtl = Utilities.isRtl(context.getResources());
         mColorExtractor = LocalColorExtractor.newInstance(getContext());
         mColorExtractor.setListener(this);
 
@@ -321,12 +319,13 @@
         mIsScrollable = checkScrollableRecursively(this);
 
         if (!mIsInDragMode && getTag() instanceof LauncherAppWidgetInfo) {
+            mCurrentWidgetSize.left = left;
+            mCurrentWidgetSize.top = top;
+            mCurrentWidgetSize.right = right;
+            mCurrentWidgetSize.bottom = bottom;
             LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) getTag();
-            getBoundsForViewInDragLayer(mLauncher.getDragLayer(), this, mCurrentWidgetSize, true,
-                    mTempRectF);
-            setRect(mTempRectF, mCurrentWidgetSize);
-            updateColorExtraction(mCurrentWidgetSize,
-                    mWorkspace.getPageIndexForScreenId(info.screenId));
+            int pageId = mWorkspace.getPageIndexForScreenId(info.screenId);
+            updateColorExtraction(mCurrentWidgetSize, pageId);
         }
 
         enforceRoundedCorners();
@@ -339,8 +338,8 @@
     }
 
     /** Handles a drag event occurred on a workspace page, {@code pageId}. */
-    public void handleDrag(Rect rectInDragLayer, int pageId) {
-        mWidgetSizeAtDrag.set(rectInDragLayer);
+    public void handleDrag(Rect rect, int pageId) {
+        mWidgetSizeAtDrag.set(rect);
         updateColorExtraction(mWidgetSizeAtDrag, pageId);
     }
 
@@ -352,14 +351,53 @@
         requestLayout();
     }
 
-    /**
-     * @param rectInDragLayer Rect of widget in drag layer coordinates.
-     * @param pageId The workspace page the widget is on.
-     */
-    private void updateColorExtraction(Rect rectInDragLayer, int pageId) {
-        getColorExtractionRect(mLauncher, pageId, rectInDragLayer, mTempRectF);
-
-        if (mTempRectF.isEmpty()) {
+    private void updateColorExtraction(Rect widgetLocation, int pageId) {
+        // If the widget hasn't been measured and laid out, we cannot do this.
+        if (widgetLocation.isEmpty()) {
+            return;
+        }
+        int screenWidth = mLauncher.getDeviceProfile().widthPx;
+        int screenHeight = mLauncher.getDeviceProfile().heightPx;
+        int numScreens = mWorkspace.getNumPagesForWallpaperParallax();
+        pageId = mIsRtl ? numScreens - pageId - 1 : pageId;
+        float relativeScreenWidth = 1f / numScreens;
+        float absoluteTop = widgetLocation.top;
+        float absoluteBottom = widgetLocation.bottom;
+        View v = this;
+        while (v.getParent() instanceof View) {
+            v = (View) v.getParent();
+            if (v.getId() != R.id.launcher) {
+                break;
+            }
+            absoluteBottom += v.getTop();
+            absoluteTop += v.getTop();
+        }
+        float xOffset = 0;
+        View parentView = (View) getParent();
+        // The layout depends on the orientation.
+        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
+            int parentViewWidth = parentView == null ? 0 : parentView.getWidth();
+            xOffset = screenWidth - mWorkspace.getPaddingRight() - parentViewWidth;
+        } else {
+            int parentViewPaddingLeft = parentView == null ? 0 : parentView.getPaddingLeft();
+            xOffset = mWorkspace.getPaddingLeft() + parentViewPaddingLeft;
+        }
+        // This is the position of the widget relative to the wallpaper, as expected by the
+        // local color extraction of the WallpaperManager.
+        // The coordinate system is such that, on the horizontal axis, each screen has a
+        // distinct range on the [0,1] segment. So if there are 3 screens, they will have the
+        // ranges [0, 1/3], [1/3, 2/3] and [2/3, 1]. The position on the subrange should be
+        // the position of the widget relative to the screen. For the vertical axis, this is
+        // simply the location of the widget relative to the screen.
+        mTempRectF.left = ((widgetLocation.left + xOffset) / screenWidth + pageId)
+                * relativeScreenWidth;
+        mTempRectF.right = ((widgetLocation.right + xOffset) / screenWidth + pageId)
+                * relativeScreenWidth;
+        mTempRectF.top = absoluteTop / screenHeight;
+        mTempRectF.bottom = absoluteBottom / screenHeight;
+        if (mTempRectF.left < 0 || mTempRectF.right > 1 || mTempRectF.top < 0
+                || mTempRectF.bottom > 1) {
+            Log.e(LOG_TAG, "   Error, invalid relative position");
             return;
         }
         if (!mTempRectF.equals(mLastLocationRegistered)) {
diff --git a/src/com/android/launcher3/widget/LocalColorExtractor.java b/src/com/android/launcher3/widget/LocalColorExtractor.java
index 2121bc2..be4faea 100644
--- a/src/com/android/launcher3/widget/LocalColorExtractor.java
+++ b/src/com/android/launcher3/widget/LocalColorExtractor.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3.widget;
 
+import android.app.WallpaperColors;
 import android.appwidget.AppWidgetHostView;
 import android.content.Context;
 import android.graphics.RectF;
@@ -44,7 +45,7 @@
     }
 
     /**
-     * Returns a new instance of the LocalColorExtractor.
+     * Creates a new instance of LocalColorExtractor
      */
     public static LocalColorExtractor newInstance(Context context) {
         return Overrides.getObject(LocalColorExtractor.class, context.getApplicationContext(),
@@ -65,4 +66,9 @@
     public void removeLocations() {
         // no-op
     }
+
+    /**
+     * Updates the base context to contain the colors override
+     */
+    public void applyColorsOverride(Context base, WallpaperColors colors) { }
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index ebad154..e5b93b1 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -695,6 +695,7 @@
                         waitUntilLauncherObjectGone(CONTEXT_MENU_RES_ID);
                         // Swiping up can temporarily bring Nexus Launcher if the current
                         // Launcher is a Launcher3 one. Wait for the current launcher to reappear.
+                        SystemClock.sleep(5000); // b/187080582
                         waitForLauncherObject(getAnyObjectSelector());
                     }
                 }