Merge "Add funtional animation for SplitSelect from Grid." into sc-dev
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index 842abc3..7ab09c5 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -103,16 +103,40 @@
              android:clearTaskOnLaunch="true"
              android:exported="false"/>
 
+        <!--
+        Activity for gesture nav onboarding.
+        It's protected by android.permission.REBOOT to ensure that only system apps can start it
+        (setup wizard already has this permission)
+        -->
         <activity android:name="com.android.quickstep.interaction.GestureSandboxActivity"
-             android:autoRemoveFromRecents="true"
-             android:excludeFromRecents="true"
-             android:screenOrientation="portrait"
-             android:exported="true">
+            android:autoRemoveFromRecents="true"
+            android:excludeFromRecents="true"
+            android:screenOrientation="portrait"
+            android:permission="android.permission.REBOOT"
+            android:exported="true">
             <intent-filter>
                 <action android:name="com.android.quickstep.action.GESTURE_SANDBOX"/>
                 <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
         </activity>
+
+        <!--
+        Activity following gesture nav onboarding.
+        It's protected by android.permission.REBOOT to ensure that only system apps can start it
+        (setup wizard already has this permission)
+        -->
+        <activity android:name="com.android.quickstep.interaction.AllSetActivity"
+            android:autoRemoveFromRecents="true"
+            android:excludeFromRecents="true"
+            android:screenOrientation="portrait"
+            android:permission="android.permission.REBOOT"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="com.android.quickstep.action.GESTURE_ONBOARDING_ALL_SET"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+
         <activity
             android:name=".hybridhotseat.HotseatEduActivity"
             android:theme="@android:style/Theme.NoDisplay"
diff --git a/quickstep/res/drawable/ic_all_set.xml b/quickstep/res/drawable/ic_all_set.xml
new file mode 100644
index 0000000..a6852aa
--- /dev/null
+++ b/quickstep/res/drawable/ic_all_set.xml
@@ -0,0 +1,24 @@
+<!--
+     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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="42dp"
+    android:height="40dp"
+    android:viewportWidth="42"
+    android:viewportHeight="40">
+    <path
+        android:pathData="M38,14H25.38L27.28,4.86L27.34,4.22C27.34,3.4 27,2.64 26.46,2.1L24.34,0C24.34,0 10.16,13.7 10,14H0V40H32C33.66,40 35.08,39 35.68,37.56L41.72,23.46C41.9,23 42,22.52 42,22V18C42,15.8 40.2,14 38,14ZM10,36H4V18H10V36ZM38,22L32,36H14V16L22.68,7.32L20,18H38V22Z"
+        android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/quickstep/res/layout/activity_allset.xml b/quickstep/res/layout/activity_allset.xml
new file mode 100644
index 0000000..a6a17e5
--- /dev/null
+++ b/quickstep/res/layout/activity_allset.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingStart="@dimen/allset_page_margin_horizontal"
+    android:paddingEnd="@dimen/allset_page_margin_horizontal"
+    android:layoutDirection="locale"
+    android:textDirection="locale"
+    android:background="?android:attr/colorBackground">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_gravity="start"
+        android:gravity="start"
+        android:orientation="vertical">
+
+        <ImageView
+            android:id="@+id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/allset_title_icon_margin_top"
+            android:src="@drawable/ic_all_set"/>
+
+        <TextView
+            android:id="@+id/title"
+            style="@style/TextAppearance.GestureTutorial.Feedback.Title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/allset_title_margin_top"
+            android:gravity="start"
+            android:text="@string/allset_title"/>
+
+        <TextView
+            android:id="@+id/subtitle"
+            style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/allset_subtitle_margin_top"
+            android:gravity="start"
+            android:text="@string/allset_description"/>
+    </LinearLayout>
+
+    <TextView
+        android:id="@+id/navigation_settings"
+        style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle"
+        android:textSize="14sp"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_above="@+id/hint"
+        android:gravity="center_horizontal"
+        android:layout_marginBottom="72dp"/>
+
+    <TextView
+        android:id="@id/hint"
+        style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle"
+        android:textSize="14sp"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="@dimen/allset_hint_margin_bottom"
+        android:layout_alignParentBottom="true"
+        android:layout_centerHorizontal="true"
+        android:text="@string/allset_hint"/>
+</RelativeLayout>
diff --git a/quickstep/res/values/attrs.xml b/quickstep/res/values/attrs.xml
new file mode 100644
index 0000000..336fb57
--- /dev/null
+++ b/quickstep/res/values/attrs.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<resources>
+    <declare-styleable name="AllSetLinkSpan">
+        <attr name="android:textSize"/>
+        <attr name="android:fontFamily"/>
+    </declare-styleable>
+</resources>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 9c0a083..4f9b3eb 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -99,6 +99,13 @@
     <dimen name="gesture_tutorial_feedback_margin_start_end">24dp</dimen>
     <dimen name="gesture_tutorial_button_margin_start_end">18dp</dimen>
 
+    <!-- All Set page -->
+    <dimen name="allset_page_margin_horizontal">40dp</dimen>
+    <dimen name="allset_title_margin_top">28dp</dimen>
+    <dimen name="allset_title_icon_margin_top">80dp</dimen>
+    <dimen name="allset_hint_margin_bottom">52dp</dimen>
+    <dimen name="allset_subtitle_margin_top">24dp</dimen>
+
     <!-- All Apps Education tutorial -->
     <dimen name="swipe_edu_padding">8dp</dimen>
     <dimen name="swipe_edu_circle_size">64dp</dimen>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index a0f1638..7ada496 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -177,6 +177,15 @@
     <!-- Feedback subtext displaying the current step and the total number of steps for the tutorial. [CHAR LIMIT=30] -->
     <string name="gesture_tutorial_step">Tutorial <xliff:g id="current">%1$d</xliff:g>/<xliff:g id="total">%2$d</xliff:g></string>
 
+    <!-- Title of "All Set" page [CHAR LIMIT=NONE] -->
+    <string name="allset_title">All set!</string>
+    <!-- Hint string at the bottom of "All Set" page [CHAR LIMIT=NONE] -->
+    <string name="allset_hint">Swipe up to go home</string>
+    <!-- Description of "All Set" page [CHAR LIMIT=NONE] -->
+    <string name="allset_description">You\u2019re ready to start using your phone</string>
+    <!-- String linking to navigation settings on "All Set" page [CHAR LIMIT=NONE] -->
+    <string name="allset_navigation_settings"><annotation id="link">Navigation settings for accessibility</annotation></string>
+
     <!-- ******* Overview ******* -->
     <!-- Label for a button that causes the current overview app to be shared. [CHAR_LIMIT=40] -->
     <string name="action_share">Share</string>
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index 7c7d20a..0a8ecb8 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -59,7 +59,7 @@
         parent="TextAppearance.GestureTutorial">
         <item name="android:gravity">start</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
-        <item name="android:fontFamily">google-sans</item>
+        <item name="android:fontFamily">google-sans-text</item>
         <item name="android:letterSpacing">0.03</item>
         <item name="android:textSize">18sp</item>
         <item name="android:lineHeight">24sp</item>
@@ -99,6 +99,11 @@
         <item name="android:textColor">@color/gesture_tutorial_primary_color</item>
     </style>
 
+    <style name="TextAppearance.GestureTutorial.LinkText"
+        parent="TextAppearance.GestureTutorial.Feedback.Subtitle">
+        <item name="android:textSize">14sp</item>
+    </style>
+
     <!--
       Can be applied to views to color things like ripples and list highlights the workspace text
       color.
diff --git a/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java b/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
index 70a143e..7c97b93 100644
--- a/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
+++ b/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
@@ -36,6 +36,7 @@
 
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.icons.ComponentWithLabel;
 import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.model.BgDataModel.FixedContainerItems;
@@ -44,6 +45,7 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.shadows.ShadowDeviceFlag;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.ItemInfoMatcher;
@@ -60,6 +62,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
 import org.robolectric.shadows.ShadowAppWidgetManager;
 import org.robolectric.shadows.ShadowPackageManager;
 import org.robolectric.util.ReflectionHelpers;
@@ -174,6 +177,41 @@
         assertWidgetInfo(recommendedWidgets.get(2).info, mApp1Provider1);
     }
 
+    @Test
+    public void widgetsRecommendationRan_localFilterDisabled_shouldReturnWidgetsInPredicationOrder()
+            throws Exception {
+        ShadowDeviceFlag shadowDeviceFlag = Shadow.extract(
+                FeatureFlags.ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER);
+        shadowDeviceFlag.setValue(false);
+
+        // WHEN newPredicationTask is executed with 5 predicated widgets.
+        AppTarget widget1 = new AppTarget(new AppTargetId("app1"), "app1", "provider1",
+                mUserHandle);
+        AppTarget widget2 = new AppTarget(new AppTargetId("app1"), "app1", "provider2",
+                mUserHandle);
+        // Not installed app
+        AppTarget widget3 = new AppTarget(new AppTargetId("app2"), "app3", "provider1",
+                mUserHandle);
+        // Not installed widget
+        AppTarget widget4 = new AppTarget(new AppTargetId("app4"), "app4", "provider3",
+                mUserHandle);
+        AppTarget widget5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1",
+                mUserHandle);
+        mModelHelper.executeTaskForTest(
+                newWidgetsPredicationTask(List.of(widget5, widget3, widget2, widget4, widget1)))
+                .forEach(Runnable::run);
+
+        // THEN only 3 widgets are returned because the launcher only filters out non-exist widgets.
+        List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
+                .stream()
+                .map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
+                .collect(Collectors.toList());
+        assertThat(recommendedWidgets).hasSize(3);
+        assertWidgetInfo(recommendedWidgets.get(0).info, mApp5Provider1);
+        assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider2);
+        assertWidgetInfo(recommendedWidgets.get(2).info, mApp1Provider1);
+    }
+
     private void assertWidgetInfo(
             LauncherAppWidgetProviderInfo actual, AppWidgetProviderInfo expected) {
         assertThat(actual.provider).isEqualTo(expected.provider);
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index c6c6c01..cd22196 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -19,7 +19,7 @@
 import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
 import static com.android.launcher3.LauncherState.FLAG_HIDE_BACK_BUTTON;
 import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.util.DisplayController.CHANGE_SIZE;
+import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
@@ -240,7 +240,7 @@
     public void onDisplayInfoChanged(Context context, DisplayController.Info info,
             int flags) {
         super.onDisplayInfoChanged(context, info, flags);
-        if ((flags & CHANGE_SIZE) != 0) {
+        if ((flags & CHANGE_ACTIVE_SCREEN) != 0) {
             addTaskbarIfNecessary();
         }
     }
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index cc3ccea..6d5975f 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -33,7 +33,6 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
 import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
 import com.android.launcher3.allapps.FloatingHeaderRow;
 import com.android.launcher3.allapps.FloatingHeaderView;
@@ -80,9 +79,9 @@
         setOrientation(LinearLayout.HORIZONTAL);
 
         mFocusHelper = new SimpleFocusIndicatorHelper(this);
-        mNumPredictedAppsPerRow = LauncherAppState.getIDP(context).numAllAppsColumns;
         mLauncher = Launcher.getLauncher(context);
         mLauncher.addOnDeviceProfileChangeListener(this);
+        mNumPredictedAppsPerRow = mLauncher.getDeviceProfile().numShownAllAppsColumns;
         updateVisibility();
     }
 
@@ -174,7 +173,7 @@
 
     @Override
     public void onDeviceProfileChanged(DeviceProfile dp) {
-        mNumPredictedAppsPerRow = dp.inv.numAllAppsColumns;
+        mNumPredictedAppsPerRow = dp.numShownAllAppsColumns;
         removeAllViews();
         applyPredictionApps();
     }
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index 8c68872..b0c13f9 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -104,8 +104,8 @@
         // TODO: Implement caching and preloading
         super.loadItems(ums, pinnedShortcuts);
 
-        WorkspaceItemFactory allAppsFactory =
-                new WorkspaceItemFactory(mApp, ums, pinnedShortcuts, mIDP.numAllAppsColumns);
+        WorkspaceItemFactory allAppsFactory = new WorkspaceItemFactory(
+                mApp, ums, pinnedShortcuts, mIDP.numDatabaseAllAppsColumns);
         mAllAppsState.items.setItems(
                 mAllAppsState.storage.read(mApp.getContext(), allAppsFactory, ums.allUsers::get));
         mDataModel.extraItems.put(CONTAINER_PREDICTION, mAllAppsState.items);
@@ -204,7 +204,7 @@
         registerPredictor(mAllAppsState, apm.createAppPredictionSession(
                 new AppPredictionContext.Builder(context)
                         .setUiSurface("home")
-                        .setPredictedTargetCount(mIDP.numAllAppsColumns)
+                        .setPredictedTargetCount(mIDP.numDatabaseAllAppsColumns)
                         .build()));
 
         // TODO: get bundle
diff --git a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
index a29ac1a..22a8c9b 100644
--- a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
@@ -16,16 +16,17 @@
 package com.android.launcher3.model;
 
 import android.app.prediction.AppTarget;
+import android.content.ComponentName;
+import android.text.TextUtils;
 
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.BgDataModel.FixedContainerItems;
 import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
-import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.PackageUserKey;
 import com.android.launcher3.widget.PendingAddWidgetInfo;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -56,25 +57,43 @@
         Map<PackageUserKey, List<WidgetItem>> allWidgets =
                 dataModel.widgetsModel.getAllWidgetsWithoutShortcuts();
 
-        ArrayList<ItemInfo> recommendedWidgetsInDescendingOrder = new ArrayList<>();
-        for (AppTarget app : mTargets) {
-            PackageUserKey packageUserKey = new PackageUserKey(app.getPackageName(), app.getUser());
-            if (allWidgets.containsKey(packageUserKey)) {
-                List<WidgetItem> notAddedWidgets = allWidgets.get(packageUserKey).stream()
-                        .filter(item ->
-                                !widgetsInWorkspace.contains(
-                                        new ComponentKey(item.componentName, item.user)))
-                        .collect(Collectors.toList());
-                if (notAddedWidgets.size() > 0) {
-                    // Even an apps have more than one widgets, we only include one widget.
-                    recommendedWidgetsInDescendingOrder.add(
-                            new PendingAddWidgetInfo(notAddedWidgets.get(0).widgetInfo));
+        FixedContainerItems fixedContainerItems = mPredictorState.items;
+        fixedContainerItems.items.clear();
+
+        if (FeatureFlags.ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER.get()) {
+            for (AppTarget app : mTargets) {
+                PackageUserKey packageUserKey = new PackageUserKey(app.getPackageName(),
+                        app.getUser());
+                if (allWidgets.containsKey(packageUserKey)) {
+                    List<WidgetItem> notAddedWidgets = allWidgets.get(packageUserKey).stream()
+                            .filter(item ->
+                                    !widgetsInWorkspace.contains(
+                                            new ComponentKey(item.componentName, item.user)))
+                            .collect(Collectors.toList());
+                    if (notAddedWidgets.size() > 0) {
+                        // Even an apps have more than one widgets, we only include one widget.
+                        fixedContainerItems.items.add(
+                                new PendingAddWidgetInfo(notAddedWidgets.get(0).widgetInfo));
+                    }
+                }
+            }
+        } else {
+            Map<ComponentKey, WidgetItem> widgetItems =
+                    allWidgets.values().stream().flatMap(List::stream)
+                            .collect(Collectors.toMap(widget -> (ComponentKey) widget,
+                                    widget -> widget));
+            for (AppTarget app : mTargets) {
+                if (TextUtils.isEmpty(app.getClassName())) {
+                    continue;
+                }
+                ComponentKey targetWidget = new ComponentKey(
+                        new ComponentName(app.getPackageName(), app.getClassName()), app.getUser());
+                if (widgetItems.containsKey(targetWidget)) {
+                    fixedContainerItems.items.add(
+                            new PendingAddWidgetInfo(widgetItems.get(targetWidget).widgetInfo));
                 }
             }
         }
-        FixedContainerItems fixedContainerItems = mPredictorState.items;
-        fixedContainerItems.items.clear();
-        fixedContainerItems.items.addAll(recommendedWidgetsInDescendingOrder);
         bindExtraContainerItems(fixedContainerItems);
 
         // Don't store widgets prediction to disk because it is not used frequently.
diff --git a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
index 1e03b05..76a5782 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -18,13 +18,23 @@
 
 import android.app.Person;
 import android.content.pm.ShortcutInfo;
+import android.view.Display;
 
 import com.android.launcher3.Utilities;
 
 public class ApiWrapper {
 
+    public static final boolean TASKBAR_DRAWN_IN_PROCESS = true;
+
     public static Person[] getPersons(ShortcutInfo si) {
         Person[] persons = si.getPersons();
         return persons == null ? Utilities.EMPTY_PERSON_ARRAY : persons;
     }
+
+    /**
+     * Returns true if the display is an internal displays
+     */
+    public static boolean isInternalDisplay(Display display) {
+        return display.getType() == Display.TYPE_INTERNAL;
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java b/quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java
index bb1f6fc..c115bbb 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java
@@ -68,6 +68,12 @@
         mListeners.remove(r);
     }
 
+    @Override
+    public boolean get() {
+        // Override this method in order to let Robolectric ShadowDeviceFlag to stub it.
+        return super.get();
+    }
+
     private void registerDeviceConfigChangedListener(Context context) {
         DeviceConfig.addOnPropertiesChangedListener(
                 NAMESPACE_LAUNCHER,
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
index 5c19ab8..a54f963 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
@@ -50,6 +50,7 @@
         Pair<Intent, ActivityOptions> options = remoteResponse.getLaunchOptions(hostView);
         ActivityOptionsWrapper activityOptions = mLauncher.getAppTransitionManager()
                 .getActivityLaunchOptions(mLauncher, hostView);
+        activityOptions.options.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         Object itemInfo = hostView.getTag();
         if (itemInfo instanceof ItemInfo) {
             mLauncher.addLaunchCookie((ItemInfo) itemInfo, activityOptions.options);
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/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/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 12de4a6..8278a5a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -36,11 +36,13 @@
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
 import static com.android.launcher3.states.StateAnimationConfig.SKIP_ALL_ANIMATIONS;
 import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
+import static com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM;
 import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
 import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
 import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
 import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
 import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
+import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
 import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
 import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
 import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
@@ -207,7 +209,7 @@
     /** Create state animation to control non-overview components. */
     private void updateNonOverviewAnim(LauncherState toState, StateAnimationConfig config) {
         config.duration = (long) (Math.max(mXRange, mYRange) * 2);
-        config.animFlags |= SKIP_OVERVIEW;
+        config.animFlags |= SKIP_OVERVIEW | SKIP_SCRIM;
         mNonOverviewAnim = mLauncher.getStateManager()
                 .createAnimationToNewWorkspace(toState, config);
         mNonOverviewAnim.getTarget().addListener(mClearStateOnCancelListener);
@@ -229,10 +231,14 @@
         // As we drag right, animate the following properties:
         //   - RecentsView translationX
         //   - OverviewScrim
+        //   - RecentsView fade (if it's empty)
         PendingAnimation xAnim = new PendingAnimation((long) (mXRange * 2));
         xAnim.setFloat(mRecentsView, ADJACENT_PAGE_OFFSET, scaleAndOffset[1], LINEAR);
         xAnim.setViewBackgroundColor(mLauncher.getScrimView(),
                 toState.getWorkspaceScrimColor(mLauncher), LINEAR);
+        if (mRecentsView.getTaskViewCount() == 0) {
+            xAnim.addFloat(mRecentsView, CONTENT_ALPHA, 0f, 1f, LINEAR);
+        }
         mXOverviewAnim = xAnim.createPlaybackController();
         mXOverviewAnim.dispatchOnStart();
 
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/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index ecaac94..10384a8 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -47,7 +47,6 @@
 import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
 import static com.android.quickstep.util.SwipePipToHomeAnimator.FRACTION_END;
 import static com.android.quickstep.util.SwipePipToHomeAnimator.FRACTION_START;
-import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS;
 import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
@@ -55,7 +54,6 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.annotation.TargetApi;
 import android.app.ActivityManager;
@@ -464,8 +462,6 @@
                     mDeviceState.getRotationTouchHelper()
                             .onEndTargetCalculated(mGestureState.getEndTarget(),
                                     mActivityInterface);
-
-                    mRecentsView.onGestureEndTargetCalculated(mGestureState.getEndTarget());
                 });
 
         notifyGestureStartedAsync();
@@ -1133,6 +1129,10 @@
             }
             homeAnimFactory.playAtomicAnimation(velocityPxPerMs.y);
             mLauncherTransitionController = null;
+
+            if (mRecentsView != null) {
+                mRecentsView.onPrepareGestureEndAnimation(null, mGestureState.getEndTarget());
+            }
         } else {
             AnimatorSet animatorSet = new AnimatorSet();
             ValueAnimator windowAnim = mCurrentShift.animateToValue(start, end);
@@ -1171,9 +1171,9 @@
                 }
             });
             animatorSet.play(windowAnim);
-            S state = mActivityInterface.stateFromGestureEndTarget(mGestureState.getEndTarget());
-            if (mRecentsView != null && state.displayOverviewTasksAsGrid(mDp)) {
-                animatorSet.play(ObjectAnimator.ofFloat(mRecentsView, RECENTS_GRID_PROGRESS, 1));
+            if (mRecentsView != null) {
+                mRecentsView.onPrepareGestureEndAnimation(
+                        animatorSet, mGestureState.getEndTarget());
             }
             animatorSet.setDuration(duration).setInterpolator(interpolator);
             animatorSet.start();
@@ -1701,7 +1701,7 @@
         // No need to apply any transform if there is ongoing swipe-pip-to-home animator since
         // that animator handles the leash solely.
         if (mRecentsAnimationTargets != null && !mIsSwipingPipToHome) {
-            if (mRecentsViewScrollLinked) {
+            if (mRecentsViewScrollLinked && mRecentsView != null) {
                 mTaskViewSimulator.setScroll(mRecentsView.getScrollOffset());
             }
             mTaskViewSimulator.apply(mTransformParams);
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
index 9fa65d9..3c81d1b 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
@@ -163,7 +163,9 @@
 
     @Override
     public boolean isInLiveTileMode() {
-        return false;
+        RecentsActivity activity = getCreatedActivity();
+        return activity != null && activity.getStateManager().getState() == DEFAULT &&
+                activity.isStarted();
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index 9398277..46cd8a2 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -260,6 +260,7 @@
             @Override
             public void setAnimation(RectFSpringAnim anim) {
                 anim.addAnimatorListener(floatingWidgetView);
+                floatingWidgetView.setOnTargetChangeListener(anim::onTargetPositionChanged);
                 floatingWidgetView.setFastFinishRunnable(anim::end);
             }
 
diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
index c47300c..62b821c 100644
--- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
@@ -191,7 +191,7 @@
      * @see #enableMultipleRegions(boolean, Info)
      */
     void createOrAddTouchRegion(Info info) {
-        mCurrentDisplay = new CurrentDisplay(info.realSize, info.rotation);
+        mCurrentDisplay = new CurrentDisplay(info.currentSize, info.rotation);
 
         if (mQuickStepStartingRotation > QUICKSTEP_ROTATION_UNINITIALIZED
                 && mCurrentDisplay.rotation == mQuickStepStartingRotation) {
@@ -256,7 +256,7 @@
             Log.d(TAG, "clearing all regions except rotation: " + mCurrentDisplay.rotation);
         }
 
-        mCurrentDisplay = new CurrentDisplay(region.realSize, region.rotation);
+        mCurrentDisplay = new CurrentDisplay(region.currentSize, region.rotation);
         OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCurrentDisplay);
         if (DEBUG) {
             Log.d(TestProtocol.NO_SWIPE_TO_HOME, "cached region: " + regionToKeep
@@ -289,7 +289,7 @@
             + " with mode: " + mMode + " displayRotation: " + display.rotation);
         }
 
-        Point size = display.realSize;
+        Point size = display.currentSize;
         int rotation = display.rotation;
         int touchHeight = mNavBarGesturalHeight;
         OrientationRectF orientationRectF =
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 3b92779..0e9e3ad 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -22,10 +22,13 @@
 import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSITION_DURATION;
 import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSITION_PRE_DELAY;
 import static com.android.launcher3.Utilities.createHomeIntent;
+import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS;
 import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
 import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
 import static com.android.quickstep.TaskViewUtils.createRecentsWindowAnimator;
+import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -35,6 +38,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.view.SurfaceControl.Transaction;
 import android.view.View;
 
 import androidx.annotation.Nullable;
@@ -47,6 +51,7 @@
 import com.android.launcher3.R;
 import com.android.launcher3.WrappedAnimationRunnerImpl;
 import com.android.launcher3.WrappedLauncherAnimationRunner;
+import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.compat.AccessibilityManagerCompat;
@@ -69,6 +74,7 @@
 import com.android.quickstep.util.RecentsAtomicAnimationFactory;
 import com.android.quickstep.util.SplitSelectStateController;
 import com.android.quickstep.views.OverviewActionsView;
+import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.SplitPlaceholderView;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.system.ActivityOptionsCompat;
@@ -90,6 +96,8 @@
 
     private Handler mUiHandler = new Handler(Looper.getMainLooper());
 
+    private static final long HOME_APPEAR_DURATION = 250;
+
     private RecentsDragLayer mDragLayer;
     private ScrimView mScrimView;
     private FallbackRecentsView mFallbackRecentsView;
@@ -112,6 +120,7 @@
         mScrimView = findViewById(R.id.scrim_view);
         mFallbackRecentsView = findViewById(R.id.overview_panel);
         mActionsView = findViewById(R.id.overview_actions_view);
+        SYSUI_PROGRESS.set(getRootView().getSysUiScrim(), 0f);
 
         SplitPlaceholderView splitPlaceholderView = findViewById(R.id.split_placeholder);
         splitPlaceholderView.init(
@@ -291,6 +300,16 @@
         super.onConfigurationChanged(newConfig);
     }
 
+    @Override
+    public void onStateSetEnd(RecentsState state) {
+        super.onStateSetEnd(state);
+
+        if (state == RecentsState.DEFAULT) {
+            AccessibilityManagerCompat.sendStateEventToTest(getBaseContext(),
+                    OVERVIEW_STATE_ORDINAL);
+        }
+    }
+
     /**
      * Initialize/update the device profile.
      */
@@ -329,7 +348,42 @@
     }
 
     public void startHome() {
-        startActivity(createHomeIntent());
+        if (LIVE_TILE.get()) {
+            RecentsView recentsView = getOverviewPanel();
+            recentsView.switchToScreenshot(() -> recentsView.finishRecentsAnimation(true,
+                    this::startHomeInternal));
+        } else {
+            startHomeInternal();
+        }
+    }
+
+    private void startHomeInternal() {
+        WrappedLauncherAnimationRunner runner = new WrappedLauncherAnimationRunner(
+                getMainThreadHandler(), this::onCreateAnimationToHome, true);
+        RemoteAnimationAdapterCompat adapterCompat =
+                new RemoteAnimationAdapterCompat(runner, HOME_APPEAR_DURATION, 0);
+        startActivity(createHomeIntent(),
+                ActivityOptionsCompat.makeRemoteAnimation(adapterCompat).toBundle());
+    }
+
+    private void onCreateAnimationToHome(
+            int transit, RemoteAnimationTargetCompat[] appTargets,
+            RemoteAnimationTargetCompat[] wallpaperTargets,
+            RemoteAnimationTargetCompat[] nonAppTargets, AnimationResult result) {
+        AnimatorPlaybackController controller = getStateManager()
+                .createAnimationToNewWorkspace(RecentsState.BG_LAUNCHER, HOME_APPEAR_DURATION);
+        controller.dispatchOnStart();
+
+        RemoteAnimationTargets targets = new RemoteAnimationTargets(
+                appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
+        for (RemoteAnimationTargetCompat app : targets.apps) {
+            new Transaction().setAlpha(app.leash.getSurfaceControl(), 1).apply();
+        }
+        AnimatorSet anim = new AnimatorSet();
+        anim.play(controller.getAnimationPlayer());
+        anim.setDuration(HOME_APPEAR_DURATION);
+        result.setAnimation(anim, this,
+                () -> getStateManager().goToState(RecentsState.HOME, false));
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index ef09957..e271203 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -18,7 +18,7 @@
 import static android.content.Intent.ACTION_USER_UNLOCKED;
 
 import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
-import static com.android.launcher3.util.DisplayController.CHANGE_FRAME_DELAY;
+import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
 import static com.android.launcher3.util.SettingsCache.ONE_HANDED_ENABLED;
 import static com.android.launcher3.util.SettingsCache.ONE_HANDED_SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED;
 import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
@@ -271,15 +271,9 @@
 
     @Override
     public void onDisplayInfoChanged(Context context, Info info, int flags) {
-        if (info.id != getDisplayId() || flags == CHANGE_FRAME_DELAY) {
-            // ignore displays that aren't running launcher and frame refresh rate changes
-            return;
+        if ((flags & CHANGE_ROTATION) != 0) {
+            mNavBarPosition = new NavBarPosition(mMode, info);
         }
-
-        if (!mMode.hasGestures) {
-            return;
-        }
-        mNavBarPosition = new NavBarPosition(mMode, info);
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
index fd0de42..7629862 100644
--- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java
+++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
@@ -17,8 +17,9 @@
 
 import static android.view.Surface.ROTATION_0;
 
+import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
 import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
-import static com.android.launcher3.util.DisplayController.CHANGE_FRAME_DELAY;
+import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.quickstep.SysUINavigationMode.Mode.THREE_BUTTONS;
 
@@ -274,8 +275,7 @@
 
     @Override
     public void onDisplayInfoChanged(Context context, Info info, int flags) {
-        if (info.id != mDisplayId|| flags == CHANGE_FRAME_DELAY) {
-            // ignore displays that aren't running launcher and frame refresh rate changes
+        if ((flags & (CHANGE_ROTATION | CHANGE_ACTIVE_SCREEN)) == 0) {
             return;
         }
 
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/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 4d4b6e1..1bb8e96 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -20,6 +20,7 @@
 import static com.android.quickstep.fallback.RecentsState.HOME;
 import static com.android.quickstep.fallback.RecentsState.MODAL_TASK;
 
+import android.animation.AnimatorSet;
 import android.annotation.TargetApi;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.content.Context;
@@ -27,6 +28,9 @@
 import android.util.AttributeSet;
 import android.util.Log;
 
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.statemanager.StateManager.StateListener;
 import com.android.launcher3.testing.TestProtocol;
@@ -67,7 +71,6 @@
     @Override
     public void startHome() {
         mActivity.startHome();
-        mActivity.getStateManager().goToState(RecentsState.HOME);
     }
 
     /**
@@ -86,14 +89,17 @@
      * to the center.
      */
     @Override
-    public void onGestureEndTargetCalculated(GestureState.GestureEndTarget endTarget) {
-        super.onGestureEndTargetCalculated(endTarget);
-        if (mHomeTaskInfo != null && endTarget == RECENTS) {
+    public void onPrepareGestureEndAnimation(
+            @Nullable AnimatorSet animatorSet, GestureState.GestureEndTarget endTarget) {
+        super.onPrepareGestureEndAnimation(animatorSet, endTarget);
+        if (mHomeTaskInfo != null && endTarget == RECENTS && animatorSet != null) {
             TaskView tv = getTaskView(mHomeTaskInfo.taskId);
             if (tv != null) {
                 PendingAnimation pa = createTaskDismissAnimation(tv, true, false, 150);
                 pa.addEndListener(e -> setCurrentTask(-1));
-                runDismissAnimation(pa);
+                AnimatorPlaybackController controller = pa.createPlaybackController();
+                controller.dispatchOnStart();
+                animatorSet.play(controller.getAnimationPlayer());
             }
         }
     }
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsState.java b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
index b3d6cfa..b6cfdce 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsState.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
@@ -39,15 +39,18 @@
     private static final int FLAG_OVERVIEW_ACTIONS = BaseState.getFlag(3);
     private static final int FLAG_SHOW_AS_GRID = BaseState.getFlag(4);
     private static final int FLAG_SCRIM = BaseState.getFlag(5);
+    private static final int FLAG_LIVE_TILE = BaseState.getFlag(6);
 
     public static final RecentsState DEFAULT = new RecentsState(0,
-            FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_SHOW_AS_GRID | FLAG_SCRIM);
+            FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_SHOW_AS_GRID | FLAG_SCRIM
+                    | FLAG_LIVE_TILE);
     public static final RecentsState MODAL_TASK = new ModalState(1,
             FLAG_DISABLE_RESTORE | FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_MODAL
-                    | FLAG_SHOW_AS_GRID | FLAG_SCRIM);
+                    | FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_LIVE_TILE);
     public static final RecentsState BACKGROUND_APP = new BackgroundAppState(2,
             FLAG_DISABLE_RESTORE | FLAG_NON_INTERACTIVE | FLAG_FULL_SCREEN);
     public static final RecentsState HOME = new RecentsState(3, 0);
+    public static final RecentsState BG_LAUNCHER = new LauncherState(4, 0);
 
     public final int ordinal;
     private final int mFlags;
@@ -108,6 +111,13 @@
     }
 
     /**
+     * For this state, whether live tile should be shown.
+     */
+    public boolean hasLiveTile() {
+        return hasFlag(FLAG_LIVE_TILE);
+    }
+
+    /**
      * For this state, what color scrim should be drawn behind overview.
      */
     public int getScrimColor(RecentsActivity activity) {
@@ -152,4 +162,15 @@
             return getOverviewScaleAndOffsetForBackgroundState(activity);
         }
     }
+
+    private static class LauncherState extends RecentsState {
+        LauncherState(int id, int flags) {
+            super(id, flags);
+        }
+
+        @Override
+        public float[] getOverviewScaleAndOffset(RecentsActivity activity) {
+            return new float[] { NO_SCALE, 1 };
+        }
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java b/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
index d7458d2..273d1f6 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
@@ -15,6 +15,8 @@
  */
 package com.android.quickstep.fallback;
 
+import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
+
 import com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController;
 import com.android.quickstep.RecentsActivity;
 
@@ -26,7 +28,8 @@
 
     @Override
     protected boolean isRecentsInteractive() {
-        return mActivity.hasWindowFocus();
+        return mActivity.hasWindowFocus() || (LIVE_TILE.get()
+                && mActivity.getStateManager().getState().hasLiveTile());
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index 9c64794..fcc0217 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -116,7 +116,7 @@
                 R.dimen.device_locked_y_offset);
 
         // Do not use DeviceProfile as the user data might be locked
-        mDisplaySize = DisplayController.INSTANCE.get(context).getInfo().realSize;
+        mDisplaySize = DisplayController.INSTANCE.get(context).getInfo().currentSize;
 
         // Init states
         mStateCallback = new MultiStateCallback(STATE_NAMES);
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
index d82d43d..8d9c524 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
@@ -70,7 +70,7 @@
         mDragDistThreshold = context.getResources().getDimensionPixelSize(
                 R.dimen.gestures_onehanded_drag_threshold);
         mSquaredSlop = Utilities.squaredTouchSlop(context);
-        mDisplaySize = DisplayController.INSTANCE.get(mContext).getInfo().realSize;
+        mDisplaySize = DisplayController.INSTANCE.get(mContext).getInfo().currentSize;
         mNavBarSize = ResourceUtils.getNavbarSize(NAVBAR_BOTTOM_GESTURE_SIZE,
                 mContext.getResources());
     }
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
new file mode 100644
index 0000000..76f43c9
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -0,0 +1,133 @@
+/*
+ * 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.quickstep.interaction;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.text.TextPaint;
+import android.text.method.LinkMovementMethod;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.R;
+
+import java.net.URISyntaxException;
+
+/**
+ * A page shows after SUW flow to hint users to swipe up from the bottom of the screen to go home
+ * for the gestural system navigation.
+ */
+public class AllSetActivity extends Activity {
+
+    private static final String LOG_TAG = "AllSetActivity";
+    private static final String URI_SYSTEM_NAVIGATION_SETTING =
+            "#Intent;action=com.android.settings.SEARCH_RESULT_TRAMPOLINE;S.:settings:fragment_args_key=gesture_system_navigation_input_summary;S.:settings:show_fragment=com.android.settings.gestures.SystemNavigationGestureSettings;end";
+    private static final String EXTRA_ACCENT_COLOR_DARK_MODE = "accent_color_dark_mode";
+    private static final String EXTRA_ACCENT_COLOR_LIGHT_MODE = "accent_color_light_mode";
+
+    private int mAccentColor;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_allset);
+        setTitle(R.string.allset_title);
+
+        final int mode =
+                getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+        mAccentColor = getIntent().getIntExtra(
+                mode == Configuration.UI_MODE_NIGHT_YES
+                        ? EXTRA_ACCENT_COLOR_DARK_MODE : EXTRA_ACCENT_COLOR_LIGHT_MODE,
+                /* defValue= */ Color.BLACK);
+
+        ((ImageView) findViewById(R.id.icon)).getDrawable().mutate().setTint(mAccentColor);
+
+        TextView navigationSettings = findViewById(R.id.navigation_settings);
+        navigationSettings.setMovementMethod(LinkMovementMethod.getInstance());
+        AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo(
+                AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION,
+                new AllSetLinkSpan(
+                        /* context= */ this,
+                        view -> {
+                            try {
+                                startActivityForResult(
+                                        Intent.parseUri(URI_SYSTEM_NAVIGATION_SETTING, 0), 0);
+                            } catch (URISyntaxException e) {
+                                Log.e(LOG_TAG, "Failed to parse system nav settings intent", e);
+                            }
+                            finish();
+                        }));
+        navigationSettings.setText(
+                AnnotationSpan.linkify(getText(R.string.allset_navigation_settings), linkInfo));
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+        if (hasFocus) {
+            hideSystemUI();
+        }
+    }
+
+    private void hideSystemUI() {
+        getWindow().getDecorView().setSystemUiVisibility(
+                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                        | View.SYSTEM_UI_FLAG_FULLSCREEN);
+        getWindow().setNavigationBarColor(Color.TRANSPARENT);
+    }
+
+    private final class AllSetLinkSpan extends AnnotationSpan {
+
+        private final String mFontFamily;
+        private final int mTextSize;
+
+        AllSetLinkSpan(Context context, View.OnClickListener listener) {
+            super(listener);
+            TypedArray typedArray =
+                    context.obtainStyledAttributes(R.style.TextAppearance_GestureTutorial_LinkText,
+                            R.styleable.AllSetLinkSpan);
+            mFontFamily = typedArray.getString(R.styleable.AllSetLinkSpan_android_fontFamily);
+            mTextSize =
+                    typedArray.getDimensionPixelSize(
+                            R.styleable.AllSetLinkSpan_android_textSize, /* defValue= */ -1);
+            typedArray.recycle();
+        }
+
+        @Override
+        public void updateDrawState(TextPaint ds) {
+            super.updateDrawState(ds);
+            ds.setColor(mAccentColor);
+            ds.setTypeface(Typeface.create(mFontFamily, Typeface.NORMAL));
+            ds.setUnderlineText(false);
+            if (mTextSize != -1) {
+                ds.setTextSize(mTextSize);
+            }
+        }
+    }
+
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/AnnotationSpan.java b/quickstep/src/com/android/quickstep/interaction/AnnotationSpan.java
new file mode 100644
index 0000000..fea5078
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/AnnotationSpan.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.interaction;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.text.Annotation;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.style.URLSpan;
+import android.util.Log;
+import android.view.View;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * This class is used to add {@link View.OnClickListener} for the text been wrapped by
+ * annotation.
+ *
+ * Copied from packages/apps/Settings/src/com/android/settings/utils/AnnotationSpan.java.
+ */
+public class AnnotationSpan extends URLSpan {
+
+    private final View.OnClickListener mClickListener;
+
+    AnnotationSpan(View.OnClickListener lsn) {
+        super((String) null);
+        mClickListener = lsn;
+    }
+
+    @Override
+    public void onClick(View widget) {
+        if (mClickListener != null) {
+            mClickListener.onClick(widget);
+        }
+    }
+
+    public static CharSequence linkify(CharSequence rawText, LinkInfo... linkInfos) {
+        SpannableString msg = new SpannableString(rawText);
+        Annotation[] spans = msg.getSpans(0, msg.length(), Annotation.class);
+        SpannableStringBuilder builder = new SpannableStringBuilder(msg);
+        for (Annotation annotation : spans) {
+            final String key = annotation.getValue();
+            int start = msg.getSpanStart(annotation);
+            int end = msg.getSpanEnd(annotation);
+            AnnotationSpan link = null;
+            for (LinkInfo linkInfo : linkInfos) {
+                if (linkInfo.mAnnotation.equals(key)) {
+                    link = linkInfo.mCustomizedSpan != null ? linkInfo.mCustomizedSpan
+                            : new AnnotationSpan(linkInfo.mClickListener);
+                    break;
+                }
+            }
+            if (link != null) {
+                builder.setSpan(link, start, end, msg.getSpanFlags(link));
+            }
+        }
+        return builder;
+    }
+
+    /**
+     * get the text part without having text for link part
+     */
+    public static CharSequence textWithoutLink(CharSequence encodedText) {
+        SpannableString msg = new SpannableString(encodedText);
+        Annotation[] spans = msg.getSpans(0, msg.length(), Annotation.class);
+        if (spans == null) {
+            return encodedText;
+        }
+        Arrays.sort(spans, Comparator.comparingInt(span -> -msg.getSpanStart(span)));
+        StringBuilder msgWithoutLink = new StringBuilder(msg.toString());
+        for (Annotation span : spans) {
+            msgWithoutLink.delete(msg.getSpanStart(span), msg.getSpanEnd(span));
+        }
+        return msgWithoutLink.toString();
+    }
+
+    /** Data class to store the annotation and the click action. */
+    public static class LinkInfo {
+        public static final String DEFAULT_ANNOTATION = "link";
+        private static final String TAG = "AnnotationSpan.LinkInfo";
+        private final String mAnnotation;
+        private final Boolean mActionable;
+        private final View.OnClickListener mClickListener;
+        private final AnnotationSpan mCustomizedSpan;
+
+        public LinkInfo(String annotation, View.OnClickListener listener) {
+            mAnnotation = annotation;
+            mClickListener = listener;
+            mActionable = true; // assume actionable
+            mCustomizedSpan = null;
+        }
+
+        public LinkInfo(String annotation, AnnotationSpan customizedSpan) {
+            mAnnotation = annotation;
+            mClickListener = null;
+            mActionable = customizedSpan != null;
+            mCustomizedSpan = customizedSpan;
+        }
+
+        public LinkInfo(Context context, String annotation, Intent intent) {
+            mAnnotation = annotation;
+            mCustomizedSpan = null;
+            if (intent != null) {
+                mActionable = context.getPackageManager().resolveActivity(intent, 0) != null;
+            } else {
+                mActionable = false;
+            }
+            if (mActionable) {
+                mClickListener =
+                        view -> {
+                            try {
+                                context.startActivity(intent);
+                            } catch (ActivityNotFoundException e) {
+                                Log.w(TAG, "Activity was not found for intent, " + intent);
+                            }
+                        };
+            } else {
+                mClickListener = null;
+            }
+        }
+
+        public boolean isActionable() {
+            return mActionable;
+        }
+    }
+}
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/src/com/android/quickstep/util/AssistContentRequester.java b/quickstep/src/com/android/quickstep/util/AssistContentRequester.java
index 3730284..71c6382 100644
--- a/quickstep/src/com/android/quickstep/util/AssistContentRequester.java
+++ b/quickstep/src/com/android/quickstep/util/AssistContentRequester.java
@@ -28,6 +28,10 @@
 
 import com.android.launcher3.util.Executors;
 
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
 import java.util.concurrent.Executor;
 
 /**
@@ -51,6 +55,10 @@
     private final String mPackageName;
     private final Executor mCallbackExecutor;
 
+    // If system loses the callback, our internal cache of original callback will also get cleared.
+    private final Map<Object, Callback> mPendingCallbacks =
+            Collections.synchronizedMap(new WeakHashMap<>());
+
     public AssistContentRequester(Context context) {
         mActivityTaskManager = ActivityTaskManager.getService();
         mPackageName = context.getApplicationContext().getPackageName();
@@ -66,20 +74,28 @@
     public void requestAssistContent(int taskId, Callback callback) {
         try {
             mActivityTaskManager.requestAssistDataForTask(
-                    new AssistDataReceiver(callback, mCallbackExecutor), taskId, mPackageName);
+                    new AssistDataReceiver(callback, this), taskId, mPackageName);
         } catch (RemoteException e) {
             Log.e(TAG, "Requesting assist content failed for task: " + taskId, e);
         }
     }
 
+    private void executeOnMainExecutor(Runnable callback) {
+        mCallbackExecutor.execute(callback);
+    }
+
     private static final class AssistDataReceiver extends IAssistDataReceiver.Stub {
 
-        private final Executor mExecutor;
-        private final Callback mCallback;
+        // The AssistDataReceiver binder callback object is passed to a system server, that may
+        // keep hold of it for longer than the lifetime of the AssistContentRequester object,
+        // potentially causing a memory leak. In the callback passed to the system server, only
+        // keep a weak reference to the parent object and lookup its callback if it still exists.
+        private final WeakReference<AssistContentRequester> mParentRef;
+        private final Object mCallbackKey = new Object();
 
-        AssistDataReceiver(Callback callback, Executor callbackExecutor) {
-            mCallback = callback;
-            mExecutor = callbackExecutor;
+        AssistDataReceiver(Callback callback, AssistContentRequester parent) {
+            parent.mPendingCallbacks.put(mCallbackKey, callback);
+            mParentRef = new WeakReference<>(parent);
         }
 
         @Override
@@ -94,7 +110,18 @@
                 return;
             }
 
-            mExecutor.execute(() -> mCallback.onAssistContentAvailable(content));
+            AssistContentRequester requester = mParentRef.get();
+            if (requester != null) {
+                Callback callback = requester.mPendingCallbacks.get(mCallbackKey);
+                if (callback != null) {
+                    requester.executeOnMainExecutor(
+                            () -> callback.onAssistContentAvailable(content));
+                } else {
+                    Log.d(TAG, "Callback received after calling UI was disposed of");
+                }
+            } else {
+                Log.d(TAG, "Callback received after Requester was collected");
+            }
         }
 
         @Override
diff --git a/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java b/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
index c527be3..60c7add 100644
--- a/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
+++ b/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
@@ -20,8 +20,6 @@
 
 import android.content.Context;
 
-import com.android.quickstep.OverviewComponentObserver;
-import com.android.quickstep.RecentsAnimationDeviceState;
 import com.android.quickstep.SysUINavigationMode;
 
 import java.util.function.Predicate;
@@ -37,7 +35,6 @@
     private final Supplier<Boolean> mBasePredicate;
     private final Predicate<SysUINavigationMode.Mode> mModePredicate;
     private boolean mSupported;
-    private OverviewComponentObserver mObserver;
 
     private NavigationModeFeatureFlag(Supplier<Boolean> basePredicate,
             Predicate<SysUINavigationMode.Mode> modePredicate) {
@@ -46,17 +43,12 @@
     }
 
     public boolean get() {
-        return mBasePredicate.get() && mSupported && mObserver != null
-                && mObserver.isHomeAndOverviewSame();
+        return mBasePredicate.get() && mSupported;
     }
 
     public void initialize(Context context) {
         onNavigationModeChanged(SysUINavigationMode.INSTANCE.get(context).getMode());
         SysUINavigationMode.INSTANCE.get(context).addModeChangeListener(this);
-
-        // Temporary solution to disable live tile for the fallback launcher
-        RecentsAnimationDeviceState rads = new RecentsAnimationDeviceState(context);
-        mObserver = new OverviewComponentObserver(context, rads);
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index 188efad..d164c8c 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -33,6 +33,7 @@
 import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.graphics.Matrix;
+import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.util.Log;
@@ -49,6 +50,7 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.touch.PagedOrientationHandler;
+import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.SettingsCache;
 import com.android.launcher3.util.WindowBounds;
 import com.android.quickstep.BaseActivityInterface;
@@ -561,11 +563,27 @@
      */
     public DeviceProfile getLauncherDeviceProfile() {
         InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mContext);
-        // TODO also check the natural orientation is landscape or portrait
-        return  (mRecentsActivityRotation == ROTATION_90
-                || mRecentsActivityRotation == ROTATION_270)
-                ? idp.landscapeProfile
-                : idp.portraitProfile;
+        Point currentSize = DisplayController.INSTANCE.get(mContext).getInfo().currentSize;
+
+        int width, height;
+        if ((mRecentsActivityRotation == ROTATION_90 || mRecentsActivityRotation == ROTATION_270)) {
+            width = Math.max(currentSize.x, currentSize.y);
+            height = Math.min(currentSize.x, currentSize.y);
+        } else {
+            width = Math.min(currentSize.x, currentSize.y);
+            height = Math.max(currentSize.x, currentSize.y);
+        }
+
+        DeviceProfile bestMatch = idp.supportedProfiles.get(0);
+        float minDiff = Float.MAX_VALUE;
+        for (DeviceProfile profile : idp.supportedProfiles) {
+            float diff = Math.abs(profile.widthPx - width) + Math.abs(profile.heightPx - height);
+            if (diff < minDiff) {
+                minDiff = diff;
+                bestMatch = profile;
+            }
+        }
+        return bestMatch;
     }
 
     private static String nameAndAddress(Object obj) {
diff --git a/quickstep/src/com/android/quickstep/util/SplitScreenBounds.java b/quickstep/src/com/android/quickstep/util/SplitScreenBounds.java
index 88cc650..483a1c6 100644
--- a/quickstep/src/com/android/quickstep/util/SplitScreenBounds.java
+++ b/quickstep/src/com/android/quickstep/util/SplitScreenBounds.java
@@ -20,10 +20,7 @@
 
 import android.annotation.TargetApi;
 import android.content.Context;
-import android.graphics.Insets;
-import android.graphics.Rect;
 import android.os.Build;
-import android.view.WindowInsets.Type;
 import android.view.WindowManager;
 import android.view.WindowMetrics;
 
@@ -73,10 +70,8 @@
      */
     private static WindowBounds createDefaultWindowBounds(Context context) {
         WindowMetrics wm = context.getSystemService(WindowManager.class).getMaximumWindowMetrics();
-        Insets insets = wm.getWindowInsets().getInsets(Type.systemBars());
+        WindowBounds bounds = WindowBounds.fromWindowMetrics(wm);
 
-        WindowBounds bounds = new WindowBounds(wm.getBounds(),
-                new Rect(insets.left, insets.top, insets.right, insets.bottom));
         int rotation = DisplayController.INSTANCE.get(context).getInfo().rotation;
         int halfDividerSize = context.getResources()
                 .getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index e63f8bb..f578ad1 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -36,6 +36,7 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.util.TraceHelper;
 import com.android.quickstep.AnimatedFloat;
 import com.android.quickstep.BaseActivityInterface;
 import com.android.quickstep.views.TaskThumbnailView.PreviewPositionHelper;
@@ -95,7 +96,9 @@
         mContext = context;
         mSizeStrategy = sizeStrategy;
 
-        mOrientationState = new RecentsOrientedState(context, sizeStrategy, i -> { });
+        // TODO(b/187074722): Don't create this per-TaskViewSimulator
+        mOrientationState = TraceHelper.allowIpcs("",
+                () -> new RecentsOrientedState(context, sizeStrategy, i -> { }));
         mOrientationState.setGestureActive(true);
         mCurrentFullscreenParams = new FullscreenDrawParams(context);
         mOrientationStateId = mOrientationState.getStateId();
diff --git a/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java b/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
index f74aa55..9ea2369 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
@@ -100,8 +100,8 @@
     /** Restores the drawables to the source view. */
     void finish() {
         if (isUninitialized()) return;
-        mSourceView.setForeground(mOriginalForeground);
-        mSourceView.setBackground(mOriginalBackground);
+        if (mOriginalForeground != null) mSourceView.setForeground(mOriginalForeground);
+        if (mOriginalBackground != null) mSourceView.setBackground(mOriginalBackground);
     }
 
     void recycle() {
diff --git a/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
index 8499902..ed54f10 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
@@ -27,6 +27,7 @@
 import android.view.GhostView;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.widget.FrameLayout;
 
 import com.android.launcher3.Launcher;
@@ -39,7 +40,8 @@
 
 /** A view that mimics an App Widget through a launch animation. */
 @TargetApi(Build.VERSION_CODES.S)
-public class FloatingWidgetView extends FrameLayout implements AnimatorListener {
+public class FloatingWidgetView extends FrameLayout implements AnimatorListener,
+        OnGlobalLayoutListener {
     private static final Matrix sTmpMatrix = new Matrix();
 
     private final Launcher mLauncher;
@@ -54,6 +56,7 @@
 
     private Runnable mEndRunnable;
     private Runnable mFastFinishRunnable;
+    private Runnable mOnTargetChangeRunnable;
 
     public FloatingWidgetView(Context context) {
         this(context, null);
@@ -93,6 +96,32 @@
     public void onAnimationRepeat(Animator animator) {
     }
 
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        getViewTreeObserver().addOnGlobalLayoutListener(this);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        getViewTreeObserver().removeOnGlobalLayoutListener(this);
+        super.onDetachedFromWindow();
+    }
+
+    @Override
+    public void onGlobalLayout() {
+        if (isUninitialized()) return;
+        positionViews();
+        if (mOnTargetChangeRunnable != null) {
+            mOnTargetChangeRunnable.run();
+        }
+    }
+
+    /** Sets a runnable that is called on global layout change. */
+    public void setOnTargetChangeListener(Runnable onTargetChangeListener) {
+        mOnTargetChangeRunnable = onTargetChangeListener;
+    }
+
     /** Sets a runnable that is called after a call to {@link #fastFinish()}. */
     public void setFastFinishRunnable(Runnable runnable) {
         mFastFinishRunnable = runnable;
@@ -205,6 +234,7 @@
     private void recycle() {
         mEndRunnable = null;
         mFastFinishRunnable = null;
+        mOnTargetChangeRunnable = null;
         mBackgroundPosition = null;
         mListenerView.setListener(null);
         mAppWidgetView = null;
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 206f71b..63981b1 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -1644,7 +1644,16 @@
     /**
      * Called when a gesture from an app has finished, and an end target has been determined.
      */
-    public void onGestureEndTargetCalculated(GestureState.GestureEndTarget endTarget) {
+    public void onPrepareGestureEndAnimation(
+            @Nullable AnimatorSet animatorSet, GestureState.GestureEndTarget endTarget) {
+        if (mSizeStrategy.stateFromGestureEndTarget(endTarget)
+                .displayOverviewTasksAsGrid(mActivity.getDeviceProfile())) {
+            if (animatorSet == null) {
+                setGridProgress(1);
+            } else {
+                animatorSet.play(ObjectAnimator.ofFloat(this, RECENTS_GRID_PROGRESS, 1));
+            }
+        }
         mCurrentGestureEndTarget = endTarget;
         if (endTarget == GestureState.GestureEndTarget.NEW_TASK
                 || endTarget == GestureState.GestureEndTarget.LAST_TASK) {
@@ -2286,7 +2295,8 @@
         mPendingAnimation.addEndListener(new Consumer<Boolean>() {
             @Override
             public void accept(Boolean success) {
-                if (LIVE_TILE.get() && taskView.isRunningTask() && success) {
+                if (LIVE_TILE.get() && mEnableDrawingLiveTile && taskView.isRunningTask()
+                        && success) {
                     finishRecentsAnimation(true /* toHome */, () -> onEnd(success));
                 } else {
                     onEnd(success);
@@ -2384,7 +2394,7 @@
         return true;
     }
 
-    protected void runDismissAnimation(PendingAnimation pendingAnim) {
+    private void runDismissAnimation(PendingAnimation pendingAnim) {
         AnimatorPlaybackController controller = pendingAnim.createPlaybackController();
         controller.dispatchOnStart();
         controller.getAnimationPlayer().setInterpolator(FAST_OUT_SLOW_IN);
@@ -2518,15 +2528,6 @@
     @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();
@@ -3519,7 +3520,7 @@
      * capturing the snapshot at the same time.
      */
     public void switchToScreenshot(Runnable onFinishRunnable) {
-        switchToScreenshot(mRecentsAnimationController == null || mRunningTaskId == -1 ? null
+        switchToScreenshot(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 079d24b..1477933 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -582,6 +582,7 @@
 
                 @Override
                 public void onAnimationEnd(Animator animator) {
+                    recentsView.getLiveTileTaskViewSimulator().setDrawsBelowRecents(true);
                     mIsClickableAsLiveTile = true;
                 }
             });
@@ -1467,9 +1468,10 @@
     }
 
     private void setColorTint(float amount) {
-        mSnapshotView.setDimAlpha(amount);
-        mIconView.setIconColorTint(mTintingColor, amount);
-        mDigitalWellBeingToast.setBannerColorTint(mTintingColor, amount);
+        mTintAmount = amount;
+        mSnapshotView.setDimAlpha(mTintAmount);
+        mIconView.setIconColorTint(mTintingColor, mTintAmount);
+        mDigitalWellBeingToast.setBannerColorTint(mTintingColor, mTintAmount);
     }
 
     private float getColorTint() {
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index e516468..c6d372a 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dubbeltik en hou om \'n legstuk te skuif of gebruik gepasmaakte handelinge."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d breed by %2$d hoog"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Raak en hou die legstuk om dit op die Tuisskerm rond te beweeg"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Voeg by Tuisskerm"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> legstukke</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> legstuk</item>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 5241acd..7123a8b 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ምግብርን ለማንቀሳቀስ ወይም ብጁ እርምጃዎችን ለመጠቀም ሁለቴ መታ ያድርጉ እና ይያዙ።"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ስፋት በ%2$d ከፍታ"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"በመነሻ ገጽ አካባቢ ላይ ለማንቀሳቀስ ነክተው ይያዙት"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"ወደ መነሻ ገጽ አክል"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> ንዑስ ፕሮግራሞች</item>
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> ንዑስ ፕሮግራሞች</item>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 669aa91..c6ab52a 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"انقر مرتين مع تثبيت إصبعك لنقل أداة أو استخدام الإجراءات المخصّصة."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"‏العرض %1$d الطول %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"يمكنك النقر على الأداة مع الاستمرار لتحريكها على الشاشة الرئيسية."</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"إضافة إلى الشاشة الرئيسية"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="zero"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> أداة</item>
       <item quantity="two">أداتان (<xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g>)</item>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 931b3ab..5e80e65 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"কোনো ৱিজেট স্থানান্তৰ কৰিবলৈ দুবাৰ টিপি ধৰি ৰাখক অথবা কাষ্টম কাৰ্য ব্যৱহাৰ কৰক।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d বহল x %2$d ওখ"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"ৱিজেটটো গৃহ স্ক্ৰীনৰ আশে-পাশে নিবলৈ সেইটোত স্পৰ্শ কৰি ধৰি ৰাখক"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"গৃহ স্ক্ৰীনত যোগ কৰক"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> টা ৱিজেট</item>
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> টা ৱিজেট</item>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 8b525f2..17f600c 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Vidceti daşımaq üçün iki dəfə toxunub saxlayın və ya fərdi əməliyyatlardan istifadə edin."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%2$d hündürlük %1$d enində"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Əsas ekranda hərəkət etdirmək üçün vidcetə toxunub saxlayın"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Əsas ekrana əlavə edin"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> vidcet</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> vidcet</item>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index d4f013a..dc04fed 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvaput dodirnite i zadržite da biste pomerali vidžet ili koristite prilagođene radnje."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"širina od %1$d i visina od %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Dodirnite i zadržite vidžet da biste ga pomerali po početnom ekranu"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Dodaj na početni ekran"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> vidžet</item>
       <item quantity="few"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> vidžeta</item>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index cf02d48..9bb2c00 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Дакраніцеся двойчы і ўтрымлівайце, каб перамясціць віджэт або выкарыстоўваць спецыяльныя дзеянні."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Шырына: %1$d, вышыня: %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Утрымліваючы віджэт націснутым, перамяшчайце яго па Галоўным экране"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Дадаць на Галоўны экран"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> віджэт</item>
       <item quantity="few"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> віджэты</item>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index b3c5ca4..0d398ee 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Докоснете двукратно и задръжте за преместване на приспособление или използвайте персонал. действия."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Ширина %1$d и височина %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Докоснете приспособлението и го задръжте, за да го местите на началния екран"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Добавяне към началния екран"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> приспособления</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> приспособление</item>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index fcd6f3f..50aff80 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvaput dodirnite i zadržite da pomjerite vidžet ili da koristite prilagođene radnje."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Širina %1$d, visina %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Dodirnite i držite vidžet da ga pomjerate po Početnom ekranu"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Dodaj na početni ekran"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> vidžet</item>
       <item quantity="few"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> vidžeta</item>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index d54670b..9ea5fc7 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Fes doble toc i mantén premut per moure un widget o per utilitzar accions personalitzades."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d d\'amplada per %2$d d\'alçada"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Mantén premut el widget per moure\'l per la pantalla d\'inici"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Afegeix a la pantalla d\'inici"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgets</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> widget</item>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index a9ea587..9ae37cc 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvojitým klepnutím a podržením přesunete widget, případně použijte vlastní akce."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"šířka %1$d, výška %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Pokud widgetem chcete pohybovat po ploše, dotkněte se ho a podržte ho"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Přidat na plochu"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="few"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgety</item>
       <item quantity="many"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgetu</item>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index e5dacac..3b4e07b 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Tryk to gange, og hold en widget nede for at flytte den eller bruge tilpassede handlinger."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d i bredden og %2$d i højden"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Hold widgetten nede for at flytte den rundt på startskærmen"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Føj til startskærm"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widget</item>
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgets</item>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index a9deedb..1d93bfc 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Πατήστε δύο φορές παρατεταμένα για μετακίνηση γραφικού στοιχείου ή χρήση προσαρμοσμένων ενεργειών."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Πλάτος %1$d επί ύψος %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Αγγίξτε παρατεταμένα το γραφικό στοιχείο για να το μετακινήσετε στην Αρχική οθόνη"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Προσθήκη στην Αρχική οθόνη"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> γραφικά στοιχεία</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> γραφικό στοιχείο</item>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 0330795..79d33fd 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Presiona dos veces y mantén presionado para mover un widget o usar acciones personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de ancho por %2$d de alto"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Mantén presionado el widget para moverlo por la pantalla principal"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Agregar a pantalla principal"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgets</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> widget</item>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 888436f..1bc4c60 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toca dos veces y mantén pulsado un widget para moverlo o usar acciones personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de ancho por %2$d de alto"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Mantén pulsado el widget para moverlo por la pantalla de inicio"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Añadir a la pantalla de inicio"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other">Widgets: <xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g></item>
       <item quantity="one">Widget: <xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g></item>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 15b6177..916aafc 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Vidina teisaldamiseks või kohandatud toimingute kasutamiseks topeltpuudutage ja hoidke all."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d lai ja %2$d kõrge"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Vidina avakuval liigutamiseks puudutage vidinat ja hoidke all"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Lisa avakuvale"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> vidinat</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> vidin</item>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 5309052..901d3cb 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Sakatu birritan eta eduki sakatuta widget bat mugitzeko edo ekintza pertsonalizatuak erabiltzeko."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d zabal eta %2$d luze"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Eduki sakatuta widgeta hasierako pantailan zehar mugitzeko"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Gehitu hasierako pantailan"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widget</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> widget</item>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index b0c300c..194ea0d 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"برای جابه‌جا کردن ابزارک یا استفاده از کنش‌های سفارشی، دوضربه بزنید و نگه دارید."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"‏%1$d عرض در %2$d طول"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"ابزارک را لمس و کنید و نگه دارید تا آن را در صفحه اصلی حرکت دهید"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"افزودن به صفحه اصلی"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> ابزارک</item>
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> ابزارک</item>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 47466cf..6cffafc 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Kaksoisnapauta ja paina pitkään, niin voit siirtää widgetiä tai käyttää muokattuja toimintoja."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Leveys: %1$d, korkeus: %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Voit siirtää widgetiä aloitusnäytöllä koskettamalla sitä pitkään"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Lisää aloitusnäytölle"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgetiä</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> widget</item>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index f50d837..3ebd61a 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Touchez 2x un widget et maintenez le doigt dessus pour le déplacer ou utiliser des actions personnalisées."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largeur sur %2$d de hauteur"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Maintenez le doigt sur le widget pour le déplacer sur l\'écran d\'accueil"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Ajouter à l\'écran d\'accueil"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widget</item>
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgets</item>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index f51c3d9..bb56bac 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Appuyez deux fois et maintenez la pression pour déplacer widget ou utiliser actions personnalisées."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largeur et %2$d de hauteur"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Appuyez de manière prolongée sur le widget pour le déplacer sur l\'écran d\'accueil"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Ajouter à l\'écran d\'accueil"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widget</item>
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgets</item>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index c3e3596..d3f3f0b 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toca dúas veces un widget e manteno premido para movelo ou utiliza accións personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largo por %2$d de alto"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Mantén premido o widget para movelo pola pantalla de inicio"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Engadir á pantalla de inicio"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgets</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> widget</item>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 61776d6..9a3c56c 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"किसी विजेट को एक से दूसरी जगह ले जाने के लिए, उस पर दो बार टैप करके दबाकर रखें या पसंद के मुताबिक कार्रवाइयां इस्तेमाल करें."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d चौड़ाई गुणा %2$d ऊंचाई"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"होम स्क्रीन पर यहां-वहां ले जाने के लिए विजेट को दबाकर रखें"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"होम स्क्रीन पर जोड़ें"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> विजेट</item>
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> विजेट</item>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 171f5d0..d1cb5bf 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvaput dodirnite i zadržite pritisak da biste premjestili widget ili upotrijebite prilagođene radnje"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d širine i %2$d visine"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Dodirnite i zadržite widget da biste ga pomicali po početnom zaslonu"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Dodaj na početni zaslon"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widget</item>
       <item quantity="few"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgeta</item>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index bbb24e9..9e2c358 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Modul áthelyezéséhez koppintson duplán, tartsa nyomva az ujját, vagy használjon egyéni műveleteket."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d széles és %2$d magas"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Tartsa lenyomva a modult a kezdőképernyőn való mozgatáshoz"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Hozzáadás a kezdőképernyőhöz"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> modul</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> modul</item>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index c1889ff..d42e4f9 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ketuk dua kali &amp; tahan untuk memindahkan widget atau gunakan tindakan khusus."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"lebar %1$d x tinggi %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Sentuh lama widget untuk memindahkannya di sekitar Layar utama"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Tambahkan ke Layar utama"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widget</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> widget</item>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 1dce7c7..30e73b4 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ýttu tvisvar og haltu fingri á græju til að færa hana eða notaðu sérsniðnar aðgerðir."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d á breidd og %2$d á hæð"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Haltu fingri á græjunni til að hreyfa hana um heimaskjáinn"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Bæta á heimaskjá"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> græja</item>
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> græjur</item>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 3d1cb5b..1d420a9 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Tocca due volte e tieni premuto per spostare un widget o per usare le azioni personalizzate."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d di larghezza per %2$d di altezza"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Tocca e tieni premuto il widget per spostarlo nella schermata Home"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Aggiungi a schermata Home"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widget</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> widget</item>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 4cf0eb2..7cd53fa 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"כדי להעביר ווידג\'ט למקום אחר או להשתמש בפעולות מותאמות אישית, יש ללחוץ פעמיים ולא להרפות."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"‏רוחב %1$d על גובה %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"יש ללחוץ לחיצה ארוכה על הווידג\'ט כדי להזיז אותו ברחבי מסך הבית"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"הוספה למסך הבית"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="two"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> ווידג\'טים</item>
       <item quantity="many"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> ווידג\'טים</item>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 77efbad..c1136a4 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ウィジェットをダブルタップして長押ししながら移動するか、カスタム操作を使用してください。"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$dx%2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"幅 %1$d、高さ %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"ウィジェットを押し続けた状態で、ホーム画面上に移動させます。"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"ホーム画面に追加"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> 件のウィジェット</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> 件のウィジェット</item>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index e3be57f..c701795 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ორმაგი შეხებით აირჩიეთ და გეჭიროთ ვიჯეტის გადასაადგილებლად ან მორგებული მოქმედებების გამოსაყენებლად."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"სიგრძე: %1$d, სიგანე: %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"ხანგრძლივად შეეხეთ ვიჯეტს მთავარ ეკრანზე მის გადასაადგილებლად"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"მთავარ ეკრანზე დამატება"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> ვიჯეტი</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> ვიჯეტი</item>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 392dc8b..8f92db0 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетті жылжыту үшін екі рет түртіңіз де, ұстап тұрыңыз немесе арнаулы әрекеттерді пайдаланыңыз."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Ені: %1$d, биіктігі: %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Негізгі экран бойымен қозғалту үшін виджетті басып, ұстап тұрыңыз."</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Негізгі экранға қосу"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> виджет</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> виджет</item>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index dd04c01..8a82bda 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ចុចពីរដង រួចសង្កត់ឱ្យជាប់ ដើម្បីផ្លាស់ទី​ធាតុក្រាហ្វិក ឬប្រើ​សកម្មភាព​តាមបំណង​។"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"ទទឺង %1$d គុណនឹងកម្ពស់ %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"ចុចធាតុក្រាហ្វិក​ឱ្យជាប់ ដើម្បីផ្លាស់ទីវា​ជុំវិញអេក្រង់ដើម"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"បញ្ចូល​ទៅអេក្រង់ដើម"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other">ធាតុ​ក្រាហ្វិក <xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g></item>
       <item quantity="one">ធាតុ​ក្រាហ្វិក <xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g></item>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 7e24dc3..b98ee5c 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"두 번 탭한 다음 길게 터치하여 위젯을 이동하거나 맞춤 작업을 사용하세요."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"너비 %1$d, 높이 %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"홈 화면에서 위젯을 이동하려면 길게 터치하세요."</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"홈 화면에 추가"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other">위젯 <xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g>개</item>
       <item quantity="one">위젯 <xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g>개</item>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index a4f54bf..62fb75c 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетти жылдыруу үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Туурасы: %1$d, бийиктиги: %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Башкы экранга жылдыруу үчүн виджетти коё бербей басып туруңуз"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Башкы экранга кошуу"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> виджет</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> виджет</item>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 43055a5..0677e88 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dukart palieskite ir palaikykite, kad perkeltumėte valdiklį ar naudotumėte tinkintus veiksmus."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d plotis ir %2$d aukštis"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Paliesdami ir palaikydami valdiklį galite judėti pagrindiniame ekrane"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Pridėti prie pagrindinio ekrano"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> valdiklis</item>
       <item quantity="few"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> valdikliai</item>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 8bcf250..6310375 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Lai pārvietotu logrīku, uz tā veiciet dubultskārienu un turiet. Varat arī veikt pielāgotas darbības."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d plats un %2$d augsts"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Pieskarieties logrīkam un turiet to, lai to pārvietotu pa sākuma ekrānu."</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Pievienot sākuma ekrānam"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="zero"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> logrīku</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> logrīks</item>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index b512dc2..3e99d67 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Жижиг хэрэгслийг зөөх эсвэл захиалгат үйлдлийг ашиглахын тулд хоёр товшоод, удаан дарна уу."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d өргөн %2$d өндөр"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Жижиг хэрэгслийг Үндсэн нүүрний эргэн тойронд зөөхийн тулд түүнд хүрээд, удаан дарна уу"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Үндсэн нүүрэнд нэмэх"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> жижиг хэрэгсэл</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> жижиг хэрэгсэл</item>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 91f2a4d..9401040 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ketik dua kali &amp; tahan untuk menggerakkan widget atau menggunakan tindakan tersuai."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Lebar %1$d kali tinggi %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Sentuh &amp; tahan widget untuk menggerakkan widget di sekitar Skrin utama"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Tambah pada Skrin utama"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widget</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> widget</item>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index f042629..4dcd6c1 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ဝိဂျက်ကို ရွှေ့ရန် (သို့) စိတ်ကြိုက်လုပ်ဆောင်ချက်များကို သုံးရန် နှစ်ချက်တို့ပြီး ဖိထားပါ။"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"အလျား %1$d နှင့် အမြင့် %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"ပင်မစာမျက်နှာအနီးတွင် ဝိဂျက်ကိုရွှေ့ရန် ၎င်းကို တို့ထိ၍ဖိထားပါ"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"ပင်မစာမျက်နှာသို့ ထည့်ရန်"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other">ဝိဂျက် <xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> ခု</item>
       <item quantity="one">ဝိဂျက် <xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> ခု</item>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 540d726..ad5affb 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dobbelttrykk og hold inne for å flytte en modul eller bruke tilpassede handlinger."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d bredde x %2$d høyde"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Trykk og hold på modulen for å bevege den rundt på startskjermen"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Legg til på startskjermen"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> moduler</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> modul</item>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index d4478b7..cc16a89 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dubbeltik en houd vast om een widget te verplaatsen of aangepaste acties te gebruiken."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d breed en %2$d hoog"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Houd de widget ingedrukt om deze te verplaatsen op het startscherm"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Toevoegen aan startscherm"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgets</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> widget</item>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 3595f33..7f3495a 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ଦୁଇଥର-ଟାପ୍ କରି ଧରି ରଖନ୍ତୁ କିମ୍ବା କଷ୍ଟମ୍ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ଓସାର ଓ %2$d ଉଚ୍ଚ"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"ମୂଳସ୍କ୍ରିନର ଆଖପାଖରେ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ଏହାକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"ମୂଳସ୍କ୍ରିନରେ ଯୋଗ କରନ୍ତୁ"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g>ଟି ୱିଜେଟ୍</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g>ଟି ୱିଜେଟ୍</item>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 306a9a0..ceb8046 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Naciśnij dwukrotnie i przytrzymaj, aby przenieść widżet lub użyć działań niestandardowych."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Szerokość %1$d, wysokość %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Kliknij i przytrzymaj widżet, by poruszać nim po ekranie głównym."</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Dodaj do ekranu głównego"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="few"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widżety</item>
       <item quantity="many"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widżetów</item>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index a104931..e40accf 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toque duas vezes sem soltar para mover um widget ou utilizar ações personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largura por %2$d de altura"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Toque sem soltar no widget para o mover à volta do ecrã principal"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Adicionar ao ecrã principal"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgets</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> widget</item>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 35d1e5d..8b18329 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toque duas vezes e mantenha a tela pressionada para mover um widget ou usar ações personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largura por %2$d de altura"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Toque no widget e mantenha-o pressionado para movê-lo pela tela inicial"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Adicionar à tela inicial"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widget</item>
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgets</item>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index f614b18..a71f999 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Atingeți de două ori și țineți apăsat pentru a muta un widget sau folosiți acțiuni personalizate."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d lățime și %2$d înălțime"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Atingeți lung widgetul pentru a-l muta pe ecranul de pornire"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Adăugați pe ecranul de pornire"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="few"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgeturi</item>
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> de widgeturi</item>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 3336b0b..0c1acbc 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Чтобы использовать специальные действия или перенести виджет, нажмите на него дважды и удерживайте."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Ширина %1$d, высота %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Нажмите на виджет и удерживайте его, чтобы переместить в нужное место на главном экране."</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Добавить на главный экран"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> виджет</item>
       <item quantity="few"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> виджета</item>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index fa3287d..6b27168 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"විජට් එකක් ගෙන යාමට හෝ අභිරුචි ක්‍රියා භාවිත කිරීමට දෙවරක් තට්ටු කර අල්ලා ගෙන සිටින්න."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"පළල %1$d උස %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"එය මුල් පිටු තිරය වටා ගෙන යාමට විජට් එක ස්පර්ශ කර අල්ලා ගන්න"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"මුල් පිටු තිරය වෙත එක් කරන්න"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one">විජට් <xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g></item>
       <item quantity="other">විජට් <xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g></item>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index bd90155..7ea59d6 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvojitým klepnutím a pridržaním presuňte miniaplikáciu alebo použite vlastné akcie."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"šírka %1$d, výška %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Po pridržaní môžete miniaplikáciu môžete posúvať po ploche"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Pridať na plochu"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="few"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> miniaplikácie</item>
       <item quantity="many"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgets</item>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index df1db7e..f74bdcc 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvakrat se dotaknite pripomočka in ga pridržite, da ga premaknete, ali pa uporabite dejanja po meri."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Širina %1$d, višina %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Pridržite pripomoček, če ga želite premikati po začetnem zaslonu."</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Dodaj na začetni zaslon"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> pripomoček</item>
       <item quantity="two"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> pripomočka</item>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 4d97676..9a53936 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Trokit dy herë dhe mbaje shtypur një miniapliikacion për ta zhvendosur atë ose për të përdorur veprimet e personalizuara."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d i gjerë me %2$d i lartë"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Prek dhe mbaj miniaplikacionin për ta lëvizur nëpër \"Ekranin bazë\""</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Shto në \"Ekranin bazë\""</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> miniaplikacione</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> miniaplikacion</item>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 4103b00..4f67b23 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Двапут додирните и задржите да бисте померали виџет или користите прилагођене радње."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"ширина од %1$d и висина од %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Додирните и задржите виџет да бисте га померали по почетном екрану"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Додај на почетни екран"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> виџет</item>
       <item quantity="few"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> виџета</item>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index fb3e8c1..91b9b88 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Tryck snabbt två gånger och håll kvar för att flytta en widget eller använda anpassade åtgärder."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d bred gånger %2$d hög"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Tryck länge på widgeten om du vill flytta den på startskärmen"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Lägg till på startskärmen"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widgetar</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> widget</item>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 6caadaa..6227239 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Gusa mara mbili na ushikilie ili usogeze wijeti au utumie vitendo maalum."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Upana wa %1$d na kimo cha %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Gusa na ushikilie wijeti ili uisogeze kwenye Skrini ya kwanza"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Weka kwenye Skrini ya kwanza"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other">Wijeti <xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g></item>
       <item quantity="one">Wijeti <xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g></item>
diff --git a/res/values-sw600dp/config.xml b/res/values-sw600dp/config.xml
index d50115b..09bdaaf 100644
--- a/res/values-sw600dp/config.xml
+++ b/res/values-sw600dp/config.xml
@@ -1,6 +1,3 @@
 <resources>
     <bool name="allow_rotation">true</bool>
-
-    <!-- Hotseat -->
-    <bool name="hotseat_transpose_layout_with_orientation">false</bool>
 </resources>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index a2bc2c5..cae7e24 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"விட்ஜெட்டை நகர்த்த இருமுறை தட்டிப் பிடிக்கவும் அல்லது பிரத்தியேகச் செயல்களைப் பயன்படுத்தவும்."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d அகலத்திற்கு %2$d உயரம்"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"முகப்புத் திரைக்கு விட்ஜெட்டை நகர்த்த அதைத் தொட்டுப் பிடிக்கவும்"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"முகப்புத் திரையில் சேர்"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> விட்ஜெட்டுகள்</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> விட்ஜெட்</item>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 1b79b9c..4f98cd2 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"แตะสองครั้งค้างไว้เพื่อย้ายวิดเจ็ตหรือใช้การดำเนินการที่กำหนดเอง"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"กว้าง %1$d x สูง %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"แตะวิดเจ็ตค้างไว้เพื่อย้ายไปรอบๆ หน้าจอหลัก"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"เพิ่มลงในหน้าจอหลัก"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other">วิดเจ็ต <xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> รายการ</item>
       <item quantity="one">วิดเจ็ต <xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> รายการ</item>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 58e8c8a..a3504fe 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"I-double tap at pindutin nang matagal para ilipat ang widget o gumamit ng mga custom na pagkilos."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ang lapad at %2$d ang taas"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Pindutin nang matagal ang widget para ilipat-lipat ito sa Home screen"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Idagdag sa Home screen"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widget</item>
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> na widget</item>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index bc6ad44..8029aeb 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Widget\'ı taşımak veya özel işlemleri kullanmak için iki kez dokunup basılı tutun."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"genişlik: %1$d, yükseklik: %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Ana ekranda taşımak için widget\'a dokunup basılı tutun"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Ana ekrana ekle"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> widget</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> widget</item>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index fdba5e61..5e179aa 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Двічі натисніть і втримуйте віджет, щоб перемістити його або виконати інші дії."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Ширина – %1$d, висота – %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Натисніть і втримуйте віджет, щоб переміщувати його головним екраном"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Додати на головний екран"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> віджет</item>
       <item quantity="few"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> віджети</item>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 1ab449d..9c8f7ed 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ikki marta bosib va bosib turgan holatda vidjetni tanlang yoki maxsus amaldan foydalaning."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Eni %1$d, bo‘yi %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Bosh ekranda surish uchun vidjet ustiga bosib turing"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Bosh ekranga chiqarish"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> ta vidjet</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> ta vidjet</item>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index acb101b..a026dbc 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Nhấn đúp và giữ để di chuyển một tiện ích hoặc sử dụng các thao tác tùy chỉnh."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Rộng %1$d x cao %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Chạm và giữ để di chuyển tiện ích xung quanh Màn hình chính"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Thêm vào Màn hình chính"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> tiện ích</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> tiện ích</item>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 5b06896..d32611d 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"㩒兩下之後㩒住,就可以郁小工具或者用自訂操作。"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d 闊,%2$d 高"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"按住小工具即可將其移至主畫面上任何位置"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"新增至主畫面"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> 個小工具</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> 個小工具</item>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 9566a8c..58e8f19 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"輕觸兩下並按住即可移動小工具或使用自訂操作。"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"寬度為 %1$d,高度為 %2$d"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"按住小工具即可將小工具移到主畫面的任一位置"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"新增到主畫面"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> 項小工具</item>
       <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> 項小工具</item>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 0da9ed7..3892f6b 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -32,10 +32,8 @@
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Thepha kabili uphinde ubambe ukuze uhambise iwijethi noma usebenzise izindlela ezingokwezifiso."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ububanzi ngokungu-%2$d ukuya phezulu"</string>
-    <!-- no translation found for add_item_request_drag_hint (5653291305078645405) -->
-    <skip />
-    <!-- no translation found for add_to_home_screen (8631549138215492708) -->
-    <skip />
+    <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Thinta uphinde ubambe iwijethi ukuyihambisa Kusikrini sasekhaya"</string>
+    <string name="add_to_home_screen" msgid="8631549138215492708">"Engeza kusikrini sasekhaya"</string>
     <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
       <item quantity="one">Amawijethi angu-<xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g></item>
       <item quantity="other">Amawijethi angu-<xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g></item>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 93d88c2..a81802d 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -127,17 +127,24 @@
         <!-- numFolderRows & numFolderColumns defaults to numRows & numColumns, if not specified -->
         <attr name="numFolderRows" format="integer" />
         <attr name="numFolderColumns" format="integer" />
+        <!-- numAllAppsColumns defaults to numColumns, if not specified -->
+        <attr name="numAllAppsColumns" format="integer" />
+        <!-- Number of columns to use when extending the all-apps size,
+         defaults to 2 * numAllAppsColumns -->
+        <attr name="numExtendedAllAppsColumns" format="integer" />
+
         <!-- numHotseatIcons defaults to numColumns, if not specified -->
         <attr name="numHotseatIcons" format="integer" />
+        <!-- Number of icons to use when extending the hotseat size,
+         defaults to 2 * numHotseatIcons -->
+        <attr name="numExtendedHotseatIcons" format="integer" />
+
         <attr name="dbFile" format="string" />
         <attr name="defaultLayoutId" format="reference" />
         <attr name="demoModeLayoutId" format="reference" />
         <attr name="isScalable" format="boolean" />
         <attr name="devicePaddingId" format="reference" />
 
-        <!-- whether the grid option is shown to the user -->
-        <attr name="visible" format="boolean" />
-
     </declare-styleable>
 
     <declare-styleable name="DevicePadding">
@@ -167,8 +174,12 @@
         <attr name="iconTextSize" format="float" />
         <!-- landscapeIconTextSize defaults to iconTextSize, if not specified -->
         <attr name="landscapeIconTextSize" format="float" />
-        <!-- If true, this display option is used to determine the default grid -->
-        <attr name="canBeDefault" format="boolean" />
+
+        <!-- If set, this display option is used to determine the default grid -->
+        <attr name="canBeDefault" format="boolean|integer" >
+            <!-- The profile can be default on split display devices -->
+            <flag name="split_display" value="0x2" />
+        </attr>
 
         <!-- The following values are only enabled if grid is supported. -->
         <!-- allAppsIconSize defaults to iconSize, if not specified -->
@@ -176,11 +187,6 @@
         <!-- allAppsIconTextSize defaults to iconTextSize, if not specified -->
         <attr name="allAppsIconTextSize" format="float" />
 
-        <!-- numAllAppsColumns defaults to GridDisplayOption.numColumns, if not specified -->
-        <attr name="numAllAppsColumns" format="integer" />
-
-        <!-- numShownHotseatIcons defaults to GridDisplayOption.numHotseatIcons, if not specified -->
-        <attr name="numShownHotseatIcons" format="integer" />
     </declare-styleable>
 
     <declare-styleable name="CellLayout">
diff --git a/res/values/config.xml b/res/values/config.xml
index 1e78373..9ad1224 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -55,9 +55,6 @@
     <!-- The duration of the caret animation -->
     <integer name="config_caretAnimationDuration">200</integer>
 
-    <!-- Hotseat -->
-    <bool name="hotseat_transpose_layout_with_orientation">true</bool>
-
     <!-- Various classes overriden by projects/build flavors. -->
     <string name="folder_name_provider_class" translatable="false"></string>
     <string name="stats_log_manager_class" translatable="false"></string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d6936ab..eae32b7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -221,7 +221,7 @@
     <!-- Text for wallpaper change button [CHAR LIMIT=30]-->
     <string name="wallpaper_button_text">Wallpapers</string>
     <!-- Text for wallpaper change button [CHAR LIMIT=30]-->
-    <string name="styles_wallpaper_button_text">Styles &amp; wallpapers</string>
+    <string name="styles_wallpaper_button_text">Wallpaper &amp; style</string>
     <!-- Text for settings button [CHAR LIMIT=30]-->
     <string name="settings_button_text">Home settings</string>
     <!-- Message shown when a feature is disabled by the administrator -->
diff --git a/robolectric_tests/src/com/android/launcher3/shadows/ShadowDeviceFlag.java b/robolectric_tests/src/com/android/launcher3/shadows/ShadowDeviceFlag.java
index 344f532..b58e4b7 100644
--- a/robolectric_tests/src/com/android/launcher3/shadows/ShadowDeviceFlag.java
+++ b/robolectric_tests/src/com/android/launcher3/shadows/ShadowDeviceFlag.java
@@ -18,11 +18,15 @@
 
 import android.content.Context;
 
+import androidx.annotation.Nullable;
+
 import com.android.launcher3.uioverrides.DeviceFlag;
 import com.android.launcher3.util.LooperExecutor;
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.RealObject;
+import org.robolectric.shadow.api.Shadow;
 
 /**
  * Shadow for {@link LooperExecutor} to provide reset functionality for static executors.
@@ -30,6 +34,9 @@
 @Implements(value = DeviceFlag.class, isInAndroidSdk = false)
 public class ShadowDeviceFlag {
 
+    @RealObject private DeviceFlag mRealObject;
+    @Nullable private Boolean mValue;
+
     /**
      * Mock change listener as it uses internal system classes not available to robolectric
      */
@@ -40,4 +47,16 @@
     protected static boolean getDeviceValue(String key, boolean defaultValue) {
         return defaultValue;
     }
+
+    @Implementation
+    public boolean get() {
+        if (mValue != null) {
+            return mValue;
+        }
+        return Shadow.directlyOn(mRealObject, DeviceFlag.class, "get");
+    }
+
+    public void setValue(boolean value) {
+        mValue = new Boolean(value);
+    }
 }
diff --git a/robolectric_tests/src/com/android/launcher3/ui/LauncherUIScrollTest.java b/robolectric_tests/src/com/android/launcher3/ui/LauncherUIScrollTest.java
index 4d151f1..ea75548 100644
--- a/robolectric_tests/src/com/android/launcher3/ui/LauncherUIScrollTest.java
+++ b/robolectric_tests/src/com/android/launcher3/ui/LauncherUIScrollTest.java
@@ -161,7 +161,7 @@
 
     private static MotionEvent createScrollEvent(int scroll) {
         DeviceProfile dp = InvariantDeviceProfile.INSTANCE
-                .get(RuntimeEnvironment.application).portraitProfile;
+                .get(RuntimeEnvironment.application).supportedProfiles.get(0);
 
         final PointerProperties[] pointerProperties = new PointerProperties[1];
         pointerProperties[0] = new PointerProperties();
diff --git a/robolectric_tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java b/robolectric_tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
index 92f77f2..d977011 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
@@ -17,6 +17,9 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+
 import android.content.Context;
 import android.graphics.Point;
 
@@ -109,10 +112,14 @@
 
     private InvariantDeviceProfile createIDP() {
         DeviceProfile profile = Mockito.mock(DeviceProfile.class);
+        doAnswer(i -> {
+            ((Point) i.getArgument(0)).set(CELL_SIZE, CELL_SIZE);
+            return null;
+        }).when(profile).getCellSize(any(Point.class));
         Mockito.when(profile.getCellSize()).thenReturn(new Point(CELL_SIZE, CELL_SIZE));
 
         InvariantDeviceProfile idp = new InvariantDeviceProfile();
-        idp.landscapeProfile = idp.portraitProfile = profile;
+        idp.supportedProfiles.add(profile);
         return idp;
     }
 
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 5d41bb5..c1f3ac5 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -1,5 +1,7 @@
 package com.android.launcher3;
 
+import static android.appwidget.AppWidgetHostView.getDefaultPaddingForWidget;
+
 import static com.android.launcher3.LauncherAnimUtils.LAYOUT_HEIGHT;
 import static com.android.launcher3.LauncherAnimUtils.LAYOUT_WIDTH;
 import static com.android.launcher3.Utilities.ATLEAST_S;
@@ -10,7 +12,9 @@
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -25,16 +29,14 @@
 import android.widget.ImageButton;
 import android.widget.ImageView;
 
-import androidx.annotation.Nullable;
-
 import com.android.launcher3.accessibility.DragViewStateAnnouncer;
 import com.android.launcher3.dragndrop.DragLayer;
-import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.widget.LauncherAppWidgetHostView;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 public class AppWidgetResizeFrame extends AbstractFloatingView implements View.OnKeyListener {
     private static final int SNAP_DURATION = 150;
@@ -43,22 +45,6 @@
 
     private static final Rect sTmpRect = new Rect();
 
-    // Represents the cell size on the grid in the two orientations.
-    public static final MainThreadInitializedObject<Point[]> CELL_SIZE =
-            new MainThreadInitializedObject<>(c -> {
-                InvariantDeviceProfile inv = LauncherAppState.getIDP(c);
-                return new Point[] {inv.landscapeProfile.getCellSize(),
-                        inv.portraitProfile.getCellSize()};
-            });
-
-    // Represents the border spacing size on the grid in the two orientations.
-    public static final MainThreadInitializedObject<int[]> BORDER_SPACING_SIZE =
-            new MainThreadInitializedObject<>(c -> {
-                InvariantDeviceProfile inv = LauncherAppState.getIDP(c);
-                return new int[] {inv.landscapeProfile.cellLayoutBorderSpacingPx,
-                        inv.portraitProfile.cellLayoutBorderSpacingPx};
-            });
-
     private static final int HANDLE_COUNT = 4;
     private static final int INDEX_LEFT = 0;
     private static final int INDEX_TOP = 1;
@@ -71,6 +57,22 @@
 
     private final View[] mDragHandles = new View[HANDLE_COUNT];
     private final List<Rect> mSystemGestureExclusionRects = new ArrayList<>(HANDLE_COUNT);
+    private final OnAttachStateChangeListener mWidgetViewAttachStateChangeListener =
+            new OnAttachStateChangeListener() {
+                @Override
+                public void onViewAttachedToWindow(View view) {
+                    // Do nothing
+                }
+
+                @Override
+                public void onViewDetachedFromWindow(View view) {
+                    // When the app widget view is detached, we should close the resize frame.
+                    // An example is when the dragging starts, the widget view is detached from
+                    // CellLayout and then reattached to DragLayout.
+                    close(false);
+                }
+            };
+
 
     private LauncherAppWidgetHostView mWidgetView;
     private CellLayout mCellLayout;
@@ -191,7 +193,11 @@
     private void setupForWidget(LauncherAppWidgetHostView widgetView, CellLayout cellLayout,
             DragLayer dragLayer) {
         mCellLayout = cellLayout;
+        if (mWidgetView != null) {
+            mWidgetView.removeOnAttachStateChangeListener(mWidgetViewAttachStateChangeListener);
+        }
         mWidgetView = widgetView;
+        mWidgetView.addOnAttachStateChangeListener(mWidgetViewAttachStateChangeListener);
         LauncherAppWidgetProviderInfo info = (LauncherAppWidgetProviderInfo)
                 widgetView.getAppWidgetInfo();
         mResizeMode = info.resizeMode;
@@ -202,7 +208,7 @@
         mMaxHSpan = info.maxSpanX;
         mMaxVSpan = info.maxSpanY;
 
-        mWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(getContext(),
+        mWidgetPadding = getDefaultPaddingForWidget(getContext(),
                 widgetView.getAppWidgetInfo().provider, null);
 
         if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
@@ -392,81 +398,82 @@
         mWidgetView.requestLayout();
     }
 
-    public static void updateWidgetSizeRanges(AppWidgetHostView widgetView, Launcher launcher,
-                                              int spanX, int spanY) {
-        List<SizeF> sizes = getWidgetSizes(launcher, spanX, spanY);
+    public static void updateWidgetSizeRanges(
+            AppWidgetHostView widgetView, Context context, int spanX, int spanY) {
+        List<SizeF> sizes = getWidgetSizes(context, spanX, spanY);
         if (ATLEAST_S) {
             widgetView.updateAppWidgetSize(new Bundle(), sizes);
         } else {
-            Rect bounds = getMinMaxSizes(sizes, null /* outRect */);
+            Rect bounds = getMinMaxSizes(sizes);
             widgetView.updateAppWidgetSize(new Bundle(), bounds.left, bounds.top, bounds.right,
                     bounds.bottom);
         }
     }
 
-    private static SizeF getWidgetSize(Context context, Point cellSize, int spanX, int spanY,
-            int borderSpacing) {
-        final float density = context.getResources().getDisplayMetrics().density;
-        final float hBorderSpacing = (spanX - 1) * borderSpacing;
-        final float vBorderSpacing = (spanY - 1) * borderSpacing;
-
-        return new SizeF(((spanX * cellSize.x) + hBorderSpacing) / density,
-                ((spanY * cellSize.y) + vBorderSpacing) / density);
-    }
-
     /** Returns the list of sizes for a widget of given span, in dp. */
     public static ArrayList<SizeF> getWidgetSizes(Context context, int spanX, int spanY) {
-        final Point[] cellSize = CELL_SIZE.get(context);
-        final int[] borderSpacing = BORDER_SPACING_SIZE.get(context);
-
-        SizeF landSize = getWidgetSize(context, cellSize[0], spanX, spanY, borderSpacing[0]);
-        SizeF portSize = getWidgetSize(context, cellSize[1], spanX, spanY, borderSpacing[1]);
-
         ArrayList<SizeF> sizes = new ArrayList<>(2);
-        sizes.add(landSize);
-        sizes.add(portSize);
+        final float density = context.getResources().getDisplayMetrics().density;
+        Point cellSize = new Point();
+
+        for (DeviceProfile profile : LauncherAppState.getIDP(context).supportedProfiles) {
+            final float hBorderSpacing = (spanX - 1) * profile.cellLayoutBorderSpacingPx;
+            final float vBorderSpacing = (spanY - 1) * profile.cellLayoutBorderSpacingPx;
+            profile.getCellSize(cellSize);
+            sizes.add(new SizeF(
+                    ((spanX * cellSize.x) + hBorderSpacing) / density,
+                    ((spanY * cellSize.y) + vBorderSpacing) / density));
+        }
         return sizes;
     }
 
     /**
+     * Returns the bundle to be used as the default options for a widget with provided size
+     */
+    public static Bundle getWidgetSizeOptions(
+            Context context, ComponentName provider, int spanX, int spanY) {
+        ArrayList<SizeF> sizes = getWidgetSizes(context, spanX, spanY);
+        Rect padding = getDefaultPaddingForWidget(context, provider, null);
+        float density = context.getResources().getDisplayMetrics().density;
+        float xPaddingDips = (padding.left + padding.right) / density;
+        float yPaddingDips = (padding.top + padding.bottom) / density;
+
+        ArrayList<SizeF> paddedSizes = sizes.stream()
+                .map(size -> new SizeF(
+                        Math.max(0.f, size.getWidth() - xPaddingDips),
+                        Math.max(0.f, size.getHeight() - yPaddingDips)))
+                .collect(Collectors.toCollection(ArrayList::new));
+
+        Rect rect = AppWidgetResizeFrame.getMinMaxSizes(paddedSizes);
+        Bundle options = new Bundle();
+        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, rect.left);
+        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, rect.top);
+        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, rect.right);
+        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, rect.bottom);
+        options.putParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES, paddedSizes);
+        return options;
+    }
+
+    /**
      * Returns the min and max widths and heights given a list of sizes, in dp.
      *
      * @param sizes List of sizes to get the min/max from.
-     * @param outRect Rectangle in which the result can be stored, to avoid extra allocations. If
-     *               null, a new rectangle will be allocated.
      * @return A rectangle with the left (resp. top) is used for the min width (resp. height) and
      * the right (resp. bottom) for the max. The returned rectangle is set with 0s if the list is
      * empty.
      */
-    public static Rect getMinMaxSizes(List<SizeF> sizes, @Nullable Rect outRect) {
-        if (outRect == null) {
-            outRect = new Rect();
-        }
+    private static Rect getMinMaxSizes(List<SizeF> sizes) {
         if (sizes.isEmpty()) {
-            outRect.set(0, 0, 0, 0);
+            return new Rect();
         } else {
             SizeF first = sizes.get(0);
-            outRect.set((int) first.getWidth(), (int) first.getHeight(), (int) first.getWidth(),
-                    (int) first.getHeight());
+            Rect result = new Rect((int) first.getWidth(), (int) first.getHeight(),
+                    (int) first.getWidth(), (int) first.getHeight());
             for (int i = 1; i < sizes.size(); i++) {
-                outRect.union((int) sizes.get(i).getWidth(), (int) sizes.get(i).getHeight());
+                result.union((int) sizes.get(i).getWidth(), (int) sizes.get(i).getHeight());
             }
+            return result;
         }
-        return outRect;
-    }
-
-    /**
-     * Returns the range of sizes a widget may be displayed, given its span.
-     *
-     * @param context Context in which the View is rendered.
-     * @param spanX Width of the widget, in cells.
-     * @param spanY Height of the widget, in cells.
-     * @param outRect Rectangle in which the result can be stored, to avoid extra allocations. If
-     *               null, a new rectangle will be allocated.
-     */
-    public static Rect getWidgetSizeRanges(Context context, int spanX, int spanY,
-            @Nullable Rect outRect) {
-        return getMinMaxSizes(getWidgetSizes(context, spanX, spanY), outRect);
     }
 
     @Override
@@ -641,6 +648,9 @@
     @Override
     protected void handleClose(boolean animate) {
         mDragLayer.removeView(this);
+        if (mWidgetView != null) {
+            mWidgetView.removeOnAttachStateChangeListener(mWidgetViewAttachStateChangeListener);
+        }
     }
 
     @Override
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 2f755e1..1df9df6 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -18,6 +18,7 @@
 
 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;
@@ -193,6 +194,8 @@
     private static final int INVALID_DIRECTION = -100;
 
     private final Rect mTempRect = new Rect();
+    private final RectF mTempRectF = new RectF();
+    private final float[] mTmpFloatArray = new float[4];
 
     private static final Paint sPaint = new Paint();
 
@@ -1070,11 +1073,16 @@
         // Apply local extracted color if the DragView is an AppWidgetHostViewDrawable.
         View view = dragObject.dragView.getContentView();
         if (view instanceof LauncherAppWidgetHostView) {
-            Workspace workspace =
-                    Launcher.getLauncher(dragObject.dragView.getContext()).getWorkspace();
+            Launcher launcher = Launcher.getLauncher(dragObject.dragView.getContext());
+            Workspace workspace = launcher.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,
+                    mTmpFloatArray, mTempRectF);
+            Utilities.setRect(mTempRectF, mTempRect);
             ((LauncherAppWidgetHostView) view).handleDrag(mTempRect, pageId);
         }
     }
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index fd97936..d5860dc 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -31,7 +31,6 @@
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
 import android.util.DisplayMetrics;
-import android.util.Log;
 import android.view.Surface;
 import android.view.WindowInsets;
 import android.view.WindowManager;
@@ -42,7 +41,6 @@
 import com.android.launcher3.icons.DotRenderer;
 import com.android.launcher3.icons.GraphicsUtils;
 import com.android.launcher3.icons.IconNormalizer;
-import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.DisplayController.Info;
 import com.android.launcher3.util.WindowBounds;
@@ -52,9 +50,6 @@
 @SuppressLint("NewApi")
 public class DeviceProfile {
 
-    private static final float TABLET_MIN_DPS = 600;
-    private static final float LARGE_TABLET_MIN_DPS = 720;
-
     private static final int DEFAULT_DOT_SIZE = 100;
 
     public final InvariantDeviceProfile inv;
@@ -63,9 +58,9 @@
 
     // Device properties
     public final boolean isTablet;
-    public final boolean isLargeTablet;
     public final boolean isPhone;
     public final boolean transposeLayoutWithOrientation;
+    public final boolean isTwoPanels;
 
     // Device properties in current orientation
     public final boolean isLandscape;
@@ -164,6 +159,7 @@
     public int allAppsCellWidthPx;
     public int allAppsIconSizePx;
     public int allAppsIconDrawablePaddingPx;
+    public final int numShownAllAppsColumns;
     public float allAppsIconTextSizePx;
 
     // Overview
@@ -194,42 +190,30 @@
     // How much of the bottom inset is due to Taskbar rather than other system elements.
     public int nonOverlappingTaskbarInset;
 
-    DeviceProfile(Context context, InvariantDeviceProfile inv, Info info,
-            Point minSize, Point maxSize, int width, int height, boolean isLandscape,
+    DeviceProfile(Context context, InvariantDeviceProfile inv, Info info, WindowBounds windowBounds,
             boolean isMultiWindowMode, boolean transposeLayoutWithOrientation,
-            Point windowPosition) {
+            boolean useTwoPanels) {
 
         this.inv = inv;
-        this.isLandscape = isLandscape;
+        this.isLandscape = windowBounds.isLandscape();
         this.isMultiWindowMode = isMultiWindowMode;
         this.transposeLayoutWithOrientation = transposeLayoutWithOrientation;
-        windowX = windowPosition.x;
-        windowY = windowPosition.y;
+        windowX = windowBounds.bounds.left;
+        windowY = windowBounds.bounds.top;
 
         isScalableGrid = inv.isScalable && !isVerticalBarLayout() && !isMultiWindowMode;
 
         // Determine sizes.
-        widthPx = width;
-        heightPx = height;
-        int nonFinalAvailableHeightPx;
-        if (isLandscape) {
-            availableWidthPx = maxSize.x;
-            nonFinalAvailableHeightPx = minSize.y;
-        } else {
-            availableWidthPx = minSize.x;
-            nonFinalAvailableHeightPx = maxSize.y;
-        }
+        widthPx = windowBounds.bounds.width();
+        heightPx = windowBounds.bounds.height();
+        availableWidthPx = windowBounds.availableSize.x;
+        int nonFinalAvailableHeightPx = windowBounds.availableSize.y;
 
         mInfo = info;
+        isTablet = info.isTablet(windowBounds);
+        isPhone = !isTablet;
+        isTwoPanels = isTablet && useTwoPanels;
 
-        // Constants from resources
-        float swDPs = dpiFromPx(Math.min(info.smallestSize.x, info.smallestSize.y),
-                info.densityDpi);
-        boolean allowRotation = context.getResources().getBoolean(R.bool.allow_rotation);
-        // Tablet UI is built with assumption that simulated landscape is disabled.
-        isTablet = allowRotation && swDPs >= TABLET_MIN_DPS;
-        isLargeTablet = isTablet && swDPs >= LARGE_TABLET_MIN_DPS;
-        isPhone = !isTablet && !isLargeTablet;
         aspectRatio = ((float) Math.max(widthPx, heightPx)) / Math.min(widthPx, heightPx);
         boolean isTallDevice = Float.compare(aspectRatio, TALL_DEVICE_ASPECT_RATIO_THRESHOLD) >= 0;
 
@@ -284,7 +268,7 @@
                 ? 0
                 : res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_layout_padding);
 
-        if (FeatureFlags.ENABLE_TWO_PANEL_HOME.get() && isTablet) {
+        if (isTwoPanels) {
             cellLayoutPaddingLeftRightPx =
                     res.getDimensionPixelSize(R.dimen.two_panel_home_side_padding);
             cellLayoutBottomPaddingPx = 0;
@@ -309,7 +293,10 @@
 
         workspaceCellPaddingXPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_x);
 
-        numShownHotseatIcons = inv.numShownHotseatIcons;
+        numShownHotseatIcons =
+                isTwoPanels ? inv.numDatabaseHotseatIcons : inv.numShownHotseatIcons;
+        numShownAllAppsColumns =
+                isTwoPanels ? inv.numDatabaseAllAppsColumns : inv.numAllAppsColumns;
         hotseatBarTopPaddingPx =
                 res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding);
         hotseatBarBottomPaddingPx = (isTallDevice ? 0
@@ -393,11 +380,12 @@
     }
 
     public Builder toBuilder(Context context) {
-        Point size = new Point(availableWidthPx, availableHeightPx);
+        WindowBounds bounds =
+                new WindowBounds(widthPx, heightPx, availableWidthPx, availableHeightPx);
+        bounds.bounds.offsetTo(windowX, windowY);
         return new Builder(context, inv, mInfo)
-                .setSizeRange(size, size)
-                .setSize(widthPx, heightPx)
-                .setWindowPosition(windowX, windowY)
+                .setWindowBounds(bounds)
+                .setUseTwoPanels(isTwoPanels)
                 .setMultiWindowMode(isMultiWindowMode);
     }
 
@@ -409,15 +397,8 @@
      * TODO: Move this to the builder as part of setMultiWindowMode
      */
     public DeviceProfile getMultiWindowProfile(Context context, WindowBounds windowBounds) {
-        // We take the minimum sizes of this profile and it's multi-window variant to ensure that
-        // the system decor is always excluded.
-        Point mwSize = new Point(Math.min(availableWidthPx, windowBounds.availableSize.x),
-                Math.min(availableHeightPx, windowBounds.availableSize.y));
-
         DeviceProfile profile = toBuilder(context)
-                .setSizeRange(mwSize, mwSize)
-                .setSize(windowBounds.bounds.width(), windowBounds.bounds.height())
-                .setWindowPosition(windowBounds.bounds.left, windowBounds.bounds.top)
+                .setWindowBounds(windowBounds)
                 .setMultiWindowMode(true)
                 .build();
 
@@ -434,14 +415,6 @@
     }
 
     /**
-     * Inverse of {@link #getMultiWindowProfile(Context, WindowBounds)}
-     * @return device profile corresponding to the current orientation in non multi-window mode.
-     */
-    public DeviceProfile getFullScreenProfile() {
-        return isLandscape ? inv.landscapeProfile : inv.portraitProfile;
-    }
-
-    /**
      * Checks if there is enough space for labels on the workspace.
      * If there is not, labels on the Workspace are hidden.
      * It is important to call this method after the All Apps variables have been set.
@@ -553,7 +526,7 @@
         }
 
         // All apps
-        if (allAppsHasDifferentNumColumns()) {
+        if (numShownAllAppsColumns != inv.numColumns) {
             allAppsIconSizePx = pxFromDp(inv.allAppsIconSize, mMetrics);
             allAppsIconTextSizePx = Utilities.pxFromSp(inv.allAppsIconTextSize, mMetrics);
             allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx;
@@ -667,18 +640,20 @@
     }
 
     public Point getCellSize() {
-        return getCellSize(inv.numColumns, inv.numRows);
+        return getCellSize(null);
     }
 
-    private Point getCellSize(int numColumns, int numRows) {
-        Point result = new Point();
+    public Point getCellSize(Point result) {
+        if (result == null) {
+            result = new Point();
+        }
         // Since we are only concerned with the overall padding, layout direction does
         // not matter.
         Point padding = getTotalWorkspacePadding();
         result.x = calculateCellWidth(availableWidthPx - padding.x
-                - cellLayoutPaddingLeftRightPx * 2, cellLayoutBorderSpacingPx, numColumns);
+                - cellLayoutPaddingLeftRightPx * 2, cellLayoutBorderSpacingPx, inv.numColumns);
         result.y = calculateCellHeight(availableHeightPx - padding.y
-                - cellLayoutBottomPaddingPx, cellLayoutBorderSpacingPx, numRows);
+                - cellLayoutBottomPaddingPx, cellLayoutBorderSpacingPx, inv.numRows);
         return result;
     }
 
@@ -723,7 +698,7 @@
                 padding.set(availablePaddingX / 2, edgeMarginPx + availablePaddingY / 2,
                         availablePaddingX / 2, paddingBottom + availablePaddingY / 2);
 
-                if (FeatureFlags.ENABLE_TWO_PANEL_HOME.get()) {
+                if (isTwoPanels) {
                     padding.set(0, padding.top, 0, padding.bottom);
                 }
             } else {
@@ -751,7 +726,7 @@
             // for this, we pad the left and right of the hotseat with half of the difference of a
             // workspace cell vs a hotseat cell.
             float workspaceCellWidth = (float) widthPx / inv.numColumns;
-            float hotseatCellWidth = (float) widthPx / inv.numShownHotseatIcons;
+            float hotseatCellWidth = (float) widthPx / numShownHotseatIcons;
             int hotseatAdjustment = Math.round((workspaceCellWidth - hotseatCellWidth) / 2);
             mHotseatPadding.set(
                     hotseatAdjustment + workspacePadding.left + cellLayoutPaddingLeftRightPx
@@ -802,13 +777,6 @@
     }
 
     /**
-     * Returns true when the number of workspace columns and all apps columns differs.
-     */
-    private boolean allAppsHasDifferentNumColumns() {
-        return inv.numAllAppsColumns != inv.numColumns;
-    }
-
-    /**
      * Updates orientation information and returns true if it has changed from the previous value.
      */
     public boolean updateIsSeascape(Context context) {
@@ -828,7 +796,7 @@
     }
 
     public boolean shouldFadeAdjacentWorkspaceScreens() {
-        return isVerticalBarLayout() || isLargeTablet;
+        return isVerticalBarLayout();
     }
 
     public int getCellHeight(@ContainerType int containerType) {
@@ -854,13 +822,13 @@
         writer.println(prefix + "\t1 dp = " + mMetrics.density + " px");
 
         writer.println(prefix + "\tisTablet:" + isTablet);
-        writer.println(prefix + "\tisLargeTablet:" + isLargeTablet);
         writer.println(prefix + "\tisPhone:" + isPhone);
         writer.println(prefix + "\ttransposeLayoutWithOrientation:"
                 + transposeLayoutWithOrientation);
 
         writer.println(prefix + "\tisLandscape:" + isLandscape);
         writer.println(prefix + "\tisMultiWindowMode:" + isMultiWindowMode);
+        writer.println(prefix + "\tisTwoPanels:" + isTwoPanels);
 
         writer.println(prefix + pxToDpStr("windowX", windowX));
         writer.println(prefix + pxToDpStr("windowY", windowY));
@@ -907,6 +875,7 @@
         writer.println(prefix + pxToDpStr("allAppsIconDrawablePaddingPx",
                 allAppsIconDrawablePaddingPx));
         writer.println(prefix + pxToDpStr("allAppsCellHeightPx", allAppsCellHeightPx));
+        writer.println(prefix + "\tnumShownAllAppsColumns: " + numShownAllAppsColumns);
 
         writer.println(prefix + pxToDpStr("hotseatBarSizePx", hotseatBarSizePx));
         writer.println(prefix + pxToDpStr("hotseatCellHeightPx", hotseatCellHeightPx));
@@ -916,6 +885,7 @@
                 hotseatBarSidePaddingStartPx));
         writer.println(prefix + pxToDpStr("hotseatBarSidePaddingEndPx",
                 hotseatBarSidePaddingEndPx));
+        writer.println(prefix + "\tnumShownHotseatIcons: " + numShownHotseatIcons);
 
         writer.println(prefix + "\tisTaskbarPresent:" + isTaskbarPresent);
 
@@ -967,41 +937,16 @@
         private InvariantDeviceProfile mInv;
         private Info mInfo;
 
-        private final Point mWindowPosition = new Point();
-        private Point mMinSize, mMaxSize;
-        private int mWidth, mHeight;
+        private WindowBounds mWindowBounds;
+        private boolean mUseTwoPanels;
 
-        private boolean mIsLandscape;
         private boolean mIsMultiWindowMode = false;
-        private boolean mTransposeLayoutWithOrientation;
+        private Boolean mTransposeLayoutWithOrientation;
 
         public Builder(Context context, InvariantDeviceProfile inv, Info info) {
             mContext = context;
             mInv = inv;
             mInfo = info;
-            mTransposeLayoutWithOrientation = context.getResources()
-                    .getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
-            if (TestProtocol.sDebugTracing) {
-                Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED,
-                        "transposeLayout=" + mTransposeLayoutWithOrientation);
-            }
-        }
-
-        public Builder setSizeRange(Point minSize, Point maxSize) {
-            mMinSize = minSize;
-            mMaxSize = maxSize;
-            return this;
-        }
-
-        public Builder setSize(int width, int height) {
-            mWidth = width;
-            mHeight = height;
-            mIsLandscape = mWidth > mHeight;
-            if (TestProtocol.sDebugTracing) {
-                Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED,
-                        "isLandscape=" + mIsLandscape + " w=" + mWidth + " h=" + mHeight);
-            }
-            return this;
         }
 
         public Builder setMultiWindowMode(boolean isMultiWindowMode) {
@@ -1009,11 +954,14 @@
             return this;
         }
 
-        /**
-         * Sets the window position if not full-screen
-         */
-        public Builder setWindowPosition(int x, int y) {
-            mWindowPosition.set(x, y);
+        public Builder setUseTwoPanels(boolean useTwoPanels) {
+            mUseTwoPanels = useTwoPanels;
+            return this;
+        }
+
+
+        public Builder setWindowBounds(WindowBounds bounds) {
+            mWindowBounds = bounds;
             return this;
         }
 
@@ -1023,9 +971,14 @@
         }
 
         public DeviceProfile build() {
-            return new DeviceProfile(mContext, mInv, mInfo, mMinSize, mMaxSize,
-                    mWidth, mHeight, mIsLandscape, mIsMultiWindowMode,
-                    mTransposeLayoutWithOrientation, mWindowPosition);
+            if (mWindowBounds == null) {
+                throw new IllegalArgumentException("Window bounds not set");
+            }
+            if (mTransposeLayoutWithOrientation == null) {
+                mTransposeLayoutWithOrientation = !mInfo.isTablet(mWindowBounds);
+            }
+            return new DeviceProfile(mContext, mInv, mInfo, mWindowBounds,
+                    mIsMultiWindowMode, mTransposeLayoutWithOrientation, mUseTwoPanels);
         }
     }
 
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 8496fd5..b2a9e75 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -90,11 +90,11 @@
     public void resetLayout(boolean hasVerticalHotseat) {
         removeAllViewsInLayout();
         mHasVerticalHotseat = hasVerticalHotseat;
-        InvariantDeviceProfile idp = mActivity.getDeviceProfile().inv;
+        DeviceProfile dp = mActivity.getDeviceProfile();
         if (hasVerticalHotseat) {
-            setGridSize(1, idp.numShownHotseatIcons);
+            setGridSize(1, dp.numShownHotseatIcons);
         } else {
-            setGridSize(idp.numShownHotseatIcons, 1);
+            setGridSize(dp.numShownHotseatIcons, 1);
         }
     }
 
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 1332e14..b263d38 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -16,11 +16,12 @@
 
 package com.android.launcher3;
 
+import static com.android.launcher3.Utilities.dpiFromPx;
 import static com.android.launcher3.Utilities.getDevicePrefs;
 import static com.android.launcher3.Utilities.getPointString;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_TWO_PANEL_HOME;
 import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
-import static com.android.launcher3.util.DisplayController.CHANGE_SIZE;
+import static com.android.launcher3.util.DisplayController.CHANGE_SUPPORTED_BOUNDS;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;
 
@@ -55,6 +56,7 @@
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.Themes;
+import com.android.launcher3.util.WindowBounds;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -62,6 +64,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 
 public class InvariantDeviceProfile {
 
@@ -73,6 +76,9 @@
     public static final String KEY_MIGRATION_SRC_WORKSPACE_SIZE = "migration_src_workspace_size";
     public static final String KEY_MIGRATION_SRC_HOTSEAT_COUNT = "migration_src_hotseat_count";
 
+    private static final int DEFAULT_TRUE = -1;
+    private static final int DEFAULT_SPLIT_DISPLAY = 2;
+
     private static final String KEY_IDP_GRID_NAME = "idp_grid_name";
 
     private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48;
@@ -136,6 +142,7 @@
      * Number of columns in the all apps list.
      */
     public int numAllAppsColumns;
+    public int numDatabaseAllAppsColumns;
 
     /**
      * Do not query directly. see {@link DeviceProfile#isScalableGrid}.
@@ -147,8 +154,7 @@
     public int defaultLayoutId;
     int demoModeLayoutId;
 
-    public DeviceProfile landscapeProfile;
-    public DeviceProfile portraitProfile;
+    public final List<DeviceProfile> supportedProfiles = new ArrayList<>();
 
     @Nullable public DevicePaddings devicePaddings;
 
@@ -175,6 +181,7 @@
         numShownHotseatIcons = p.numShownHotseatIcons;
         numDatabaseHotseatIcons = p.numDatabaseHotseatIcons;
         numAllAppsColumns = p.numAllAppsColumns;
+        numDatabaseAllAppsColumns = p.numDatabaseAllAppsColumns;
         isScalable = p.isScalable;
         devicePaddingId = p.devicePaddingId;
         minCellHeight = p.minCellHeight;
@@ -204,7 +211,7 @@
 
         DisplayController.INSTANCE.get(context).addChangeListener(
                 (displayContext, info, flags) -> {
-                    if ((flags & (CHANGE_SIZE | CHANGE_DENSITY)) != 0) {
+                    if ((flags & (CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS)) != 0) {
                         onConfigChanged(displayContext);
                     }
                 });
@@ -232,35 +239,29 @@
         // Get the display info based on default display and interpolate it to existing display
         DisplayOption defaultDisplayOption = invDistWeightedInterpolate(
                 DisplayController.INSTANCE.get(context).getInfo(),
-                getPredefinedDeviceProfiles(context, gridName));
+                getPredefinedDeviceProfiles(context, gridName, false), false);
 
         Info myInfo = new Info(context, display);
         DisplayOption myDisplayOption = invDistWeightedInterpolate(
-                myInfo, getPredefinedDeviceProfiles(context, gridName));
+                myInfo, getPredefinedDeviceProfiles(context, gridName, false), false);
 
         DisplayOption result = new DisplayOption(defaultDisplayOption.grid)
                 .add(myDisplayOption);
         result.iconSize = defaultDisplayOption.iconSize;
         result.landscapeIconSize = defaultDisplayOption.landscapeIconSize;
-        result.numShownHotseatIcons = myDisplayOption.numShownHotseatIcons;
         if (defaultDisplayOption.allAppsIconSize < myDisplayOption.allAppsIconSize) {
             result.allAppsIconSize = defaultDisplayOption.allAppsIconSize;
-            result.numAllAppsColumns = defaultDisplayOption.numAllAppsColumns;
         } else {
             result.allAppsIconSize = myDisplayOption.allAppsIconSize;
-            result.numAllAppsColumns = myDisplayOption.numAllAppsColumns;
         }
         result.minCellHeight = defaultDisplayOption.minCellHeight;
         result.minCellWidth = defaultDisplayOption.minCellWidth;
         result.borderSpacing = defaultDisplayOption.borderSpacing;
 
-        initGrid(context, myInfo, result);
+        initGrid(context, myInfo, result, false);
     }
 
     public static String getCurrentGridName(Context context) {
-        if (ENABLE_TWO_PANEL_HOME.get()) {
-            return ENABLE_TWO_PANEL_HOME.key;
-        }
         return Utilities.isGridOptionsEnabled(context)
                 ? Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null) : null;
     }
@@ -278,20 +279,33 @@
 
     private String initGrid(Context context, String gridName) {
         Info displayInfo = DisplayController.INSTANCE.get(context).getInfo();
-        ArrayList<DisplayOption> allOptions = getPredefinedDeviceProfiles(context, gridName);
+        // Determine if we have split display
 
-        DisplayOption displayOption = invDistWeightedInterpolate(displayInfo, allOptions);
-        initGrid(context, displayInfo, displayOption);
+        boolean isTablet = false, isPhone = false;
+        for (WindowBounds bounds : displayInfo.supportedBounds) {
+            if (displayInfo.isTablet(bounds)) {
+                isTablet = true;
+            } else {
+                isPhone = true;
+            }
+        }
+        boolean isSplitDisplay = isPhone && isTablet && ENABLE_TWO_PANEL_HOME.get();
+
+        ArrayList<DisplayOption> allOptions =
+                getPredefinedDeviceProfiles(context, gridName, isSplitDisplay);
+        DisplayOption displayOption =
+                invDistWeightedInterpolate(displayInfo, allOptions, isSplitDisplay);
+        initGrid(context, displayInfo, displayOption, isSplitDisplay);
         return displayOption.grid.name;
     }
 
     private void initGrid(
-            Context context, Info displayInfo, DisplayOption displayOption) {
+            Context context, Info displayInfo, DisplayOption displayOption,
+            boolean isSplitDisplay) {
         DisplayMetrics metrics = context.getResources().getDisplayMetrics();
         GridOption closestProfile = displayOption.grid;
         numRows = closestProfile.numRows;
         numColumns = closestProfile.numColumns;
-        numDatabaseHotseatIcons = closestProfile.numDatabaseHotseatIcons;
         dbFile = closestProfile.dbFile;
         defaultLayoutId = closestProfile.defaultLayoutId;
         demoModeLayoutId = closestProfile.demoModeLayoutId;
@@ -313,8 +327,14 @@
         minCellHeight = displayOption.minCellHeight;
         minCellWidth = displayOption.minCellWidth;
         borderSpacing = displayOption.borderSpacing;
-        numShownHotseatIcons = Math.round(displayOption.numShownHotseatIcons);
-        numAllAppsColumns = Math.round(displayOption.numAllAppsColumns);
+
+        numShownHotseatIcons = closestProfile.numHotseatIcons;
+        numDatabaseHotseatIcons = isSplitDisplay
+                ? closestProfile.numDatabaseHotseatIcons : closestProfile.numHotseatIcons;
+
+        numAllAppsColumns = closestProfile.numAllAppsColumns;
+        numDatabaseAllAppsColumns = isSplitDisplay
+                ? closestProfile.numDatabaseAllAppsColumns : closestProfile.numAllAppsColumns;
 
         if (Utilities.isGridOptionsEnabled(context)) {
             allAppsIconSize = displayOption.allAppsIconSize;
@@ -332,31 +352,26 @@
         // Supported overrides: numRows, numColumns, iconSize
         applyPartnerDeviceProfileOverrides(context, metrics);
 
-        Point realSize = new Point(displayInfo.realSize);
-        // The real size never changes. smallSide and largeSide will remain the
-        // same in any orientation.
-        int smallSide = Math.min(realSize.x, realSize.y);
-        int largeSide = Math.max(realSize.x, realSize.y);
+        supportedProfiles.clear();
+        defaultWallpaperSize = new Point(displayInfo.currentSize);
+        for (WindowBounds bounds : displayInfo.supportedBounds) {
+            supportedProfiles.add(new DeviceProfile.Builder(context, this, displayInfo)
+                    .setUseTwoPanels(isSplitDisplay)
+                    .setWindowBounds(bounds).build());
 
-        DeviceProfile.Builder builder = new DeviceProfile.Builder(context, this, displayInfo)
-                .setSizeRange(new Point(displayInfo.smallestSize),
-                        new Point(displayInfo.largestSize));
-        if (TestProtocol.sDebugTracing) {
-            Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED,
-                    "largeSide=" + largeSide + " smallSide=" + smallSide);
-        }
+            // Wallpaper size should be the maximum of the all possible sizes Launcher expects
+            int displayWidth = bounds.bounds.width();
+            int displayHeight = bounds.bounds.height();
+            defaultWallpaperSize.y = Math.max(defaultWallpaperSize.y, displayHeight);
 
-        landscapeProfile = builder.setSize(largeSide, smallSide).build();
-        portraitProfile = builder.setSize(smallSide, largeSide).build();
-
-        // We need to ensure that there is enough extra space in the wallpaper
-        // for the intended parallax effects
-        if (context.getResources().getConfiguration().smallestScreenWidthDp >= 720) {
-            defaultWallpaperSize = new Point(
-                    (int) (largeSide * wallpaperTravelToScreenWidthRatio(largeSide, smallSide)),
-                    largeSide);
-        } else {
-            defaultWallpaperSize = new Point(Math.max(smallSide * 2, largeSide), largeSide);
+            // We need to ensure that there is enough extra space in the wallpaper
+            // for the intended parallax effects
+            float parallaxFactor =
+                    dpiFromPx(Math.min(displayWidth, displayHeight), displayInfo.densityDpi) < 720
+                            ? 2
+                            : wallpaperTravelToScreenWidthRatio(displayWidth, displayHeight);
+            defaultWallpaperSize.x =
+                    Math.max(defaultWallpaperSize.x, Math.round(parallaxFactor * displayWidth));
         }
 
         ComponentName cn = new ComponentName(context.getPackageName(), getClass().getName());
@@ -385,7 +400,7 @@
         } else if (!savedIconMaskPath.equals(getIconShapePath(context))) {
             getDevicePrefs(context).edit().putString(KEY_ICON_PATH_REF, getIconShapePath(context))
                     .apply();
-            apply(context, CHANGE_FLAG_ICON_PARAMS);
+            apply(CHANGE_FLAG_ICON_PARAMS);
         }
     }
 
@@ -423,16 +438,17 @@
             IconShape.init(context);
         }
 
-        apply(context, changeFlags);
+        apply(changeFlags);
     }
 
-    private void apply(Context context, int changeFlags) {
+    private void apply(int changeFlags) {
         for (OnIDPChangeListener listener : mChangeListeners) {
             listener.onIdpChanged(changeFlags, this);
         }
     }
 
-    static ArrayList<DisplayOption> getPredefinedDeviceProfiles(Context context, String gridName) {
+    private static ArrayList<DisplayOption> getPredefinedDeviceProfiles(
+            Context context, String gridName, boolean isSplitDisplay) {
         ArrayList<DisplayOption> profiles = new ArrayList<>();
         try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
             final int depth = parser.getDepth();
@@ -449,8 +465,9 @@
                             && type != XmlPullParser.END_DOCUMENT) {
                         if ((type == XmlPullParser.START_TAG) && "display-option".equals(
                                 parser.getName())) {
-                            profiles.add(new DisplayOption(
-                                    gridOption, context, Xml.asAttributeSet(parser)));
+                            profiles.add(new DisplayOption(gridOption, context,
+                                    Xml.asAttributeSet(parser),
+                                    isSplitDisplay ? DEFAULT_SPLIT_DISPLAY : DEFAULT_TRUE));
                         }
                     }
                 }
@@ -521,17 +538,29 @@
         return (float) Math.hypot(x1 - x0, y1 - y0);
     }
 
-    @VisibleForTesting
-    static DisplayOption invDistWeightedInterpolate(
-            Info displayInfo, ArrayList<DisplayOption> points) {
-        Point smallestSize = new Point(displayInfo.smallestSize);
-        Point largestSize = new Point(displayInfo.largestSize);
+    private static DisplayOption invDistWeightedInterpolate(
+            Info displayInfo, ArrayList<DisplayOption> points, boolean isSplitDisplay) {
+        int minWidthPx = Integer.MAX_VALUE;
+        int minHeightPx = Integer.MAX_VALUE;
+        for (WindowBounds bounds : displayInfo.supportedBounds) {
+            boolean isTablet = displayInfo.isTablet(bounds);
+            if (isTablet && isSplitDisplay) {
+                // For split displays, take half width per page
+                minWidthPx = Math.min(minWidthPx, bounds.availableSize.x / 2);
+                minHeightPx = Math.min(minHeightPx, bounds.availableSize.y);
 
-        // This guarantees that width < height
-        float width = Utilities.dpiFromPx((float) Math.min(smallestSize.x, smallestSize.y),
-                displayInfo.densityDpi);
-        float height = Utilities.dpiFromPx((float) Math.min(largestSize.x, largestSize.y),
-                displayInfo.densityDpi);
+            } else if (!isTablet && bounds.isLandscape()) {
+                // We will use transposed layout in this case
+                minWidthPx = Math.min(minWidthPx, bounds.availableSize.y);
+                minHeightPx = Math.min(minHeightPx, bounds.availableSize.x);
+            } else {
+                minWidthPx = Math.min(minWidthPx, bounds.availableSize.x);
+                minHeightPx = Math.min(minHeightPx, bounds.availableSize.y);
+            }
+        }
+
+        float width = dpiFromPx(minWidthPx, displayInfo.densityDpi);
+        float height = dpiFromPx(minHeightPx, displayInfo.densityDpi);
 
         // Sort the profiles based on the closeness to the device size
         Collections.sort(points, (a, b) ->
@@ -556,33 +585,30 @@
         return out.multiply(1.0f / weights);
     }
 
-    @VisibleForTesting
-    static DisplayOption invDistWeightedInterpolate(float width, float height,
-            ArrayList<DisplayOption> points) {
-        float weights = 0;
-
-        DisplayOption p = points.get(0);
-        if (dist(width, height, p.minWidthDps, p.minHeightDps) == 0) {
-            return p;
-        }
-
-        DisplayOption out = new DisplayOption();
-        for (int i = 0; i < points.size() && i < KNEARESTNEIGHBOR; ++i) {
-            p = points.get(i);
-            float w = weight(width, height, p.minWidthDps, p.minHeightDps, WEIGHT_POWER);
-            weights += w;
-            out.add(new DisplayOption().add(p).multiply(w));
-        }
-        return out.multiply(1.0f / weights);
-    }
-
     public DeviceProfile getDeviceProfile(Context context) {
+        Resources res = context.getResources();
+        Configuration config = context.getResources().getConfiguration();
+
+        float availableWidth = config.screenWidthDp * res.getDisplayMetrics().density;
+        float availableHeight = config.screenHeightDp * res.getDisplayMetrics().density;
+
         if (TestProtocol.sDebugTracing) {
-            Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "getDeviceProfile: orientation="
-                    + context.getResources().getConfiguration().orientation);
+            Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED,
+                    "getDeviceProfile: orientation=" + config.orientation
+                            + " size=" + availableWidth + "x" + availableHeight);
         }
-        return context.getResources().getConfiguration().orientation
-                == Configuration.ORIENTATION_LANDSCAPE ? landscapeProfile : portraitProfile;
+        DeviceProfile bestMatch = supportedProfiles.get(0);
+        float minDiff = Float.MAX_VALUE;
+
+        for (DeviceProfile profile : supportedProfiles) {
+            float diff = Math.abs(profile.availableWidthPx - availableWidth)
+                    + Math.abs(profile.availableHeightPx - availableHeight);
+            if (diff < minDiff) {
+                minDiff = diff;
+                bestMatch = profile;
+            }
+        }
+        return bestMatch;
     }
 
     private static float weight(float x0, float y0, float x1, float y1, float pow) {
@@ -639,6 +665,9 @@
         private final int numFolderRows;
         private final int numFolderColumns;
 
+        private final int numAllAppsColumns;
+        private final int numDatabaseAllAppsColumns;
+        private final int numHotseatIcons;
         private final int numDatabaseHotseatIcons;
 
         private final String dbFile;
@@ -649,8 +678,6 @@
         private final boolean isScalable;
         private final int devicePaddingId;
 
-        public final boolean visible;
-
         private final SparseArray<TypedValue> extraAttrs;
 
         public GridOption(Context context, AttributeSet attrs) {
@@ -665,8 +692,17 @@
                     R.styleable.GridDisplayOption_defaultLayoutId, 0);
             demoModeLayoutId = a.getResourceId(
                     R.styleable.GridDisplayOption_demoModeLayoutId, defaultLayoutId);
-            numDatabaseHotseatIcons = a.getInt(
+
+            numAllAppsColumns = a.getInt(
+                    R.styleable.GridDisplayOption_numAllAppsColumns, numColumns);
+            numDatabaseAllAppsColumns = a.getInt(
+                    R.styleable.GridDisplayOption_numExtendedAllAppsColumns, 2 * numAllAppsColumns);
+
+            numHotseatIcons = a.getInt(
                     R.styleable.GridDisplayOption_numHotseatIcons, numColumns);
+            numDatabaseHotseatIcons = a.getInt(
+                    R.styleable.GridDisplayOption_numExtendedHotseatIcons, 2 * numHotseatIcons);
+
             numFolderRows = a.getInt(
                     R.styleable.GridDisplayOption_numFolderRows, numRows);
             numFolderColumns = a.getInt(
@@ -677,24 +713,21 @@
             devicePaddingId = a.getResourceId(
                     R.styleable.GridDisplayOption_devicePaddingId, 0);
 
-            visible = a.getBoolean(R.styleable.GridDisplayOption_visible, true);
-
             a.recycle();
-
             extraAttrs = Themes.createValueMap(context, attrs,
                     IntArray.wrap(R.styleable.GridDisplayOption));
         }
     }
 
-    private static final class DisplayOption {
-        private final GridOption grid;
+    @VisibleForTesting
+    static final class DisplayOption {
+
+        public final GridOption grid;
 
         private final float minWidthDps;
         private final float minHeightDps;
         private final boolean canBeDefault;
 
-        private float numShownHotseatIcons;
-        private float numAllAppsColumns;
         private float minCellHeight;
         private float minCellWidth;
         private float borderSpacing;
@@ -706,7 +739,7 @@
         private float allAppsIconSize;
         private float allAppsIconTextSize;
 
-        DisplayOption(GridOption grid, Context context, AttributeSet attrs) {
+        DisplayOption(GridOption grid, Context context, AttributeSet attrs, int defaultFlagValue) {
             this.grid = grid;
 
             TypedArray a = context.obtainStyledAttributes(
@@ -714,12 +747,9 @@
 
             minWidthDps = a.getFloat(R.styleable.ProfileDisplayOption_minWidthDps, 0);
             minHeightDps = a.getFloat(R.styleable.ProfileDisplayOption_minHeightDps, 0);
-            canBeDefault = a.getBoolean(
-                    R.styleable.ProfileDisplayOption_canBeDefault, false);
-            numShownHotseatIcons = a.getInt(R.styleable.ProfileDisplayOption_numShownHotseatIcons,
-                    grid.numDatabaseHotseatIcons);
-            numAllAppsColumns = a.getInt(R.styleable.ProfileDisplayOption_numAllAppsColumns,
-                    grid.numColumns);
+
+            canBeDefault = a.getInt(R.styleable.ProfileDisplayOption_canBeDefault, 0)
+                    == defaultFlagValue;
 
             minCellHeight = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightDps, 0);
             minCellWidth = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthDps, 0);
@@ -748,16 +778,12 @@
             minWidthDps = 0;
             minHeightDps = 0;
             canBeDefault = false;
-            numShownHotseatIcons = 0;
-            numAllAppsColumns = 0;
             minCellHeight = 0;
             minCellWidth = 0;
             borderSpacing = 0;
         }
 
         private DisplayOption multiply(float w) {
-            numShownHotseatIcons *= w;
-            numAllAppsColumns *= w;
             iconSize *= w;
             landscapeIconSize *= w;
             allAppsIconSize *= w;
@@ -771,8 +797,6 @@
         }
 
         private DisplayOption add(DisplayOption p) {
-            numShownHotseatIcons += p.numShownHotseatIcons;
-            numAllAppsColumns += p.numAllAppsColumns;
             iconSize += p.iconSize;
             landscapeIconSize += p.landscapeIconSize;
             allAppsIconSize += p.allAppsIconSize;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index f640118..09c7b7a 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -189,7 +189,6 @@
 import com.android.launcher3.widget.PendingAddWidgetInfo;
 import com.android.launcher3.widget.PendingAppWidgetHostView;
 import com.android.launcher3.widget.WidgetAddFlowHandler;
-import com.android.launcher3.widget.WidgetHostViewLoader;
 import com.android.launcher3.widget.WidgetManagerHelper;
 import com.android.launcher3.widget.custom.CustomWidgetManager;
 import com.android.launcher3.widget.model.WidgetsListBaseEntry;
@@ -2332,8 +2331,7 @@
                         pendingInfo.spanY = item.spanY;
                         pendingInfo.minSpanX = item.minSpanX;
                         pendingInfo.minSpanY = item.minSpanY;
-                        Bundle options = WidgetHostViewLoader.getDefaultOptionsForWidget(this,
-                                pendingInfo);
+                        Bundle options = pendingInfo.getDefaultSizeOptions(this);
 
                         boolean isDirectConfig =
                                 item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG);
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index a799b4a..972a6e8 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -33,6 +33,7 @@
 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;
@@ -74,9 +75,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;
@@ -84,6 +85,7 @@
 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;
@@ -104,6 +106,8 @@
     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();
@@ -133,6 +137,15 @@
             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;
@@ -219,6 +232,33 @@
     }
 
     /**
+     * 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, float[] recycle, RectF outRect) {
+        float[] points = recycle == null ? new float[4] : recycle;
+        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) {
@@ -273,6 +313,16 @@
         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();
@@ -596,13 +646,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/Workspace.java b/src/com/android/launcher3/Workspace.java
index 05d6e04..7c5f99e 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -456,7 +456,7 @@
     }
 
     private boolean isTwoPanelEnabled() {
-        return mLauncher.mDeviceProfile.isTablet && FeatureFlags.ENABLE_TWO_PANEL_HOME.get();
+        return mLauncher.mDeviceProfile.isTwoPanels;
     }
 
     @Override
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/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index a5852ba..dbdfb2b 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -32,6 +32,7 @@
 import com.android.launcher3.Workspace;
 import com.android.launcher3.dragndrop.DragController.DragListener;
 import com.android.launcher3.dragndrop.DragOptions;
+import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.keyboard.KeyboardDragAndDropView;
 import com.android.launcher3.model.data.AppInfo;
@@ -290,7 +291,12 @@
             return actions;
         }
 
-        CellLayout layout = (CellLayout) host.getParent().getParent();
+        CellLayout layout;
+        if (host.getParent() instanceof DragView) {
+            layout = (CellLayout) ((DragView) host.getParent()).getContentViewParent().getParent();
+        } else {
+            layout = (CellLayout) host.getParent().getParent();
+        }
         if ((providerInfo.resizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0) {
             if (layout.isRegionVacant(info.cellX + info.spanX, info.cellY, 1, info.spanY) ||
                     layout.isRegionVacant(info.cellX - 1, info.cellY, 1, info.spanY)) {
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 40f7ab1..b11b63e 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -75,7 +75,7 @@
 public class AllAppsContainerView extends SpringRelativeLayout implements DragSource,
         Insettable, OnDeviceProfileChangeListener, OnActivePageChangedListener {
 
-    private static final float FLING_VELOCITY_MULTIPLIER = 1800f;
+    private static final float FLING_VELOCITY_MULTIPLIER = 1000f;
 
     // Starts the springs after at least 25% of the animation has passed.
     private static final float FLING_ANIMATION_THRESHOLD = 0.25f;
@@ -157,7 +157,7 @@
     @Override
     public void onDeviceProfileChanged(DeviceProfile dp) {
         for (AdapterHolder holder : mAH) {
-            holder.adapter.setAppsPerRow(dp.inv.numAllAppsColumns);
+            holder.adapter.setAppsPerRow(dp.numShownAllAppsColumns);
             if (holder.recyclerView != null) {
                 // Remove all views and clear the pool, while keeping the data same. After this
                 // call, all the viewHolders will be recreated.
@@ -611,7 +611,7 @@
             public void onAnimationUpdate(ValueAnimator valueAnimator) {
                 if (shouldSpring
                         && valueAnimator.getAnimatedFraction() >= FLING_ANIMATION_THRESHOLD) {
-                    absorbSwipeUpVelocity(-Math.abs(
+                    absorbSwipeUpVelocity(Math.abs(
                             Math.round(velocity * FLING_VELOCITY_MULTIPLIER)));
                     shouldSpring = false;
                 }
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 5b4c4c5..70588ea 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -283,7 +283,7 @@
         mOnIconClickListener = launcher.getItemOnClickListener();
 
         mSearchAdapterProvider = searchAdapterProvider;
-        setAppsPerRow(mLauncher.getDeviceProfile().inv.numAllAppsColumns);
+        setAppsPerRow(mLauncher.getDeviceProfile().numShownAllAppsColumns);
     }
 
     public void setAppsPerRow(int appsPerRow) {
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index c61c0d6..c4c7891 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -15,13 +15,15 @@
  */
 package com.android.launcher3.allapps;
 
+import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.ALL_APPS_CONTENT;
-import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
+import static com.android.launcher3.anim.Interpolators.ACCEL_2;
+import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
 import static com.android.launcher3.util.SystemUiController.UI_STATE_ALLAPPS;
 
@@ -154,9 +156,9 @@
             return;
         }
 
-        Interpolator interpolator = config.userControlled ? LINEAR : toState == OVERVIEW
-                ? config.getInterpolator(ANIM_OVERVIEW_SCALE, FAST_OUT_SLOW_IN)
-                : FAST_OUT_SLOW_IN;
+        Interpolator interpolator = toState.equals(ALL_APPS)
+                ? (config.userControlled ? ACCEL_2 : ACCEL_0_75) :
+                        (config.userControlled ? DEACCEL_2 : DEACCEL);
 
         Animator anim = createSpringAnimation(mProgress, targetProgress);
         anim.setInterpolator(config.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index bad8704..3b88a0b 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(
@@ -226,6 +230,10 @@
     public static final BooleanFlag ENABLE_ENFORCED_ROUNDED_CORNERS = new DeviceFlag(
             "ENABLE_ENFORCED_ROUNDED_CORNERS", true, "Enforce rounded corners on all App Widgets");
 
+    public static final BooleanFlag ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER = new DeviceFlag(
+            "ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER", true,
+            "Enables a local filter for recommended widgets.");
+
     public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag("NOTIFY_CRASHES", false,
             "Sends a notification whenever launcher encounters an uncaught exception.");
 
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index d5a04a6..5ba36f2 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -64,7 +64,6 @@
 import com.android.launcher3.widget.PendingAddWidgetInfo;
 import com.android.launcher3.widget.WidgetCell;
 import com.android.launcher3.widget.WidgetCellPreview;
-import com.android.launcher3.widget.WidgetHostViewLoader;
 import com.android.launcher3.widget.WidgetImageView;
 import com.android.launcher3.widget.WidgetManagerHelper;
 
@@ -234,7 +233,7 @@
         PendingAddWidgetInfo pendingInfo = new PendingAddWidgetInfo(widgetInfo);
         pendingInfo.spanX = Math.min(mIdp.numColumns, widgetInfo.spanX);
         pendingInfo.spanY = Math.min(mIdp.numRows, widgetInfo.spanY);
-        mWidgetOptions = WidgetHostViewLoader.getDefaultOptionsForWidget(this, pendingInfo);
+        mWidgetOptions = pendingInfo.getDefaultSizeOptions(this);
         mWidgetCell.getWidgetView().setTag(pendingInfo);
 
         applyWidgetItemAsync(() -> new WidgetItem(widgetInfo, mIdp, mApp.getIconCache()));
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/GridCustomizationsProvider.java b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
index 911f8c3..cb42e7a 100644
--- a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
+++ b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
@@ -90,10 +90,7 @@
                     parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
                 if ((type == XmlPullParser.START_TAG)
                         && GridOption.TAG_NAME.equals(parser.getName())) {
-                    GridOption option = new GridOption(getContext(), Xml.asAttributeSet(parser));
-                    if (option.visible) {
-                        result.add(option);
-                    }
+                    result.add(new GridOption(getContext(), Xml.asAttributeSet(parser)));
                 }
             }
         } catch (IOException | XmlPullParserException e) {
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 31764c5..f5b6890 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,11 +219,11 @@
     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;
-        mDp = idp.portraitProfile.copy(context);
+        mDp = idp.getDeviceProfile(context).copy(context);
         mMigrated = migrated;
 
         // TODO: get correct insets once display cutout API is available.
@@ -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 13ae866..e45b8f7 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -21,7 +21,6 @@
 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;
@@ -34,6 +33,7 @@
 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,9 +119,7 @@
                 info,
                 IconPalette.getPreloadProgressColor(context, info.bitmap.color),
                 getPreloadColors(context),
-            (context.getResources().getConfiguration().uiMode
-                    & Configuration.UI_MODE_NIGHT_MASK
-                    & Configuration.UI_MODE_NIGHT_YES) != 0) /* isDarkMode */;
+                Utilities.isDarkTheme(context));
     }
 
     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/model/data/SearchActionItemInfo.java b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
index b3057d5..0eea92c 100644
--- a/src/com/android/launcher3/model/data/SearchActionItemInfo.java
+++ b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
@@ -94,6 +94,11 @@
                     "SearchActionItemInfo can only have either an Intent or a PendingIntent");
         }
         mIntent = intent;
+        // bandage fix for just one week
+        if (intent != null && "com.android.server.telecom".equals(intent.getPackage())) {
+            intent.setAction(Intent.ACTION_DIAL);
+            intent.setPackage(null);
+        }
     }
 
     public PendingIntent getPendingIntent() {
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index c19dfe9..c63d69d 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -16,7 +16,6 @@
 
 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;
 
@@ -31,6 +30,7 @@
 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;
@@ -41,17 +41,21 @@
 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;
@@ -59,9 +63,11 @@
 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.
@@ -73,6 +79,9 @@
 
     // +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();
 
@@ -104,8 +113,14 @@
 
     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);
@@ -113,7 +128,9 @@
         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
@@ -158,6 +175,10 @@
                 mColors[i] =
                         (int) argb.evaluate((i + 1) * step, primaryColor, secondaryColor);
             }
+
+            if (Utilities.ATLEAST_S) {
+                setupColorExtraction();
+            }
         }
     }
 
@@ -342,6 +363,15 @@
             // 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(),
@@ -350,9 +380,6 @@
                     mArrowColor));
             mArrow.setElevation(getElevation());
         }
-
-        mArrow.setPivotX(mArrowWidth / 2.0f);
-        mArrow.setPivotY(mIsAboveIcon ? mArrowHeight : 0);
     }
 
     /**
@@ -671,6 +698,12 @@
         getPopupContainer().removeView(this);
         getPopupContainer().removeView(mArrow);
         mOnCloseCallback.run();
+        mArrowColorRectString = null;
+        mViewForRect.clear();
+        if (mColorExtractor != null) {
+            mColorExtractor.removeLocations();
+            mColorExtractor.setListener(null);
+        }
     }
 
     /**
@@ -680,6 +713,68 @@
         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();
+                        mColorExtractor.getExtractedRectForView(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/qsb/QsbContainerView.java b/src/com/android/launcher3/qsb/QsbContainerView.java
index a191df4..22c3f58 100644
--- a/src/com/android/launcher3/qsb/QsbContainerView.java
+++ b/src/com/android/launcher3/qsb/QsbContainerView.java
@@ -20,7 +20,7 @@
 import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID;
 import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_PROVIDER;
 
-import static com.android.launcher3.Utilities.ATLEAST_S;
+import static com.android.launcher3.AppWidgetResizeFrame.getWidgetSizeOptions;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -32,11 +32,9 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.graphics.Rect;
 import android.os.Bundle;
 import android.provider.Settings;
 import android.util.AttributeSet;
-import android.util.SizeF;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -45,7 +43,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
-import com.android.launcher3.AppWidgetResizeFrame;
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
@@ -53,8 +50,6 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.graphics.FragmentWithPreview;
 
-import java.util.ArrayList;
-
 /**
  * A frame layout which contains a QSB. This internally uses fragment to bind the view, which
  * allows it to contain the logic for {@link Fragment#startActivityForResult(Intent, int)}.
@@ -163,7 +158,7 @@
 
         protected String mKeyWidgetId = "qsb_widget_id";
         private QsbWidgetHost mQsbWidgetHost;
-        private AppWidgetProviderInfo mWidgetInfo;
+        protected AppWidgetProviderInfo mWidgetInfo;
         private QsbWidgetHostView mQsb;
 
         // We need to store the orientation here, due to a bug (b/64916689) that results in widgets
@@ -297,19 +292,7 @@
 
         protected Bundle createBindOptions() {
             InvariantDeviceProfile idp = LauncherAppState.getIDP(getContext());
-
-            Bundle opts = new Bundle();
-            ArrayList<SizeF> sizes = AppWidgetResizeFrame
-                    .getWidgetSizes(getContext(), idp.numColumns, 1);
-            Rect size = AppWidgetResizeFrame.getMinMaxSizes(sizes, null /* outRect */);
-            opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, size.left);
-            opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, size.top);
-            opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, size.right);
-            opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, size.bottom);
-            if (ATLEAST_S) {
-                opts.putParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES, sizes);
-            }
-            return opts;
+            return getWidgetSizeOptions(getContext(), mWidgetInfo.provider, idp.numColumns, 1);
         }
 
         protected View getDefaultView(ViewGroup container, boolean showSetupIcon) {
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
index f5e74b7..5999091 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
@@ -87,8 +87,8 @@
         if (mDragLayer != null) {
             return;
         }
-        InvariantDeviceProfile currentDisplayIdp =
-                new InvariantDeviceProfile(this, getWindow().getDecorView().getDisplay());
+        InvariantDeviceProfile currentDisplayIdp = new InvariantDeviceProfile(
+                this, getWindow().getDecorView().getDisplay());
 
         // Disable transpose layout and use multi-window mode so that the icons are scaled properly
         mDeviceProfile = currentDisplayIdp.getDeviceProfile(this)
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
index 40630d3..f78f6dd 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
@@ -29,7 +29,6 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.allapps.AllAppsContainerView;
 import com.android.launcher3.model.data.ItemInfo;
@@ -109,8 +108,6 @@
         setMeasuredDimension(width, height);
 
         DeviceProfile grid = mActivity.getDeviceProfile();
-        InvariantDeviceProfile idp = grid.inv;
-
         int count = getChildCount();
         for (int i = 0; i < count; i++) {
             final View child = getChildAt(i);
@@ -118,10 +115,10 @@
                 int padding = 2 * (grid.desiredWorkspaceLeftRightMarginPx
                         + grid.cellLayoutPaddingLeftRightPx);
 
-                int maxWidth = grid.allAppsCellWidthPx * idp.numAllAppsColumns + padding;
+                int maxWidth = grid.allAppsCellWidthPx * grid.numShownAllAppsColumns + padding;
                 int appsWidth = Math.min(width, maxWidth);
 
-                int maxHeight = grid.allAppsCellHeightPx * idp.numAllAppsColumns + padding;
+                int maxHeight = grid.allAppsCellHeightPx * grid.numShownAllAppsColumns + padding;
                 int appsHeight = Math.min(height, maxHeight);
 
                 mAppsView.measure(
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/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 01897d7..d3d77fd 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -296,7 +296,7 @@
         } else {
             // Phone Portrait, LargeScreen Landscape/Portrait
             viewGroup.setOrientation(LinearLayout.HORIZONTAL);
-            lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;
+            lp.width = LinearLayout.LayoutParams.MATCH_PARENT;
         }
 
         lp.height = LinearLayout.LayoutParams.WRAP_CONTENT;
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 75c089e..b751207 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -18,8 +18,10 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 
+import static com.android.launcher3.Utilities.dpiFromPx;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.launcher3.util.WindowManagerCompat.MIN_TABLET_WIDTH;
 
 import android.annotation.SuppressLint;
 import android.annotation.TargetApi;
@@ -32,16 +34,22 @@
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManager.DisplayListener;
 import android.os.Build;
+import android.util.ArraySet;
 import android.util.Log;
 import android.view.Display;
+import android.view.WindowMetrics;
 
 import androidx.annotation.AnyThread;
 import androidx.annotation.UiThread;
 import androidx.annotation.WorkerThread;
 
 import com.android.launcher3.Utilities;
+import com.android.launcher3.uioverrides.ApiWrapper;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
 
 /**
  * Utility class to cache properties of default display to avoid a system RPC on every call.
@@ -54,13 +62,14 @@
     public static final MainThreadInitializedObject<DisplayController> INSTANCE =
             new MainThreadInitializedObject<>(DisplayController::new);
 
-    public static final int CHANGE_SIZE = 1 << 0;
+    public static final int CHANGE_ACTIVE_SCREEN = 1 << 0;
     public static final int CHANGE_ROTATION = 1 << 1;
     public static final int CHANGE_FRAME_DELAY = 1 << 2;
     public static final int CHANGE_DENSITY = 1 << 3;
+    public static final int CHANGE_SUPPORTED_BOUNDS = 1 << 4;
 
-    public static final int CHANGE_ALL = CHANGE_SIZE | CHANGE_ROTATION
-            | CHANGE_FRAME_DELAY | CHANGE_DENSITY;
+    public static final int CHANGE_ALL = CHANGE_ACTIVE_SCREEN | CHANGE_ROTATION
+            | CHANGE_FRAME_DELAY | CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS;
 
     private final Context mContext;
     private final DisplayManager mDM;
@@ -87,7 +96,22 @@
                     new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
         }
 
-        mInfo = new Info(getContext(display), display);
+        // Create a single holder for all internal displays. External display holders created
+        // lazily.
+        Set<PortraitSize> extraInternalDisplays = new ArraySet<>();
+        for (Display d : mDM.getDisplays()) {
+            if (ApiWrapper.isInternalDisplay(display) && d.getDisplayId() != DEFAULT_DISPLAY) {
+                Point size = new Point();
+                d.getRealSize(size);
+                extraInternalDisplays.add(new PortraitSize(size.x, size.y));
+            }
+        }
+
+        if (extraInternalDisplays.isEmpty() || !Utilities.ATLEAST_S) {
+            mInfo = new Info(createDisplayInfoContext(display), display, Collections.emptySet());
+        } else {
+            mInfo = new Info(mWindowContext, display, extraInternalDisplays);
+        }
         mDM.registerDisplayListener(this, UI_HELPER_EXECUTOR.getHandler());
     }
 
@@ -139,7 +163,7 @@
      */
     private void onConfigChanged(Intent intent) {
         Configuration config = mContext.getResources().getConfiguration();
-        if (config.fontScale != config.fontScale || mInfo.densityDpi != config.densityDpi) {
+        if (mInfo.fontScale != config.fontScale || mInfo.densityDpi != config.densityDpi) {
             Log.d(TAG, "Configuration changed, notifying listeners");
             Display display = mDM.getDisplay(DEFAULT_DISPLAY);
             if (display != null) {
@@ -157,8 +181,7 @@
                 || config.fontScale != mInfo.fontScale
                 || display.getRotation() != mInfo.rotation
                 || !mInfo.mScreenSizeDp.equals(
-                        Math.min(config.screenHeightDp, config.screenWidthDp),
-                        Math.max(config.screenHeightDp, config.screenWidthDp))) {
+                        new PortraitSize(config.screenHeightDp, config.screenWidthDp))) {
             handleInfoChange(display);
         }
     }
@@ -178,18 +201,23 @@
         return mInfo;
     }
 
-    private Context getContext(Display display) {
-        return Utilities.ATLEAST_S ? mWindowContext : mContext.createDisplayContext(display);
+    private Context createDisplayInfoContext(Display display) {
+        return Utilities.ATLEAST_S
+                ? mContext.createWindowContext(display, TYPE_APPLICATION, null)
+                : mContext.createDisplayContext(display);
     }
 
     @AnyThread
     private void handleInfoChange(Display display) {
         Info oldInfo = mInfo;
-        Context context = getContext(display);
-        Info newInfo = new Info(context, display);
+        Set<PortraitSize> extraDisplaysSizes = oldInfo.mAllSizes.size() > 1
+                ? oldInfo.mAllSizes : Collections.emptySet();
+
+        Context displayContext = createDisplayInfoContext(display);
+        Info newInfo = new Info(displayContext, display, extraDisplaysSizes);
         int change = 0;
-        if (newInfo.hasDifferentSize(oldInfo)) {
-            change |= CHANGE_SIZE;
+        if (!newInfo.mScreenSizeDp.equals(oldInfo.mScreenSizeDp)) {
+            change |= CHANGE_ACTIVE_SCREEN;
         }
         if (newInfo.rotation != oldInfo.rotation) {
             change |= CHANGE_ROTATION;
@@ -200,11 +228,14 @@
         if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale) {
             change |= CHANGE_DENSITY;
         }
+        if (!newInfo.supportedBounds.equals(oldInfo.supportedBounds)) {
+            change |= CHANGE_SUPPORTED_BOUNDS;
+        }
 
         if (change != 0) {
             mInfo = newInfo;
             final int flags = change;
-            MAIN_EXECUTOR.execute(() -> notifyChange(context, flags));
+            MAIN_EXECUTOR.execute(() -> notifyChange(displayContext, flags));
         }
     }
 
@@ -224,13 +255,18 @@
         public final float fontScale;
         public final int densityDpi;
 
-        private final Point mScreenSizeDp;
+        private final PortraitSize mScreenSizeDp;
+        private final Set<PortraitSize> mAllSizes;
 
-        public final Point realSize;
-        public final Point smallestSize;
-        public final Point largestSize;
+        public final Point currentSize;
+
+        public final Set<WindowBounds> supportedBounds = new ArraySet<>();
 
         public Info(Context context, Display display) {
+            this(context, display, Collections.emptySet());
+        }
+
+        private Info(Context context, Display display, Set<PortraitSize> extraDisplaysSizes) {
             id = display.getDisplayId();
 
             rotation = display.getRotation();
@@ -238,35 +274,67 @@
             Configuration config = context.getResources().getConfiguration();
             fontScale = config.fontScale;
             densityDpi = config.densityDpi;
-            mScreenSizeDp = new Point(
-                    Math.min(config.screenHeightDp, config.screenWidthDp),
-                    Math.max(config.screenHeightDp, config.screenWidthDp));
+            mScreenSizeDp = new PortraitSize(config.screenHeightDp, config.screenWidthDp);
 
             singleFrameMs = getSingleFrameMs(display);
+            currentSize = new Point();
 
-            realSize = new Point();
-            smallestSize = new Point();
-            largestSize = new Point();
+            display.getRealSize(currentSize);
 
-            display.getRealSize(realSize);
-            display.getCurrentSizeRange(smallestSize, largestSize);
+            if (extraDisplaysSizes.isEmpty() || !Utilities.ATLEAST_S) {
+                Point smallestSize = new Point();
+                Point largestSize = new Point();
+                display.getCurrentSizeRange(smallestSize, largestSize);
+
+                int portraitWidth = Math.min(currentSize.x, currentSize.y);
+                int portraitHeight = Math.max(currentSize.x, currentSize.y);
+
+                supportedBounds.add(new WindowBounds(portraitWidth, portraitHeight,
+                        smallestSize.x, largestSize.y));
+                supportedBounds.add(new WindowBounds(portraitHeight, portraitWidth,
+                        largestSize.x, smallestSize.y));
+                mAllSizes = Collections.singleton(new PortraitSize(currentSize.x, currentSize.y));
+            } else {
+                mAllSizes = new ArraySet<>(extraDisplaysSizes);
+                mAllSizes.add(new PortraitSize(currentSize.x, currentSize.y));
+                Set<WindowMetrics> metrics = WindowManagerCompat.getDisplayProfiles(
+                        context, mAllSizes, densityDpi,
+                        ApiWrapper.TASKBAR_DRAWN_IN_PROCESS);
+                metrics.forEach(wm -> supportedBounds.add(WindowBounds.fromWindowMetrics(wm)));
+            }
         }
 
-        private boolean hasDifferentSize(Info info) {
-            if (!realSize.equals(info.realSize)
-                    && !realSize.equals(info.realSize.y, info.realSize.x)) {
-                Log.d(TAG, String.format("Display size changed from %s to %s",
-                        info.realSize, realSize));
-                return true;
-            }
+        /**
+         * Returns true if the bounds represent a tablet
+         */
+        public boolean isTablet(WindowBounds bounds) {
+            return dpiFromPx(Math.min(bounds.bounds.width(), bounds.bounds.height()),
+                    densityDpi) >= MIN_TABLET_WIDTH;
+        }
+    }
 
-            if (!smallestSize.equals(info.smallestSize) || !largestSize.equals(info.largestSize)) {
-                Log.d(TAG, String.format("Available size changed from [%s, %s] to [%s, %s]",
-                        smallestSize, largestSize, info.smallestSize, info.largestSize));
-                return true;
-            }
+    /**
+     * Utility class to hold a size information in an orientation independent way
+     */
+    public static class PortraitSize {
+        public final int width, height;
 
-            return false;
+        public PortraitSize(int w, int h) {
+            width = Math.min(w, h);
+            height = Math.max(w, h);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            PortraitSize that = (PortraitSize) o;
+            return width == that.width && height == that.height;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(width, height);
         }
     }
 
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
index 99942aa..06cac08 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -22,7 +22,6 @@
 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;
@@ -54,16 +53,12 @@
     }
 
     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 (darkTheme) {
+        if (Utilities.isDarkTheme(context)) {
             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/util/WindowBounds.java b/src/com/android/launcher3/util/WindowBounds.java
index 3c2fb62..c92770e 100644
--- a/src/com/android/launcher3/util/WindowBounds.java
+++ b/src/com/android/launcher3/util/WindowBounds.java
@@ -15,11 +15,16 @@
  */
 package com.android.launcher3.util;
 
+import android.graphics.Insets;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.view.WindowInsets.Type;
+import android.view.WindowMetrics;
 
 import androidx.annotation.Nullable;
 
+import java.util.Objects;
+
 /**
  * Utility class to hold information about window position and layout
  */
@@ -36,6 +41,18 @@
                 bounds.height() - insets.top - insets.bottom);
     }
 
+    public WindowBounds(int width, int height, int availableWidth, int availableHeight) {
+        this.bounds = new Rect(0, 0, width, height);
+        this.availableSize = new Point(availableWidth, availableHeight);
+        // We don't care about insets in this case
+        this.insets = new Rect(0, 0, width - availableWidth, height - availableHeight);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(bounds, insets);
+    }
+
     @Override
     public boolean equals(@Nullable Object obj) {
         if (!(obj instanceof WindowBounds)) {
@@ -44,4 +61,30 @@
         WindowBounds other = (WindowBounds) obj;
         return other.bounds.equals(bounds) && other.insets.equals(insets);
     }
+
+    @Override
+    public String toString() {
+        return "WindowBounds{"
+                + "bounds=" + bounds
+                + ", insets=" + insets
+                + ", availableSize=" + availableSize
+                + '}';
+    }
+
+    /**
+     * Returns true if the device is in landscape orientation
+     */
+    public final boolean isLandscape() {
+        return availableSize.x > availableSize.y;
+    }
+
+    /**
+     * Returns the bounds corresponding to the provided WindowMetrics
+     */
+    @SuppressWarnings("NewApi")
+    public static WindowBounds fromWindowMetrics(WindowMetrics wm) {
+        Insets insets = wm.getWindowInsets().getInsets(Type.systemBars());
+        return new WindowBounds(wm.getBounds(),
+                new Rect(insets.left, insets.top, insets.right, insets.bottom));
+    }
 }
diff --git a/src/com/android/launcher3/util/WindowManagerCompat.java b/src/com/android/launcher3/util/WindowManagerCompat.java
new file mode 100644
index 0000000..38a63de
--- /dev/null
+++ b/src/com/android/launcher3/util/WindowManagerCompat.java
@@ -0,0 +1,107 @@
+/*
+ * 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 static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE;
+import static com.android.launcher3.Utilities.dpiFromPx;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.os.Build;
+import android.view.WindowInsets;
+import android.view.WindowInsets.Type;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import com.android.launcher3.R;
+import com.android.launcher3.ResourceUtils;
+import com.android.launcher3.util.DisplayController.PortraitSize;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Utility class to simulate window manager APIs until proper APIs are available
+ */
+@TargetApi(Build.VERSION_CODES.S)
+public class WindowManagerCompat {
+
+    public static final int MIN_TABLET_WIDTH = 600;
+
+    /**
+     * Returns a set of supported render sizes for a set of internal displays.
+     * This is a temporary workaround which assumes only nav-bar insets change across displays
+     * @param consumeTaskBar if true, it assumes that task bar is part of the app window
+     *                       and ignores any insets because of task bar.
+     */
+    public static Set<WindowMetrics> getDisplayProfiles(
+            Context windowContext, Collection<PortraitSize> allDisplaySizes,
+            int densityDpi, boolean consumeTaskBar) {
+        WindowInsets metrics = windowContext.getSystemService(WindowManager.class)
+                .getMaximumWindowMetrics().getWindowInsets();
+        boolean hasNavbar = ResourceUtils.getIntegerByName(
+                "config_navBarInteractionMode",
+                windowContext.getResources(),
+                INVALID_RESOURCE_HANDLE) != 0;
+
+        WindowInsets.Builder insetsBuilder = new WindowInsets.Builder(metrics);
+
+        Set<WindowMetrics> result = new HashSet<>();
+        for (PortraitSize size : allDisplaySizes) {
+            int swDP = (int) dpiFromPx(size.width, densityDpi);
+            boolean isTablet = swDP >= MIN_TABLET_WIDTH;
+
+            final Insets portraitNav, landscapeNav;
+            if (isTablet && !consumeTaskBar) {
+                portraitNav = landscapeNav = Insets.of(0, 0, 0, windowContext.getResources()
+                        .getDimensionPixelSize(R.dimen.taskbar_size));
+            } else if (hasNavbar) {
+                portraitNav = Insets.of(0, 0, 0,
+                        getSystemResource(windowContext, "navigation_bar_height", swDP));
+                landscapeNav = isTablet
+                        ? Insets.of(0, 0, 0, getSystemResource(windowContext,
+                                "navigation_bar_height_landscape", swDP))
+                        : Insets.of(0, 0, getSystemResource(windowContext,
+                                "navigation_bar_width", swDP), 0);
+            } else {
+                portraitNav = landscapeNav = Insets.of(0, 0, 0, 0);
+            }
+
+            result.add(new WindowMetrics(
+                    new Rect(0, 0, size.width, size.height),
+                    insetsBuilder.setInsets(Type.navigationBars(), portraitNav).build()));
+            result.add(new WindowMetrics(
+                    new Rect(0, 0, size.height, size.width),
+                    insetsBuilder.setInsets(Type.navigationBars(), landscapeNav).build()));
+        }
+        return result;
+    }
+
+    private static int getSystemResource(Context context, String key, int swDp) {
+        int resourceId = context.getResources().getIdentifier(key, "dimen", "android");
+        if (resourceId > 0) {
+            Configuration conf = new Configuration();
+            conf.smallestScreenWidthDp = swDp;
+            return context.createConfigurationContext(conf)
+                    .getResources().getDimensionPixelSize(resourceId);
+        }
+        return 0;
+    }
+}
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index d49320b..81581fa 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -233,15 +233,8 @@
             outViewBounds.set(0, 0, v.getWidth(), v.getHeight());
         }
 
-        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]));
+        Utilities.getBoundsForViewInDragLayer(launcher.getDragLayer(), v, outViewBounds,
+                ignoreTransform, null /** recycle */, outRect);
     }
 
     /**
diff --git a/src/com/android/launcher3/widget/DeferredAppWidgetHostView.java b/src/com/android/launcher3/widget/DeferredAppWidgetHostView.java
index 3a24c3d..149ac57 100644
--- a/src/com/android/launcher3/widget/DeferredAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/DeferredAppWidgetHostView.java
@@ -44,7 +44,7 @@
         mPaint = new TextPaint();
         mPaint.setColor(Color.WHITE);
         mPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,
-                mLauncher.getDeviceProfile().getFullScreenProfile().iconTextSizePx,
+                mLauncher.getDeviceProfile().iconTextSizePx,
                 getResources().getDisplayMetrics()));
         setBackgroundResource(R.drawable.bg_deferred_app_widget);
     }
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index 620604a..5deecd4 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -16,6 +16,9 @@
 
 package com.android.launcher3.widget;
 
+import static com.android.launcher3.Utilities.getBoundsForViewInDragLayer;
+import static com.android.launcher3.Utilities.setRect;
+
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -25,7 +28,6 @@
 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;
@@ -95,11 +97,12 @@
     private RectF mLastLocationRegistered = null;
     @Nullable private AppWidgetHostViewDragListener mDragListener;
 
-    // Used to store the widget size during onLayout.
+    // Used to store the widget sizes in drag layer coordinates.
     private final Rect mCurrentWidgetSize = new Rect();
     private final Rect mWidgetSizeAtDrag = new Rect();
+
+    private final float[] mTmpFloatArray = new float[4];
     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() {
@@ -129,7 +132,6 @@
         if (Utilities.ATLEAST_Q && Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText)) {
             setOnLightBackground(true);
         }
-        mIsRtl = Utilities.isRtl(context.getResources());
         mColorExtractor = LocalColorExtractor.newInstance(getContext());
         mColorExtractor.setListener(this);
 
@@ -319,13 +321,12 @@
         mIsScrollable = checkScrollableRecursively(this);
 
         if (!mIsInDragMode && getTag() instanceof LauncherAppWidgetInfo) {
-            mCurrentWidgetSize.left = left;
-            mCurrentWidgetSize.top = top;
-            mCurrentWidgetSize.right = right;
-            mCurrentWidgetSize.bottom = bottom;
             LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) getTag();
-            int pageId = mWorkspace.getPageIndexForScreenId(info.screenId);
-            updateColorExtraction(mCurrentWidgetSize, pageId);
+            getBoundsForViewInDragLayer(mLauncher.getDragLayer(), this, mCurrentWidgetSize, true,
+                    mTmpFloatArray, mTempRectF);
+            setRect(mTempRectF, mCurrentWidgetSize);
+            updateColorExtraction(mCurrentWidgetSize,
+                    mWorkspace.getPageIndexForScreenId(info.screenId));
         }
 
         enforceRoundedCorners();
@@ -338,8 +339,8 @@
     }
 
     /** Handles a drag event occurred on a workspace page, {@code pageId}. */
-    public void handleDrag(Rect rect, int pageId) {
-        mWidgetSizeAtDrag.set(rect);
+    public void handleDrag(Rect rectInDragLayer, int pageId) {
+        mWidgetSizeAtDrag.set(rectInDragLayer);
         updateColorExtraction(mWidgetSizeAtDrag, pageId);
     }
 
@@ -351,53 +352,14 @@
         requestLayout();
     }
 
-    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");
+    /**
+     * @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) {
+        mColorExtractor.getExtractedRectForViewRect(mLauncher, pageId, rectInDragLayer, mTempRectF);
+
+        if (mTempRectF.isEmpty()) {
             return;
         }
         if (!mTempRectF.equals(mLastLocationRegistered)) {
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
index ad61495..de511cd 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
@@ -13,6 +13,7 @@
 import android.os.Parcel;
 import android.os.UserHandle;
 
+import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.Utilities;
@@ -66,20 +67,25 @@
     }
 
     public void initSpans(Context context, InvariantDeviceProfile idp) {
-        Point landCellSize = idp.landscapeProfile.getCellSize();
-        Point portCellSize = idp.portraitProfile.getCellSize();
-
         // Always assume we're working with the smallest span to make sure we
         // reserve enough space in both orientations.
-        float smallestCellWidth = Math.min(landCellSize.x, portCellSize.x);
-        float smallestCellHeight = Math.min(landCellSize.y, portCellSize.y);
+        float smallestCellWidth = Float.MAX_VALUE;
+        float smallestCellHeight = Float.MAX_VALUE;
+
+        Point cellSize = new Point();
+        boolean isWidgetPadded = false;
+        for (DeviceProfile dp : idp.supportedProfiles) {
+            dp.getCellSize(cellSize);
+            smallestCellWidth = Math.min(smallestCellWidth, cellSize.x);
+            smallestCellHeight = Math.min(smallestCellHeight, cellSize.y);
+            isWidgetPadded = isWidgetPadded || !dp.shouldInsetWidgets();
+        }
 
         // We want to account for the extra amount of padding that we are adding to the widget
         // to ensure that it gets the full amount of space that it has requested.
         // If grids supports insetting widgets, we do not account for widget padding.
         Rect widgetPadding = new Rect();
-        if (!idp.landscapeProfile.shouldInsetWidgets()
-                || !idp.portraitProfile.shouldInsetWidgets()) {
+        if (isWidgetPadded) {
             AppWidgetHostView.getDefaultPaddingForWidget(context, provider, widgetPadding);
         }
 
diff --git a/src/com/android/launcher3/widget/LocalColorExtractor.java b/src/com/android/launcher3/widget/LocalColorExtractor.java
index 097158b..8ae6b2e 100644
--- a/src/com/android/launcher3/widget/LocalColorExtractor.java
+++ b/src/com/android/launcher3/widget/LocalColorExtractor.java
@@ -16,13 +16,17 @@
 
 package com.android.launcher3.widget;
 
+import android.app.WallpaperColors;
 import android.appwidget.AppWidgetHostView;
 import android.content.Context;
+import android.graphics.Rect;
 import android.graphics.RectF;
 import android.util.SparseIntArray;
+import android.view.View;
 
 import androidx.annotation.Nullable;
 
+import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.util.ResourceBasedOverride;
 
@@ -43,7 +47,10 @@
         void onColorsChanged(RectF rect, SparseIntArray extractedColors);
     }
 
-    static LocalColorExtractor newInstance(Context context) {
+    /**
+     * Creates a new instance of LocalColorExtractor
+     */
+    public static LocalColorExtractor newInstance(Context context) {
         return Overrides.getObject(LocalColorExtractor.class, context.getApplicationContext(),
                 R.string.local_colors_extraction_class);
     }
@@ -62,4 +69,38 @@
     public void removeLocations() {
         // no-op
     }
+
+    /**
+     * Updates the base context to contain the colors override
+     */
+    public void applyColorsOverride(Context base, WallpaperColors colors) { }
+
+    /**
+     * 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 void getExtractedRectForView(Launcher launcher, int pageId, View v,
+            RectF colorExtractionRectOut) {
+        // no-op
+    }
+
+    /**
+     * 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 void getExtractedRectForViewRect(Launcher launcher, int pageId, Rect rectInDragLayer,
+            RectF colorExtractionRectOut) {
+        // no-op
+    }
 }
diff --git a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
index ee0b84e..3377abb 100644
--- a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
+++ b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
@@ -15,9 +15,11 @@
  */
 package com.android.launcher3.widget;
 
+import static com.android.launcher3.AppWidgetResizeFrame.getWidgetSizeOptions;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
 
 import android.appwidget.AppWidgetHostView;
+import android.content.Context;
 import android.os.Bundle;
 
 import com.android.launcher3.LauncherSettings;
@@ -57,4 +59,8 @@
     public WidgetAddFlowHandler getHandler() {
         return new WidgetAddFlowHandler(info);
     }
+
+    public Bundle getDefaultSizeOptions(Context context) {
+        return getWidgetSizeOptions(context, componentName, spanX, spanY);
+    }
 }
diff --git a/src/com/android/launcher3/widget/WidgetHostViewLoader.java b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
index 12e0d43..46141e0 100644
--- a/src/com/android/launcher3/widget/WidgetHostViewLoader.java
+++ b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
@@ -1,16 +1,12 @@
 package com.android.launcher3.widget;
 
 import android.appwidget.AppWidgetHostView;
-import android.appwidget.AppWidgetManager;
 import android.content.Context;
-import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
 import android.util.Log;
-import android.util.SizeF;
 import android.view.View;
 
-import com.android.launcher3.AppWidgetResizeFrame;
 import com.android.launcher3.DropTarget;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.dragndrop.DragController;
@@ -18,9 +14,6 @@
 import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.util.Thunk;
 
-import java.util.ArrayList;
-import java.util.stream.Collectors;
-
 public class WidgetHostViewLoader implements DragController.DragListener {
     private static final String TAG = "WidgetHostViewLoader";
     private static final boolean LOGD = false;
@@ -90,7 +83,7 @@
         if (pInfo.isCustomWidget()) {
             return false;
         }
-        final Bundle options = getDefaultOptionsForWidget(mLauncher, mInfo);
+        final Bundle options = mInfo.getDefaultSizeOptions(mLauncher);
 
         // If there is a configuration activity, do not follow thru bound and inflate.
         if (mInfo.getHandler().needsConfigure()) {
@@ -154,29 +147,4 @@
         return true;
     }
 
-    public static Bundle getDefaultOptionsForWidget(Context context, PendingAddWidgetInfo info) {
-        ArrayList<SizeF> sizes = AppWidgetResizeFrame
-                .getWidgetSizes(context, info.spanX, info.spanY);
-
-        Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(context,
-                info.componentName, null);
-        float density = context.getResources().getDisplayMetrics().density;
-        float xPaddingDips = (padding.left + padding.right) / density;
-        float yPaddingDips = (padding.top + padding.bottom) / density;
-
-        ArrayList<SizeF> paddedSizes = sizes.stream().map(
-                size -> new SizeF(Math.max(0.f, size.getWidth() - xPaddingDips),
-                        Math.max(0.f, size.getHeight() - yPaddingDips))).collect(
-                Collectors.toCollection(ArrayList::new));
-
-        Rect rect = AppWidgetResizeFrame.getMinMaxSizes(paddedSizes, null /* outRect */);
-
-        Bundle options = new Bundle();
-        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, rect.left);
-        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, rect.top);
-        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, rect.right);
-        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, rect.bottom);
-        options.putParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES, paddedSizes);
-        return options;
-    }
 }
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java b/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
index 6fd147a..4407fe1 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -18,12 +18,22 @@
 
 import android.app.Person;
 import android.content.pm.ShortcutInfo;
+import android.view.Display;
 
 import com.android.launcher3.Utilities;
 
 public class ApiWrapper {
 
+    public static final boolean TASKBAR_DRAWN_IN_PROCESS = false;
+
     public static Person[] getPersons(ShortcutInfo si) {
         return Utilities.EMPTY_PERSON_ARRAY;
     }
+
+    /**
+     * Returns true if the display is an internal displays
+     */
+    public static boolean isInternalDisplay(Display display) {
+        return display.getDisplayId() == Display.DEFAULT_DISPLAY;
+    }
 }
diff --git a/tests/src_common/com/android/launcher3/common/WidgetUtils.java b/tests/src_common/com/android/launcher3/common/WidgetUtils.java
index ffad93f..5e17e0a 100644
--- a/tests/src_common/com/android/launcher3/common/WidgetUtils.java
+++ b/tests/src_common/com/android/launcher3/common/WidgetUtils.java
@@ -16,7 +16,6 @@
 package com.android.launcher3.common;
 
 import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
-import static com.android.launcher3.widget.WidgetHostViewLoader.getDefaultOptionsForWidget;
 
 import android.appwidget.AppWidgetHost;
 import android.content.ContentResolver;
@@ -62,7 +61,7 @@
             pendingInfo.spanY = item.spanY;
             pendingInfo.minSpanX = item.minSpanX;
             pendingInfo.minSpanY = item.minSpanY;
-            Bundle options = getDefaultOptionsForWidget(targetContext, pendingInfo);
+            Bundle options = pendingInfo.getDefaultSizeOptions(targetContext);
 
             AppWidgetHost host = new LauncherAppWidgetHost(targetContext);
             int widgetId = host.allocateAppWidgetId();