Snap for 7333400 from c71f134ec606856bb8a0a5a1e98670c9adbaa111 to sc-v2-release

Change-Id: Ic7e92c7154d062fb401141786a592ef51dc99792
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/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 910e473..c6c6c01 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -460,7 +460,8 @@
             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
             case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
             case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
-                // Fall through and continue if it's an app or shortcut
+            case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+                // Fall through and continue if it's an app, shortcut, or widget
                 break;
             default:
                 return;
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index fb67645..36764a1 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -60,6 +60,7 @@
 import android.os.Looper;
 import android.os.SystemProperties;
 import android.util.Pair;
+import android.util.Size;
 import android.view.View;
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
@@ -780,7 +781,9 @@
         final float finalWindowRadius = mDeviceProfile.isMultiWindowMode
                 ? 0 : getWindowCornerRadius(mLauncher.getResources());
         final FloatingWidgetView floatingView = FloatingWidgetView.getFloatingWidgetView(mLauncher,
-                v, widgetBackgroundBounds, windowTargetBounds, finalWindowRadius);
+                v, widgetBackgroundBounds,
+                new Size(windowTargetBounds.width(), windowTargetBounds.height()),
+                finalWindowRadius);
         final float initialWindowRadius = supportsRoundedCornersOnWindows(mLauncher.getResources())
                 ? floatingView.getInitialCornerRadius() : 0;
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
index 66e4f4c..5c19ab8 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
@@ -23,6 +23,7 @@
 import android.view.View;
 import android.widget.RemoteViews;
 
+import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.util.ActivityOptionsWrapper;
 import com.android.launcher3.widget.LauncherAppWidgetHostView;
 
@@ -49,6 +50,10 @@
         Pair<Intent, ActivityOptions> options = remoteResponse.getLaunchOptions(hostView);
         ActivityOptionsWrapper activityOptions = mLauncher.getAppTransitionManager()
                 .getActivityLaunchOptions(mLauncher, hostView);
+        Object itemInfo = hostView.getTag();
+        if (itemInfo instanceof ItemInfo) {
+            mLauncher.addLaunchCookie((ItemInfo) itemInfo, activityOptions.options);
+        }
         options = Pair.create(options.first, activityOptions.options);
         return RemoteViews.startPendingIntent(hostView, pendingIntent, options);
     }
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index 2ea34d7..9398277 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -30,9 +30,11 @@
 import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
 import android.content.Context;
+import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.IBinder;
 import android.os.UserHandle;
+import android.util.Size;
 import android.view.View;
 
 import androidx.annotation.NonNull;
@@ -50,9 +52,11 @@
 import com.android.launcher3.util.DynamicResource;
 import com.android.launcher3.util.ObjectWrapper;
 import com.android.launcher3.views.FloatingIconView;
+import com.android.launcher3.widget.LauncherAppWidgetHostView;
 import com.android.quickstep.util.AppCloseConfig;
 import com.android.quickstep.util.RectFSpringAnim;
 import com.android.quickstep.util.StaggeredWorkspaceAnim;
+import com.android.quickstep.views.FloatingWidgetView;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.plugins.ResourceProvider;
@@ -77,155 +81,206 @@
     @Override
     protected HomeAnimationFactory createHomeAnimationFactory(ArrayList<IBinder> launchCookies,
             long duration) {
-        HomeAnimationFactory homeAnimFactory;
-        if (mActivity != null) {
-            final View workspaceView = findWorkspaceView(launchCookies,
-                    mRecentsView.getRunningTaskView());
-            boolean canUseWorkspaceView =
-                    workspaceView != null && workspaceView.isAttachedToWindow();
-
-            mActivity.getRootView().setForceHideBackArrow(true);
-            mActivity.setHintUserWillBeActive();
-
-            if (canUseWorkspaceView) {
-                final ResourceProvider rp = DynamicResource.provider(mActivity);
-                final float transY = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp));
-                float dpPerSecond = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp_per_s));
-                final float launcherAlphaMax =
-                        rp.getFloat(R.dimen.swipe_up_launcher_alpha_max_progress);
-
-                RectF iconLocation = new RectF();
-                FloatingIconView floatingIconView = getFloatingIconView(mActivity, workspaceView,
-                        true /* hideOriginal */, iconLocation, false /* isOpening */);
-
-                // We want the window alpha to be 0 once this threshold is met, so that the
-                // FolderIconView can be seen morphing into the icon shape.
-                float windowAlphaThreshold = 1f - SHAPE_PROGRESS_DURATION;
-                homeAnimFactory = new LauncherHomeAnimationFactory() {
-
-                    // There is a delay in loading the icon, so we need to keep the window
-                    // opaque until it is ready.
-                    private boolean mIsFloatingIconReady = false;
-
-                    private @Nullable ValueAnimator mBounceBackAnimator;
-
-                    @Override
-                    public RectF getWindowTargetRect() {
-                        if (PROTOTYPE_APP_CLOSE.get()) {
-                            // We want the target rect to be at this offset position, so that all
-                            // launcher content can spring back upwards.
-                            floatingIconView.setPositionOffsetY(transY);
-                        }
-                        return iconLocation;
-                    }
-
-                    @Override
-                    public void setAnimation(RectFSpringAnim anim) {
-                        anim.addAnimatorListener(floatingIconView);
-                        floatingIconView.setOnTargetChangeListener(anim::onTargetPositionChanged);
-                        floatingIconView.setFastFinishRunnable(anim::end);
-                        if (PROTOTYPE_APP_CLOSE.get()) {
-                            mBounceBackAnimator = bounceBackToRestingPosition();
-                            // Use a spring to put drag layer translation back to 0.
-                            anim.addAnimatorListener(new AnimatorListenerAdapter() {
-                                @Override
-                                public void onAnimationEnd(Animator animation) {
-                                    floatingIconView.setPositionOffsetY(0);
-                                    mBounceBackAnimator.start();
-                                }
-                            });
-
-                            Workspace workspace = mActivity.getWorkspace();
-                            workspace.setPivotToScaleWithSelf(mActivity.getHotseat());
-                        }
-                    }
-
-                    private ValueAnimator bounceBackToRestingPosition() {
-                        DragLayer dl = mActivity.getDragLayer();
-                        Workspace workspace = mActivity.getWorkspace();
-                        Hotseat hotseat = mActivity.getHotseat();
-
-                        final float startValue = transY;
-                        final float endValue = 0;
-                        // Ensures the velocity is always aligned with the direction.
-                        float pixelPerSecond = Math.abs(dpPerSecond)
-                                * Math.signum(endValue - transY);
-
-                        ValueAnimator springTransY = new SpringAnimationBuilder(dl.getContext())
-                                .setStiffness(rp.getFloat(R.dimen.swipe_up_trans_y_stiffness))
-                                .setDampingRatio(rp.getFloat(R.dimen.swipe_up_trans_y_damping))
-                                .setMinimumVisibleChange(1f)
-                                .setStartValue(startValue)
-                                .setEndValue(endValue)
-                                .setStartVelocity(pixelPerSecond)
-                                .build(dl, VIEW_TRANSLATE_Y);
-                        springTransY.addListener(new AnimatorListenerAdapter() {
-                            @Override
-                            public void onAnimationEnd(Animator animation) {
-                                dl.setTranslationY(0f);
-                                dl.setAlpha(1f);
-                                SCALE_PROPERTY.set(workspace, 1f);
-                                SCALE_PROPERTY.set(hotseat, 1f);
-                            }
-                        });
-                        return springTransY;
-                    }
-
-                    @Override
-                    public boolean keepWindowOpaque() {
-                        if (mIsFloatingIconReady || floatingIconView.isVisibleToUser()) {
-                            mIsFloatingIconReady = true;
-                            return false;
-                        }
-                        return true;
-                    }
-
-                    @Override
-                    public void update(@Nullable AppCloseConfig config, RectF currentRect,
-                            float progress, float radius) {
-                        int fgAlpha = 255;
-                        if (config != null && PROTOTYPE_APP_CLOSE.get()) {
-                            DragLayer dl = mActivity.getDragLayer();
-                            float translationY = config.getWorkspaceTransY();
-                            dl.setTranslationY(translationY);
-
-                            float alpha = mapToRange(progress, 0, launcherAlphaMax, 0, 1f, LINEAR);
-                            dl.setAlpha(Math.min(alpha, 1f));
-
-                            float scale = Math.min(1f, config.getWorkspaceScale());
-                            SCALE_PROPERTY.set(mActivity.getWorkspace(), scale);
-                            SCALE_PROPERTY.set(mActivity.getHotseat(), scale);
-                            SCALE_PROPERTY.set(mActivity.getAppsView(), scale);
-
-                            progress = config.getInterpolatedProgress();
-                            fgAlpha = config.getFgAlpha();
-                        }
-                        floatingIconView.update(1f, fgAlpha, currentRect, progress,
-                                windowAlphaThreshold, radius, false);
-                    }
-
-                    @Override
-                    public void onCancel() {
-                        floatingIconView.fastFinish();
-                        if (mBounceBackAnimator != null) {
-                            mBounceBackAnimator.cancel();
-                        }
-                    }
-                };
-            } else {
-                homeAnimFactory = new LauncherHomeAnimationFactory();
-            }
-        } else {
-            homeAnimFactory = new HomeAnimationFactory() {
+        if (mActivity == null) {
+            mStateCallback.addChangeListener(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
+                    isPresent -> mRecentsView.startHome());
+            return new HomeAnimationFactory() {
                 @Override
                 public AnimatorPlaybackController createActivityAnimationToHome() {
                     return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
                 }
             };
-            mStateCallback.addChangeListener(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
-                    isPresent -> mRecentsView.startHome());
         }
-        return homeAnimFactory;
+
+        final View workspaceView = findWorkspaceView(launchCookies,
+                mRecentsView.getRunningTaskView());
+        boolean canUseWorkspaceView = workspaceView != null && workspaceView.isAttachedToWindow();
+
+        mActivity.getRootView().setForceHideBackArrow(true);
+        mActivity.setHintUserWillBeActive();
+
+        if (!canUseWorkspaceView) {
+            return new LauncherHomeAnimationFactory();
+        }
+        if (workspaceView instanceof LauncherAppWidgetHostView) {
+            return createWidgetHomeAnimationFactory((LauncherAppWidgetHostView) workspaceView);
+        }
+        return createIconHomeAnimationFactory(workspaceView);
+    }
+
+    private HomeAnimationFactory createIconHomeAnimationFactory(View workspaceView) {
+        final ResourceProvider rp = DynamicResource.provider(mActivity);
+        final float transY = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp));
+        float dpPerSecond = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp_per_s));
+        final float launcherAlphaMax =
+                rp.getFloat(R.dimen.swipe_up_launcher_alpha_max_progress);
+
+        RectF iconLocation = new RectF();
+        FloatingIconView floatingIconView = getFloatingIconView(mActivity, workspaceView,
+                true /* hideOriginal */, iconLocation, false /* isOpening */);
+
+        // We want the window alpha to be 0 once this threshold is met, so that the
+        // FolderIconView can be seen morphing into the icon shape.
+        float windowAlphaThreshold = 1f - SHAPE_PROGRESS_DURATION;
+        return new LauncherHomeAnimationFactory() {
+
+            // There is a delay in loading the icon, so we need to keep the window
+            // opaque until it is ready.
+            private boolean mIsFloatingIconReady = false;
+
+            private @Nullable ValueAnimator mBounceBackAnimator;
+
+            @Override
+            public RectF getWindowTargetRect() {
+                if (PROTOTYPE_APP_CLOSE.get()) {
+                    // We want the target rect to be at this offset position, so that all
+                    // launcher content can spring back upwards.
+                    floatingIconView.setPositionOffsetY(transY);
+                }
+                return iconLocation;
+            }
+
+            @Override
+            public void setAnimation(RectFSpringAnim anim) {
+                anim.addAnimatorListener(floatingIconView);
+                floatingIconView.setOnTargetChangeListener(anim::onTargetPositionChanged);
+                floatingIconView.setFastFinishRunnable(anim::end);
+                if (PROTOTYPE_APP_CLOSE.get()) {
+                    mBounceBackAnimator = bounceBackToRestingPosition();
+                    // Use a spring to put drag layer translation back to 0.
+                    anim.addAnimatorListener(new AnimatorListenerAdapter() {
+                        @Override
+                        public void onAnimationEnd(Animator animation) {
+                            floatingIconView.setPositionOffsetY(0);
+                            mBounceBackAnimator.start();
+                        }
+                    });
+
+                    Workspace workspace = mActivity.getWorkspace();
+                    workspace.setPivotToScaleWithSelf(mActivity.getHotseat());
+                }
+            }
+
+            private ValueAnimator bounceBackToRestingPosition() {
+                DragLayer dl = mActivity.getDragLayer();
+                Workspace workspace = mActivity.getWorkspace();
+                Hotseat hotseat = mActivity.getHotseat();
+
+                final float startValue = transY;
+                final float endValue = 0;
+                // Ensures the velocity is always aligned with the direction.
+                float pixelPerSecond = Math.abs(dpPerSecond) * Math.signum(endValue - transY);
+
+                ValueAnimator springTransY = new SpringAnimationBuilder(dl.getContext())
+                        .setStiffness(rp.getFloat(R.dimen.swipe_up_trans_y_stiffness))
+                        .setDampingRatio(rp.getFloat(R.dimen.swipe_up_trans_y_damping))
+                        .setMinimumVisibleChange(1f)
+                        .setStartValue(startValue)
+                        .setEndValue(endValue)
+                        .setStartVelocity(pixelPerSecond)
+                        .build(dl, VIEW_TRANSLATE_Y);
+                springTransY.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        dl.setTranslationY(0f);
+                        dl.setAlpha(1f);
+                        SCALE_PROPERTY.set(workspace, 1f);
+                        SCALE_PROPERTY.set(hotseat, 1f);
+                    }
+                });
+                return springTransY;
+            }
+
+            @Override
+            public boolean keepWindowOpaque() {
+                if (mIsFloatingIconReady || floatingIconView.isVisibleToUser()) {
+                    mIsFloatingIconReady = true;
+                    return false;
+                }
+                return true;
+            }
+
+            @Override
+            public void update(@Nullable AppCloseConfig config, RectF currentRect,
+                    float progress, float radius) {
+                int fgAlpha = 255;
+                if (config != null && PROTOTYPE_APP_CLOSE.get()) {
+                    DragLayer dl = mActivity.getDragLayer();
+                    float translationY = config.getWorkspaceTransY();
+                    dl.setTranslationY(translationY);
+
+                    float alpha = mapToRange(progress, 0, launcherAlphaMax, 0, 1f, LINEAR);
+                    dl.setAlpha(Math.min(alpha, 1f));
+
+                    float scale = Math.min(1f, config.getWorkspaceScale());
+                    SCALE_PROPERTY.set(mActivity.getWorkspace(), scale);
+                    SCALE_PROPERTY.set(mActivity.getHotseat(), scale);
+                    SCALE_PROPERTY.set(mActivity.getAppsView(), scale);
+
+                    progress = config.getInterpolatedProgress();
+                    fgAlpha = config.getFgAlpha();
+                }
+                floatingIconView.update(1f, fgAlpha, currentRect, progress,
+                        windowAlphaThreshold, radius, false);
+            }
+
+            @Override
+            public void onCancel() {
+                floatingIconView.fastFinish();
+                if (mBounceBackAnimator != null) {
+                    mBounceBackAnimator.cancel();
+                }
+            }
+        };
+    }
+
+    private HomeAnimationFactory createWidgetHomeAnimationFactory(
+            LauncherAppWidgetHostView hostView) {
+
+        RectF backgroundLocation = new RectF();
+        Rect crop = new Rect();
+        mTaskViewSimulator.getCurrentCropRect().roundOut(crop);
+        Size windowSize = new Size(crop.width(), crop.height());
+        FloatingWidgetView floatingWidgetView = FloatingWidgetView.getFloatingWidgetView(mActivity,
+                hostView, backgroundLocation, windowSize,
+                mTaskViewSimulator.getCurrentCornerRadius());
+
+        return new LauncherHomeAnimationFactory() {
+
+            @Override
+            public RectF getWindowTargetRect() {
+                return backgroundLocation;
+            }
+
+            @Override
+            public float getEndRadius(RectF cropRectF) {
+                return floatingWidgetView.getInitialCornerRadius();
+            }
+
+            @Override
+            public void setAnimation(RectFSpringAnim anim) {
+                anim.addAnimatorListener(floatingWidgetView);
+                floatingWidgetView.setFastFinishRunnable(anim::end);
+            }
+
+            @Override
+            public boolean keepWindowOpaque() {
+                return false;
+            }
+
+            @Override
+            public void update(@Nullable AppCloseConfig config, RectF currentRect,
+                    float progress, float radius) {
+                floatingWidgetView.update(currentRect, 1 /* floatingWidgetAlpha */,
+                        config != null ? config.getFgAlpha() : 1f /* foregroundAlpha */,
+                        0 /* fallbackBackgroundAlpha */, 1 - progress);
+            }
+
+            @Override
+            public void onCancel() {
+                floatingWidgetView.fastFinish();
+            }
+        };
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index 0f34a72..29a00d1 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -145,6 +145,11 @@
                     targetX + halfIconSize, targetY + halfIconSize);
         }
 
+        /** Returns the corner radius of the window at the end of the animation. */
+        public float getEndRadius(RectF cropRectF) {
+            return cropRectF.width() / 2f;
+        }
+
         public abstract @NonNull AnimatorPlaybackController createActivityAnimationToHome();
 
         public void playAtomicAnimation(float velocity) {
@@ -197,8 +202,7 @@
         final RectF targetRect = homeAnimationFactory.getWindowTargetRect();
 
         Matrix homeToWindowPositionMap = new Matrix();
-        final RectF startRect = updateProgressForStartRect(
-                homeToWindowPositionMap, startProgress);
+        final RectF startRect = updateProgressForStartRect(homeToWindowPositionMap, startProgress);
         RectF cropRectF = new RectF(mTaskViewSimulator.getCurrentCropRect());
 
         // Move the startRect to Launcher space as floatingIconView runs in Launcher
@@ -210,7 +214,7 @@
         if (PROTOTYPE_APP_CLOSE.get()) {
             anim = new RectFSpringAnim2(startRect, targetRect, mContext,
                     mTaskViewSimulator.getCurrentCornerRadius(),
-                    cropRectF.width() / 2f);
+                    homeAnimationFactory.getEndRadius(cropRectF));
         } else {
             anim = new RectFSpringAnim(startRect, targetRect, mContext);
         }
@@ -269,7 +273,7 @@
             // End on a "round-enough" radius so that the shape reveal doesn't have to do too much
             // rounding at the end of the animation.
             mStartRadius = mTaskViewSimulator.getCurrentCornerRadius();
-            mEndRadius = cropRectF.width() / 2f;
+            mEndRadius = factory.getEndRadius(cropRectF);
         }
 
         @Override
diff --git a/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
index d23884c..8499902 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
@@ -20,10 +20,10 @@
 import android.annotation.TargetApi;
 import android.content.Context;
 import android.graphics.Matrix;
-import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.Build;
 import android.util.AttributeSet;
+import android.util.Size;
 import android.view.GhostView;
 import android.view.View;
 import android.view.ViewGroup;
@@ -113,7 +113,7 @@
     }
 
     private void init(DragLayer dragLayer, LauncherAppWidgetHostView originalView,
-            RectF widgetBackgroundPosition, Rect windowTargetBounds, float windowCornerRadius) {
+            RectF widgetBackgroundPosition, Size windowSize, float windowCornerRadius) {
         mAppWidgetView = originalView;
         mAppWidgetView.beginDeferringUpdates();
         mBackgroundPosition = widgetBackgroundPosition;
@@ -128,7 +128,7 @@
         getRelativePosition(mAppWidgetBackgroundView, mAppWidgetView, mBackgroundOffset);
         mBackgroundView.init(mAppWidgetView, mAppWidgetBackgroundView, windowCornerRadius);
         // Layout call before GhostView creation so that the overlaid view isn't clipped
-        layout(0, 0, windowTargetBounds.width(), windowTargetBounds.height());
+        layout(0, 0, windowSize.getWidth(), windowSize.getHeight());
         mForegroundOverlayView = GhostView.addGhost(mAppWidgetView, this);
         positionViews();
 
@@ -219,19 +219,19 @@
      *
      * @param widgetBackgroundPosition a {@link RectF} that will be updated with the widget's
      *                                 background bounds
-     * @param windowTargetBounds       the bounds of the window when launched
+     * @param windowSize               the size of the window when launched
      * @param windowCornerRadius       the corner radius of the window
      */
     public static FloatingWidgetView getFloatingWidgetView(Launcher launcher,
             LauncherAppWidgetHostView originalView, RectF widgetBackgroundPosition,
-            Rect windowTargetBounds, float windowCornerRadius) {
+            Size windowSize, float windowCornerRadius) {
         final DragLayer dragLayer = launcher.getDragLayer();
         ViewGroup parent = (ViewGroup) dragLayer.getParent();
         FloatingWidgetView floatingView =
                 launcher.getViewCache().getView(R.layout.floating_widget_view, launcher, parent);
         floatingView.recycle();
 
-        floatingView.init(dragLayer, originalView, widgetBackgroundPosition, windowTargetBounds,
+        floatingView.init(dragLayer, originalView, widgetBackgroundPosition, windowSize,
                 windowCornerRadius);
         parent.addView(floatingView);
         return floatingView;
@@ -240,7 +240,7 @@
     private static void getRelativePosition(View descendant, View ancestor, RectF position) {
         float[] points = new float[]{0, 0, descendant.getWidth(), descendant.getHeight()};
         Utilities.getDescendantCoordRelativeToAncestor(descendant, ancestor, points,
-                false /* includeRootScroll */);
+                false /* includeRootScroll */, true /* ignoreTransform */);
         position.set(
                 Math.min(points[0], points[2]),
                 Math.min(points[1], points[3]),
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index c9e7a73..53f880f 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -2481,6 +2481,15 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
+        if (LIVE_TILE.get() && mRunningTaskId != -1) {
+            switchToScreenshot(
+                    () -> finishRecentsAnimation(true, this::onConfigurationChangedInternal));
+        } else {
+            onConfigurationChangedInternal();
+        }
+    }
+
+    private void onConfigurationChangedInternal() {
         final int rotation = mActivity.getDisplay().getRotation();
         if (mOrientationState.setRecentsRotation(rotation)) {
             updateOrientationHandler();
@@ -3433,7 +3442,7 @@
      * capturing the snapshot at the same time.
      */
     public void switchToScreenshot(Runnable onFinishRunnable) {
-        switchToScreenshot(mRunningTaskId == -1 ? null
+        switchToScreenshot(mRecentsAnimationController == null || mRunningTaskId == -1 ? null
                 : mRecentsAnimationController.screenshotTask(mRunningTaskId), onFinishRunnable);
     }
 
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 3349b74..45bcdc3 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -777,8 +777,7 @@
         float upperClamp = invert ? 1 : iconScalePercentage;
         float scale = Interpolators.clampToProgress(FAST_OUT_SLOW_IN, lowerClamp, upperClamp)
                 .getInterpolation(progress);
-        mIconView.setScaleX(scale);
-        mIconView.setScaleY(scale);
+        mIconView.setAlpha(scale);
         if (mContextualChipWrapper != null && mContextualChipWrapper != null) {
             mContextualChipWrapper.setAlpha(scale);
             mContextualChipWrapper.setScaleX(Math.min(scale, comp(mModalness)));
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/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..a799b4a 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;
@@ -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();
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/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/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 898ac25..99942aa 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -19,8 +19,10 @@
 import static android.app.WallpaperColors.HINT_SUPPORTS_DARK_TEXT;
 import static android.app.WallpaperColors.HINT_SUPPORTS_DARK_THEME;
 
+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;
@@ -40,19 +42,28 @@
 public class Themes {
 
     public static int getActivityThemeRes(Context context) {
-        int colorHints = Utilities.ATLEAST_P ? context.getSystemService(WallpaperManager.class)
-                .getWallpaperColors(WallpaperManager.FLAG_SYSTEM).getColorHints()
-                : 0;
+        final int colorHints;
+        if (Utilities.ATLEAST_P) {
+            WallpaperColors colors = context.getSystemService(WallpaperManager.class)
+                    .getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
+            colorHints = colors == null ? 0 : colors.getColorHints();
+        } else {
+            colorHints = 0;
+        }
         return getActivityThemeRes(context, colorHints);
     }
 
     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..097158b 100644
--- a/src/com/android/launcher3/widget/LocalColorExtractor.java
+++ b/src/com/android/launcher3/widget/LocalColorExtractor.java
@@ -43,10 +43,7 @@
         void onColorsChanged(RectF rect, SparseIntArray extractedColors);
     }
 
-    /**
-     * Returns a new instance of the LocalColorExtractor.
-     */
-    public static LocalColorExtractor newInstance(Context context) {
+    static LocalColorExtractor newInstance(Context context) {
         return Overrides.getObject(LocalColorExtractor.class, context.getApplicationContext(),
                 R.string.local_colors_extraction_class);
     }