Merge "Add strict_mode: false" into main
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index edbea88..80d2eac 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -179,7 +179,7 @@
             </intent-filter>
         </activity>
 
-        <!-- [b/197780098] Disable eager initialization of Jetpack libraries. -->
+        <!-- Disable eager initialization of Jetpack libraries. See bug 197780098. -->
         <provider
             android:name="androidx.startup.InitializationProvider"
             android:authorities="${applicationId}.androidx-startup"
diff --git a/OWNERS b/OWNERS
index 654493f..a66bf54 100644
--- a/OWNERS
+++ b/OWNERS
@@ -28,6 +28,8 @@
 tracyzhou@google.com
 peanutbutter@google.com
 jeremysim@google.com
+atsjenk@google.com
+brianji@google.com
 
 # Overview eng team
 alexchau@google.com
@@ -48,3 +50,6 @@
 
 per-file DeviceConfigWrapper.java, globs = set noparent
 per-file DeviceConfigWrapper.java = sunnygoyal@google.com, winsonc@google.com, adamcohen@google.com, hyunyoungs@google.com
+
+# Predictive Back
+per-file LauncherBackAnimationController.java = shanh@google.com, gallmann@google.com
\ No newline at end of file
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index 163fc17..9147e4c 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -253,3 +253,34 @@
     description: "Enables fallback recents opening inside of a window instead of an activity."
     bug: "292269949"
 }
+
+flag {
+    name: "enable_smartspace_as_a_widget"
+    namespace: "launcher"
+    description: "Enables smartspace as a widget"
+    bug: "300140279"
+}
+
+flag {
+    name: "enable_smartspace_removal_toggle"
+    namespace: "launcher"
+    description: "Enables smartspace removal toggle"
+    bug: "303471576"
+}
+
+flag {
+  name: "enable_additional_home_animations"
+  namespace: "launcher"
+  description: "Enables custom home animations for non-running tasks"
+  bug: "237638627"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
+    name: "enabled_folders_in_all_apps"
+    namespace: "launcher"
+    description: "Enables folders in all apps"
+    bug: "341582436"
+}
diff --git a/aconfig/launcher_search.aconfig b/aconfig/launcher_search.aconfig
index 31d8d34..b243922 100644
--- a/aconfig/launcher_search.aconfig
+++ b/aconfig/launcher_search.aconfig
@@ -42,3 +42,11 @@
     description: "This flag disables drag and drop for Private Space Items."
     bug: "289223923"
 }
+
+
+flag {
+    name: "private_space_floating_mask_view"
+    namespace: "launcher_search"
+    description: "This flag enables the floating mask view as part of the Private Space animation. "
+    bug: "339850589"
+}
diff --git a/go/quickstep/res/layout/overview_actions_container.xml b/go/quickstep/res/layout/overview_actions_container.xml
index df09124..b1a6202 100644
--- a/go/quickstep/res/layout/overview_actions_container.xml
+++ b/go/quickstep/res/layout/overview_actions_container.xml
@@ -121,6 +121,17 @@
             android:layout_weight="1"
             android:visibility="gone" />
 
+    </LinearLayout>
+
+    <!-- Unused. Included only for compatibility with parent class. -->
+    <LinearLayout
+        android:id="@+id/group_action_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/overview_actions_height"
+        android:layout_gravity="top|center_horizontal"
+        android:orientation="horizontal"
+        android:visibility="gone">
+
         <Button
             android:id="@+id/action_save_app_pair"
             style="@style/GoOverviewActionButton"
@@ -128,8 +139,8 @@
             android:layout_height="wrap_content"
             android:drawableStart="@drawable/ic_save_app_pair_up_down"
             android:text="@string/action_save_app_pair"
-            android:theme="@style/ThemeControlHighlightWorkspaceColor"
-            android:visibility="gone" />
+            android:theme="@style/ThemeControlHighlightWorkspaceColor" />
+
     </LinearLayout>
 
 </com.android.quickstep.views.GoOverviewActionsView>
\ No newline at end of file
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
index 0eb8775..26ca06a 100644
--- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -56,7 +56,7 @@
 import com.android.quickstep.util.AssistContentRequester;
 import com.android.quickstep.util.RecentsOrientedState;
 import com.android.quickstep.views.GoOverviewActionsView;
-import com.android.quickstep.views.TaskThumbnailViewDeprecated;
+import com.android.quickstep.views.TaskView.TaskContainer;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 
@@ -101,8 +101,8 @@
     /**
      * Create a new overlay instance for the given View
      */
-    public TaskOverlayGo createOverlay(TaskThumbnailViewDeprecated thumbnailView) {
-        return new TaskOverlayGo(thumbnailView, mContentRequester);
+    public TaskOverlayGo createOverlay(TaskContainer taskContainer) {
+        return new TaskOverlayGo(taskContainer, mContentRequester);
     }
 
     /**
@@ -120,9 +120,9 @@
         private OverlayDialogGo mDialog;
         private ArrowTipView mArrowTipView;
 
-        private TaskOverlayGo(TaskThumbnailViewDeprecated taskThumbnailView,
+        private TaskOverlayGo(TaskContainer taskContainer,
                 AssistContentRequester assistContentRequester) {
-            super(taskThumbnailView);
+            super(taskContainer);
             mFactoryContentRequester = assistContentRequester;
             mSharedPreferences = LauncherPrefs.getPrefs(mApplicationContext);
         }
@@ -148,7 +148,8 @@
             // Disable Overview Actions for Work Profile apps
             boolean isManagedProfileTask =
                     UserManager.get(mApplicationContext).isManagedProfile(task.key.userId);
-            boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot() && !isManagedProfileTask;
+            boolean isAllowedByPolicy = mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot()
+                    && !isManagedProfileTask;
             getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
             mTaskPackageName = task.key.getPackageName();
             mSharedPreferences = LauncherPrefs.getPrefs(mApplicationContext);
@@ -162,8 +163,7 @@
             int taskId = task.key.id;
             mFactoryContentRequester.requestAssistContent(taskId, this::onAssistContentReceived);
 
-            RecentsOrientedState orientedState =
-                    mThumbnailView.getTaskView().getRecentsView().getPagedViewOrientedState();
+            RecentsOrientedState orientedState = mTaskContainer.getTaskView().getOrientedState();
             boolean isInLandscape = orientedState.getDisplayRotation() != ROTATION_0;
 
             // show tooltips in portrait mode only
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index 7c648b6..823c821 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -121,6 +121,20 @@
 }
 
 message TaskSwitcherContainer {
+  /**
+   * Indicates the current OrientationHandler in use in Overview.
+   * In fake landscape, the value will be
+   * {@link com.android.quickstep.orientation.LandscapePagedViewHandler} and in real landscape,
+   * the value will be {@link com.android.quickstep.orientation.PortraitPagedViewHandler} for
+   * example.
+   */
+  optional OrientationHandler orientation_handler = 1;
+
+  enum OrientationHandler {
+    PORTRAIT = 0;
+    LANDSCAPE = 1;
+    SEASCAPE = 2;
+  }
 }
 
 // Container for taskbar.
diff --git a/quickstep/res/drawable/bg_bubble_expanded_view_drop_target.xml b/quickstep/res/drawable/bg_bubble_expanded_view_drop_target.xml
new file mode 100644
index 0000000..d722dd7
--- /dev/null
+++ b/quickstep/res/drawable/bg_bubble_expanded_view_drop_target.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2024 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.
+  -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:inset="@dimen/bubble_expanded_view_drop_target_padding">
+    <shape
+        android:shape="rectangle">
+        <corners android:radius="@dimen/bubble_expanded_view_drop_target_corner_radius" />
+        <solid android:color="@color/bubblebar_drop_target_bg_color" />
+        <stroke
+            android:width="1dp"
+            android:color="?androidprv:attr/materialColorPrimaryContainer" />
+    </shape>
+</inset>
diff --git a/quickstep/res/layout/bubble_expanded_view_drop_target.xml b/quickstep/res/layout/bubble_expanded_view_drop_target.xml
new file mode 100644
index 0000000..3bd5d31
--- /dev/null
+++ b/quickstep/res/layout/bubble_expanded_view_drop_target.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2024 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.
+  -->
+
+<!-- TODO(b/330585402): replace 600dp height with calculated value -->
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="@dimen/bubble_expanded_view_drop_target_default_width"
+    android:layout_height="@dimen/bubble_expanded_view_drop_target_default_height"
+    android:layout_margin="@dimen/bubble_expanded_view_drop_target_margin"
+    android:background="@drawable/bg_bubble_expanded_view_drop_target"
+    android:elevation="@dimen/bubblebar_elevation" />
\ No newline at end of file
diff --git a/quickstep/res/layout/floating_desktop_app_select.xml b/quickstep/res/layout/floating_desktop_app_select.xml
deleted file mode 100644
index 375fc44..0000000
--- a/quickstep/res/layout/floating_desktop_app_select.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<com.android.quickstep.views.DesktopAppSelectView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="@dimen/desktop_mode_floating_app_select_height"
-    android:layout_gravity="top|center_horizontal"
-    android:background="@drawable/bg_floating_desktop_select"
-    android:elevation="@dimen/desktop_mode_floating_app_select_elevation"
-    android:gravity="center_vertical"
-    android:orientation="horizontal">
-
-    <TextView
-        android:id="@+id/desktop_app_select_text"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="@dimen/desktop_mode_floating_app_select_text_margin"
-        android:layout_marginStart="@dimen/desktop_mode_floating_app_select_margin"
-        android:drawablePadding="@dimen/desktop_mode_floating_app_select_text_margin"
-        android:drawableStart="@drawable/ic_desktop"
-        android:drawableTint="?androidprv:attr/materialColorOnPrimaryContainer"
-        android:fontFamily="google-sans-medium"
-        android:gravity="center_vertical"
-        android:text="@string/desktop_select_app_toast"
-        android:textColor="?androidprv:attr/materialColorOnPrimaryContainer"
-        android:textSize="@dimen/desktop_mode_floating_app_select_text_size" />
-
-    <Button
-        android:id="@+id/close_button"
-        style="@android:style/Widget.DeviceDefault.Button.Borderless"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="@dimen/desktop_mode_floating_app_select_margin"
-        android:minWidth="0dp"
-        android:fontFamily="google-sans-medium"
-        android:text="@string/desktop_button_close_app_toast"
-        android:textAllCaps="false"
-        android:textColor="?androidprv:attr/materialColorPrimary"
-        android:textSize="@dimen/desktop_mode_floating_app_select_text_size" />
-
-</com.android.quickstep.views.DesktopAppSelectView>
diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/res/layout/overview_actions_container.xml
index d086da4..7aaf744 100644
--- a/quickstep/res/layout/overview_actions_container.xml
+++ b/quickstep/res/layout/overview_actions_container.xml
@@ -45,14 +45,24 @@
             android:theme="@style/ThemeControlHighlightWorkspaceColor"
             android:visibility="gone" />
 
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/group_action_buttons"
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/overview_actions_height"
+        android:layout_gravity="bottom|center_horizontal"
+        android:orientation="horizontal"
+        android:visibility="gone">
+
         <Button
             android:id="@+id/action_save_app_pair"
             style="@style/OverviewActionButton"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="@string/action_save_app_pair"
-            android:theme="@style/ThemeControlHighlightWorkspaceColor"
-            android:visibility="gone" />
+            android:theme="@style/ThemeControlHighlightWorkspaceColor" />
+
     </LinearLayout>
 
 </com.android.quickstep.views.OverviewActionsView>
\ No newline at end of file
diff --git a/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml b/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
index a1bcad0..b004dfd 100644
--- a/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
@@ -134,11 +134,12 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
+        android:layout_above="@id/gesture_tutorial_fragment_action_button"
         android:layout_centerHorizontal="true"
         android:background="@android:color/transparent"
-        android:paddingEnd="24dp"
-        android:paddingStart="24dp"
-        android:paddingTop="24dp">
+        android:paddingTop="24dp"
+        android:paddingHorizontal="24dp"
+        android:layout_marginBottom="16dp">
 
         <TextView
             android:id="@+id/gesture_tutorial_fragment_feedback_title"
@@ -169,7 +170,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
 
-            app:layout_constraintBottom_toBottomOf="@id/gesture_tutorial_fragment_action_button"
+            app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toTopOf="parent" />
@@ -193,7 +194,7 @@
             android:id="@+id/checkmark_animation"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginBottom="44dp"
+            android:layout_marginBottom="28dp"
             android:gravity="center"
             android:scaleType="centerCrop"
             app:lottie_loop="false"
@@ -204,19 +205,6 @@
             app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_fragment_feedback_subtitle"
             app:layout_constraintBottom_toBottomOf="parent" />
 
-        <Button
-            android:id="@+id/gesture_tutorial_fragment_action_button"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:background="@drawable/gesture_tutorial_action_button_background"
-            android:stateListAnimator="@null"
-            android:text="@string/gesture_tutorial_action_button_label"
-            android:visibility="invisible"
-            android:layout_marginBottom="60dp"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintTop_toBottomOf="@id/checkmark_animation" />
 
     </androidx.constraintlayout.widget.ConstraintLayout>
 
@@ -228,4 +216,18 @@
         android:src="@drawable/gesture_tutorial_finger_dot"
         android:visibility="gone" />
 
+    <Button
+        android:id="@+id/gesture_tutorial_fragment_action_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@dimen/gesture_tutorial_done_button_end_margin"
+        android:layout_marginBottom="@dimen/gesture_tutorial_done_button_bottom_margin"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentEnd="true"
+        android:background="@drawable/gesture_tutorial_action_button_background"
+        android:stateListAnimator="@null"
+        android:text="@string/gesture_tutorial_action_button_label"
+        android:visibility="invisible"
+         />
+
 </com.android.quickstep.interaction.RootSandboxLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index 9f648a7..cc3b30e 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -28,10 +28,7 @@
     launcher:focusBorderColor="?androidprv:attr/materialColorOutline"
     launcher:hoverBorderColor="?androidprv:attr/materialColorPrimary">
 
-    <com.android.quickstep.views.TaskThumbnailViewDeprecated
-        android:id="@+id/snapshot"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"/>
+    <include layout="@layout/task_thumbnail" />
 
     <!-- Filtering affects only alpha instead of the visibility since visibility can be altered
          separately through RecentsView#resetFromSplitSelectionState() -->
diff --git a/quickstep/res/layout/task_desktop.xml b/quickstep/res/layout/task_desktop.xml
index 36d7f86..89e9b3d 100644
--- a/quickstep/res/layout/task_desktop.xml
+++ b/quickstep/res/layout/task_desktop.xml
@@ -42,10 +42,7 @@
          views that do not inherint from TaskView only or create a generic TaskView that have
          N number of tasks.
      -->
-    <com.android.quickstep.views.TaskThumbnailViewDeprecated
-        android:id="@+id/snapshot"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
+    <include layout="@layout/task_thumbnail"
         android:visibility="gone" />
 
     <ViewStub
diff --git a/quickstep/res/layout/task_grouped.xml b/quickstep/res/layout/task_grouped.xml
index ec657bd..87a0f70 100644
--- a/quickstep/res/layout/task_grouped.xml
+++ b/quickstep/res/layout/task_grouped.xml
@@ -33,15 +33,10 @@
     launcher:focusBorderColor="?androidprv:attr/materialColorOutline"
     launcher:hoverBorderColor="?androidprv:attr/materialColorPrimary">
 
-    <com.android.quickstep.views.TaskThumbnailViewDeprecated
-        android:id="@+id/snapshot"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"/>
+    <include layout="@layout/task_thumbnail"/>
 
-    <com.android.quickstep.views.TaskThumbnailViewDeprecated
-        android:id="@+id/bottomright_snapshot"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"/>
+    <include layout="@layout/task_thumbnail"
+        android:id="@+id/bottomright_snapshot" />
 
     <!-- Filtering affects only alpha instead of the visibility since visibility can be altered
          separately through RecentsView#resetFromSplitSelectionState() -->
diff --git a/quickstep/res/layout/task_thumbnail.xml b/quickstep/res/layout/task_thumbnail.xml
new file mode 100644
index 0000000..f1a3d62
--- /dev/null
+++ b/quickstep/res/layout/task_thumbnail.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+     Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.quickstep.views.TaskThumbnailViewDeprecated
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/snapshot"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/quickstep/res/layout/taskbar_nav_button.xml b/quickstep/res/layout/taskbar_nav_button.xml
index aea4885..8f1c904 100644
--- a/quickstep/res/layout/taskbar_nav_button.xml
+++ b/quickstep/res/layout/taskbar_nav_button.xml
@@ -19,6 +19,7 @@
     android:layout_width="@dimen/taskbar_nav_buttons_size"
     android:layout_height="@dimen/taskbar_nav_buttons_size"
     android:background="@drawable/taskbar_icon_click_feedback_roundrect"
+    android:focusable="false"
     android:scaleType="center"
     android:tint="@color/taskbar_nav_icon_light_color"
     tools:ignore="UseAppTint" />
\ No newline at end of file
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index f347eae..0b03e02 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Doen meer met die Taakbalk"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Wys altyd die Taakbalk"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Raak en hou die verdeler in om altyd die Taakbalk onderaan jou skerm te wys"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Raak en hou die handelingsleutel om te soek wat op jou skerm is"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Hierdie produk gebruik die gekose deel van jou skerm om te soek. Google se <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>privaatheidsbeleid<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> en <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>diensbepalings<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> geld."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Maak toe"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Klaar"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Tuis"</string>
@@ -142,6 +140,4 @@
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Wys nog # app.}other{Wys nog # apps.}}"</string>
     <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Wys # rekenaarapp.}other{Wys # rekenaarapps.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> en <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Voeg nou app by werkskerm"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Kanselleer"</string>
 </resources>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index bde3a2d..c8fd276 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"በተግባር አሞሌው ተጨማሪ ነገር ያድርጉ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"የተግባር አሞሌውን ሁልጊዜ አሳይ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"በማያ ገጽዎ ግርጌ ላይ ያለውን የተግባር አሞሌ ሁልጊዜ ለማሳየት፣ መክፈያን ይንኩ እና ይያዙ"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"በማያ ገጽዎ ላይ ያለውን ነገር ለመፈለግ የተግባር ቁልፉን ነክተው ይያዙ"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"ይህ ምርት የተመረጠውን የማያ ገጽዎን ክፍል ለመፈለግ ይጠቀማል። የGoogle <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>የግላዊነት መመሪያ<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> እና <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>የአገልግሎት ውል<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ተፈጻሚ ናቸው።"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ዝጋ"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ተጠናቅቋል"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"መነሻ"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ወደ ላይ/ግራ ይውሰዱ"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ወደ ታች/ቀኝ ይውሰዱ"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ተጨማሪ # መተግበሪያ አሳይ።}one{ተጨማሪ # መተግበሪያ አሳይ።}other{ተጨማሪ # መተግበሪያዎች አሳይ።}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# የዴስክቶፕ መተግበሪያ አሳይ።}one{# የዴስክቶፕ መተግበሪያ አሳይ።}other{# የዴስክቶፕ መተግበሪያዎች አሳይ።}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> እና <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"መተግበሪያን ወደ ዴስክቶፕ በማከል ላይ"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ይቅር"</string>
 </resources>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index 957da2c..ca0e1dd 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -88,9 +88,9 @@
     <string name="gesture_tutorial_nice" msgid="2936275692616928280">"أحسنت"</string>
     <string name="gesture_tutorial_step" msgid="1279786122817620968">"الدليل التوجيهي <xliff:g id="CURRENT">%1$d</xliff:g> من إجمالي <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="allset_title" msgid="5021126669778966707">"اكتملت عملية الإعداد"</string>
-    <string name="allset_hint" msgid="459504134589971527">"يمكنك التمرير السريع إلى الأعلى للانتقال إلى الشاشة الرئيسية."</string>
+    <string name="allset_hint" msgid="459504134589971527">"يمكنك التمرير سريعًا إلى الأعلى للانتقال إلى الشاشة الرئيسية"</string>
     <string name="allset_button_hint" msgid="2395219947744706291">"انقر على زر الشاشة الرئيسية للانتقال إلى الشاشة الرئيسية."</string>
-    <string name="allset_description_generic" msgid="5385500062202019855">"يمكنك الآن بدء استخدام \"<xliff:g id="DEVICE">%1$s</xliff:g>\"."</string>
+    <string name="allset_description_generic" msgid="5385500062202019855">"يمكنك الآن بدء استخدام <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
     <string name="default_device_name" msgid="6660656727127422487">"الجهاز"</string>
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"إعدادات التنقّل داخل النظام"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"مشاركة"</string>
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"إنجاز المزيد باستخدام شريط التطبيقات"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"عرض \"شريط التطبيقات\" دائمًا"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"انقر مع الاستمرار على أداة تقسيم الشاشة لعرض \"شريط التطبيقات\" دائمًا في أسفل الشاشة."</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"انقر مع الاستمرار على مفتاح الإجراء للبحث عن المحتوى الذي يظهر على شاشتك"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"‏يستخدم هذا المنتج الجزء المحدّد من الشاشة للبحث. تسري <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>سياسة الخصوصية<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> و<xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>بنود الخدمة<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> في Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"إغلاق"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"تم"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"الرئيسية"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"الانتقال إلى يمين الشاشة أو أعلاها"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"الانتقال إلى يسار الشاشة أو أسفلها"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{إظهار تطبيق واحد آخر}zero{إظهار # تطبيق آخر}two{إظهار تطبيقَين آخرَين}few{إظهار # تطبيقات أخرى}many{إظهار # تطبيقًا آخر}other{إظهار # تطبيق آخر}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{عرض تطبيق واحد متوافق مع الكمبيوتر المكتبي}zero{عرض # تطبيق متوافق مع الكمبيوتر المكتبي}two{عرض تطبيقَين متوافقين مع الكمبيوتر المكتبي}few{عرض # تطبيقات متوافقة مع الكمبيوتر المكتبي}many{عرض # تطبيقًا متوافقًا مع الكمبيوتر المكتبي}other{عرض # تطبيق متوافق مع الكمبيوتر المكتبي}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"\"<xliff:g id="APP_NAME_1">%1$s</xliff:g>\" و\"<xliff:g id="APP_NAME_2">%2$s</xliff:g>\""</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"إضافة تطبيق إلى سطح المكتب"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"إلغاء"</string>
 </resources>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index 900521e..7cd7696 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"টাস্কবাৰৰ জৰিয়তে অধিক কাৰ্য সম্পাদন কৰক"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"টাস্কবাৰডাল সদায় দেখুৱাওক"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"আপোনাৰ স্ক্ৰীনৰ তলত সদায় টাস্কবাৰডাল দেখুৱাবলৈ বিভাজকডাল স্পৰ্শ কৰি ধৰি ৰাখক"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"আপোনাৰ স্ক্ৰীনখনত থকা সমল সন্ধান কৰিবলৈ কাৰ্য কীটো স্পৰ্শ কৰি ধৰি ৰাখক"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"এই প্ৰ’ডাক্টটোৱে সন্ধান কৰিবলৈ আপোনাৰ স্ক্ৰীনখনৰ বাছনি কৰা অংশ ব্যৱহাৰ কৰে। Googleৰ <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>গোপনীয়তাৰ নীতি<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> আৰু <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>সেৱাৰ চৰ্তাৱলী<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> প্ৰযোজ্য।"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"বন্ধ কৰক"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"হ’ল"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"গৃহপৃষ্ঠা"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ওপৰৰ বাঁওফাললৈ নিয়ক"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"তলৰ সোঁফাললৈ নিয়ক"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{আৰু # টা এপ্‌ দেখুৱাওক।}one{আৰু # টা এপ্‌ দেখুৱাওক।}other{আৰু # টা এপ্‌ দেখুৱাওক।}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# টা ডেস্কটপ এপ্ দেখুৱাওক।}one{# টা ডেস্কটপ এপ্ দেখুৱাওক।}other{# টা ডেস্কটপ এপ্ দেখুৱাওক।}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> আৰু <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ডেস্কটপত এপ্ যোগ দি থকা হৈছে"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"বাতিল কৰক"</string>
 </resources>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 82b0d72..f5840ab 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Tapşırıq paneli ilə daha çox şey edin"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"İşləmə panelini həmişə göstərin"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"İşləmə panelini həmişə ekranın aşağısında göstərmək üçün ayırıcı üzərinə toxunun və saxlayın"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Ekranda axtarış etmək üçün fəaliyyət açarına toxunub saxlayın"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Bu məhsul axtarış üçün ekranın seçilmiş hissəsindən istifadə edir. Google <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Məxfilik Siyasəti<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> və <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Xidmət Şərtləri<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> tətbiq edilir."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Bağlayın"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Hazırdır"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Ev"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Yuxarı/sola köçürün"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Aşağı/sağa köçürün"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Daha # tətbiqi göstərin.}other{Daha # tətbiqi göstərin.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# masaüstü tətbiqini göstərin.}other{# masaüstü tətbiqini göstərin.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> və <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Tətbiqin masaüstünə əlavə edilməsi"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ləğv edin"</string>
 </resources>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index c88c0a2..276a8b9 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Uradite više pomoću trake zadataka"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Uvek prikazuj traku zadataka"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Da bi traka zadataka uvek bila prikazana u dnu ekrana, dodirnite i zadržite razdelnik"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Dodirnite i zadržite taster radnji da biste pretražili ono što je na ekranu"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Ovaj proizvod koristi izabrani deo ekrana za pretragu. Primenjuju se Google <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>politika privatnosti<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> i <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>uslovi korišćenja usluge<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zatvori"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Gotovo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Početna"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premesti gore levo"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premesti dole desno"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Prikaži # aplikaciju za računare.}one{Prikaži # aplikaciju za računare.}few{Prikaži # aplikacije za računare.}other{Prikaži # aplikacija za računare.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodaje se aplikacija na radnu povrršinu"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Otkaži"</string>
 </resources>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 6a9fa06..0785e0f 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Выкарыстоўвайце магчымасці панэлі задач"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Замацуйце панэль задач унізе экрана"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Для гэтага націсніце на раздзяляльнік і ўтрымлівайце яго"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Для пошуку па змесціве экрана націсніце і ўтрымлівайце клавішу дзеяння"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Гэты прадукт выконвае пошук па змесціве выбранай часткі экрана. Прымяняюцца <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Умовы выкарыстання<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> і <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Палітыка прыватнасці<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Закрыць"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Гатова"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Галоўны экран"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Перамясціць уверх/улева"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Перамясціць уніз/управа"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Паказаць ячшэ # праграму.}one{Паказаць ячшэ # праграму.}few{Паказаць ячшэ # праграмы.}many{Паказаць ячшэ # праграм.}other{Паказаць ячшэ # праграмы.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Паказаць # праграму для ПК.}one{Паказаць # праграму для ПК.}few{Паказаць # праграмы для ПК.}many{Паказаць # праграм для ПК.}other{Паказаць # праграмы для ПК.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> і <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Дадаванне праграмы на камп\'ютар"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Скасаваць"</string>
 </resources>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index 0faaaf7..c26bc6f 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Правете повече неща с лентата на задачите"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Лентата на задачите да се показва винаги"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"За да фиксирате лентата на задачите най-долу на екрана, докоснете и задръжте разделителя"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Докоснете и задръжте клавиша за действия, за да извършите търсене със съдържанието на екрана"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Този продукт използва избраната част на екрана ви, за да търси. Прилагат се <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Декларацията за поверителност<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> и <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Общите условия<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> на Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Затваряне"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Начало"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Преместване горе/вляво"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Преместване долу/вдясно"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показване на още # приложение.}other{Показване на още # приложения.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Показване на # настолно приложение.}other{Показване на # настолни приложения.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Приложението се добавя на настолния компютър"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Отказ"</string>
 </resources>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index de0c613..f7f666b 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"\'টাস্কবার\' ফিচারের সাহায্যে আরও অনেক কিছু করুন"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"টাস্কবার সবসময় দেখানো"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"স্ক্রিনের নিচে টাস্কবার সবসময় দেখাতে ডিভাইডার টাচ করে ধরে থাকুন"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"আপনার স্ক্রিনে দেখতে পাওয়া কন্টেন্ট সার্চ করতে অ্যাকশন কী স্পর্শ করে ধরে রাখুন"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"সার্চ করার জন্য এই প্রোডাক্ট স্ক্রিনের বেছে নেওয়া অংশটুকু ব্যবহার করে। Google-এর <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>গোপনীয়তা নীতি<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> এবং <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>পরিষেবার শর্তাবলী<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> প্রযোজ্য।"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"বন্ধ করুন"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"হয়ে গেছে"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"হোম"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"উপরে/বাঁদিকে সরান"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"নিচে/ডানদিকে সরান"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{আরও #টি অ্যাপ দেখুন।}one{আরও #টি অ্যাপ দেখুন।}other{আরও #টি অ্যাপ দেখুন।}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{#টি ডেস্কটপ অ্যাপ দেখুন।}one{#টি ডেস্কটপ অ্যাপ দেখুন।}other{#টি ডেস্কটপ অ্যাপ দেখুন।}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ও <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ডেস্কটপে অ্যাপ যোগ করা হচ্ছে"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"বাতিল করুন"</string>
 </resources>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 6be4fb7..1167145 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Uradite više pomoću trake zadataka"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Stalni prikaz trake zadataka"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Da se traka zadataka uvijek prikazuje na dnu ekrana, dodirnite i zadržite razdjelnik"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Dodirnite i zadržite tipku radnji da pretražite sadržaj na ekranu"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Ovaj proizvod koristi odabrani dio ekrana za pretraživanje. Primjenjuju se Googleova <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Pravila privatnosti<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> i <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Uslovi korištenja usluge<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zatvori"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Gotovo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Dom"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premjesti gore lijevo"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premjesti dolje desno"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Prikaži # aplikaciju za računar.}one{Prikaži # aplikaciju za računar.}few{Prikaži # aplikacije za računar.}other{Prikaži # aplikacija za računar.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodavanje aplikacije na radnu površinu"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Otkaži"</string>
 </resources>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index e7fe6df..ba8e3c1 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Treu més partit de la Barra de tasques"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mostra sempre la Barra de tasques"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Perquè es mostri sempre la Barra de tasques a la part inferior de la pantalla, mantén premut el separador"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Mantén premuda la tecla d\'acció per cercar què es mostra a la pantalla"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Aquest producte utilitza la part seleccionada de la pantalla per fer cerques. S\'apliquen la <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>política de privadesa<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> i les <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>condicions del servei<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> de Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Tanca"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Fet"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Inici"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mou a la part superior o a l\'esquerra"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mou a la part inferior o a la dreta"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostra # aplicació més.}other{Mostra # aplicacions més.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostra # aplicació per a ordinadors.}other{Mostra # aplicacions per a ordinadors.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"S\'està afegint l\'aplicació a l\'ordinador"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel·la"</string>
 </resources>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index ad482af..7f1cd94 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Více možností s panelem aplikací"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Stálé zobrazení panelu aplikací"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Pokud chcete, aby se panel aplikací vždy zobrazoval ve spodní části obrazovky, podržte oddělovač."</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Podržením akční klávesy můžete vyhledat obsah na obrazovce"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Tato služba používá k vyhledávání vybranou část obrazovky. Platí <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>zásady ochrany soukromí<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> a <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>smluvní podmínky<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> společnosti Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zavřít"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Hotovo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Domů"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Přesunout doleva nahoru"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Přesunout doprava dolů"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Zobrazit # další aplikaci.}few{Zobrazit # další aplikace.}many{Zobrazit # další aplikace.}other{Zobrazit # dalších aplikací.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Zobrazit # aplikaci pro počítač.}few{Zobrazit # aplikace pro počítač.}many{Zobrazit # aplikace pro počítač.}other{Zobrazit # aplikací pro počítač.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> a <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Přidání aplikace na plochu"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Zrušit"</string>
 </resources>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index 9d002f01..1daf365 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Få mere fra hånden med proceslinjen"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Vis altid proceslinjen"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Hvis du vil have, at proceslinjen altid vises nederst på din skærm, skal du holde fingeren på skillelinjen"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Hold fingeren på handlingstasten for at søge efter det, der vises på din skærm"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Dette produkt bruger den valgte del af din skærm til at søge. Googles <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>privatlivspolitik<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> og <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>servicevilkår<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> er gældende."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Luk"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Luk"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Hjem"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Flyt til toppen eller venstre side"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Flyt til bunden eller højre side"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Vis # app mere.}one{Vis # app mere.}other{Vis # apps mere.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Vis # computerprogram.}one{Vis # computerprogram.}other{Vis # computerprogrammer.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Appen føjes til computeren"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuller"</string>
 </resources>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 5baab32..b089976 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -95,7 +95,7 @@
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Einstellungen der Systemsteuerung"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Teilen"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
-    <string name="action_split" msgid="2098009717623550676">"Teilen"</string>
+    <string name="action_split" msgid="2098009717623550676">"Splitscreen"</string>
     <string name="action_save_app_pair" msgid="5974823919237645229">"App-Paar speichern"</string>
     <string name="toast_split_select_app" msgid="8464310533320556058">"Für Splitscreen auf weitere App tippen"</string>
     <string name="toast_contextual_split_select_app" msgid="433510957123687090">"Für Splitscreen andere App auswählen"</string>
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Mehr Möglichkeiten mit der Taskleiste"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Taskleiste immer anzeigen"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Damit die Taskleiste immer unten angezeigt wird, halte den Teiler gedrückt"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Aktionstaste gedrückt halten, um auf dem Bildschirm zu suchen"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Dieses Produkt verwendet den ausgewählten Teil deines Bildschirms für die Suche. Es gelten die <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Datenschutzerklärung<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> und die <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Nutzungsbedingungen<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> von Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Schließen"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Fertig"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Startbildschirm"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Nach oben / Nach links verschieben"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Nach unten / Nach rechts verschieben"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# weitere App anzeigen}other{# weitere Apps anzeigen}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# Desktop-App anzeigen.}other{# Desktop-Apps anzeigen.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> und <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Hinzufügen einer App zum Desktop"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Abbrechen"</string>
 </resources>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 59e8b12..66ca90e 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Κάντε περισσότερα με τη Γραμμή εργαλείων"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Να εμφανίζεται πάντα η Γραμμή εργαλείων"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Για να εμφανίζεται πάντα η Γραμμή εργαλείων στο κάτω μέρος της οθόνης, αγγίξτε παρατεταμένα το διαχωριστικό"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Αγγίξτε παρατεταμένα το πλήκτρο ενέργειας για να αναζητήσετε το περιεχόμενο της οθόνης"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Αυτό το προϊόν χρησιμοποιεί το επιλεγμένο τμήμα της οθόνης σας για αναζήτηση. Ισχύουν η <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Πολιτική απορρήτου<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> και οι <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Όροι Παροχής Υπηρεσιών<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> της Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Κλείσιμο"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Τέλος"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Αρχική σελίδα"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Μετακίνηση επάνω/αριστερά"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Μετακίνηση κάτω/δεξιά"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Εμφάνιση # ακόμα εφαρμογής.}other{Εμφάνιση # ακόμα εφαρμογών.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Εμφάνιση # εφαρμογής υπολογιστή.}other{Εμφάνιση # εφαρμογών υπολογιστή.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> και <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Γίνεται προσθήκη εφαρμογής στον υπολογιστή"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ακύρωση"</string>
 </resources>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index 42521a9..fe5b479 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the Taskbar"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Always show the Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"To always show the Taskbar on the bottom of your screen, touch and hold the divider"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Touch and hold the action key to search what\'s on your screen"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"This product uses the selected part of your screen to search. Google\'s <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Privacy Policy<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> and <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Terms of Service<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> apply."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Done"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
 </resources>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index 9539da6..3bd2bdd 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -140,6 +140,4 @@
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
     <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to Desktop"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
 </resources>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index 42521a9..fe5b479 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the Taskbar"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Always show the Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"To always show the Taskbar on the bottom of your screen, touch and hold the divider"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Touch and hold the action key to search what\'s on your screen"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"This product uses the selected part of your screen to search. Google\'s <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Privacy Policy<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> and <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Terms of Service<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> apply."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Done"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
 </resources>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index 42521a9..fe5b479 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the Taskbar"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Always show the Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"To always show the Taskbar on the bottom of your screen, touch and hold the divider"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Touch and hold the action key to search what\'s on your screen"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"This product uses the selected part of your screen to search. Google\'s <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Privacy Policy<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> and <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Terms of Service<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> apply."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Done"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
 </resources>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index f3499e1..52efe9d 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -140,6 +140,4 @@
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎Show # more app.‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎Show # more apps.‎‏‎‎‏‎}}"</string>
     <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎Show # desktop app.‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎Show # desktop apps.‎‏‎‎‏‎}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME_1">%1$s</xliff:g>‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎<xliff:g id="APP_NAME_2">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‎‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎Adding app to Desktop‎‏‎‎‏‎"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‎Cancel‎‏‎‎‏‎"</string>
 </resources>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 8b221cc..095b06e 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Aprovecha mejor la Barra de tareas"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mostrar siempre la Barra de tareas"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Mantén presionado el divisor para mostrar siempre la Barra de tareas en la parte inferior de la pantalla"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Mantén presionada la tecla de acción para buscar qué hay en la pantalla"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Este producto usa la parte seleccionada de la pantalla para buscar. Se aplican la <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Política de Privacidad<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> y las <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Condiciones del Servicio<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> de Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Cerrar"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Listo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Botón de inicio"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover a la parte superior o izquierda"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover a la parte inferior o derecha"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # app más.}other{Mostrar # apps más.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostrar # app para computadoras.}other{Mostrar # apps para computadoras.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> y <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Agregando app al escritorio"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
 </resources>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 5093400..dbc7caa 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Sácale más partido a la barra de tareas"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mostrar siempre la barra de tareas"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Para mostrar siempre la barra de tareas en la parte inferior, mantén pulsada la línea divisoria"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Mantén pulsada la tecla de acción para buscar lo que ves en pantalla"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Este producto usa la parte seleccionada de tu pantalla para hacer búsquedas. Se aplican la <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Política de Privacidad<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> y los <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Términos del Servicio<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> de Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Cerrar"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Hecho"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Inicio"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover arriba/a la izquierda"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover abajo/a la derecha"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # aplicación más.}other{Mostrar # aplicaciones más.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostrar # aplicación para ordenadores.}other{Mostrar # aplicaciones para ordenadores.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> y <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Añadiendo aplicación al ordenador"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
 </resources>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 16d2248..c53f80c 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -90,12 +90,12 @@
     <string name="allset_title" msgid="5021126669778966707">"Valmis!"</string>
     <string name="allset_hint" msgid="459504134589971527">"Avalehele liikumiseks pühkige üles"</string>
     <string name="allset_button_hint" msgid="2395219947744706291">"Avakuvale liikumiseks puudutage avakuva nuppu"</string>
-    <string name="allset_description_generic" msgid="5385500062202019855">"Olete valmis oma seadet <xliff:g id="DEVICE">%1$s</xliff:g> kasutama"</string>
+    <string name="allset_description_generic" msgid="5385500062202019855">"<xliff:g id="DEVICE">%1$s</xliff:g> on nüüd kasutamiseks valmis"</string>
     <string name="default_device_name" msgid="6660656727127422487">"seade"</string>
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Süsteemi navigeerimisseaded"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Jaga"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Ekraanipilt"</string>
-    <string name="action_split" msgid="2098009717623550676">"Eralda"</string>
+    <string name="action_split" msgid="2098009717623550676">"Jaga pooleks"</string>
     <string name="action_save_app_pair" msgid="5974823919237645229">"Salvesta rakendusepaar"</string>
     <string name="toast_split_select_app" msgid="8464310533320556058">"Jagatud ekraanikuva kasutamiseks puudutage muud rakendust"</string>
     <string name="toast_contextual_split_select_app" msgid="433510957123687090">"Valige jagatud ekraanikuva jaoks muu rakendus."</string>
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Tehke tegumiriba abil enamat"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Alati kuvatud tegumiriba"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Puudutage pikalt jaoturit, et tegumiriba oleks ekraani allosas alati kuvatud"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Puudutage pikalt toiminguklahvi, et ekraanil kuvatut otsida"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"See toode kasutab otsingu jaoks ekraani valitud osa. Kehtivad Google\'i <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>privaatsuseeskirjad<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> ja <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>teenusetingimused<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Sule"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Valmis"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Avaleht"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Teisalda üles/vasakule"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Teisalda alla/paremale"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Kuva veel # rakendus.}other{Kuva veel # rakendust.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Kuva # töölauarakendus.}other{Kuva # töölauarakendust.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ja <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Rakenduse lisamine arvutisse"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Tühista"</string>
 </resources>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index 690603b..ecdacd2 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Egin gauza gehiago zereginen barrarekin"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Erakutsi beti zereginen barra"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Pantailaren behealdeko zereginen barra beti erakusteko, eduki sakatuta zatitzailea"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Eduki sakatuta ekintza-tekla pantailan dagoena bilatzeko"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Produktu honek pantailan hautatutako zatia erabiltzen du bilaketa egiteko. Google-ren <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Pribatutasun-gidalerroak<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> eta <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Zerbitzu-baldintzak<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> aplikatzen dira."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Itxi"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Eginda"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Hasiera"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Eraman gora, ezkerretara"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Eraman behera, eskuinetara"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Erakutsi beste # aplikazio.}other{Erakutsi beste # aplikazio.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Erakutsi ordenagailuetarako # aplikazio.}other{Erakutsi ordenagailuetarako # aplikazio.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> eta <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Aplikazioa mahaigainean gehitzen"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Utzi"</string>
 </resources>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index 8d5045b..0dad801 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"با «نوار وظیفه» می‌توانید کارهای بیشتر انجام دهید"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"همیشه نشان داده شدن «نوار وظیفه»"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"برای اینکه «نوار وظیفه» همیشه در پایین صفحه نشان داده شود، تقسیم‌کننده را لمس کنید و نگه دارید"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"برای جستجوی محتوای صفحه‌نمایش، دکمه کنش را لمس کنید و نگه دارید"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"‏این محصول از قسمت انتخاب‌شده صفحه‌نمایش شما برای جستجو استفاده می‌کند. <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>خط‌مشی رازداری<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> و <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>شرایط خدمات<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google اعمال می‌شود."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"بستن"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"تمام"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"صفحه اصلی"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"انتقال به بالا/ چپ"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"انتقال به پایین/ راست"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{نمایش # برنامه دیگر.}one{نمایش # برنامه دیگر.}other{نمایش # برنامه دیگر.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{نمایش # برنامه رایانه.}one{نمایش # برنامه رایانه.}other{نمایش # برنامه رایانه.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> و <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"درحال افزودن برنامه به رایانه"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"لغو"</string>
 </resources>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index e6befd6..8624fe7 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -95,7 +95,7 @@
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Järjestelmän navigointiasetukset"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Jaa"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Kuvakaappaus"</string>
-    <string name="action_split" msgid="2098009717623550676">"Jaa"</string>
+    <string name="action_split" msgid="2098009717623550676">"Jaettu näyttö"</string>
     <string name="action_save_app_pair" msgid="5974823919237645229">"Tallenna pari"</string>
     <string name="toast_split_select_app" msgid="8464310533320556058">"Avaa jaettu näyttö napauttamalla toista sovellusta"</string>
     <string name="toast_contextual_split_select_app" msgid="433510957123687090">"Käytä jaettua näyttöä valitsemalla toinen sovellus"</string>
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Vinkkejä tehtäväpalkin tehokkaampaan käyttöön"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Näytä tehtäväpalkki aina"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Jos haluat tehtäväpalkin näkyvän aina näytön alaosassa, kosketa jakajaa pitkään"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Kosketa toimintonäppäintä pitkään, niin voit hakea näytöltä"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Tämä tuote käyttää hakuun valittua näytön osaa. Tähän sovelletaan Googlen <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>tietosuojakäytäntöä<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> ja <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>käyttöehtoja<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Sulje"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Valmis"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Etusivu"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Siirrä ylös tai vasemmalle"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Siirrä alas tai oikealle"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Näytä # muu sovellus.}other{Näytä # muuta sovellusta.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Näytä # työpöytäsovellus.}other{Näytä # työpöytäsovellusta.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ja <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Sovelluksen lisääminen työpöydälle"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Peru"</string>
 </resources>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 875ad8f..7373800 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Faites-en plus avec la barre des tâches"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Toujours afficher la Barre des tâches"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Pour toujours afficher la Barre des tâches en bas de l\'écran, maintenez le doigt sur le séparateur"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Maintenez le doigt sur la touche d\'action pour rechercher ce qui se trouve sur votre écran"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Ce produit utilise la partie sélectionnée de votre écran pour effectuer une recherche. La <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>politique de confidentialité<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> et les <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>conditions d\'utilisation<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> de Google s\'appliquent."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Fermer"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"OK"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Accueil"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Déplacer vers le coin supérieur gauche de l\'écran"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Déplacer vers le coin inférieur droit de l\'écran"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afficher # autre application.}one{Afficher # autre application.}other{Afficher # autres applications.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Afficher # appli de bureau.}one{Afficher # appli de bureau.}other{Afficher # applis de bureau.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> et <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Ajout de l\'application au bureau en cours…"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuler"</string>
 </resources>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 1d82277..f19a435 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Faites-en plus avec la barre des tâches"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Toujours afficher la barre des tâches"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Pour toujours afficher la barre des tâches en bas de votre écran, appuyez sur le séparateur de manière prolongée."</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Appuyez de manière prolongée sur la touche d\'action pour rechercher ce qui se trouve à l\'écran"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Ce produit utilise la zone sélectionnée de l\'écran pour rechercher. Les <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Règles de confidentialité<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> et les <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Conditions d\'utilisation<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> de Google s\'appliquent."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Fermer"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"OK"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Accueil"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Déplacer en haut ou à gauche"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Déplacer en bas ou à droite"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afficher # autre appli}one{Afficher # autre appli}other{Afficher # autre applis}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Afficher # application de bureau.}one{Afficher # application de bureau.}other{Afficher # applications de bureau.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> et <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Ajout de l\'appli au bureau"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuler"</string>
 </resources>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 096709c..0afb288 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Tira máis proveito da barra de tarefas"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mostrar sempre a barra de tarefas"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Para fixar a barra de tarefas na parte inferior, mantén premida a liña divisoria"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Mantén premida a tecla de acción para buscar o que hai na pantalla"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Este produto utiliza a parte seleccionada da pantalla para facer buscas. Aplícanse as <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Condicións de servizo<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> e a <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Política de privacidade<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> de Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Pechar"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Listo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Inicio"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover á parte superior ou á esquerda"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover á parte inferior ou á dereita"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # aplicación máis.}other{Mostrar # aplicacións máis.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostrar # aplicación para ordenadores.}other{Mostrar # aplicacións para ordenadores.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Engadindo aplicación ao ordenador"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
 </resources>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index d495c59..fd5dca6 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ટાસ્કબાર વડે બીજું ઘણું કરો"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ટાસ્કબાર હંમેશાં બતાવો"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ટાસ્કબાર હંમેશાં તમારી સ્ક્રીનમાં સૌથી નીચે દેખાય તે માટે વિભાજકને ટચ કરીને થોડીવાર દબાવી રાખો"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"તમારી સ્ક્રીન પર જે હોય તે શોધવા માટે, ઍક્શન કી ટચ કરીને દબાવી રાખો"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"શોધવા માટે, આ પ્રોડક્ટ તમારી સ્ક્રીનના પસંદ કરેલા ભાગનો ઉપયોગ કરે છે. Googleની <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>પ્રાઇવસી પૉલિસી<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> અને <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>સેવાની શરતો<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> લાગુ થાય છે."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"બંધ કરો"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"થઈ ગયું"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"હોમ"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"સૌથી ઉપર ડાબી બાજુએ ખસેડો"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"સૌથી નીચે જમણી બાજુએ ખસેડો"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{વધુ # ઍપ બતાવો.}one{વધુ # ઍપ બતાવો.}other{વધુ # ઍપ બતાવો.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ડેસ્કટૉપ ઍપ બતાવો.}one{# ડેસ્કટૉપ ઍપ બતાવો.}other{# ડેસ્કટૉપ ઍપ બતાવો.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> અને <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ડેસ્કટૉપ પર ઍપ ઉમેરી રહ્યાં છીએ"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"રદ કરો"</string>
 </resources>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index 960b489..246bdc7 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"टास्कबार के साथ कई और काम करें"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"टास्कबार को हमेशा दिखाएं"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"टास्कबार को हमेशा अपनी स्क्रीन के नीचे दिखाने के लिए, डिवाइडर दबाकर रखें"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"स्क्रीन पर दिख रहे कॉन्टेंट को खोजने के लिए, ऐक्शन बटन को दबाकर रखें"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"यह प्रॉडक्ट, स्क्रीन के चुनिंदा हिस्से पर कॉन्टेंट खोजता है. Google की <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>निजता नीति<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> और <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>सेवा की शर्तें<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> लागू."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"बंद करें"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"हो गया"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"होम"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ऊपर/बाईं तरफ़ ले जाएं"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"नीचे/दाईं तरफ़ ले जाएं"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# और ऐप्लिकेशन दिखाएं.}one{# और ऐप्लिकेशन दिखाएं.}other{# और ऐप्लिकेशन दिखाएं.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}one{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}other{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> और <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटॉप पर ऐप्लिकेशन जोड़ा जा रहा है"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द करें"</string>
 </resources>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index cc4db5b..0069eda 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -90,12 +90,12 @@
     <string name="allset_title" msgid="5021126669778966707">"Sve je spremno!"</string>
     <string name="allset_hint" msgid="459504134589971527">"Prijeđite prstom prema gore da biste otvorili početni zaslon"</string>
     <string name="allset_button_hint" msgid="2395219947744706291">"Dodirnite gumb početnog zaslona da biste prešli na početni zaslon"</string>
-    <string name="allset_description_generic" msgid="5385500062202019855">"Spremni ste za početak upotrebe uređaja <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+    <string name="allset_description_generic" msgid="5385500062202019855">"<xliff:g id="DEVICE">%1$s</xliff:g> je spreman za početak upotrebe"</string>
     <string name="default_device_name" msgid="6660656727127422487">"uređaj"</string>
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Postavke navigacije sustavom"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Podijeli"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Snimka zaslona"</string>
-    <string name="action_split" msgid="2098009717623550676">"Podijeli"</string>
+    <string name="action_split" msgid="2098009717623550676">"Podjela"</string>
     <string name="action_save_app_pair" msgid="5974823919237645229">"Spremi par apl."</string>
     <string name="toast_split_select_app" msgid="8464310533320556058">"Dodirnite drugu aplikaciju za podijeljeni zaslon"</string>
     <string name="toast_contextual_split_select_app" msgid="433510957123687090">"Odaberite drugu aplikaciju za upotrebu podijeljenog zaslona"</string>
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Učinite više pomoću trake sa zadacima"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Uvijek prikazuj traku sa zadacima"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Da bi se traka prikazivala, dodirnite i držite razdjelnik"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Dodirnite i zadržite tipku za radnju da biste pretražili što se nalazi na zaslonu"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Ovaj proizvod upotrebljava odabrani dio zaslona za pretraživanje. Primjenjuju se Googleova <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>pravila o privatnosti<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> i <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>uvjeti pružanja usluge<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zatvori"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Gotovo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Početna"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premjesti gore/lijevo"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premjesti dolje/desno"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži još # aplikaciju}one{Prikaži još # aplikaciju}few{Prikaži još # aplikacije}other{Prikaži još # aplikacija}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Prikaži # računalnu aplikaciju.}one{Prikaži # računalnu aplikaciju.}few{Prikaži # računalne aplikacije.}other{Prikaži # računalnih aplikacija.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodavanje aplikacije na radnu površinu"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Odustani"</string>
 </resources>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index b0e0d39..162337e 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Jobban kihasználhatja a Feladatsávot"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mindig jelenjen meg a Feladatsáv"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Ahhoz, hogy a Feladatsáv mindig megjelenjen a képernyő alján, érintse meg és tartsa lenyomva az elválasztót"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"A műveletbillentyűt lenyomva tartva kereshet a képernyőn található tartalmak között"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Ez a termék a képernyő kiválasztott részét használja a kereséshez. A Google <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Adatvédelmi irányelvei<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> és <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Általános Szerződési Feltételei<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> érvényesek."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Bezárás"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Kész"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Kezdőlap"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mozgatás felülre vagy a bal oldalra"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mozgatás alulra vagy a jobb oldalra"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# további alkalmazás megjelenítése.}other{# további alkalmazás megjelenítése.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# asztali alkalmazás megjelenítése.}other{# asztali alkalmazás megjelenítése.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> és <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Alkalmazás hozzáadása az asztalhoz"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Mégse"</string>
 </resources>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 0d1f5cd..8919191 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Օգտվեք հավելվածների վահանակի բոլոր հնարավորություններից"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Ամրացրեք հավելվածների վահանակը"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Հավելվածների վահանակն էկրանի ներքևում ամրացնելու համար հպեք և պահեք բաժանիչը"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Սեղմած պահեք գործողության ստեղնը՝ էկրանին բովանդակություն որոնելու համար"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Այս պրոդուկտն օգտագործում է էկրանի ընտրված հատվածը որոնման համար։ Կիրառվում են Google-ի <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Գաղտնիության քաղաքականությունը<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> և <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Օգտագործման պայմանները<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>։"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Փակել"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Պատրաստ է"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Սկիզբ"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Տեղափոխել վերևի ձախ անկյուն"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Տեղափոխել ներքևի աջ անկյուն"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Ցուցադրել ևս # հավելված։}one{Ցուցադրել ևս # հավելված։}other{Ցուցադրել ևս # հավելված։}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Ցույց տալ # համակարգչային հավելված։}one{Ցույց տալ # համակարգչային հավելված։}other{Ցույց տալ # համակարգչային հավելված։}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> և <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Հավելվածն ավելացվում է աշխատասեղանին"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Չեղարկել"</string>
 </resources>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 16aa8c4..ea62b4d 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Lakukan lebih banyak hal dengan Taskbar"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Selalu tampilkan Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Untuk selalu menampilkan Taskbar di bagian bawah layar Anda, sentuh &amp; tahan pembatasnya"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Sentuh &amp; tahan tombol tindakan untuk mencari konten di layar Anda"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Produk ini menggunakan bagian layar terpilih untuk menelusuri. <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Kebijakan Privasi<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> dan <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Persyaratan Layanan<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google berlaku."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Tutup"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Selesai"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Layar utama"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Pindahkan ke atas/kiri"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Pindahkan ke bawah/kanan"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Tampilkan # aplikasi lainnya.}other{Tampilkan # aplikasi lainnya.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Tampilkan # aplikasi desktop.}other{Tampilkan # aplikasi desktop.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dan <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Menambahkan aplikasi ke Desktop"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Batalkan"</string>
 </resources>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index bed6542..3e204ce 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Nýttu forritastikuna betur"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Halda forritastikunni sýnilegri"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Haltu skjáskiptingunni neðst á skjánum inni til að halda forritastikunni sýnilegri"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Haltu aðgerðalyklinum inni til að leita að því sem er á skjánum"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Þessi vara notar valinn hluta skjásins til að leita. <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Persónuverndarstefna<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> og <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>þjónustuskilmálar<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google gilda."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Loka"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Lokið"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Heim"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Færa efst/til vinstri"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Færa neðst/til hægri"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Sýna # forrit í viðbót.}one{Sýna # forrit í viðbót.}other{Sýna # forrit í viðbót.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Sýna # skjáborðsforrit.}one{Sýna # skjáborðsforrit.}other{Sýna # skjáborðsforrit.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Forriti bætt við skjáborð"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Hætta við"</string>
 </resources>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 663b334..f295b07 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Fai di più con la barra delle app"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mostra sempre la barra delle app"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Per mostrare sempre la barra delle app in basso, tocca e tieni premuto il divisore"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Tocca e tieni premuto il tasto azione per cercare gli elementi sullo schermo"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Il prodotto usa la parte selezionata dello schermo per cercare. Si applicano le <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Norme sulla privacy<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> e i <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Termini di servizio<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> di Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Chiudi"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Fine"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Sposta in alto/a sinistra"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Sposta in basso/a destra"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostra # altra app.}other{Mostra altre # app.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostra # app desktop.}other{Mostra # app desktop.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Aggiunta app a desktop in corso…"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annulla"</string>
 </resources>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index ef4ab6e..037deec 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"פעולות נוספות שאפשר לעשות עם סרגל האפליקציות"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"תמיד להציג את סרגל האפליקציות"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"כדי להציג תמיד את סרגל האפליקציות בתחתית המסך, יש ללחוץ לחיצה ארוכה על המחיצה"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"כדי לחפש במסך, צריך ללחוץ לחיצה ארוכה על מקש הפעולה"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"‏המוצר הזה משתמש בחלק שבחרת במסך לצורך חיפוש, בכפוף ל<xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>מדיניות הפרטיות<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> ו<xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>לתנאים ולהגבלות<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> של Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"סגירה"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"סיום"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"בית"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"העברה לפינה השמאלית/העליונה"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"העברה לפינה הימנית/התחתונה"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{הצגת אפליקציה אחת (#) נוספת.}one{הצגת # אפליקציות נוספות.}two{הצגת # אפליקציות נוספות.}other{הצגת # אפליקציות נוספות.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{הצגת אפליקציה אחת (#) למחשב.}one{הצגת # אפליקציות למחשב.}two{הצגת # אפליקציות למחשב.}other{הצגת # אפליקציות למחשב.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ו-<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"האפליקציה מתווספת לשולחן העבודה"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ביטול"</string>
 </resources>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 8855381..ef335f2 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"タスクバーの各種機能"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"タスクバーを常に表示"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"タスクバーを画面下部に常に表示するには分割線を長押しします"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"画面上の内容を検索するには、アクションキーを長押ししてください"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"このサービスは、検索する際に画面上で選択された箇所を使用します。Google の<xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>プライバシー ポリシー<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g>と<xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>利用規約<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>が適用されます。"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"閉じる"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"完了"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ホーム"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"上 / 左に移動"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"下 / 右に移動"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{他 # 件のアプリを表示できます。}other{他 # 件のアプリを表示できます。}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# 個のデスクトップ アプリが表示されます。}other{# 個のデスクトップ アプリが表示されます。}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> と <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"アプリをデスクトップに追加する"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"キャンセル"</string>
 </resources>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index 63368b5..6da246a 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"გააკეთეთ მეტი ამოცანათა ზოლის მეშვეობით"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ამოცანათა ზოლის მუდმივად ჩვენება"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"თქვენი ეკრანის ქვედა ნაწილში ამოცანათა ზოლის მუდმივად საჩვენებლად, ხანგრძლივად შეეხეთ გამყოფს"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"შეეხეთ და გეჭიროთ მოქმედების ღილაკი, რათა მოძებნოთ ის, რაც თქვენს ეკრანზეა"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"ეს პროდუქტი ძიებისთვის იყენებს თქვენი ეკრანის არჩეულ ნაწილს. მოქმედებს Google-ის <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>კონფიდენციალურობის დებულება<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> და <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>მომსახურებს პირობები<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"დახურვა"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"მზადაა"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"მთავარი"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ზემოთ/მარცხნივ გადატანა"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ქვემოთ/მარჯვნივ გადატანა"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{#-ით მეტი აპის ჩენება}other{#-ით მეტი აპის ჩვენება.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# დესკტოპის აპის ჩვენება.}other{# დესკტოპის აპის ჩვენება.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> და <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"მიმდინარეობს აპის დესკტოპზე დამატება"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"გაუქმება"</string>
 </resources>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index d610fc8..20a1d59 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Тапсырмалар жолағында мүмкіндік көп"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Тапсырмалар жолағын әрдайым көрсету"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Экранның төменгі жағында тапсырмалар жолағы әрдайым көрсетілуі үшін, бөлгішті басып тұрыңыз."</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Экраннан іздеу үшін әрекет пернесін басып тұрыңыз"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Бұл өнім іздеу үшін экранның таңдалған бөлігін пайдаланады. Google <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Құпиялық саясаты<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> мен <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Қызмет көрсету шарттары<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> қолданылады."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Жабу"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Дайын"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Негізгі экран"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Жоғары/солға жылжыту"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Төмен/оңға жылжыту"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Тағы # қолданбаны көрсету.}other{Тағы # қолданбаны көрсету.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Компьютерге арналған # қолданбаны көрсету}other{Компьютерге арналған # қолданбаны көрсету}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> және <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Жұмыс үстеліне қолданба қосу"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Бас тарту"</string>
 </resources>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index 9810518..6d5e6f1 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ធ្វើបានកាន់តែច្រើនដោយប្រើរបារកិច្ចការ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"បង្ហាញរបារកិច្ចការជានិច្ច"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ដើម្បីបង្ហាញរបារកិច្ចការនៅផ្នែកខាងក្រោមនៃអេក្រង់របស់អ្នកជានិច្ច សូមចុចបន្ទាត់ខណ្ឌចែកឱ្យជាប់"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"ចុចគ្រាប់ចុចសកម្មភាពឱ្យជាប់ ដើម្បីស្វែងរកអ្វីដែលមាននៅលើអេក្រង់របស់អ្នក"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"ផលិតផលនេះប្រើប្រាស់ផ្នែកដែលបានជ្រើសរើសនៃអេក្រង់របស់អ្នក ដើម្បីស្វែងរក។ <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>គោលការណ៍​ឯកជនភាព<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> និង<xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>លក្ខខណ្ឌ​ប្រើប្រាស់<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>របស់ Google ត្រូវបានអនុវត្ត។"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"បិទ"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"រួចរាល់"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ទំព័រដើម"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ផ្លាស់ទីទៅខាងលើ/ឆ្វេង"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ផ្លាស់ទីទៅខាងក្រោម/ស្ដាំ"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{បង្ហាញកម្មវិធី # ទៀត។}other{បង្ហាញ​កម្មវិធី # ទៀត។}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{បង្ហាញកម្មវិធី​កុំព្យូទ័រ #។}other{បង្ហាញកម្មវិធី​កុំព្យូទ័រ #។}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> និង <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"កំពុងបញ្ចូល​កម្មវិធីទៅកុំព្យូទ័រ"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"បោះបង់"</string>
 </resources>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 10bb08a..10ab922 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ಟಾಸ್ಕ್‌ಬಾರ್ ಮೂಲಕ ಹೆಚ್ಚಿನದನ್ನು ಮಾಡಿ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ಯಾವಾಗಲೂ ಟಾಸ್ಕ್‌ಬಾರ್ ಅನ್ನು ತೋರಿಸಿ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ಯಾವಾಗಲೂ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ನ ಕೆಳಭಾಗದಲ್ಲಿ ಟಾಸ್ಕ್ ಬಾರ್ ಅನ್ನು ತೋರಿಸಲು, ಡಿವೈಡರ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಿ"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ನ ಮೇಲೆ ಏನಿದೆ ಎಂಬುದನ್ನು ಹುಡುಕಲು ಆ್ಯಕ್ಷನ್ ಕೀಯನ್ನು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"ಈ ಉತ್ಪನ್ನವು ಹುಡುಕಲು ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ನ ಆಯ್ದ ಭಾಗವನ್ನು ಬಳಸುತ್ತದೆ. Google ನ <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>ಗೌಪ್ಯತೆ ನೀತಿ<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> ಮತ್ತು <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>ಸೇವಾ ನಿಯಮಗಳು<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ಅನ್ವಯಿಸುತ್ತವೆ."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ಮುಚ್ಚಿರಿ"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ಆಯಿತು"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ಮುಖಪುಟ"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ಮೇಲಿನ/ಎಡಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ಕೆಳಗಿನ/ಬಲಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ಇನ್ನೂ # ಆ್ಯಪ್ ಅನ್ನು ತೋರಿಸಿ.}one{ಇನ್ನೂ # ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}other{ಇನ್ನೂ # ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ಡೆಸ್ಕ್‌ಟಾಪ್ ಆ್ಯಪ್ ತೋರಿಸಿ.}one{# ಡೆಸ್ಕ್‌ಟಾಪ್ ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}other{# ಡೆಸ್ಕ್‌ಟಾಪ್ ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ಮತ್ತು <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ಡೆಸ್ಕ್‌ಟಾಪ್‌ಗೆ ಆ್ಯಪ್ ಅನ್ನು ಸೇರಿಸಲಾಗುತ್ತಿದೆ"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ರದ್ದುಮಾಡಿ"</string>
 </resources>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index 91b9924..24934f9 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"태스크 바 최대한 활용하기"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"태스크 바 항상 표시"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"화면 하단에 태스크 바를 항상 표시하려면 구분선을 길게 터치하세요."</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"화면 내용을 검색하려면 작업 키 길게 터치"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"이 제품은 사용자가 화면에서 선택한 부분을 사용하여 검색하며, Google <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>개인정보처리방침<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> 및 <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>서비스 약관<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>이 적용됩니다."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"닫기"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"완료"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"홈"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"상단/왼쪽으로 이동"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"하단/오른쪽으로 이동"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{앱 #개 더 표시}other{앱 #개 더 표시}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{데스크톱 앱 #개를 표시합니다.}other{데스크톱 앱 #개를 표시합니다.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> 및 <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"데스크톱에 앱 추가하기"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"취소"</string>
 </resources>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index df82b1a..525a248 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Тапшырмалар тактасы менен көбүрөөк иш бүтүрөсүз"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Тапшырмалар панелин ар дайым көрсөтүү"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Тапшырмалар панелин экрандын ылдый жагында ар дайым көрсөтүү үчүн бөлгүчтү коё бербей басыңыз"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Экрандагы нерсени издөө үчүн аракет баскычын коё бербей кармап туруңуз"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Бул кызмат издөө үчүн экранда тандалган бөлүктү колдонот. Google\'дун <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Купуялык эрежелери<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> жана <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Тейлөө шарттары<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> колдонулат."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Жабуу"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Бүттү"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Башкы бет"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Жогорку/сол бурчка жылдыруу"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Төмөнкү/оң бурчка жылдыруу"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Дагы # колдонмону көрсөтүү.}other{Дагы # колдонмону көрсөтүү.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# иш такта колдонмосун көрсөтүү.}other{# иш такта колдонмосун көрсөтүү.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> жана <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Колдонмону иш тактага кошуу"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Жокко чыгаруу"</string>
 </resources>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index a360a58..b5a7ebb 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ເຮັດສິ່ງຕ່າງໆໄດ້ຫຼາຍຂຶ້ນດ້ວຍແຖບໜ້າວຽກ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ສະແດງແຖບໜ້າວຽກສະເໝີ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ເພື່ອໃຫ້ແຖບໜ້າວຽກສະແດງຢູ່ລຸ່ມໜ້າຈໍຂອງທ່ານຢູ່ສະເໝີ, ໃຫ້ແຕະຕົວແບ່ງຄ້າງໄວ້"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"ແຕະປຸ່ມຄຳສັ່ງຄ້າງໄວ້ເພື່ອຊອກຫາສິ່ງທີ່ຢູ່ເທິງໜ້າຈໍຂອງທ່ານ"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"ສິນຄ້ານີ້ໃຊ້ສ່ວນທີ່ເລືອກຂອງໜ້າຈໍຂອງທ່ານເພື່ອຊອກຫາ. ເປັນໄປຕາມ <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>ນະໂຍບາຍຄວາມເປັນສ່ວນຕົວ<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> ແລະ <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>ຂໍ້ກຳນົດບໍລິການ<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ຂອງ Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ປິດ"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ແລ້ວໆ"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ໜ້າຫຼັກ"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ຍ້າຍໄປຊ້າຍ/ເທິງ"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ຍ້າຍໄປຂວາ/ລຸ່ມ"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ສະແດງອີກ # ແອັບ.}other{ສະແດງອີກ # ແອັບ.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{ສະແດງແອັບເດັສທັອບ # ລາຍການ.}other{ສະແດງແອັບເດັສທັອບ # ລາຍການ.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ແລະ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ການເພີ່ມແອັບໄປໃສ່ເດັສທັອບ"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ຍົກເລີກ"</string>
 </resources>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index b7e63cc..4817e25 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Atlikite daugiau naudodami Užduočių juostą"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Visada rodyti užduočių juostą"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Jei norite, kad užduočių juosta visada būtų rodoma ekrano apačioje, palieskite ir palaikykite daliklį"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Ekrane rodomo turinio paieška palietus ir laikant veiksmų klavišą"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Šis produktas paieškai naudoja pasirinktą ekrano dalį. Taikomos „Google“ <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>privatumo politikos<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> ir <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>paslaugų teikimo sąlygos<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Uždaryti"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Atlikta"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Pagrindinis"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Perkelti aukštyn, kairėn"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Perkelti žemyn, dešinėn"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Rodyti dar # programą.}one{Rodyti dar # programą.}few{Rodyti dar # programas.}many{Rodyti dar # programos.}other{Rodyti dar # programų.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Rodyti # darbalaukio programą.}one{Rodyti # darbalaukio programą.}few{Rodyti # darbalaukio programas.}many{Rodyti # darbalaukio programos.}other{Rodyti # darbalaukio programų.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"„<xliff:g id="APP_NAME_1">%1$s</xliff:g>“ ir „<xliff:g id="APP_NAME_2">%2$s</xliff:g>“"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Pridedama programa prie darbalaukio"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Atšaukti"</string>
 </resources>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index d855f6f..aa80b7e 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Plašākas iespējas, izmantojot uzdevumu joslu"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Vienmēr rādīt uzdevumu joslu"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Lai uzdevumu joslu rādītu apakšdaļā, pieskarieties atdalītājam un turiet"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Pieskarieties darbību taustiņam un turiet to, lai meklētu ekrānā redzamo saturu"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Šajā produktā atlasītā ekrāna daļa tiek izmantota meklēšanai. Ir spēkā Google <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>konfidencialitātes politika<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> un <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>pakalpojumu sniegšanas noteikumi<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Aizvērt"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Gatavs"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Sākums"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Pārvietot uz augšējo/kreiso stūri"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Pārvietot uz apakšējo/labo stūri"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Rādīt vēl # lietotni}zero{Rādīt vēl # lietotnes}one{Rādīt vēl # lietotni}other{Rādīt vēl # lietotnes}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Rādīt # datora lietotni.}zero{Rādīt # datora lietotnes.}one{Rādīt # datora lietotni.}other{Rādīt # datora lietotnes.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"“<xliff:g id="APP_NAME_1">%1$s</xliff:g>” un “<xliff:g id="APP_NAME_2">%2$s</xliff:g>”"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Notiek lietotnes pievienošana datoram"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Atcelt"</string>
 </resources>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index 495aaaa..039ee9f 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Правете сешто со „Лентата со задачи“"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Како секогаш да се прикажува „Лентата со задачи“"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Допрете и задржете го разделникот за да може „Лентата со задачи“ секогаш да се прикажува на дното на екранот"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Допрете и задржете го копчето за дејство за да пребарувате на екранот"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Производов го користи избраниот дел од екранот за пребарување. Важат <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Политиката за приватност<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> и <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Условите за користење<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> на Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Затвори"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Дома"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Премести горе лево"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Премести долу десно"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Прикажи уште # апликација.}one{Прикажи уште # апликација.}other{Прикажи уште # апликации.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Прикажи # апликација за компјутер.}one{Прикажи # апликација за компјутер.}other{Прикажи # апликации за компјутер.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Додавање на апликацијата во „Работна површина“"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Откажи"</string>
 </resources>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index 06accba..8fbc8f7 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ടാസ്‌ക്‌ബാർ ഉപയോഗിച്ച് കൂടുതൽ ചെയ്യുക"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"എല്ലായ്‌പ്പോഴും ടാസ്‌ക്‌ബാർ കാണിക്കുക"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ടാസ്‌ക്ബാർ എല്ലായ്‌പ്പോഴും നിങ്ങളുടെ സ്‌ക്രീനിന്റെ ചുവടെ കാണിക്കുന്നതിന് ഡിവൈഡറിൽ സ്‌പർശിച്ച് പിടിക്കുക"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"നിങ്ങളുടെ സ്‌ക്രീനിൽ എന്താണ് ഉള്ളതെന്ന് തിരയാൻ ആക്ഷൻ കീ സ്‌പർശിച്ച് പിടിക്കുക"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"തിരയുന്നതിന് ഈ ഉൽപ്പന്നം സ്‌ക്രീനിലെ തിരഞ്ഞെടുത്ത ഭാഗം ഉപയോഗിക്കുന്നു. Google-ന്റെ <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>സ്വകാര്യതാ നയവും<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>സേവന നിബന്ധനകളും<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ബാധകമാണ്."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"അടയ്ക്കുക"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"പൂർത്തിയായി"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ഹോം"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"മുകളിലേക്കോ ഇടത്തേക്കോ നീക്കുക"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"താഴേക്കോ വലത്തേക്കോ നീക്കുക"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# ആപ്പ് കൂടി കാണിക്കുക.}other{# ആപ്പുകൾ കൂടി കാണിക്കുക.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ഡെസ്‌ക്ടോപ്പ് ആപ്പ് കാണിക്കുക.}other{# ഡെസ്‌ക്ടോപ്പ് ആപ്പുകൾ കാണിക്കുക.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ആപ്പ് ഡെസ്ക്ടോപ്പിലേക്ക് ചേർക്കുന്നു"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"റദ്ദാക്കുക"</string>
 </resources>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 79acca3..d5e4105 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Ажлын хэсгийн тусламжтай илүү ихийг хийгээрэй"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Ажлын хэсгийг үргэлж харуулах"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Дэлгэцийнхээ доод талд Ажлын хэсгийг үргэлж харуулахын тулд хуваагч дээр хүрээд удаан дарна уу"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Дэлгэц дээрээ байгаа зүйлийг хайхын тулд тусгай товчлуурыг удаан дарна уу"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Энэ бүтээгдэхүүн хайхын тулд таны дэлгэцийн сонгосон хэсгийг ашигладаг. Google-н <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>нууцлалын бодлого<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> болон <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>үйлчилгээний нөхцөл<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> хэрэгжинэ."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Хаах"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Дууссан"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Гэр"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Зүүн дээд хэсэг рүү зөөх"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Баруун доод хэсэг рүү зөөх"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Өөр # аппыг харуулна уу.}other{Өөр # аппыг харуулна уу.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Компьютерын # аппыг харуулна уу.}other{Компьютерын # аппыг харуулна уу.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> болон <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Компьютерт апп нэмж байна"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Цуцлах"</string>
 </resources>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index 03cfa56..cbce562 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"टास्कबार चा पुरेपूर वापर करा"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"टास्कबार नेहमी दाखवा"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"टास्कबार नेहमी तुमच्या स्क्रीनच्या तळाशी दाखवण्यासाठी, विभाजकाला स्पर्श करून धरून ठेवा"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"तुमच्या स्क्रीनवरील गोष्टी शोधण्यासाठी अ‍ॅक्शन की स्पर्श करून धरून ठेवा"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"हे उत्पादन शोधण्याच्या हेतूसाठी तुमच्या स्क्रीनचा निवडक भाग वापरते. Google चे <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>गोपनीयता धोरण<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> आणि <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>सेवा अटी<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> लागू होतात."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"बंद करा"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"पूर्ण झाले"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"होम"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"सर्वात वरती/डावीकडे हलवा"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"तळाशी/उजवीकडे हलवा"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{आणखी # अ‍ॅप दाखवा.}other{आणखी # अ‍ॅप्स दाखवा.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# डेस्‍कटॉप अ‍ॅप दाखवा.}other{# डेस्‍कटॉप अ‍ॅप्स दाखवा.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> आणि <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटॉपवर ॲप जोडत आहे"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द करा"</string>
 </resources>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 23204db..cc1ecdd 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Lakukan lebih banyak perkara dengan Bar Tugas"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Sentiasa paparkan Bar Tugas"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Untuk sentiasa memaparkan Bar Tugas pada bahagian bawah skrin, sentuh &amp; tahan pembahagi"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Sentuh &amp; tahan kekunci tindakan untuk mencari kandungan yang dipaparkan pada skrin anda"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Produk ini menggunakan bahagian yang dipilih pada skrin anda untuk membuat carian. <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Dasar Privasi<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> dan <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Syarat Perkhidmatan<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google digunakan."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Tutup"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Selesai"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Laman Utama"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Alihkan ke atas/kiri"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Alihkan ke bawah/kanan"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Tunjukkan # lagi apl.}other{Tunjukkan # lagi apl.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Tunjukkan # apl desktop.}other{Tunjukkan # apl desktop.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dan <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Menambahkan apl pada Desktop"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Batal"</string>
 </resources>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index 64afeed..0b3a708 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -95,7 +95,7 @@
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"စနစ် လမ်းညွှန် ဆက်တင်များ"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"မျှဝေရန်"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
-    <string name="action_split" msgid="2098009717623550676">"ခွဲထုတ်ရန်"</string>
+    <string name="action_split" msgid="2098009717623550676">"ခွဲရန်"</string>
     <string name="action_save_app_pair" msgid="5974823919237645229">"အက်ပ်အတွဲ သိမ်းရန်"</string>
     <string name="toast_split_select_app" msgid="8464310533320556058">"မျက်နှာပြင် ခွဲ၍ပြသရန် အက်ပ်နောက်တစ်ခုကို တို့ပါ"</string>
     <string name="toast_contextual_split_select_app" msgid="433510957123687090">"မျက်နှာပြင် ခွဲ၍ပြသခြင်းသုံးရန် နောက်အက်ပ်တစ်ခုရွေးပါ"</string>
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Taskbar ဖြင့် ပိုမိုလုပ်ဆောင်နိုင်ခြင်း"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Taskbar ကို အမြဲပြပါ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Taskbar ကို စခရင်အောက်ခြေတွင် အမြဲပြရန် ခွဲခြားမျဉ်းကို တို့ထိ၍ ဖိထားပါ"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"သင့်စခရင်ပေါ်ရှိအရာကို ရှာရန် လုပ်ဆောင်ချက်ကီးကို ထိ၍ဖိထားပါ"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"ဤကုန်ပစ္စည်းသည် သင့်စခရင်၌ ရွေးထားသောအပိုင်းကိုသုံး၍ ရှာဖွေသည်။ Google ၏ <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>ကိုယ်ရေးအချက်အလက်လုံခြုံမှုဆိုင်ရာ မူဝါဒ<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> နှင့် <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>ဝန်ဆောင်မှုစည်းမျဉ်းများ<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> အကျုံးဝင်သည်။"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ပိတ်ရန်"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ပြီးပြီ"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ပင်မစာမျက်နှာ"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"အပေါ်/ဘယ်ဘက်သို့ ရွှေ့ရန်"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"အောက်ခြေ/ညာဘက်သို့ ရွှေ့ရန်"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{နောက်ထပ်အက်ပ် # ခု ပြပါ။}other{နောက်ထပ်အက်ပ် # ခု ပြပါ။}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{ဒက်စတော့ အက်ပ် # ခု ပြပါ။}other{ဒက်စတော့ အက်ပ် # ခု ပြပါ။}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> နှင့် <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"‘ဒက်စ်တော့’ တွင် အက်ပ်ကို ထည့်ခြင်း"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"မလုပ်တော့"</string>
 </resources>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index 6c5eed9..655ffec 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Gjør mer med oppgavelinjen"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Vis alltid oppgavelinjen"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"For å alltid vise oppgavelinjen nederst på skjermen, trykk og hold på skillelinjen"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Trykk og hold på handlingstasten for å søke etter det som er på skjermen"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Dette produktet bruker den merkede delen av skjermen til å søke. Googles <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>personvernregler<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> og <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>vilkår for bruk<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> gjelder."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Lukk"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Ferdig"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Hjem"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Flytt til øverst/venstre"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Flytt til nederst/høyre"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Vis # app til.}other{Vis # apper til.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Vis # datamaskinprogram.}other{Vis # datamaskinprogrammer.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Legg til apper på datamaskin"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Avbryt"</string>
 </resources>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 57bc3f9..3554aa5 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"टास्कबार प्रयोग गरेर अझ धेरै कार्य गर्नुहोस्"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"टास्कबार सधैँ देखाउनुहोस्"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"आफ्नो स्क्रिनको पुछारमा टास्कबार सधैँ देखाइराख्न डिभाइडर टच एन्ड होल्ड गर्नुहोस्"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"आफ्नो स्क्रिनमा भएका कुराहरू खोज्न एक्सन कीमा टच एन्ड होल्ड गर्नुहोस्"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"यो उत्पादनले तपाईंले चयन गर्नुभएको स्क्रिनको भाग प्रयोग गरेर खोजी गर्छ। Google को <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>गोपनीयता नीति<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> र <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>सेवाका सर्तहरू<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> लागू हुन्छन्।"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"बन्द गर्नुहोस्"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"सम्पन्न भयो"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"होम"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"सिरान/बायाँतिर सार्नुहोस्"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"फेद/दायाँतिर सार्नुहोस्"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{थप # एप देखाउनुहोस्।}other{थप # वटा एप देखाउनुहोस्।}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# डेस्कटप एप देखाउनुहोस्।}other{# वटा डेस्कटप एप देखाउनुहोस्।}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> र <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटपमा एप हालिँदै छ"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द गर्नुहोस्"</string>
 </resources>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index 6e7cff5..c5cebdb 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -138,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Naar boven/links verplaatsen"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Naar beneden/rechts verplaatsen"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Nog # app tonen.}other{Nog # apps tonen.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# desktop-app tonen.}other{# desktop-apps tonen.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> en <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"App toevoegen aan desktop"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuleren"</string>
 </resources>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 6f44c70..765935e 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ଟାସ୍କବାର ମାଧ୍ୟମରେ ଆହୁରି ଅନେକ କିଛି କରନ୍ତୁ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ସର୍ବଦା ଟାସ୍କବାର ଦେଖାନ୍ତୁ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ଆପଣଙ୍କ ସ୍କ୍ରିନର ନିମ୍ନରେ ସର୍ବଦା ଟାସ୍କବାର ଦେଖାଇବା ପାଇଁ ଡିଭାଇଡରକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"ଆପଣଙ୍କ ସ୍କ୍ରିନରେ କଣ ଅଛି ତାହା ସର୍ଚ୍ଚ କରିବା ପାଇଁ ଆକ୍ସନ କୀ\'କୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"ସର୍ଚ୍ଚ କରିବା ପାଇଁ ଏହି ପ୍ରଡକ୍ଟ ଆପଣଙ୍କ ସ୍କ୍ରିନର ଚୟନିତ ଅଂଶକୁ ବ୍ୟବହାର କରେ। Googleର <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>ଗୋପନୀୟତା ନୀତି<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> ଏବଂ <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>ସେବାର ସର୍ତ୍ତାବଳୀ<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ଲାଗୁ ହୁଏ।"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ହୋଇଗଲା"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ହୋମ"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ଶୀର୍ଷ/ବାମକୁ ମୁଭ କରନ୍ତୁ"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ନିମ୍ନ/ଡାହାଣକୁ ମୁଭ କରନ୍ତୁ"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ଅଧିକ #ଟି ଆପ ଦେଖାନ୍ତୁ।}other{ଅଧିକ #ଟି ଆପ୍ସ ଦେଖାନ୍ତୁ।}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ଡେସ୍କଟପ ଆପ ଦେଖାନ୍ତୁ।}other{# ଡେସ୍କଟପ ଆପ୍ସ ଦେଖାନ୍ତୁ।}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ଏବଂ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ଡେସ୍କଟପରେ ଆପ ଯୋଗ କରାଯାଉଛି"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ବାତିଲ କରନ୍ତୁ"</string>
 </resources>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index a638d94..769608b 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ਟਾਸਕਬਾਰ ਦਾ ਹੋਰ ਲਾਹਾ ਲਓ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ਹਮੇਸ਼ਾਂ ਟਾਸਕਬਾਰ ਦਿਖਾਉਣਾ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਹਮੇਸ਼ਾਂ ਟਾਸਕਬਾਰ ਦਿਖਾਉਣ ਲਈ, ਵਿਭਾਜਕ ਨੂੰ ਸਪਰਸ਼ ਕਰ ਕੇ ਰੱਖੋ"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਮੌਜੂਦ ਸਮੱਗਰੀ ਨੂੰ ਖੋਜਣ ਲਈ, ਕਾਰਵਾਈ ਕੁੰਜੀ ਨੂੰ ਸਪਰਸ਼ ਕਰ ਕੇ ਰੱਖੋ"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"ਇਹ ਉਤਪਾਦ ਖੋਜ ਕਰਨ ਲਈ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ ਦੇ ਚੁਣੇ ਹੋਏ ਹਿੱਸੇ ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹੈ। Google ਦੀ <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>ਪਰਦੇਦਾਰੀ ਨੀਤੀ<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> ਅਤੇ <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>ਸੇਵਾ ਦੇ ਨਿਯਮ<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ਲਾਗੂ ਹੁੰਦੇ ਹਨ।"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ਬੰਦ ਕਰੋ"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ਸਮਝ ਲਿਆ"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ਘਰ"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ਸਿਖਰਲੇ/ਖੱਬੇ ਪਾਸੇ ਲੈ ਕੇ ਜਾਓ"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ਹੇਠਾਂ/ਸੱਜੇ ਪਾਸੇ ਲੈ ਕੇ ਜਾਓ"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}one{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}other{# ਹੋਰ ਐਪਾਂ ਦਿਖਾਓ।}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ਡੈਸਕਟਾਪ ਐਪ ਦਿਖਾਓ।}one{# ਡੈਸਕਟਾਪ ਐਪ ਦਿਖਾਓ।}other{# ਡੈਸਕਟਾਪ ਐਪਾਂ ਦਿਖਾਓ।}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ਅਤੇ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ਐਪ ਨੂੰ ਡੈਸਕਟਾਪ \'ਤੇ ਸ਼ਾਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ਰੱਦ ਕਰੋ"</string>
 </resources>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 20ee3a9..752764f 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -90,7 +90,7 @@
     <string name="allset_title" msgid="5021126669778966707">"Wszystko gotowe"</string>
     <string name="allset_hint" msgid="459504134589971527">"Aby przejść na stronę główną, przesuń w górę"</string>
     <string name="allset_button_hint" msgid="2395219947744706291">"Kliknij przycisk ekranu głównego, aby otworzyć ekran główny"</string>
-    <string name="allset_description_generic" msgid="5385500062202019855">"Teraz możesz zacząć używać urządzenia <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+    <string name="allset_description_generic" msgid="5385500062202019855">"<xliff:g id="DEVICE">%1$s</xliff:g> jest gotowe – możesz zacząć z niego korzystać"</string>
     <string name="default_device_name" msgid="6660656727127422487">"urządzenie"</string>
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Ustawienia nawigacji w systemie"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Udostępnij"</string>
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Wykorzystaj potencjał paska aplikacji"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Zawsze wyświetlaj pasek aplikacji"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Aby zawsze wyświetlać pasek aplikacji u dołu ekranu, naciśnij i przytrzymaj linię dzielenia ekranu"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Aby rozpocząć wyszukiwanie na podstawie zawartości ekranu, naciśnij i przytrzymaj klawisz działania"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Usługa przy wyszukiwaniu używa zaznaczonego fragmentu ekranu. Obowiązują zapisy <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Polityki prywatności<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> i <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Warunków korzystania z usług<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zamknij"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Gotowe"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Ekran główny"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Przesuń w górny lewy róg"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Przesuń w dolny prawy róg"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Pokaż jeszcze # aplikację.}few{Pokaż jeszcze # aplikacje.}many{Pokaż jeszcze # aplikacji.}other{Pokaż jeszcze # aplikacji.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Pokaż # aplikację komputerową.}few{Pokaż # aplikacje komputerowe.}many{Pokaż # aplikacji komputerowych.}other{Pokaż # aplikacji komputerowej.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodaję aplikację do komputera"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anuluj"</string>
 </resources>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index fa47374..a692e69 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -138,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover para a parte superior esquerda"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover para a part superior direita"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar mais # app.}other{Mostrar mais # apps.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostrar # app para computador.}other{Mostrar # apps para computador.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"A adicionar a app ao computador"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
 </resources>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index 5e0a62e..dd3c037 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Aproveite ainda mais a Barra de tarefas"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Sempre mostrar a Barra de tarefas"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Toque e pressione o divisor para sempre mostrar a Barra de tarefas na parte de baixo da tela"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Toque na tecla de ação e pressione para pesquisar o que está na tela"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"O produto usa a parte selecionada da tela para pesquisar. O uso desses dados está sujeito à <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Política de Privacidade<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> e aos <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Termos de Serviço<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> do Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Fechar"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Concluído"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Início"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover para cima/para a esquerda"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover para baixo/para a direita"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar mais # app.}one{Mostrar mais # app.}other{Mostrar mais # apps.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostrar # app para computador.}one{Mostrar # app para computador.}other{Mostrar # apps para computador.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adicionando app ao computador"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
 </resources>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index 10b8b95..7efeda2 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Fă mai multe din Bara de activități"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Afișează întotdeauna Bara de activități"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Pentru a afișa mereu Bara de activități în partea de jos a ecranului, atinge lung separatorul"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Atinge lung tasta de acțiuni ca să cauți pe ecran"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Acest produs folosește partea selectată a ecranului pentru a căuta. Se aplică <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Politica de confidențialitate<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> și <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Termenii și condițiile<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Închide"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Gata"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Ecran de pornire"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mută în stânga sus"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mută în dreapta jos"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afișează încă # aplicație}few{Afișează încă # aplicații}other{Afișează încă # de aplicații}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Afișează # aplicație pentru computer.}few{Afișează # aplicații pentru computer.}other{Afișează # de aplicații pentru computer.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> și <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Se adaugă aplicația pe computer"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anulează"</string>
 </resources>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 50097b2..e8d1ddb 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Используйте все возможности панели задач"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Закрепите панель задач внизу экрана"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Для этого нажмите на разделитель и удерживайте его."</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Чтобы найти информацию об объекте на экране, нажмите и удерживайте клавишу действия"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Этот продукт использует выделенную часть экрана для поиска. При этом действуют <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Политика конфиденциальности<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> и <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Условия использования<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Закрыть"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Главный экран"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Переместить вверх или влево"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Переместить вниз или вправо"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показать ещё # приложение}one{Показать ещё # приложение}few{Показать ещё # приложения}many{Показать ещё # приложений}other{Показать ещё # приложения}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Показать # компьютерное приложение.}one{Показать # компьютерное приложение.}few{Показать # компьютерных приложения.}many{Показать # компьютерных приложений.}other{Показать # компьютерного приложения.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Добавление приложения на компьютер"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Отмена"</string>
 </resources>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index 2aee911..9d1c312 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"කාර්ය තීරුව සමග තවත් කරන්න"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"සෑම විටම කාර්ය තීරුව පෙන්වන්න"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"සෑම විටම ඔබේ තිරයේ පතුලේ ඇති කාර්ය තීරුව පෙන්වීමට, බෙදුම්කරු ස්පර්ශ කර අල්ලාගෙන සිටින්න"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"ඔබේ තිරයෙහි ඇති දේ සෙවීමට ක්‍රියා යතුර ස්පර්ශ කර සිටින්න"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"මෙම නිෂ්පාදනය සෙවීමට ඔබේ තිරයෙහි තෝරන ලද කොටස භාවිතා කරයි. Google හි <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>පෞද්ගලිකත්ව ප්‍රතිපත්තිය<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> සහ <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>සේවා නියමයන්<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> අදාළ වේ."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"වසන්න"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"නිමයි"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"මුල් පිටුව"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ඉහළ/වම වෙත ගෙන යන්න"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"පහළ/දකුණ වෙත ගෙන යන්න"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{තවත් # යෙදුමක් පෙන්වන්න.}one{තවත් යෙදුම් #ක් පෙන්වන්න.}other{තවත් යෙදුම් #ක් පෙන්වන්න.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ඩෙස්ක්ටොප් යෙදුමක් පෙන්වන්න.}one{ඩෙස්ක්ටොප් යෙදුම් # ක් පෙන්වන්න.}other{ඩෙස්ක්ටොප් යෙදුම් # ක් පෙන්වන්න.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> සහ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ඩෙස්ක්ටොප් වෙත යෙදුම එක් කිරීම"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"අවලංගු කරන්න"</string>
 </resources>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index 9858d95..a573b45 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Panel aplikácií vám ponúka ďalšie možnosti"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Vždy zobrazovať panel aplikácií"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Ak chcete, aby sa panel aplikácií vždy zobrazoval v dolnej časti obrazovky, pridržte rozdeľovač"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Ak chcete vyhľadávať, čo je na obrazovke, pridržte akčný kláves"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Táto služba používa na účely vyhľadávania vybranú časť obrazovky. Uplatňujú sa <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>pravidlá ochrany súkromia<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> a <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>zmluvné podmienky<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> spoločnosti Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zavrieť"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Hotovo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Plocha"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Presunúť hore alebo doľava"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Presunúť dole alebo doprava"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Zobraziť # ďalšiu aplikáciu.}few{Zobraziť # ďalšie aplikácie.}many{Show # more apps.}other{Zobraziť # ďalších aplikácií.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Zobraziť # aplikáciu pre počítač.}few{Zobraziť # aplikácie pre počítač.}many{Show # desktop apps.}other{Zobraziť # aplikácií pre počítač.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> a <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Pridanie aplikácie na plochu"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Zrušiť"</string>
 </resources>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index d2bc79f..355dc61 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Naredite več z opravilno vrstico"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Stalni prikaz opravilne vrstice"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Če želite, da je opravilna vrstica vedno prikazana na dnu zaslona, pridržite razdelilno črto."</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Za iskanje po zaslonu se dotaknite in pridržite tipko za dejanja"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Ta izdelek za iskanje uporablja izbrani del zaslona. Veljajo Googlov <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>pravilnik o zasebnosti<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> in <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>pogoji storitve<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zapri"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Končano"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Začetni zaslon"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premakni na vrh/levo"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premakni na dno/desno"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Pokaži še # aplikacijo.}one{Pokaži še # aplikacijo.}two{Pokaži še # aplikaciji.}few{Pokaži še # aplikacije.}other{Pokaži še # aplikacij.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Prikaz # aplikacije za namizni računalnik.}one{Prikaz # aplikacije za namizni računalnik.}two{Prikaz # aplikacij za namizni računalnik.}few{Prikaz # aplikacij za namizni računalnik.}other{Prikaz # aplikacij za namizni računalnik.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> in <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodajanje aplikacije na namizje"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Prekliči"</string>
 </resources>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index b11f413..71eca07 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Bëj më shumë me \"Shiritin e detyrave\""</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Shfaq gjithmonë \"Shiritin e detyrave\""</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Prek e mbaj ndarësin dhe shfaq gjithmonë \"Shiritin e detyrave\" në fund të ekranit"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Prek dhe mbaj shtypur tastin e veprimit për të kërkuar për gjërat në ekran"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Ky produkt përdor pjesën e zgjedhur të ekranit tënd për të kërkuar. Zbatohen <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Politika e privatësisë<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> dhe <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Kushtet e shërbimit<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> të Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Mbyll"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"U krye"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Faqja kryesore"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Lëviz në krye/majtas"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Lëviz në fund/djathtas"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Shfaq # aplikacion tjetër.}other{Shfaq # aplikacione të tjera.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Shfaq # aplikacion për desktop.}other{Shfaq # aplikacione për desktop.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dhe <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Shtimi i aplikacionit te desktopi"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anulo"</string>
 </resources>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index 950bba8..34bcb1c 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Урадите више помоћу траке задатака"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Увек приказуј траку задатака"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Да би трака задатака увек била приказана у дну екрана, додирните и задржите разделник"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Додирните и задржите тастер радњи да бисте претражили оно што је на екрану"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Овај производ користи изабрани део екрана за претрагу. Примењују се Google <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>политика приватности<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> и <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>услови коришћења услуге<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Затвори"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Почетна"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Премести горе лево"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Премести доле десно"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Прикажи још # апликацију.}one{Прикажи још # апликацију.}few{Прикажи још # апликације.}other{Прикажи још # апликација.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Прикажи # апликацију за рачунаре.}one{Прикажи # апликацију за рачунаре.}few{Прикажи # апликације за рачунаре.}other{Прикажи # апликација за рачунаре.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Додаје се апликација на радну поврршину"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Откажи"</string>
 </resources>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index 82b0f00..723cb82 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -95,7 +95,7 @@
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Systemnavigeringsinställningar"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Dela"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Skärmbild"</string>
-    <string name="action_split" msgid="2098009717623550676">"Delat"</string>
+    <string name="action_split" msgid="2098009717623550676">"Delad skärm"</string>
     <string name="action_save_app_pair" msgid="5974823919237645229">"Spara app-par"</string>
     <string name="toast_split_select_app" msgid="8464310533320556058">"Tryck på en annan app för att använda delad skärm"</string>
     <string name="toast_contextual_split_select_app" msgid="433510957123687090">"Välj en annan app för att använda delad skärm"</string>
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Gör mer med aktivitetsfältet"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Visa alltid aktivitetsfältet"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Tryck länge på avgränsaren för att alltid visa aktivitetsfältet längst ned på skärmen"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Tryck länge på åtgärdstangenten för att söka efter det som finns på skärmen"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Den här produkten använder den valda delen av skärmen för att söka. Googles <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>integritetspolicy<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> och <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>användarvillkor<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> gäller."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Stäng"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Klar"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Startsida"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Flytta högst upp/till vänster"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Flytta längst ned/till höger"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Visa # app till.}other{Visa # appar till.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Visa # datorapp.}other{Visa # datorappar.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> och <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Lägger till appen på skrivbordet"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Avbryt"</string>
 </resources>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index 2de909e..6a3f624 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Kamilisha mengi kwa kutumia Upauzana huu"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Onyesha Upauzana kila wakati"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Ili uonyeshe Upauzana kila wakati chini ya skrini yako, gusa na ushikilie kitenganishi"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Gusa na ushikilie kitufe cha vitendo ili utafute kilicho kwenye skrini yako"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Bidhaa hii hutumia sehemu uliyochagua kwenye skrini yako kutafuta. <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Sera ya Faragha<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> na <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Sheria na Masharti<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ya Google yatatumika."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Funga"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Imemaliza"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Mwanzo"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Sogeza juu/kushoto"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Sogeza chini/kulia"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Onyesha programu # zaidi.}other{Onyesha programu # zaidi.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Onyesha programu # ya kompyuta ya mezani.}other{Onyesha programu # za kompyuta ya mezani.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> na <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Kuweka programu kwenye Eneo-kazi"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ghairi"</string>
 </resources>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index 191b89d..90ff5ea 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"செயல் பட்டி மூலம் மேலும் பலவற்றைச் செய்யுங்கள்"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"செயல் பட்டியை எப்போதும் காட்டுதல்"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"திரையின் கீழ்ப்பகுதியில் செயல் பட்டியை எப்போதும் காட்டுவதற்கு, பிரிப்பானைத் தொட்டுப் பிடித்திருக்கவும்"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"உங்கள் திரையில் உள்ளவற்றைத் தேடுவதற்கு ஆக்ஷன் பட்டனைத் தொட்டுப் பிடியுங்கள்"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"தேடுவதற்கு உங்கள் திரையின் தேர்ந்தெடுக்கப்பட்ட பகுதியை இந்தத் தயாரிப்பு பயன்படுத்துகிறது. Googleளின் <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>தனியுரிமைக் கொள்கையும்<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>சேவை விதிமுறைகளும்<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> பொருந்தும்."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"மூடுக"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"முடிந்தது"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"முகப்பு"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"மேலே/இடதுபுறம் நகர்த்தும்"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"கீழே/வலதுபுறம் நகர்த்தும்"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{மேலும் # ஆப்ஸைக் காட்டு.}other{மேலும் # ஆப்ஸைக் காட்டு.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# டெஸ்க்டாப் ஆப்ஸைக் காட்டு.}other{# டெஸ்க்டாப் ஆப்ஸைக் காட்டு.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> மற்றும் <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ஆப்ஸை டெஸ்க்டாப்பில் சேர்க்கிறது"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ரத்துசெய்"</string>
 </resources>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index 078df14..c32f360 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"టాస్క్‌బార్‌తో మరిన్ని చేయండి"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"టాస్క్‌బార్‌ను నిరంతరం చూపండి"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"మీ స్క్రీన్ దిగువున టాస్క్‌బార్‌ను నిరంతరం చూపడానికి, డివైడర్‌ను తాకి, నొక్కి ఉంచండి"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"మీ స్క్రీన్‌లో ఏం ఉందో సెర్చ్ చేయడానికి యాక్షన్ కీని తాకి ఉంచండి"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"ఈ ప్రోడక్ట్, సెర్చ్ చేయడానికి మీ స్క్రీన్‌లో ఎంచుకున్న భాగాన్ని ఉపయోగిస్తుంది. Google <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>గోప్యతా పాలసీ<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g>, <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>సర్వీస్ నియమాలు<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> వర్తిస్తాయి."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"మూసివేయండి"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"పూర్తయింది"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"మొదటి ట్యాబ్"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ఎగువ/ఎడమ వైపునకు తరలించండి"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"దిగువ/కుడి వైపునకు తరలించండి"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{మరో # యాప్‌ను చూడండి.}other{మరో # యాప్‌లను చూడండి.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# డెస్క్‌టాప్ యాప్‌ను చూపండి.}other{# డెస్క్‌టాప్ యాప్‌లను చూపండి.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"డెస్క్‌టాప్‌నకు యాప్‌ను జోడిస్తోంది"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"రద్దు చేయండి"</string>
 </resources>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 8f92fc6..f1fd49b 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -92,7 +92,7 @@
     <string name="allset_button_hint" msgid="2395219947744706291">"แตะปุ่มหน้าแรกเพื่อไปที่หน้าจอหลัก"</string>
     <string name="allset_description_generic" msgid="5385500062202019855">"คุณเริ่มใช้<xliff:g id="DEVICE">%1$s</xliff:g>ได้แล้ว"</string>
     <string name="default_device_name" msgid="6660656727127422487">"อุปกรณ์"</string>
-    <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"การตั้งค่าการนำทางของระบบ"</annotation></string>
+    <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"การตั้งค่าการไปยังส่วนต่างๆ ของระบบ"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"แชร์"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"ภาพหน้าจอ"</string>
     <string name="action_split" msgid="2098009717623550676">"แยก"</string>
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ทำสิ่งต่างๆ ได้มากขึ้นด้วยแถบงาน"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"แสดงแถบงานเสมอ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"หากต้องการให้แถบงานแสดงที่ด้านล่างหน้าจออยู่เสมอ ให้แตะตัวแบ่งค้างไว้"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"แตะปุ่มดำเนินการค้างไว้เพื่อค้นหาสิ่งที่อยู่บนหน้าจอ"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"ผลิตภัณฑ์นี้ใช้ส่วนที่เลือกของหน้าจอเพื่อค้นหา เป็นไปตาม<xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>นโยบายความเป็นส่วนตัว<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g>และ<xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>ข้อกําหนดในการให้บริการ<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>ของ Google"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ปิด"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"เสร็จ"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"หน้าแรก"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ย้ายไปที่ด้านบนหรือด้านซ้าย"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ย้ายไปที่ด้านล่างหรือด้านขวา"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{แสดงเพิ่มเติมอีก # แอป}other{แสดงเพิ่มเติมอีก # แอป}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{แสดงแอปบนเดสก์ท็อป # รายการ}other{แสดงแอปบนเดสก์ท็อป # รายการ}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> และ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"การเพิ่มแอปไปยังเดสก์ท็อป"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ยกเลิก"</string>
 </resources>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index 1cbb70d..f0e2311 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Mas maraming magawa gamit ang Taskbar"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Palaging ipakita ang Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Para palaging ipakita ang Taskbar sa ibaba ng iyong screen, pindutin nang matagal ang divider"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Pindutin nang matagal ang action key para hanapin kung ano ang nasa iyong screen"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Ginagamit ng produktong ito ang piniling bahagi ng iyong screen para maghanap. Nalalapat ang <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Patakaran sa Privacy<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> at <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Mga Tuntunin ng Serbisyo<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ng Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Isara"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Tapos na"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Ilipat sa itaas/kaliwa"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Ilipat sa ibaba/kanan"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Magpakita ng # pang app.}one{Magpakita ng # pang app.}other{Magpakita ng # pang app.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Ipakita ang # desktop app.}one{Ipakita ang # desktop app.}other{Ipakita ang # na desktop app.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> at <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Idinaragdag ang app sa Desktop"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Kanselahin"</string>
 </resources>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 5c7f7e8..5eb84d6 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Görev çubuğuyla daha fazla şey yapın"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Görev çubuğunu sabitleyin"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Ayırıcıya dokunup basılı tuttuğunuzda görev çubuğu ekranın alt kısmına sabitlenir"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Ekranınızda bulunan içerikleri aramak için eylem tuşuna dokunup basılı tutun"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Bu ürün, ekranınızın seçilen bölümünü kullanarak arama yapar. Google\'ın <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Gizlilik Politikası<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> ve <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Hizmet Şartları<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> geçerlidir."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Kapat"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Bitti"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Ana ekran"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Sol üste taşı"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Sağ alta taşı"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# uygulama daha göster.}other{# uygulama daha göster}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# masaüstü uygulamasını göster.}other{# masaüstü uygulamasını göster.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ve <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Uygulama Masaüstü\'ne ekleniyor"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"İptal"</string>
 </resources>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 2c89609..3be1627 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Більше можливостей завдяки панелі завдань"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Завжди показувати панель завдань"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Щоб завжди показувати панель завдань унизу екрана, натисніть і втримуйте роздільник"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Для пошуку інформації, що відображається на екрані, натисніть і втримуйте клавішу дії"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Цей продукт використовує для пошуку вибрану частину екрана. Застосовуються <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Політика конфіденційності<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> та <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Загальні положення й умови<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Закрити"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Головний екран"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Перемістити вгору або вліво"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Перемістити вниз або вправо"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показати ще # додаток.}one{Показати ще # додаток.}few{Показати ще # додатки.}many{Показати ще # додатків.}other{Показати ще # додатка.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Показати # комп’ютерну програму.}one{Показати # комп’ютерну програму.}few{Показати # комп’ютерні програми.}many{Показати # комп’ютерних програм.}other{Показати # комп’ютерної програми.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> та <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Встановлення додатка на комп’ютер"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Скасувати"</string>
 </resources>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index ec4fa9d..0e951f0 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ٹاسک بار سے بہت کچھ کریں"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ہمیشہ ٹاسک بار دکھائیں"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ٹاسک بار کو ہمیشہ اپنی اسکرین کے نیچے دکھانے کے لیے، ڈیوائیڈر کو ٹچ کریں اور دبائے رکھیں"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"آپ کی اسکرین پر جو کچھ ہے اسے تلاش کرنے کے لیے ایکشن کلید کو ٹچ کریں اور دبائے رکھیں"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"‏یہ پروڈکٹ تلاش کرنے کے لیے آپ کی اسکرین کا منتخب حصہ استعمال کرتا ہے۔ Google کی <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>رازداری کی پالیسی<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> اور <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>سروس کی شرائط<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> لاگو ہوتی ہیں۔"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"بند کریں"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ہو گیا"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ہوم"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"اوپر/بائیں طرف منتقل کریں"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"نیچے/دائیں طرف منتقل کریں"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# مزید ایپ دکھائیں۔}other{# مزید ایپس دکھائیں۔}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ڈیسک ٹاپ ایپ دکھائیں۔}other{# ڈیسک ٹاپ ایپس دکھائیں۔}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> اور <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ڈیسک ٹاپ پر ایپ شامل کرنا"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"منسوخ کریں"</string>
 </resources>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 8085195..4d57b22 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Vazifalar panelidan maksimal darajada foydalaning"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Vazifalar paneli doim chiqarilsin"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Vazifalar panelini ekranning pastki qismida doim chiqib turishi uchun ajratkichni bosib turing"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Ekrandagi element haqida maʼlumotni topish uchun amal tugmasini bosib turing"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Bu mahsulot qidirish uchun ekranning tanlangan qismidan foydalanadi. Google <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>maxfiylik siyosati<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> va <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>xizmat shartlari<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> tatbiq qilinadi."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Yopish"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Tayyor"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Bosh ekran"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Yuqoriga yoki chapga oʻtkazish"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Pastga yoki oʻngga oʻtkazish"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Yana # ta ilovani chiqarish}other{Yana # ta ilovani chiqarish}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ta desktop ilovani chiqarish.}other{# ta desktop ilovani chiqarish.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> va <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Ilova kompyuterga qoʻshilmoqda"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Bekor qilish"</string>
 </resources>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index acc2011..df8ccdc 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -92,7 +92,7 @@
     <string name="allset_button_hint" msgid="2395219947744706291">"Nhấn vào nút màn hình chính để chuyển đến màn hình chính"</string>
     <string name="allset_description_generic" msgid="5385500062202019855">"Bạn có thể bắt đầu sử dụng <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
     <string name="default_device_name" msgid="6660656727127422487">"thiết bị"</string>
-    <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Chế độ cài đặt di chuyển trên hệ thống"</annotation></string>
+    <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Cài đặt cách thao tác trên hệ thống"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Chia sẻ"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Chụp ảnh màn hình"</string>
     <string name="action_split" msgid="2098009717623550676">"Chia đôi màn hình"</string>
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Làm nhiều việc hơn qua Thanh tác vụ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Luôn hiện Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Để luôn hiện Taskbar ở cuối màn hình, hãy nhấn và giữ đường phân chia"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Chạm và giữ phím hành động để tìm nội dung trên màn hình của bạn"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Sản phẩm này dùng phần được chọn trên màn hình để tìm kiếm. Có áp dụng <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Chính sách quyền riêng tư<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> và <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Điều khoản dịch vụ<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> của Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Đóng"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Xong"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Màn hình chính"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Chuyển lên trên cùng/sang bên trái"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Chuyển xuống dưới cùng/sang bên phải"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Hiện thêm # ứng dụng.}other{Hiện thêm # ứng dụng.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Hiện # ứng dụng dành cho máy tính.}other{Hiện # ứng dụng dành cho máy tính.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> và <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Đang thêm ứng dụng vào máy tính"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Huỷ"</string>
 </resources>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index ea721ac..e750730 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -95,7 +95,7 @@
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"系统导航设置"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"分享"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"屏幕截图"</string>
-    <string name="action_split" msgid="2098009717623550676">"拆分"</string>
+    <string name="action_split" msgid="2098009717623550676">"分屏"</string>
     <string name="action_save_app_pair" msgid="5974823919237645229">"保存应用组合"</string>
     <string name="toast_split_select_app" msgid="8464310533320556058">"点按另一个应用即可使用分屏"</string>
     <string name="toast_contextual_split_select_app" msgid="433510957123687090">"另外选择一个应用才可使用分屏模式"</string>
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"体验任务栏的更多功能"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"始终显示任务栏"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"若要始终在屏幕底部显示任务栏,请轻触并按住分隔线"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"轻触并按住操作键,即可根据屏幕上的内容进行搜索"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"此产品会根据屏幕上的所选内容进行搜索。Google 的<xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>《隐私权政策》<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g>和<xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>《服务条款》<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>适用。"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"关闭"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"完成"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"主屏幕"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"移到顶部/左侧"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移到底部/右侧"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{显示另外 # 个应用。}other{显示另外 # 个应用。}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{显示 # 款桌面应用。}other{显示 # 款桌面应用。}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>和<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"将应用添加到桌面"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
 </resources>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index e4be958..9427b07 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"工作列助你事半功倍"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"一律顯示工作列"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"如要持續在畫面底部顯示工作列,請按住分隔線"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"按住快捷操作鍵即可搜尋畫面上的內容"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"此產品使用螢幕的特定部分進行搜尋。須受 Google 的《<xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>私隱權政策<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g>》和《<xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>服務條款<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>》約束。"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"關閉"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"完成"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"住宅"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"移至上方/左側"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移至底部/右側"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{顯示另外 # 個應用程式。}other{顯示另外 # 個應用程式。}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{顯示 # 個桌面應用程式。}other{顯示 # 個桌面應用程式。}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」和「<xliff:g id="APP_NAME_2">%2$s</xliff:g>」"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"正在新增應用程式至桌面"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
 </resources>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index b2784b7..3b06eda 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"充分發揮工作列的功用"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"一律顯示工作列"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"如要一律在畫面底部顯示工作列,請按住分隔線"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"按住快捷操作鍵即可搜尋畫面上的內容"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"這項產品會搜尋你在畫面上選取的內容 (適用 Google 的《<xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>隱私權政策<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g>》和《<xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>服務條款<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>》)。"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"關閉"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"完成"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"主畫面"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"移到上方/左側"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移到底部/右側"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{再多顯示 # 個應用程式。}other{再多顯示 # 個應用程式。}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{顯示 # 個電腦版應用程式。}other{顯示 # 個電腦版應用程式。}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」和「<xliff:g id="APP_NAME_2">%2$s</xliff:g>」"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"新增應用程式至桌面"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
 </resources>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index e9ba580..cb216fc 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -117,10 +117,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Yenza okwengeziwe nge-Taskbar"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Bonisa njalo i-Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Ukuze ubonise njalo i-Taskbar phansi kwesikrini sakho, thinta bese ubamba isihlukanisi"</string>
-    <!-- no translation found for taskbar_search_edu_title (5569194922234364530) -->
-    <skip />
-    <!-- no translation found for taskbar_edu_search_disclosure (8734536088447779686) -->
-    <skip />
+    <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Thinta uphinde ubambe inkinobho yokufinyelela ukuze useshe lokho okusesikrinini sakho"</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Lo mkhiqizo usebenzisa ingxenye ekhethiwe yesikrini sakho ukusesha. <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Inqubomgomo Yobumfihlo<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> ye-Google kanye <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Nemigomo Yesevisi<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ziyasebenza."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Vala"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Kwenziwe"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Ikhaya"</string>
@@ -140,9 +138,6 @@
     <string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Hamba phezulu/kwesokunxele"</string>
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Hamba phansi/kwesokudla"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Bonisa i-app e-# ngaphezulu.}one{Bonisa ama-app angu-# ngaphezulu.}other{Bonisa ama-app angu-# ngaphezulu.}}"</string>
-    <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
-    <skip />
+    <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Bonisa i-app engu-# yedeskithophu.}one{Bonisa ama-app angu-# wedeskithophu.}other{Bonisa ama-app angu-# wedeskithophu.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"I-<xliff:g id="APP_NAME_1">%1$s</xliff:g> ne-<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
-    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Yengeza i-app ku-Deskithophu"</string>
-    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Khansela"</string>
 </resources>
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index b3502db..fd12210 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -17,8 +17,7 @@
     <string name="overscroll_plugin_factory_class" translatable="false" />
     <string name="task_overlay_factory_class" translatable="false"/>
 
-    <!-- Activities which block home gesture -->
-    <string-array name="gesture_blocking_activities" translatable="false">
+    <string-array name="back_gesture_blocking_activities" translatable="false">
         <item>com.android.launcher3/com.android.quickstep.interaction.GestureSandboxActivity</item>
     </string-array>
 
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index b862d7c..08d36d8 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -177,6 +177,8 @@
     <dimen name="gesture_tutorial_menu_done_button_top_spacing">0dp</dimen>
     <dimen name="gesture_tutorial_menu_back_shape_bottom_margin">0dp</dimen>
     <dimen name="gesture_tutorial_menu_done_button_spacing">72dp</dimen>
+    <dimen name="gesture_tutorial_done_button_bottom_margin">40dp</dimen>
+    <dimen name="gesture_tutorial_done_button_end_margin">24dp</dimen>
 
     <!-- Gesture Tutorial mock conversations -->
     <dimen name="gesture_tutorial_message_icon_size">44dp</dimen>
@@ -356,6 +358,9 @@
     <dimen name="taskbar_running_app_indicator_height">4dp</dimen>
     <dimen name="taskbar_running_app_indicator_width">14dp</dimen>
     <dimen name="taskbar_running_app_indicator_top_margin">2dp</dimen>
+    <dimen name="taskbar_minimized_app_indicator_height">2dp</dimen>
+    <dimen name="taskbar_minimized_app_indicator_width">12dp</dimen>
+    <dimen name="taskbar_minimized_app_indicator_top_margin">2dp</dimen>
 
     <!-- Transient taskbar -->
     <dimen name="transient_taskbar_padding">12dp</dimen>
@@ -456,6 +461,11 @@
 
     <!-- Bubble bar drop target -->
     <dimen name="bubblebar_drop_target_corner_radius">36dp</dimen>
+    <dimen name="bubble_expanded_view_drop_target_default_width">412dp</dimen>
+    <dimen name="bubble_expanded_view_drop_target_default_height">600dp</dimen>
+    <dimen name="bubble_expanded_view_drop_target_corner_radius">28dp</dimen>
+    <dimen name="bubble_expanded_view_drop_target_padding">24dp</dimen>
+    <dimen name="bubble_expanded_view_drop_target_margin">16dp</dimen>
 
     <!-- Launcher splash screen -->
     <!-- Note: keep this value in sync with the WindowManager/Shell dimens.xml -->
@@ -477,11 +487,4 @@
     <dimen name="keyboard_quick_switch_no_recent_items_icon_size">24dp</dimen>
     <dimen name="keyboard_quick_switch_no_recent_items_icon_margin">8dp</dimen>
 
-    <!-- Desktop mode -->
-    <dimen name="desktop_mode_floating_app_select_height">56dp</dimen>
-    <dimen name="desktop_mode_floating_app_select_elevation">4dp</dimen>
-    <dimen name="desktop_mode_floating_app_select_margin">16dp</dimen>
-    <dimen name="desktop_mode_floating_app_select_text_size">14sp</dimen>
-    <dimen name="desktop_mode_floating_app_select_text_margin">8dp</dimen>
-
 </resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 278c66a..cf987c3 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -332,10 +332,4 @@
 
     <!-- Accessibility label for quick switch tiles showing split tasks [CHAR LIMIT=NONE] -->
     <string name="quick_switch_split_task"><xliff:g id="app_name_1" example="Chrome">%1$s</xliff:g> and <xliff:g id="app_name_2" example="Gmail">%2$s</xliff:g></string>
-
-    <!-- ******* Desktop ******* -->
-    <!-- Text shown in popup to choose a desktop app. [CHAR LIMIT=60] -->
-    <string name="desktop_select_app_toast">Adding app to Desktop</string>
-    <!-- Text shown on a button that closes the popup for choosing a desktop app. [CHAR_LIMIT=40] -->
-    <string name="desktop_button_close_app_toast">Cancel</string>
 </resources>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 0697f47..0c499b8 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -58,6 +58,7 @@
 import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
 import static com.android.launcher3.testing.shared.TestProtocol.WALLPAPER_OPEN_ANIMATION_FINISHED_MESSAGE;
 import static com.android.launcher3.util.DisplayController.isTransientTaskbar;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.ORDERED_BG_EXECUTOR;
 import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
 import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
@@ -374,7 +375,7 @@
      */
     protected boolean isLaunchingFromRecents(@NonNull View v,
             @Nullable RemoteAnimationTarget[] targets) {
-        return mLauncher.getStateManager().getState().overviewUi
+        return mLauncher.getStateManager().getState().isRecentsViewVisible
                 && findTaskViewToLaunch(mLauncher.getOverviewPanel(), v, targets) != null;
     }
 
@@ -1881,7 +1882,7 @@
 
             return new ContainerAnimationRunner(
                     new ActivityTransitionAnimator.AnimationDelegate(
-                            controller, callback, listener));
+                            MAIN_EXECUTOR, controller, callback, listener));
         }
 
         /**
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index 70e01f5..a16031d 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -286,7 +286,7 @@
     }
 
     public void dump(String prefix, PrintWriter writer) {
-        writer.println(prefix + this.getClass().getSimpleName());
+        writer.println(prefix + "PredictionRowView");
         writer.println(prefix + "\tmPredictionsEnabled: " + mPredictionsEnabled);
         writer.println(prefix + "\tmPredictionUiUpdatePaused: " + mPredictionUiUpdatePaused);
         writer.println(prefix + "\tmNumPredictedAppsPerRow: " + mNumPredictedAppsPerRow);
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index 1c5a75d..de974ec 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -29,6 +29,7 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.ComponentName;
+import android.util.Log;
 import android.view.HapticFeedbackConstants;
 import android.view.View;
 import android.view.ViewGroup;
@@ -80,6 +81,7 @@
         SystemShortcut.Factory<QuickstepLauncher>, DeviceProfile.OnDeviceProfileChangeListener,
         DragSource, ViewGroup.OnHierarchyChangeListener {
 
+    private static final String TAG = "HotseatPredictionController";
     private static final int FLAG_UPDATE_PAUSED = 1 << 0;
     private static final int FLAG_DRAG_IN_PROGRESS = 1 << 1;
     private static final int FLAG_FILL_IN_PROGRESS = 1 << 2;
@@ -292,6 +294,16 @@
     }
 
     /**
+     * Ensures that if the flag FLAG_UPDATE_PAUSED is active we set it to false.
+     */
+    public void verifyUIUpdateNotPaused() {
+        if ((mPauseFlags & FLAG_UPDATE_PAUSED) != 0) {
+            setPauseUIUpdate(false);
+            Log.e(TAG, "FLAG_UPDATE_PAUSED should not be set to true (see b/339700174)");
+        }
+    }
+
+    /**
      * Sets or updates the predicted items
      */
     public void setPredictedItems(FixedContainerItems items) {
@@ -521,7 +533,7 @@
     }
 
     public void dump(String prefix, PrintWriter writer) {
-        writer.println(prefix + this.getClass().getSimpleName());
+        writer.println(prefix + "HotseatPredictionController");
         writer.println(prefix + "\tFlags: " + getStateString(mPauseFlags));
         writer.println(prefix + "\tmHotSeatItemsCount: " + mHotSeatItemsCount);
         writer.println(prefix + "\tmPredictedItems: " + mPredictedItems);
diff --git a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
index 2fcbe4e..d604742 100644
--- a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
@@ -15,8 +15,8 @@
  */
 package com.android.launcher3.model;
 
-import static com.android.launcher3.LauncherPrefs.nonRestorableItem;
 import static com.android.launcher3.EncryptionType.ENCRYPTED;
+import static com.android.launcher3.LauncherPrefs.nonRestorableItem;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
 import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKER;
 
@@ -32,6 +32,7 @@
 
 import com.android.launcher3.ConstantItem;
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
 import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.model.BgDataModel.FixedContainerItems;
 import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
@@ -47,7 +48,7 @@
 /**
  * Task to update model as a result of predicted apps update
  */
-public class PredictionUpdateTask extends BaseModelUpdateTask {
+public class PredictionUpdateTask implements ModelUpdateTask {
 
     public static final ConstantItem<Boolean> LAST_PREDICTION_ENABLED =
             nonRestorableItem("last_prediction_enabled_state", true, ENCRYPTED);
@@ -61,8 +62,9 @@
     }
 
     @Override
-    public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
-            @NonNull final AllAppsList apps) {
+    public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
+            @NonNull AllAppsList apps) {
+        LauncherAppState app = taskController.getApp();
         Context context = app.getContext();
 
         // TODO: remove this
@@ -119,7 +121,7 @@
 
         FixedContainerItems fci = new FixedContainerItems(mPredictorState.containerId, items);
         dataModel.extraItems.put(fci.containerId, fci);
-        bindExtraContainerItems(fci);
+        taskController.bindExtraContainerItems(fci);
         usersForChangedShortcuts.forEach(
                 u -> dataModel.updateShortcutPinnedState(app.getContext(), u));
 
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index 65a49bd..8b5ed7c 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -73,6 +73,7 @@
 import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.Executors;
 import com.android.launcher3.util.IntSparseArrayMap;
+import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.PersistedItemArray;
 import com.android.quickstep.logging.SettingsChangeLogger;
 import com.android.quickstep.logging.StatsLogCompatManager;
@@ -150,7 +151,8 @@
         // TODO: Implement caching and preloading
 
         WorkspaceItemFactory factory =
-                new WorkspaceItemFactory(mApp, ums, pinnedShortcuts, numColumns, state.containerId);
+                new WorkspaceItemFactory(mApp, ums, mPmHelper, pinnedShortcuts, numColumns,
+                        state.containerId);
         FixedContainerItems fci = new FixedContainerItems(state.containerId,
                 state.storage.read(mApp.getContext(), factory, ums.allUsers::get));
         if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
@@ -530,6 +532,7 @@
 
         private final LauncherAppState mAppState;
         private final UserManagerState mUMS;
+        private final PackageManagerHelper mPmHelper;
         private final Map<ShortcutKey, ShortcutInfo> mPinnedShortcuts;
         private final int mMaxCount;
         private final int mContainer;
@@ -537,9 +540,11 @@
         private int mReadCount = 0;
 
         protected WorkspaceItemFactory(LauncherAppState appState, UserManagerState ums,
-                Map<ShortcutKey, ShortcutInfo> pinnedShortcuts, int maxCount, int container) {
+                PackageManagerHelper pmHelper, Map<ShortcutKey, ShortcutInfo> pinnedShortcuts,
+                int maxCount, int container) {
             mAppState = appState;
             mUMS = ums;
+            mPmHelper = pmHelper;
             mPinnedShortcuts = pinnedShortcuts;
             mMaxCount = maxCount;
             mContainer = container;
@@ -563,6 +568,7 @@
                             lai,
                             UserCache.INSTANCE.get(mAppState.getContext()).getUserInfo(user),
                             ApiWrapper.INSTANCE.get(mAppState.getContext()),
+                            mPmHelper,
                             mUMS.isUserQuiet(user));
                     info.container = mContainer;
                     mAppState.getIconCache().getTitleAndIcon(info, lai, false);
diff --git a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
index f4cbf17..39f2c00 100644
--- a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
@@ -24,7 +24,7 @@
 
 import androidx.annotation.NonNull;
 
-import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
 import com.android.launcher3.model.BgDataModel.FixedContainerItems;
 import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
 import com.android.launcher3.model.data.ItemInfo;
@@ -41,7 +41,7 @@
 import java.util.stream.Collectors;
 
 /** Task to update model as a result of predicted widgets update */
-public final class WidgetsPredictionUpdateTask extends BaseModelUpdateTask {
+public final class WidgetsPredictionUpdateTask implements ModelUpdateTask {
     private final PredictorState mPredictorState;
     private final List<AppTarget> mTargets;
 
@@ -58,8 +58,8 @@
      * workspace.
      */
     @Override
-    public void execute(@NonNull final LauncherAppState appState,
-            @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
+    public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
+            @NonNull AllAppsList apps) {
         Set<ComponentKey> widgetsInWorkspace = dataModel.appWidgets.stream().map(
                 widget -> new ComponentKey(widget.providerName, widget.user)).collect(
                 Collectors.toSet());
@@ -98,7 +98,7 @@
 
         List<ItemInfo> items;
         if (enableCategorizedWidgetSuggestions()) {
-            Context context = appState.getContext();
+            Context context = taskController.getApp().getContext();
             WidgetRecommendationCategoryProvider categoryProvider =
                     WidgetRecommendationCategoryProvider.newInstance(context);
             items = servicePredictedItems.stream()
@@ -115,7 +115,7 @@
                 new FixedContainerItems(mPredictorState.containerId, items);
 
         dataModel.extraItems.put(mPredictorState.containerId, fixedContainerItems);
-        bindExtraContainerItems(fixedContainerItems);
+        taskController.bindExtraContainerItems(fixedContainerItems);
 
         // Don't store widgets prediction to disk because it is not used frequently.
     }
diff --git a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
index 184ea71..fe9ade9 100644
--- a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
+++ b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
@@ -25,7 +25,7 @@
 /** {@link SystemShortcut.Factory} implementation to create workspace split shortcuts */
 public interface QuickstepSystemShortcut {
 
-    String TAG = QuickstepSystemShortcut.class.getSimpleName();
+    String TAG = "QuickstepSystemShortcut";
 
     static SystemShortcut.Factory<QuickstepLauncher> getSplitSelectShortcutByPosition(
             SplitPositionOption position) {
diff --git a/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt b/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt
index 2b6f77f..c94edce 100644
--- a/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt
+++ b/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt
@@ -45,7 +45,7 @@
 ) : SystemShortcut<T>(iconResId, labelResId, target, itemInfo, originalView) where
 T : Context?,
 T : ActivityContext? {
-    private val TAG = SystemShortcut::class.java.simpleName
+    private val TAG = "SplitShortcut"
 
     // Initiate splitscreen from the Home screen or Home All Apps
     protected val splitSelectSource: SplitSelectSource?
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 882682d..747612d 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -182,7 +182,7 @@
     }
 
     public void dump(String prefix, PrintWriter writer) {
-        writer.println(prefix + this.getClass().getSimpleName());
+        writer.println(prefix + "DepthController");
         writer.println(prefix + "\tmMaxBlurRadius=" + mMaxBlurRadius);
         writer.println(prefix + "\tmCrossWindowBlursEnabled=" + mCrossWindowBlursEnabled);
         writer.println(prefix + "\tmSurface=" + mSurface);
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
index 5ac5761..62cc0bb 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
@@ -32,9 +32,9 @@
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.launcher3.util.DisplayController;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.SystemUiProxy;
-import com.android.quickstep.views.DesktopAppSelectView;
 import com.android.wm.shell.desktopmode.IDesktopTaskListener;
 
 import java.util.HashSet;
@@ -48,8 +48,6 @@
 
     private static final String TAG = "DesktopVisController";
     private static final boolean DEBUG = false;
-    private static final boolean IS_STASHING_ENABLED = SystemProperties.getBoolean(
-            "persist.wm.debug.desktop_stashing", false);
     private final Launcher mLauncher;
     private final Set<DesktopVisibilityListener> mDesktopVisibilityListeners = new HashSet<>();
 
@@ -60,7 +58,6 @@
 
     @Nullable
     private IDesktopTaskListener mDesktopTaskListener;
-    private DesktopAppSelectView mSelectAppToast;
 
     public DesktopVisibilityController(Launcher launcher) {
         mLauncher = launcher;
@@ -85,21 +82,7 @@
 
             @Override
             public void onStashedChanged(int displayId, boolean stashed) {
-                if (!IS_STASHING_ENABLED) {
-                    return;
-                }
-                MAIN_EXECUTOR.execute(() -> {
-                    if (displayId == mLauncher.getDisplayId()) {
-                        if (DEBUG) {
-                            Log.d(TAG, "desktop stashed changed value=" + stashed);
-                        }
-                        if (stashed) {
-                            showSelectAppToast();
-                        } else {
-                            hideSelectAppToast();
-                        }
-                    }
-                });
+              Log.w(TAG, "IDesktopTaskListener: onStashedChanged is deprecated");
             }
         };
         SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(mDesktopTaskListener);
@@ -110,6 +93,7 @@
      */
     public void unregisterSystemUiListener() {
         SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(null);
+        mDesktopTaskListener = null;
     }
 
     /**
@@ -189,7 +173,7 @@
         }
         setBackgroundStateEnabled(state == BACKGROUND_APP);
         // Desktop visibility tracks overview and background state separately
-        setOverviewStateEnabled(state != BACKGROUND_APP && state.overviewUi);
+        setOverviewStateEnabled(state != BACKGROUND_APP && state.isRecentsViewVisible);
     }
 
     private void setOverviewStateEnabled(boolean overviewStateEnabled) {
@@ -229,6 +213,7 @@
         for (DesktopVisibilityListener listener : mDesktopVisibilityListeners) {
             listener.onDesktopVisibilityChanged(areDesktopTasksVisible);
         }
+        DisplayController.handleInfoChangeForDesktopMode(mLauncher);
     }
 
     /**
@@ -301,15 +286,6 @@
     }
 
     /**
-     * Handle launcher moving to home due to home gesture or home button press.
-     */
-    public void onHomeActionTriggered() {
-        if (IS_STASHING_ENABLED && areDesktopTasksVisible()) {
-            SystemUiProxy.INSTANCE.get(mLauncher).stashDesktopApps(mLauncher.getDisplayId());
-        }
-    }
-
-    /**
      * TODO: b/333533253 - Remove after flag rollout
      */
     private void setLauncherViewsVisibility(int visibility) {
@@ -371,30 +347,6 @@
         }
     }
 
-    private void showSelectAppToast() {
-        if (mSelectAppToast != null) {
-            return;
-        }
-        if (DEBUG) {
-            Log.d(TAG, "show toast to select desktop apps");
-        }
-        Runnable onCloseCallback = () -> {
-            SystemUiProxy.INSTANCE.get(mLauncher).hideStashedDesktopApps(mLauncher.getDisplayId());
-        };
-        mSelectAppToast = DesktopAppSelectView.show(mLauncher, onCloseCallback);
-    }
-
-    private void hideSelectAppToast() {
-        if (mSelectAppToast == null) {
-            return;
-        }
-        if (DEBUG) {
-            Log.d(TAG, "hide toast to select desktop apps");
-        }
-        mSelectAppToast.hide();
-        mSelectAppToast = null;
-    }
-
     /** A listener for when the user enters/exits Desktop Mode. */
     public interface DesktopVisibilityListener {
         /**
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
deleted file mode 100644
index 3635827..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2022 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.taskbar;
-
-import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_NOTIFICATIONS;
-import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_QUICK_SETTINGS;
-
-import android.content.Context;
-import android.content.pm.ActivityInfo.Config;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.R;
-import com.android.launcher3.taskbar.navbutton.NearestTouchFrame;
-
-/**
- * Controller for managing buttons and status icons in taskbar in a desktop environment.
- */
-public class DesktopNavbarButtonsViewController extends NavbarButtonsViewController {
-
-    private final TaskbarActivityContext mContext;
-    private final FrameLayout mNavButtonsView;
-    private final ViewGroup mNavButtonContainer;
-    private final ViewGroup mStartContextualContainer;
-    private final View mAllAppsButton;
-
-    private TaskbarControllers mControllers;
-
-    public DesktopNavbarButtonsViewController(TaskbarActivityContext context,
-            @Nullable Context navigationBarPanelContext, NearestTouchFrame navButtonsView) {
-        super(context, navigationBarPanelContext, navButtonsView);
-        mContext = context;
-        mNavButtonsView = navButtonsView;
-        mNavButtonContainer = mNavButtonsView.findViewById(R.id.end_nav_buttons);
-        mStartContextualContainer = mNavButtonsView.findViewById(R.id.start_contextual_buttons);
-        mAllAppsButton = LayoutInflater.from(context)
-                .inflate(R.layout.taskbar_all_apps_button, mStartContextualContainer, false);
-        mAllAppsButton.setOnClickListener(v -> mControllers.taskbarAllAppsController.toggle());
-    }
-
-    /**
-     * Initializes the controller
-     */
-    @Override
-    public void init(TaskbarControllers controllers) {
-        mControllers = controllers;
-        super.init(controllers);
-    }
-
-    @Override
-    protected void setupController() {
-        mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarHeight;
-
-        // Quick settings and notifications buttons
-        addButton(R.drawable.ic_sysbar_quick_settings, BUTTON_QUICK_SETTINGS,
-                mNavButtonContainer, mControllers.navButtonController,
-                R.id.quick_settings_button);
-        addButton(R.drawable.ic_sysbar_notifications, BUTTON_NOTIFICATIONS,
-                mNavButtonContainer, mControllers.navButtonController,
-                R.id.notifications_button);
-        // All apps button
-        mStartContextualContainer.addView(mAllAppsButton);
-    }
-
-    /** Cleans up on destroy */
-    @Override
-    public void onDestroy() { }
-
-    @Override
-    public void onConfigurationChanged(@Config int configChanges) { }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRecentAppsController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRecentAppsController.java
deleted file mode 100644
index acfbea3..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRecentAppsController.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2022 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.taskbar;
-
-import android.app.ActivityManager;
-import android.content.ComponentName;
-import android.util.SparseArray;
-
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.quickstep.RecentsModel;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Provides recent apps functionality specifically in a desktop environment.
- */
-public class DesktopTaskbarRecentAppsController extends TaskbarRecentAppsController {
-
-    private final TaskbarActivityContext mContext;
-    private ArrayList<ItemInfo> mRunningApps = new ArrayList<>();
-    private AppInfo[] mApps;
-
-    public DesktopTaskbarRecentAppsController(TaskbarActivityContext context) {
-        mContext = context;
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        mApps = null;
-    }
-
-    @Override
-    protected void setApps(AppInfo[] apps) {
-        mApps = apps;
-    }
-
-    @Override
-    protected boolean isEnabled() {
-        return true;
-    }
-
-    /**
-     * Set mRunningApps to hold currently running applications using the list of currently running
-     * tasks. Filtering is also done to ignore applications that are already on the taskbar in the
-     * original hotseat.
-     */
-    @Override
-    protected void updateRunningApps(SparseArray<ItemInfo> hotseatItems) {
-        ArrayList<AppInfo> runningApps = getRunningAppsFromTasks();
-        ArrayList<ItemInfo> filteredRunningApps = new ArrayList<>();
-        for (AppInfo runningApp : runningApps) {
-            boolean shouldAddOnTaskbar = true;
-            for (int i = 0; i < hotseatItems.size(); i++) {
-                if (hotseatItems.keyAt(i) >= mControllers.taskbarActivityContext.getDeviceProfile()
-                        .numShownHotseatIcons) {
-                    break;
-                }
-                if (hotseatItems.valueAt(i).getTargetPackage()
-                        .equals(runningApp.getTargetPackage())) {
-                    shouldAddOnTaskbar = false;
-                    break;
-                }
-            }
-            if (shouldAddOnTaskbar) {
-                filteredRunningApps.add(new WorkspaceItemInfo(runningApp));
-            }
-        }
-        mRunningApps = filteredRunningApps;
-        mControllers.taskbarViewController.commitRunningAppsToUI();
-    }
-
-    /**
-     * Returns a copy of hotseatItems with the addition of currently running applications.
-     */
-    @Override
-    protected ItemInfo[] updateHotseatItemInfos(ItemInfo[] hotseatItemInfos) {
-        // hotseatItemInfos.length would be 0 if deviceProfile.numShownHotseatIcons is 0, so we
-        // don't want to show anything in the hotseat
-        if (hotseatItemInfos.length == 0) return hotseatItemInfos;
-
-        int runningAppsIndex = 0;
-        ItemInfo[] newHotseatItemsInfo = Arrays.copyOf(
-                hotseatItemInfos, hotseatItemInfos.length + mRunningApps.size());
-        for (int i = hotseatItemInfos.length; i < newHotseatItemsInfo.length; i++) {
-            newHotseatItemsInfo[i] = mRunningApps.get(runningAppsIndex);
-            runningAppsIndex++;
-        }
-        return newHotseatItemsInfo;
-    }
-
-
-    /**
-     * Returns a list of running applications from the list of currently running tasks.
-     */
-    private ArrayList<AppInfo> getRunningAppsFromTasks() {
-        ArrayList<ActivityManager.RunningTaskInfo> tasks =
-                RecentsModel.INSTANCE.get(mContext).getRunningTasks();
-        ArrayList<AppInfo> runningApps = new ArrayList<>();
-        // early return if apps is empty, since we would have no AppInfo to compare
-        if (mApps == null)  {
-            return runningApps;
-        }
-
-        Set<String> seenPackages = new HashSet<>();
-        for (ActivityManager.RunningTaskInfo taskInfo : tasks) {
-            if (taskInfo.realActivity == null) continue;
-
-            // If a different task for the same package has already been handled, skip this one
-            String taskPackage = taskInfo.realActivity.getPackageName();
-            if (seenPackages.contains(taskPackage)) continue;
-
-            // Otherwise, get the corresponding AppInfo and add it to the list
-            seenPackages.add(taskPackage);
-            AppInfo app = getAppInfo(taskInfo.realActivity);
-            if (app == null) continue;
-            runningApps.add(app);
-        }
-        return runningApps;
-    }
-
-    /**
-     * Retrieves the corresponding AppInfo for the activity.
-     */
-    private AppInfo getAppInfo(ComponentName activity) {
-        String packageName = activity.getPackageName();
-        for (AppInfo app : mApps) {
-            if (!packageName.equals(app.getTargetPackage())) {
-                continue;
-            }
-            return app;
-        }
-        return null;
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt
index 06d25a2..d4bef28 100644
--- a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt
@@ -40,12 +40,17 @@
  */
 class DesktopTaskbarRunningAppsController(
     private val recentsModel: RecentsModel,
-    private val desktopVisibilityController: DesktopVisibilityController?,
+    // Pass a provider here instead of the actual DesktopVisibilityController instance since that
+    // instance might not be available when this constructor is called.
+    private val desktopVisibilityControllerProvider: () -> DesktopVisibilityController?,
 ) : TaskbarRecentAppsController() {
 
     private var apps: Array<AppInfo>? = null
     private var allRunningDesktopAppInfos: List<AppInfo>? = null
-    private var runningDesktopAppInfosExceptHotseatItems: List<ItemInfo>? = null
+    private var allMinimizedDesktopAppInfos: List<AppInfo>? = null
+
+    private val desktopVisibilityController: DesktopVisibilityController?
+        get() = desktopVisibilityControllerProvider()
 
     private val isInDesktopMode: Boolean
         get() = desktopVisibilityController?.areDesktopTasksVisible() ?: false
@@ -63,20 +68,24 @@
     override fun isEnabled() = true
 
     @VisibleForTesting
-    public override fun updateHotseatItemInfos(hotseatItems: Array<ItemInfo>?): Array<ItemInfo>? {
-        val actualHotseatItems = hotseatItems ?: return super.updateHotseatItemInfos(null)
+    public override fun updateHotseatItemInfos(hotseatItems: Array<ItemInfo?>): Array<ItemInfo?> {
         if (!isInDesktopMode) {
             Log.d(TAG, "updateHotseatItemInfos: not in Desktop Mode")
             return hotseatItems
         }
         val newHotseatItemInfos =
-            actualHotseatItems
+            hotseatItems
+                .filterNotNull()
                 // Ignore predicted apps - we show running apps instead
                 .filter { itemInfo -> !itemInfo.isPredictedItem }
                 .toMutableList()
         val runningDesktopAppInfos =
-            runningDesktopAppInfosExceptHotseatItems ?: return newHotseatItemInfos.toTypedArray()
-        newHotseatItemInfos.addAll(runningDesktopAppInfos)
+            allRunningDesktopAppInfos?.let {
+                getRunningDesktopAppInfosExceptHotseatApps(it, newHotseatItemInfos.toList())
+            }
+        if (runningDesktopAppInfos != null) {
+            newHotseatItemInfos.addAll(runningDesktopAppInfos)
+        }
         return newHotseatItemInfos.toTypedArray()
     }
 
@@ -87,23 +96,48 @@
         return allRunningDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet()
     }
 
+    override fun getMinimizedApps(): Set<String> {
+        if (!isInDesktopMode) {
+            return emptySet()
+        }
+        return allMinimizedDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet()
+    }
+
     @VisibleForTesting
-    public override fun updateRunningApps(hotseatItems: SparseArray<ItemInfo>?) {
+    public override fun updateRunningApps() {
         if (!isInDesktopMode) {
             Log.d(TAG, "updateRunningApps: not in Desktop Mode")
             mControllers.taskbarViewController.commitRunningAppsToUI()
             return
         }
-        val allRunningDesktopAppInfos = getRunningDesktopAppInfos()
-        this.allRunningDesktopAppInfos = allRunningDesktopAppInfos
-        runningDesktopAppInfosExceptHotseatItems =
-            hotseatItems?.let {
-                getRunningDesktopAppInfosExceptHotseatApps(allRunningDesktopAppInfos, it.toList())
-            }
-
+        val runningTasks = getDesktopRunningTasks()
+        val runningAppInfo = getAppInfosFromRunningTasks(runningTasks)
+        allRunningDesktopAppInfos = runningAppInfo
+        updateMinimizedApps(runningTasks, runningAppInfo)
         mControllers.taskbarViewController.commitRunningAppsToUI()
     }
 
+    private fun updateMinimizedApps(
+        runningTasks: List<RunningTaskInfo>,
+        runningAppInfo: List<AppInfo>,
+    ) {
+        val allRunningAppTasks =
+            runningAppInfo
+                .mapNotNull { appInfo -> appInfo.targetPackage?.let { appInfo to it } }
+                .associate { (appInfo, targetPackage) ->
+                    appInfo to
+                        runningTasks
+                            .filter { it.realActivity?.packageName == targetPackage }
+                            .map { it.taskId }
+                }
+        val minimizedTaskIds = runningTasks.associate { it.taskId to !it.isVisible }
+        allMinimizedDesktopAppInfos =
+            allRunningAppTasks
+                .filterValues { taskIds -> taskIds.all { minimizedTaskIds[it] ?: false } }
+                .keys
+                .toList()
+    }
+
     private fun getRunningDesktopAppInfosExceptHotseatApps(
         allRunningDesktopAppInfos: List<AppInfo>,
         hotseatItems: List<ItemInfo>
@@ -114,15 +148,10 @@
             .map { WorkspaceItemInfo(it) }
     }
 
-    private fun getRunningDesktopAppInfos(): List<AppInfo> {
-        return getAppInfosFromRunningTasks(
-            recentsModel.runningTasks
-                .filter { taskInfo: RunningTaskInfo ->
-                    taskInfo.windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM
-                }
-                .toList()
-        )
-    }
+    private fun getDesktopRunningTasks(): List<RunningTaskInfo> =
+        recentsModel.runningTasks.filter { taskInfo: RunningTaskInfo ->
+            taskInfo.windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM
+        }
 
     // TODO(b/335398876) fetch app icons from Tasks instead of AppInfos
     private fun getAppInfosFromRunningTasks(tasks: List<RunningTaskInfo>): List<AppInfo> {
@@ -136,9 +165,10 @@
             .filterNotNull()
     }
 
-    private fun <E> SparseArray<E>.toList(): List<E> {
-        return valueIterator().asSequence().toList()
-    }
+    private fun getAppInfosFromRunningTask(task: RunningTaskInfo): AppInfo? =
+        apps?.firstOrNull { it.targetPackage == task.realActivity?.packageName }
+
+    private fun <E> SparseArray<E>.toList(): List<E> = valueIterator().asSequence().toList()
 
     companion object {
         private const val TAG = "TabletDesktopTaskbarRunningAppsController"
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java
deleted file mode 100644
index 2dd610c4..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.taskbar;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.uioverrides.QuickstepLauncher;
-import com.android.quickstep.util.TISBindHelper;
-
-/**
- * A data source which integrates with a Launcher instance, used specifically for a
- * desktop environment.
- */
-public class DesktopTaskbarUIController extends TaskbarUIController {
-
-    private final QuickstepLauncher mLauncher;
-
-    public DesktopTaskbarUIController(QuickstepLauncher launcher) {
-        mLauncher = launcher;
-    }
-
-    @SuppressWarnings("MissingSuperCall") // TODO: Fix me
-    @Override
-    protected void init(TaskbarControllers taskbarControllers) {
-        super.init(taskbarControllers);
-        mLauncher.getHotseat().setIconsAlpha(0f);
-        mControllers.taskbarViewController.updateRunningApps();
-    }
-
-    @SuppressWarnings("MissingSuperCall") // TODO: Fix me
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        mLauncher.getHotseat().setIconsAlpha(1f);
-    }
-
-    /** Disable taskbar stashing in desktop environment. */
-    @Override
-    public boolean supportsVisualStashing() {
-        return false;
-    }
-
-    @Nullable
-    @Override
-    protected TISBindHelper getTISBindHelper() {
-        return mLauncher.getTISBindHelper();
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
index c0ecc61..06d9ee6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
@@ -133,4 +133,9 @@
     protected TISBindHelper getTISBindHelper() {
         return mRecentsActivity.getTISBindHelper();
     }
+
+    @Override
+    protected String getTaskbarUIControllerName() {
+        return "FallbackTaskbarUIController";
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
index b213203..358d703 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
@@ -148,7 +148,7 @@
         });
     }
 
-    private void processLoadedTasks(ArrayList<GroupTask> tasks) {
+    private void processLoadedTasks(List<GroupTask> tasks) {
         // Only store MAX_TASK tasks, from most to least recent
         Collections.reverse(tasks);
         mTasks = tasks.stream()
@@ -157,7 +157,7 @@
         mNumHiddenTasks = Math.max(0, tasks.size() - MAX_TASKS);
     }
 
-    private void processLoadedTasksOnDesktop(ArrayList<GroupTask> tasks) {
+    private void processLoadedTasksOnDesktop(List<GroupTask> tasks) {
         // Find the single desktop task that contains a grouping of desktop tasks
         DesktopTask desktopTask = findDesktopTask(tasks);
 
@@ -173,7 +173,7 @@
     }
 
     @Nullable
-    private DesktopTask findDesktopTask(ArrayList<GroupTask> tasks) {
+    private DesktopTask findDesktopTask(List<GroupTask> tasks) {
         return (DesktopTask) tasks.stream()
                 .filter(t -> t instanceof DesktopTask)
                 .findFirst()
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
index 48fc7d1..39b4f77 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
@@ -186,7 +186,7 @@
             @NonNull ImageView thumbnailView,
             @ColorInt int backgroundColor,
             @Nullable ThumbnailData thumbnailData) {
-        Bitmap bm = thumbnailData == null ? null : thumbnailData.thumbnail;
+        Bitmap bm = thumbnailData == null ? null : thumbnailData.getThumbnail();
 
         if (thumbnailView.getVisibility() != VISIBLE) {
             thumbnailView.setVisibility(VISIBLE);
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 2c2311a..779009a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -24,10 +24,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.TaskTransitionSpec;
-import android.view.WindowManagerGlobal;
 import android.window.RemoteTransition;
 
 import androidx.annotation.NonNull;
@@ -37,7 +33,6 @@
 import com.android.launcher3.Flags;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.QuickstepTransitionManager;
-import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.logging.InstanceId;
@@ -56,6 +51,7 @@
 import com.android.quickstep.util.GroupTask;
 import com.android.quickstep.util.TISBindHelper;
 import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
@@ -139,7 +135,6 @@
         mLauncher.setTaskbarUIController(null);
         mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
         mHomeState.removeListener(mVisibilityChangeListener);
-        updateTaskTransitionSpec(true);
     }
 
     private void onInAppDisplayProgressChanged() {
@@ -278,26 +273,6 @@
     private void onStashedInAppChanged(DeviceProfile deviceProfile) {
         boolean taskbarStashedInApps = mControllers.taskbarStashController.isStashedInApp();
         deviceProfile.isTaskbarPresentInApps = !taskbarStashedInApps;
-        updateTaskTransitionSpec(taskbarStashedInApps);
-    }
-
-    private void updateTaskTransitionSpec(boolean taskbarIsHidden) {
-        try {
-            if (taskbarIsHidden) {
-                // Clear custom task transition settings when the taskbar is stashed
-                WindowManagerGlobal.getWindowManagerService().clearTaskTransitionSpec();
-            } else {
-                // Adjust task transition spec to account for taskbar being visible
-                WindowManagerGlobal.getWindowManagerService().setTaskTransitionSpec(
-                        new TaskTransitionSpec(
-                                mLauncher.getColor(R.color.taskbar_background)));
-            }
-        } catch (RemoteException e) {
-            // This shouldn't happen but if it does task animations won't look good until the
-            // taskbar stashing state is changed.
-            Log.e(TAG, "Failed to update task transition spec to account for new taskbar state",
-                    e);
-        }
     }
 
     /**
@@ -405,7 +380,7 @@
     }
 
     @Override
-    public void updateStateForSysuiFlags(int sysuiFlags) {
+    public void updateStateForSysuiFlags(@SystemUiStateFlags long sysuiFlags) {
         mTaskbarLauncherStateController.updateStateForSysuiFlags(sysuiFlags);
     }
 
@@ -472,4 +447,9 @@
 
         mTaskbarLauncherStateController.dumpLogs(prefix + "\t", pw);
     }
+
+    @Override
+    protected String getTaskbarUIControllerName() {
+        return "LauncherTaskbarUIController";
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 2c5aeb3..81581b8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -45,6 +45,7 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SHORTCUT_HELPER_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
 
 import android.animation.ArgbEvaluator;
@@ -105,6 +106,7 @@
 import com.android.systemui.shared.rotation.RotationButton;
 import com.android.systemui.shared.rotation.RotationButtonController;
 import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -133,6 +135,7 @@
     private static final int FLAG_VOICE_INTERACTION_WINDOW_SHOWING = 1 << 12;
     private static final int FLAG_SMALL_SCREEN = 1 << 13;
     private static final int FLAG_SLIDE_IN_VIEW_VISIBLE = 1 << 14;
+    private static final int FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING = 1 << 15;
 
     /**
      * Flags where a UI could be over Taskbar surfaces, so the color override should be disabled.
@@ -197,7 +200,8 @@
     private TaskbarControllers mControllers;
     private boolean mIsImeRenderingNavButtons;
     private ImageView mA11yButton;
-    private int mSysuiStateFlags;
+    @SystemUiStateFlags
+    private long mSysuiStateFlags;
     private ImageView mBackButton;
     private ImageView mHomeButton;
     private MultiValueAlpha mBackButtonAlpha;
@@ -284,8 +288,9 @@
         // - Notification shade is expanded
         // - IME is showing (add separate translation for IME)
         // - VoiceInteractionWindow (assistant) is showing
+        // - Keyboard shortcuts helper is showing
         int flagsToRemoveTranslation = FLAG_NOTIFICATION_SHADE_EXPANDED | FLAG_IME_VISIBLE
-                | FLAG_VOICE_INTERACTION_WINDOW_SHOWING;
+                | FLAG_VOICE_INTERACTION_WINDOW_SHOWING | FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING;
         mPropertyHolders.add(new StatePropertyHolder(mNavButtonInAppDisplayProgressForSysui,
                 flags -> (flags & flagsToRemoveTranslation) != 0, AnimatedFloat.VALUE,
                 1, 0));
@@ -317,38 +322,28 @@
             mPropertyHolders.add(new StatePropertyHolder(
                     mControllers.taskbarDragLayerController.getNavbarBackgroundAlpha(),
                     flags -> (flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0));
-
-            // Rotation button
-            RotationButton rotationButton = new RotationButtonImpl(
-                    addButton(mEndContextualContainer, R.id.rotate_suggestion,
-                            R.layout.taskbar_contextual_button));
-            rotationButton.hide();
-            mControllers.rotationButtonController.setRotationButton(rotationButton, null);
-        } else {
-            mFloatingRotationButton = new FloatingRotationButton(
-                    ENABLE_TASKBAR_NAVBAR_UNIFICATION ? mNavigationBarPanelContext : mContext,
-                    R.string.accessibility_rotate_button,
-                    R.layout.rotate_suggestion,
-                    R.id.rotate_suggestion,
-                    R.dimen.floating_rotation_button_min_margin,
-                    R.dimen.rounded_corner_content_padding,
-                    R.dimen.floating_rotation_button_taskbar_left_margin,
-                    R.dimen.floating_rotation_button_taskbar_bottom_margin,
-                    R.dimen.floating_rotation_button_diameter,
-                    R.dimen.key_button_ripple_max_width,
-                    R.bool.floating_rotation_button_position_left);
-            mControllers.rotationButtonController.setRotationButton(mFloatingRotationButton,
-                    mRotationButtonListener);
-
-            if (!mIsImeRenderingNavButtons) {
-                View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
-                        mStartContextualContainer, mControllers.navButtonController, R.id.back);
-                imeDownButton.setRotation(Utilities.isRtl(resources) ? 90 : -90);
-                // Only show when IME is visible.
-                mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
-                        flags -> (flags & FLAG_IME_VISIBLE) != 0));
-            }
+        } else if (!mIsImeRenderingNavButtons) {
+            View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
+                    mStartContextualContainer, mControllers.navButtonController, R.id.back);
+            imeDownButton.setRotation(Utilities.isRtl(resources) ? 90 : -90);
+            // Only show when IME is visible.
+            mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
+                    flags -> (flags & FLAG_IME_VISIBLE) != 0));
         }
+        mFloatingRotationButton = new FloatingRotationButton(
+                ENABLE_TASKBAR_NAVBAR_UNIFICATION ? mNavigationBarPanelContext : mContext,
+                R.string.accessibility_rotate_button,
+                R.layout.rotate_suggestion,
+                R.id.rotate_suggestion,
+                R.dimen.floating_rotation_button_min_margin,
+                R.dimen.rounded_corner_content_padding,
+                R.dimen.floating_rotation_button_taskbar_left_margin,
+                R.dimen.floating_rotation_button_taskbar_bottom_margin,
+                R.dimen.floating_rotation_button_diameter,
+                R.dimen.key_button_ripple_max_width,
+                R.bool.floating_rotation_button_position_left);
+        mControllers.rotationButtonController.setRotationButton(mFloatingRotationButton,
+                mRotationButtonListener);
 
         applyState();
         mPropertyHolders.forEach(StatePropertyHolder::endAnimation);
@@ -386,8 +381,15 @@
                             (flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0 ||
                             (flags & FLAG_KEYGUARD_OCCLUDED) != 0;
                     return (flags & FLAG_DISABLE_BACK) == 0
+                            && (!mContext.isGestureNav() || !mContext.isUserSetupComplete())
                             && ((flags & FLAG_KEYGUARD_VISIBLE) == 0 || showingOnKeyguard);
                 }));
+        // Hide back button in SUW if keyboard is showing (IME draws its own back).
+        if (mIsImeRenderingNavButtons) {
+            mPropertyHolders.add(new StatePropertyHolder(
+                    mBackButtonAlpha.get(ALPHA_INDEX_SUW),
+                    flags -> (flags & FLAG_IME_VISIBLE) == 0));
+        }
         mPropertyHolders.add(new StatePropertyHolder(mBackButton,
                 flags -> (flags & FLAG_IME_VISIBLE) != 0,
                 ROTATION_DRAWABLE_PERCENT, 1f, 0f));
@@ -410,8 +412,8 @@
         mPropertyHolders.add(
                 new StatePropertyHolder(mHomeButtonAlpha.get(
                         ALPHA_INDEX_KEYGUARD_OR_DISABLE),
-                flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
-                        (flags & FLAG_DISABLE_HOME) == 0));
+                        flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0
+                                && (flags & FLAG_DISABLE_HOME) == 0 && !mContext.isGestureNav()));
 
         // Recents button
         mRecentsButton = addButton(R.drawable.ic_sysbar_recent, BUTTON_RECENTS,
@@ -429,7 +431,7 @@
         });
         mPropertyHolders.add(new StatePropertyHolder(mRecentsButton,
                 flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 && (flags & FLAG_DISABLE_RECENTS) == 0
-                        && !mContext.isNavBarKidsModeActive()));
+                        && !mContext.isNavBarKidsModeActive() && !mContext.isGestureNav()));
 
         // A11y button
         mA11yButton = addButton(R.drawable.ic_sysbar_accessibility_button, BUTTON_A11Y,
@@ -445,7 +447,7 @@
                 navButtonController.onButtonLongClick(BUTTON_SPACE, view));
     }
 
-    private void parseSystemUiFlags(int sysUiStateFlags) {
+    private void parseSystemUiFlags(@SystemUiStateFlags long sysUiStateFlags) {
         mSysuiStateFlags = sysUiStateFlags;
         boolean isImeVisible = (sysUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0;
         boolean isImeSwitcherShowing = (sysUiStateFlags & SYSUI_STATE_IME_SWITCHER_SHOWING) != 0;
@@ -453,12 +455,14 @@
         boolean isHomeDisabled = (sysUiStateFlags & SYSUI_STATE_HOME_DISABLED) != 0;
         boolean isRecentsDisabled = (sysUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0;
         boolean isBackDisabled = (sysUiStateFlags & SYSUI_STATE_BACK_DISABLED) != 0;
-        int shadeExpandedFlags = SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
+        long shadeExpandedFlags = SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
                 | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
         boolean isNotificationShadeExpanded = (sysUiStateFlags & shadeExpandedFlags) != 0;
         boolean isScreenPinningActive = (sysUiStateFlags & SYSUI_STATE_SCREEN_PINNING) != 0;
         boolean isVoiceInteractionWindowShowing =
                 (sysUiStateFlags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0;
+        boolean isKeyboardShortcutHelperShowing =
+                (sysUiStateFlags & SYSUI_STATE_SHORTCUT_HELPER_SHOWING) != 0;
 
         // TODO(b/202218289) we're getting IME as not visible on lockscreen from system
         updateStateForFlag(FLAG_IME_VISIBLE, isImeVisible);
@@ -470,6 +474,7 @@
         updateStateForFlag(FLAG_NOTIFICATION_SHADE_EXPANDED, isNotificationShadeExpanded);
         updateStateForFlag(FLAG_SCREEN_PINNING_ACTIVE, isScreenPinningActive);
         updateStateForFlag(FLAG_VOICE_INTERACTION_WINDOW_SHOWING, isVoiceInteractionWindowShowing);
+        updateStateForFlag(FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING, isKeyboardShortcutHelperShowing);
 
         if (mA11yButton != null) {
             // Only used in 3 button
@@ -480,7 +485,8 @@
         }
     }
 
-    public void updateStateForSysuiFlags(int systemUiStateFlags, boolean skipAnim) {
+    public void updateStateForSysuiFlags(@SystemUiStateFlags long systemUiStateFlags,
+            boolean skipAnim) {
         if (systemUiStateFlags == mSysuiStateFlags) {
             return;
         }
@@ -791,7 +797,6 @@
             NavButtonLayoutter navButtonLayoutter =
                     NavButtonLayoutFactory.Companion.getUiLayoutter(
                             dp, mNavButtonsView, mImeSwitcherButton,
-                            mControllers.rotationButtonController.getRotationButton(),
                             mA11yButton, mSpace, res, isInKidsMode, isInSetup, isThreeButtonNav,
                             mContext.isPhoneMode(), mWindowManagerProxy.getRotation(mContext));
             navButtonLayoutter.layoutButtons(mContext, isA11yButtonPersistent());
@@ -802,13 +807,6 @@
 
         if (isInSetup) {
             handleSetupUi();
-
-            // Hide back button in SUW if keyboard is showing (IME draws its own back).
-            if (mIsImeRenderingNavButtons) {
-                mPropertyHolders.add(new StatePropertyHolder(
-                        mBackButtonAlpha.get(ALPHA_INDEX_SUW),
-                        flags -> (flags & FLAG_IME_VISIBLE) == 0));
-            }
         } else if (isInKidsMode) {
             int iconSize = res.getDimensionPixelSize(
                     R.dimen.taskbar_icon_size_kids);
@@ -1064,6 +1062,8 @@
         appendFlag(str, flags, FLAG_SCREEN_PINNING_ACTIVE, "FLAG_SCREEN_PINNING_ACTIVE");
         appendFlag(str, flags, FLAG_VOICE_INTERACTION_WINDOW_SHOWING,
                 "FLAG_VOICE_INTERACTION_WINDOW_SHOWING");
+        appendFlag(str, flags, FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING,
+                "FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING");
         return str.toString();
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
index 83e4571..94e2244 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
@@ -15,9 +15,12 @@
  */
 package com.android.launcher3.taskbar;
 
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Rect;
@@ -111,4 +114,17 @@
             setBackgroundColor(newColor);
         }
     }
+
+    /**
+     * Updates the handle scale.
+     *
+     * @param scale target scale to animate towards (starting from current scale)
+     * @param durationMs milliseconds for the animation to take
+     */
+    public void animateScale(float scale, long durationMs) {
+        ObjectAnimator scaleAnim = ObjectAnimator.ofPropertyValuesHolder(this,
+                PropertyValuesHolder.ofFloat(SCALE_PROPERTY, scale));
+        scaleAnim.setDuration(durationMs).setAutoCancel(true);
+        scaleAnim.start();
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index f258b47..252f2a8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -42,6 +42,7 @@
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.quickstep.NavHandle;
 import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 
 import java.io.PrintWriter;
 
@@ -57,6 +58,10 @@
     public static final int ALPHA_INDEX_HIDDEN_WHILE_DREAMING = 3;
     private static final int NUM_ALPHA_CHANNELS = 4;
 
+    // Values for long press animations, picked to most closely match navbar spec.
+    private static final float SCALE_TOUCH_ANIMATION_SHRINK = 0.85f;
+    private static final float SCALE_TOUCH_ANIMATION_EXPAND = 1.18f;
+
     /**
      * The SharedPreferences key for whether the stashed handle region is dark.
      */
@@ -113,7 +118,7 @@
         mControllers = controllers;
         DeviceProfile deviceProfile = mActivity.getDeviceProfile();
         Resources resources = mActivity.getResources();
-        if (mActivity.isPhoneGestureNavMode()) {
+        if (mActivity.isPhoneGestureNavMode() || mActivity.isTinyTaskbar()) {
             mTaskbarSize = resources.getDimensionPixelSize(R.dimen.taskbar_phone_size);
             mStashedHandleWidth =
                     resources.getDimensionPixelSize(R.dimen.taskbar_stashed_small_screen);
@@ -299,7 +304,7 @@
                 homeDisabled ? 0 : 1);
     }
 
-    public void updateStateForSysuiFlags(int systemUiStateFlags) {
+    public void updateStateForSysuiFlags(@SystemUiStateFlags long systemUiStateFlags) {
         mTaskbarHidden = (systemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
         updateRegionSamplingWindowVisibility();
     }
@@ -324,7 +329,13 @@
 
     @Override
     public void animateNavBarLongPress(boolean isTouchDown, boolean shrink, long durationMs) {
-        // TODO(b/308693847): Animate similarly to NavigationHandle.java (SysUI).
+        float targetScale;
+        if (isTouchDown) {
+            targetScale = shrink ? SCALE_TOUCH_ANIMATION_SHRINK : SCALE_TOUCH_ANIMATION_EXPAND;
+        } else {
+            targetScale = 1f;
+        }
+        mStashedHandleView.animateScale(targetScale, durationMs);
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 1a94424..0de0550 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -15,7 +15,6 @@
  */
 package com.android.launcher3.taskbar;
 
-import static android.content.pm.PackageManager.FEATURE_PC;
 import static android.os.Trace.TRACE_TAG_APP;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
@@ -38,11 +37,13 @@
 import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING;
 import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN;
 import static com.android.launcher3.testing.shared.ResourceUtils.getBoolByName;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.quickstep.util.AnimUtils.completeRunnableListCallback;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
 import static com.android.window.flags.Flags.enableDesktopWindowingMode;
 import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps;
+import static com.android.wm.shell.Flags.enableTinyTaskbar;
 
 import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
@@ -107,6 +108,7 @@
 import com.android.launcher3.taskbar.bubbles.BubbleControllers;
 import com.android.launcher3.taskbar.bubbles.BubbleDismissController;
 import com.android.launcher3.taskbar.bubbles.BubbleDragController;
+import com.android.launcher3.taskbar.bubbles.BubblePinController;
 import com.android.launcher3.taskbar.bubbles.BubbleStashController;
 import com.android.launcher3.taskbar.bubbles.BubbleStashedHandleViewController;
 import com.android.launcher3.taskbar.navbutton.NearestTouchFrame;
@@ -137,6 +139,7 @@
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.rotation.RotationButtonController;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 import com.android.systemui.unfold.updates.RotationChangeProvider;
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
 
@@ -248,8 +251,6 @@
 
         mAccessibilityDelegate = new TaskbarShortcutMenuAccessibilityDelegate(this);
 
-        final boolean isPcMode = getPackageManager().hasSystemFeature(FEATURE_PC);
-
         // If Bubble bar is present, TaskbarControllers depends on it so build it first.
         Optional<BubbleControllers> bubbleControllersOptional = Optional.empty();
         BubbleBarController.onTaskbarRecreated();
@@ -262,7 +263,9 @@
                     new BubbleDragController(this),
                     new BubbleDismissController(this, mDragLayer),
                     new BubbleBarPinController(this, mDragLayer,
-                            () -> getDeviceProfile().getDisplayInfo().currentSize)
+                            () -> DisplayController.INSTANCE.get(this).getInfo().currentSize),
+                    new BubblePinController(this, mDragLayer,
+                            () -> DisplayController.INSTANCE.get(this).getInfo().currentSize)
             ));
         }
 
@@ -275,16 +278,12 @@
                 R.drawable.ic_sysbar_rotate_button_cw_start_0,
                 R.drawable.ic_sysbar_rotate_button_cw_start_90,
                 () -> getDisplay().getRotation());
-        rotationButtonController.setBgExecutor(Executors.THREAD_POOL_EXECUTOR);
+        rotationButtonController.setBgExecutor(Executors.UI_HELPER_EXECUTOR);
 
         mControllers = new TaskbarControllers(this,
                 new TaskbarDragController(this),
                 buttonController,
-                isPcMode
-                        ? new DesktopNavbarButtonsViewController(this, mNavigationBarPanelContext,
-                                navButtonsView)
-                        : new NavbarButtonsViewController(this, mNavigationBarPanelContext,
-                                navButtonsView),
+                new NavbarButtonsViewController(this, mNavigationBarPanelContext, navButtonsView),
                 rotationButtonController,
                 new TaskbarDragLayerController(this, mDragLayer),
                 new TaskbarViewController(this, taskbarView),
@@ -292,7 +291,7 @@
                 new TaskbarUnfoldAnimationController(this, unfoldTransitionProgressProvider,
                         mWindowManager,
                         new RotationChangeProvider(c.getSystemService(DisplayManager.class), this,
-                                getMainThreadHandler())),
+                                UI_HELPER_EXECUTOR.getHandler(), getMainThreadHandler())),
                 new TaskbarKeyguardController(this),
                 new StashedHandleViewController(this, stashedHandleView),
                 new TaskbarStashController(this),
@@ -305,25 +304,24 @@
                 new VoiceInteractionWindowController(this),
                 new TaskbarTranslationController(this),
                 new TaskbarSpringOnStashController(this),
-                createTaskbarRecentAppsController(isPcMode),
+                createTaskbarRecentAppsController(),
                 TaskbarEduTooltipController.newInstance(this),
                 new KeyboardQuickSwitchController(),
-                new TaskbarPinningController(this),
+                new TaskbarPinningController(this, () ->
+                        DisplayController.INSTANCE.get(this).getInfo().isInDesktopMode()),
                 bubbleControllersOptional);
 
         mLauncherPrefs = LauncherPrefs.get(this);
     }
 
-    private TaskbarRecentAppsController createTaskbarRecentAppsController(boolean isPcMode) {
-        if (isPcMode) return new DesktopTaskbarRecentAppsController(this);
+    private TaskbarRecentAppsController createTaskbarRecentAppsController() {
         // TODO(b/335401172): unify DesktopMode checks in Launcher
-        final boolean showRunningAppsInDesktopMode = enableDesktopWindowingMode()
-                && enableDesktopWindowingTaskbarRunningApps();
-        return showRunningAppsInDesktopMode
-                        ? new DesktopTaskbarRunningAppsController(
-                                RecentsModel.INSTANCE.get(this),
-                                LauncherActivityInterface.INSTANCE.getDesktopVisibilityController())
-                        : TaskbarRecentAppsController.DEFAULT;
+        if (enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps()) {
+            return new DesktopTaskbarRunningAppsController(
+                    RecentsModel.INSTANCE.get(this),
+                    LauncherActivityInterface.INSTANCE::getDesktopVisibilityController);
+        }
+        return TaskbarRecentAppsController.DEFAULT;
     }
 
     /** Updates {@link DeviceProfile} instances for any Taskbar windows. */
@@ -419,7 +417,9 @@
      * single window for taskbar and navbar.
      */
     public boolean isPhoneMode() {
-        return ENABLE_TASKBAR_NAVBAR_UNIFICATION && mDeviceProfile.isPhone;
+        return ENABLE_TASKBAR_NAVBAR_UNIFICATION
+                && mDeviceProfile.isPhone
+                && !mDeviceProfile.isTaskbarPresent;
     }
 
     /**
@@ -436,6 +436,11 @@
         return isPhoneMode() && !isThreeButtonNav();
     }
 
+    /** Returns {@code true} iff a tiny version of taskbar is shown on phone. */
+    public boolean isTinyTaskbar() {
+        return enableTinyTaskbar() && mDeviceProfile.isPhone && mDeviceProfile.isTaskbarPresent;
+    }
+
     /**
      * Returns if software keyboard is docked or input toolbar is placed at the taskbar area
      */
@@ -830,7 +835,8 @@
         return mIsDestroyed;
     }
 
-    public void updateSysuiStateFlags(int systemUiStateFlags, boolean fromInit) {
+    public void updateSysuiStateFlags(@SystemUiStateFlags long systemUiStateFlags,
+            boolean fromInit) {
         mControllers.navbarButtonsViewController.updateStateForSysuiFlags(systemUiStateFlags,
                 fromInit);
         boolean isShadeVisible = (systemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE) != 0;
@@ -970,7 +976,9 @@
                 mWindowLayoutParams.paramsForRotation[rot].height = size;
             }
         }
-        mControllers.taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
+        mControllers.runAfterInit(
+                mControllers.taskbarInsetsController
+                        ::onTaskbarOrBubblebarWindowHeightOrInsetsChanged);
         notifyUpdateLayoutParams();
     }
 
@@ -981,7 +989,7 @@
     public int getDefaultTaskbarWindowSize() {
         Resources resources = getResources();
 
-        if (ENABLE_TASKBAR_NAVBAR_UNIFICATION && mDeviceProfile.isPhone) {
+        if (isPhoneMode()) {
             return isThreeButtonNav() ?
                     resources.getDimensionPixelSize(R.dimen.taskbar_phone_size) :
                     resources.getDimensionPixelSize(R.dimen.taskbar_stashed_size);
@@ -1456,7 +1464,7 @@
         });
     }
 
-    protected boolean isUserSetupComplete() {
+    public boolean isUserSetupComplete() {
         return mIsUserSetupComplete;
     }
 
@@ -1492,7 +1500,8 @@
             ((LauncherTaskbarUIController) uiController).addLauncherVisibilityChangedAnimation(
                     fullAnimation, duration);
         }
-        mControllers.taskbarStashController.addUnstashToHotseatAnimation(fullAnimation, duration);
+        mControllers.taskbarStashController.addUnstashToHotseatAnimationFromSuw(fullAnimation,
+                duration);
 
         View allAppsButton = mControllers.taskbarViewController.getAllAppsButtonView();
         if (allAppsButton != null && !FeatureFlags.ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get()) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index e290c3f..bafd059 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -97,8 +97,11 @@
     fun updateStashedHandleWidth(context: TaskbarActivityContext, res: Resources) {
         stashedHandleWidth =
             res.getDimensionPixelSize(
-                if (context.isPhoneMode) R.dimen.taskbar_stashed_small_screen
-                else R.dimen.taskbar_stashed_handle_width
+                if (context.isPhoneMode || context.isTinyTaskbar) {
+                    R.dimen.taskbar_stashed_small_screen
+                } else {
+                    R.dimen.taskbar_stashed_handle_width
+                }
             )
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 189b687..4f5922c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -74,12 +74,14 @@
 import com.android.launcher3.popup.PopupContainerWithArrow;
 import com.android.launcher3.shortcuts.DeepShortcutView;
 import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
+import com.android.launcher3.statehandlers.DesktopVisibilityController;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.IntSet;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.views.BubbleTextHolder;
+import com.android.quickstep.LauncherActivityInterface;
 import com.android.quickstep.util.LogUtils;
 import com.android.quickstep.util.MultiValueUpdateListener;
 import com.android.systemui.shared.recents.model.Task;
@@ -163,11 +165,6 @@
             return false;
         }
         TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onTaskbarItemLongClick");
-        if (TestProtocol.sDebugTracing) {
-            Log.d(TestProtocol.TWO_TASKBAR_LONG_CLICKS,
-                    "TaskbarDragController.startDragOnLongClick",
-                    new Throwable());
-        }
         BubbleTextView btv = (BubbleTextView) view;
         mActivity.onDragStart();
         btv.post(() -> {
@@ -340,8 +337,13 @@
     @Override
     protected void callOnDragStart() {
         super.callOnDragStart();
+        // TODO(297921594) clean it up when taskbar to desktop drag is implemented.
+        DesktopVisibilityController desktopController =
+                LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
+
         // Pre-drag has ended, start the global system drag.
-        if (mDisallowGlobalDrag) {
+        if (mDisallowGlobalDrag || (desktopController != null
+                && desktopController.areDesktopTasksVisible())) {
             AbstractFloatingView.closeAllOpenViewsExcept(mActivity, TYPE_TASKBAR_ALL_APPS);
             return;
         }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index 7f201b4..84874a9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -37,7 +37,7 @@
 import androidx.core.graphics.Insets;
 import androidx.core.view.WindowInsetsCompat;
 
-import com.android.app.viewcapture.SettingsAwareViewCapture;
+import com.android.app.viewcapture.ViewCaptureFactory;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
@@ -150,7 +150,7 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         getViewTreeObserver().addOnComputeInternalInsetsListener(mTaskbarInsetsComputer);
-        mViewCaptureCloseable = SettingsAwareViewCapture.getInstance(getContext())
+        mViewCaptureCloseable = ViewCaptureFactory.getInstance(getContext())
                 .startCapture(getRootView(), ".Taskbar");
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index d43055d..5cbd5c9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -81,7 +81,11 @@
     protected val activityContext: TaskbarActivityContext = ActivityContext.lookupContext(context)
     open val shouldShowSearchEdu = false
     private val isTooltipEnabled: Boolean
-        get() = !Utilities.isRunningInTestHarness() && !activityContext.isPhoneMode
+        get() {
+            return !Utilities.isRunningInTestHarness() &&
+                !activityContext.isPhoneMode &&
+                !activityContext.isTinyTaskbar
+        }
     private val isOpen: Boolean
         get() = tooltip?.isOpen ?: false
     val isBeforeTooltipFeaturesStep: Boolean
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java
index 333c07b..6ac862e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java
@@ -34,6 +34,7 @@
 import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.util.MultiPropertyFactory;
 import com.android.launcher3.util.TouchController;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 
 /**
  * Controller for taskbar when force visible in immersive mode is set.
@@ -83,7 +84,7 @@
     }
 
     /** Update values tracked via sysui flags. */
-    public void updateSysuiFlags(int sysuiFlags) {
+    public void updateSysuiFlags(@SystemUiStateFlags long sysuiFlags) {
         mIsImmersiveMode = (sysuiFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) == 0;
         if (mContext.isNavBarForceVisible()) {
             if (mIsImmersiveMode) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 95c4e25..e1ddb6a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -51,6 +51,7 @@
 import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION
 import com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate
 import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
+import com.android.launcher3.testing.shared.ResourceUtils
 import com.android.launcher3.util.DisplayController
 import java.io.PrintWriter
 import kotlin.jvm.optionals.getOrNull
@@ -155,13 +156,16 @@
             )
 
             // if there's an animating bubble add it to the touch region so that it's clickable
-            val animatingBubbleBounds =
+            val isAnimatingNewBubble =
                 controllers.bubbleControllers
                     .getOrNull()
                     ?.bubbleBarViewController
-                    ?.animatingBubbleBounds
-            if (animatingBubbleBounds != null) {
-                defaultTouchableRegion.op(animatingBubbleBounds, Region.Op.UNION)
+                    ?.isAnimatingNewBubble
+                    ?: false
+            if (isAnimatingNewBubble) {
+                val iconBounds =
+                    controllers.bubbleControllers.get().bubbleBarViewController.bubbleBarBounds
+                defaultTouchableRegion.op(iconBounds, Region.Op.UNION)
             }
         }
 
@@ -228,8 +232,24 @@
         val contentHeight = controllers.taskbarStashController.contentHeightToReportToApps
         val tappableHeight = controllers.taskbarStashController.tappableHeightToReportToApps
         val res = context.resources
-        if (provider.type == navigationBars() || provider.type == mandatorySystemGestures()) {
+        if (provider.type == navigationBars()) {
             provider.insetsSize = getInsetsForGravityWithCutout(contentHeight, gravity, endRotation)
+        } else if (provider.type == mandatorySystemGestures()) {
+            if (context.isThreeButtonNav) {
+                provider.insetsSize = Insets.of(0, 0, 0, 0)
+            } else {
+                val gestureHeight =
+                        ResourceUtils.getNavbarSize(
+                        ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
+                        context.resources)
+                val isPinnedTaskbar = context.deviceProfile.isTaskbarPresent
+                        && !context.deviceProfile.isTransientTaskbar
+                val mandatoryGestureHeight =
+                        if (isPinnedTaskbar) contentHeight
+                        else gestureHeight
+                provider.insetsSize = getInsetsForGravityWithCutout(mandatoryGestureHeight, gravity,
+                        endRotation)
+            }
         } else if (provider.type == tappableElement()) {
             provider.insetsSize = getInsetsForGravity(tappableHeight, gravity)
         } else if (provider.type == systemGestures() && provider.index == INDEX_LEFT) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
index 03d08eb..eac4eaa 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
@@ -17,6 +17,7 @@
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 
 import java.io.PrintWriter;
 
@@ -25,7 +26,7 @@
  */
 public class TaskbarKeyguardController implements TaskbarControllers.LoggableTaskbarController {
 
-    private static final int KEYGUARD_SYSUI_FLAGS = SYSUI_STATE_BOUNCER_SHOWING
+    private static final long KEYGUARD_SYSUI_FLAGS = SYSUI_STATE_BOUNCER_SHOWING
             | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING | SYSUI_STATE_DEVICE_DOZING
             | SYSUI_STATE_OVERVIEW_DISABLED | SYSUI_STATE_HOME_DISABLED
             | SYSUI_STATE_BACK_DISABLED | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
@@ -33,13 +34,13 @@
 
     // If any of these SysUi flags (via QuickstepContract) is set, the device to be considered
     // locked.
-    public static final int MASK_ANY_SYSUI_LOCKED = SYSUI_STATE_BOUNCER_SHOWING
+    public static final long MASK_ANY_SYSUI_LOCKED = SYSUI_STATE_BOUNCER_SHOWING
             | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
             | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
             | SYSUI_STATE_DEVICE_DREAMING;
 
     private final TaskbarActivityContext mContext;
-    private int mKeyguardSysuiFlags;
+    private long mKeyguardSysuiFlags;
     private boolean mBouncerShowing;
     private NavbarButtonsViewController mNavbarButtonsViewController;
     private final KeyguardManager mKeyguardManager;
@@ -53,8 +54,8 @@
         mNavbarButtonsViewController = navbarButtonUIController;
     }
 
-    public void updateStateForSysuiFlags(int systemUiStateFlags) {
-        int interestingKeyguardFlags = systemUiStateFlags & KEYGUARD_SYSUI_FLAGS;
+    public void updateStateForSysuiFlags(@SystemUiStateFlags long systemUiStateFlags) {
+        long interestingKeyguardFlags = systemUiStateFlags & KEYGUARD_SYSUI_FLAGS;
         if (interestingKeyguardFlags == mKeyguardSysuiFlags) {
             // No change in keyguard relevant flags
             return;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index ee21eac..ead1a8a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -54,6 +54,7 @@
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.animation.ViewRootSync;
 import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 
 import java.io.PrintWriter;
 import java.util.HashMap;
@@ -65,7 +66,7 @@
  */
 public class TaskbarLauncherStateController {
 
-    private static final String TAG = TaskbarLauncherStateController.class.getSimpleName();
+    private static final String TAG = "TaskbarLauncherStateController";
     private static final boolean DEBUG = false;
 
     /** Launcher activity is visible and focused. */
@@ -226,7 +227,7 @@
 
     /** Initializes the controller instance, and applies the initial state immediately. */
     public void init(TaskbarControllers controllers, QuickstepLauncher launcher,
-            int sysuiStateFlags) {
+            @SystemUiStateFlags long sysuiStateFlags) {
         mCanSyncViews = false;
 
         mControllers = controllers;
@@ -325,11 +326,12 @@
     }
 
     /** SysUI flags updated, see QuickStepContract.SYSUI_STATE_* values. */
-    public void updateStateForSysuiFlags(int systemUiStateFlags) {
+    public void updateStateForSysuiFlags(@SystemUiStateFlags long systemUiStateFlags) {
         updateStateForSysuiFlags(systemUiStateFlags, /* applyState */ true);
     }
 
-    private void updateStateForSysuiFlags(int systemUiStateFlags, boolean applyState) {
+    private void updateStateForSysuiFlags(@SystemUiStateFlags long systemUiStateFlags,
+            boolean applyState) {
         final boolean prevIsAwake = hasAnyFlag(FLAG_AWAKE);
         final boolean currIsAwake = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_AWAKE);
 
@@ -389,11 +391,11 @@
         }
     }
 
-    private boolean hasAnyFlag(int flagMask) {
+    private boolean hasAnyFlag(long flagMask) {
         return hasAnyFlag(mState, flagMask);
     }
 
-    private boolean hasAnyFlag(int flags, int flagMask) {
+    private boolean hasAnyFlag(long flags, long flagMask) {
         return (flags & flagMask) != 0;
     }
 
@@ -667,7 +669,7 @@
     }
 
     boolean isInOverviewUi() {
-        return mLauncherState.overviewUi;
+        return mLauncherState.isRecentsViewVisible;
     }
 
     private void playStateTransitionAnim(AnimatorSet animatorSet, long duration,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 3196bfb..ec2cee2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -16,7 +16,6 @@
 package com.android.launcher3.taskbar;
 
 import static android.content.Context.RECEIVER_NOT_EXPORTED;
-import static android.content.pm.PackageManager.FEATURE_PC;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
@@ -26,6 +25,7 @@
 import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
 import static com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate;
 import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
+import static com.android.launcher3.util.DisplayController.CHANGE_DESKTOP_MODE;
 import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
 import static com.android.launcher3.util.DisplayController.CHANGE_TASKBAR_PINNING;
 import static com.android.launcher3.util.DisplayController.TASKBAR_NOT_DESTROYED_TAG;
@@ -73,6 +73,7 @@
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.AssistUtils;
 import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
 
@@ -143,7 +144,7 @@
     private class RecreationListener implements DisplayController.DisplayInfoChangeListener {
         @Override
         public void onDisplayInfoChanged(Context context, DisplayController.Info info, int flags) {
-            if ((flags & (CHANGE_DENSITY | CHANGE_NAVIGATION_MODE
+            if ((flags & (CHANGE_DENSITY | CHANGE_NAVIGATION_MODE | CHANGE_DESKTOP_MODE
                     | CHANGE_TASKBAR_PINNING)) != 0) {
                 recreateTaskbar();
             }
@@ -426,9 +427,6 @@
      */
     private TaskbarUIController createTaskbarUIControllerForActivity(StatefulActivity activity) {
         if (activity instanceof QuickstepLauncher) {
-            if (mTaskbarActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
-                return new DesktopTaskbarUIController((QuickstepLauncher) activity);
-            }
             return new LauncherTaskbarUIController((QuickstepLauncher) activity);
         }
         if (activity instanceof RecentsActivity) {
@@ -494,7 +492,7 @@
         }
     }
 
-    public void onSystemUiFlagsChanged(int systemUiStateFlags) {
+    public void onSystemUiFlagsChanged(@SystemUiStateFlags long systemUiStateFlags) {
         if (DEBUG) {
             Log.d(TAG, "SysUI flags changed: " + formatFlagChange(systemUiStateFlags,
                     mSharedState.sysuiStateFlags, QuickStepContract::getSystemUiStateString));
@@ -521,7 +519,7 @@
         }
     }
 
-    private static boolean isTaskbarEnabled(DeviceProfile deviceProfile) {
+    private boolean isTaskbarEnabled(DeviceProfile deviceProfile) {
         return ENABLE_TASKBAR_NAVBAR_UNIFICATION || deviceProfile.isTaskbarPresent;
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
index be87cfd..35e1c7b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
@@ -68,7 +68,7 @@
     // Used to defer any UI updates during the SUW unstash animation.
     private boolean mDeferUpdatesForSUW;
     private Runnable mDeferredUpdates;
-    private DesktopVisibilityController.DesktopVisibilityListener mDesktopVisibilityListener =
+    private final DesktopVisibilityController.DesktopVisibilityListener mDesktopVisibilityListener =
             visible -> updateRunningApps();
 
     public TaskbarModelCallbacks(
@@ -235,20 +235,23 @@
         hotseatItemInfos = mControllers.taskbarRecentAppsController
                 .updateHotseatItemInfos(hotseatItemInfos);
         Set<String> runningPackages = mControllers.taskbarRecentAppsController.getRunningApps();
+        Set<String> minimizedPackages = mControllers.taskbarRecentAppsController.getMinimizedApps();
 
         if (mDeferUpdatesForSUW) {
             ItemInfo[] finalHotseatItemInfos = hotseatItemInfos;
             mDeferredUpdates = () ->
-                    commitHotseatItemUpdates(finalHotseatItemInfos, runningPackages);
+                    commitHotseatItemUpdates(finalHotseatItemInfos, runningPackages,
+                            minimizedPackages);
         } else {
-            commitHotseatItemUpdates(hotseatItemInfos, runningPackages);
+            commitHotseatItemUpdates(hotseatItemInfos, runningPackages, minimizedPackages);
         }
     }
 
-    private void commitHotseatItemUpdates(
-            ItemInfo[] hotseatItemInfos, Set<String> runningPackages) {
+    private void commitHotseatItemUpdates(ItemInfo[] hotseatItemInfos, Set<String> runningPackages,
+            Set<String> minimizedPackages) {
         mContainer.updateHotseatItems(hotseatItemInfos);
-        mControllers.taskbarViewController.updateIconViewsRunningStates(runningPackages);
+        mControllers.taskbarViewController.updateIconViewsRunningStates(runningPackages,
+                minimizedPackages);
     }
 
     /**
@@ -279,7 +282,7 @@
 
     /** Call TaskbarRecentAppsController to update running apps with mHotseatItems. */
     public void updateRunningApps() {
-        mControllers.taskbarRecentAppsController.updateRunningApps(mHotseatItems);
+        mControllers.taskbarRecentAppsController.updateRunningApps();
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index ade4649..d26a36d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -44,13 +44,12 @@
 
 import com.android.launcher3.R;
 import com.android.launcher3.logging.StatsLogManager;
-import com.android.launcher3.statehandlers.DesktopVisibilityController;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.quickstep.LauncherActivityInterface;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TaskUtils;
 import com.android.quickstep.util.AssistUtils;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -66,7 +65,7 @@
     /** Allow some time in between the long press for back and recents. */
     static final int SCREEN_PIN_LONG_PRESS_THRESHOLD = 200;
     static final int SCREEN_PIN_LONG_PRESS_RESET = SCREEN_PIN_LONG_PRESS_THRESHOLD + 100;
-    private static final String TAG = TaskbarNavButtonController.class.getSimpleName();
+    private static final String TAG = "TaskbarNavButtonController";
 
     private long mLastScreenPinLongPress;
     private boolean mScreenPinned;
@@ -258,7 +257,7 @@
         mLastScreenPinLongPress = 0;
     }
 
-    public void updateSysuiFlags(int sysuiFlags) {
+    public void updateSysuiFlags(@SystemUiStateFlags long sysuiFlags) {
         mScreenPinned = (sysuiFlags & SYSUI_STATE_SCREEN_PINNING) != 0;
     }
 
@@ -284,13 +283,6 @@
 
     private void navigateHome() {
         TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY);
-
-        DesktopVisibilityController desktopVisibilityController =
-                LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
-        if (desktopVisibilityController != null) {
-            desktopVisibilityController.onHomeActionTriggered();
-        }
-
         mCallbacks.onNavigateHome();
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt
index 2f2d636..6c9cc64 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt
@@ -23,6 +23,7 @@
 import com.android.app.animation.Interpolators
 import com.android.launcher3.LauncherPrefs
 import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING
+import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING_IN_DESKTOP_MODE
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_CLOSE
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_OPEN
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_PINNED
@@ -31,8 +32,10 @@
 import java.io.PrintWriter
 
 /** Controls taskbar pinning through a popup view. */
-class TaskbarPinningController(private val context: TaskbarActivityContext) :
-    TaskbarControllers.LoggableTaskbarController {
+class TaskbarPinningController(
+    private val context: TaskbarActivityContext,
+    private val isInDesktopModeProvider: () -> Boolean,
+) : TaskbarControllers.LoggableTaskbarController {
 
     private lateinit var controllers: TaskbarControllers
     private lateinit var taskbarSharedState: TaskbarSharedState
@@ -54,14 +57,22 @@
                 if (!didPreferenceChange) {
                     return
                 }
+                val shouldPinTaskbar =
+                    if (isInDesktopModeProvider()) {
+                        !launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)
+                    } else {
+                        !launcherPrefs.get(TASKBAR_PINNING)
+                    }
+
                 val animateToValue =
-                    if (!launcherPrefs.get(TASKBAR_PINNING)) {
+                    if (shouldPinTaskbar) {
                         statsLogManager.logger().log(LAUNCHER_TASKBAR_PINNED)
                         PINNING_PERSISTENT
                     } else {
                         statsLogManager.logger().log(LAUNCHER_TASKBAR_UNPINNED)
                         PINNING_TRANSIENT
                     }
+
                 taskbarSharedState.taskbarWasPinned = animateToValue == PINNING_TRANSIENT
                 animateTaskbarPinning(animateToValue)
             }
@@ -123,13 +134,24 @@
     @VisibleForTesting
     fun recreateTaskbarAndUpdatePinningValue() {
         updateIsAnimatingTaskbarPinningAndNotifyTaskbarDragLayer(false)
-        launcherPrefs.put(TASKBAR_PINNING, !launcherPrefs.get(TASKBAR_PINNING))
+        if (isInDesktopModeProvider()) {
+            launcherPrefs.put(
+                TASKBAR_PINNING_IN_DESKTOP_MODE,
+                !launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)
+            )
+        } else {
+            launcherPrefs.put(TASKBAR_PINNING, !launcherPrefs.get(TASKBAR_PINNING))
+        }
     }
 
     override fun dumpLogs(prefix: String, pw: PrintWriter) {
         pw.println(prefix + "TaskbarPinningController:")
         pw.println("$prefix\tisAnimatingTaskbarPinning=$isAnimatingTaskbarPinning")
         pw.println("$prefix\tTASKBAR_PINNING shared pref =" + launcherPrefs.get(TASKBAR_PINNING))
+        pw.println(
+            "$prefix\tTASKBAR_PINNING_IN_DESKTOP_MODE shared pref in desktop mode =" +
+                launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)
+        )
     }
 
     companion object {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java
index 9b84f1b..606ba5b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java
@@ -17,9 +17,8 @@
 
 import static java.util.Collections.emptySet;
 
-import android.util.SparseArray;
-
 import androidx.annotation.CallSuper;
+import androidx.annotation.NonNull;
 
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
@@ -59,16 +58,20 @@
     }
 
     /** Called to update hotseatItems, no-op except in desktop environment. */
-    protected ItemInfo[] updateHotseatItemInfos(ItemInfo[] hotseatItems) {
+    protected ItemInfo[] updateHotseatItemInfos(@NonNull ItemInfo[] hotseatItems) {
         return hotseatItems;
     }
 
     /** Called to update the list of currently running apps, no-op except in desktop environment. */
-    protected void updateRunningApps(SparseArray<ItemInfo> hotseatItems) {
-    }
+    protected void updateRunningApps() {}
 
     /** Returns the currently running apps, or an empty Set if outside of Desktop environment. */
     public Set<String> getRunningApps() {
         return emptySet();
     }
+
+    /** Returns the set of apps whose tasks are all minimized. */
+    public Set<String> getMinimizedApps() {
+        return emptySet();
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
index 712374d..92d9b23 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -30,6 +30,7 @@
 import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.util.DisplayController;
 import com.android.quickstep.SystemUiProxy;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 
 import java.io.PrintWriter;
 
@@ -45,7 +46,8 @@
     private final TaskbarActivityContext mActivity;
     private final TaskbarScrimView mScrimView;
     private boolean mTaskbarVisible;
-    private int mSysUiStateFlags;
+    @SystemUiStateFlags
+    private long mSysUiStateFlags;
 
     // Alpha property for the scrim.
     private final AnimatedFloat mScrimAlpha = new AnimatedFloat(this::updateScrimAlpha);
@@ -82,7 +84,7 @@
     /**
      * Updates the scrim state based on the flags.
      */
-    public void updateStateForSysuiFlags(int stateFlags, boolean skipAnim) {
+    public void updateStateForSysuiFlags(@SystemUiStateFlags long stateFlags, boolean skipAnim) {
         if (isBubbleBarEnabled() && DisplayController.isTransientTaskbar(mActivity)) {
             // These scrims aren't used if bubble bar & transient taskbar are active.
             return;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
index e2c71bf..edaeb63 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
@@ -29,6 +29,8 @@
 import android.os.IBinder;
 import android.view.InsetsFrameProvider;
 
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
+
 /**
  * State shared across different taskbar instance
  */
@@ -39,7 +41,8 @@
     private static int INDEX_RIGHT = 1;
 
     // TaskbarManager#onSystemUiFlagsChanged
-    public int sysuiStateFlags;
+    @SystemUiStateFlags
+    public long sysuiStateFlags;
 
     // TaskbarManager#disableNavBarElements()
     public int disableNavBarDisplayId;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 2162a73..74d2d60 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -71,14 +71,14 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.StringJoiner;
-import java.util.function.IntPredicate;
+import java.util.function.LongPredicate;
 
 /**
  * Coordinates between controllers such as TaskbarViewController and StashedHandleViewController to
  * create a cohesive animation between stashed/unstashed states.
  */
 public class TaskbarStashController implements TaskbarControllers.LoggableTaskbarController {
-    private static final String TAG = TaskbarStashController.class.getSimpleName();
+    private static final String TAG = "TaskbarStashController";
     private static final boolean DEBUG = false;
 
     public static final int FLAG_IN_APP = 1 << 0;
@@ -229,7 +229,7 @@
 
     /** Whether we are currently visually stashed (might change based on launcher state). */
     private boolean mIsStashed = false;
-    private int mState;
+    private long mState;
 
     private @Nullable AnimatorSet mAnimator;
     private boolean mIsSystemGestureInProgress;
@@ -240,7 +240,7 @@
     private boolean mEnableBlockingTimeoutDuringTests = false;
 
     // Evaluate whether the handle should be stashed
-    private final IntPredicate mIsStashedPredicate = flags -> {
+    private final LongPredicate mIsStashedPredicate = flags -> {
         boolean inApp = hasAnyFlag(flags, FLAGS_IN_APP);
         boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP);
         boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE);
@@ -319,8 +319,7 @@
         updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, isStashedInAppAuto);
         updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup);
         updateStateForFlag(FLAG_IN_SETUP, isInSetup);
-        updateStateForFlag(FLAG_STASHED_SMALL_SCREEN, mActivity.isPhoneMode()
-                && !mActivity.isThreeButtonNav());
+        updateStateForFlag(FLAG_STASHED_SMALL_SCREEN, mActivity.isPhoneGestureNavMode());
         // For now, assume we're in an app, since LauncherTaskbarUIController won't be able to tell
         // us that we're paused until a bit later. This avoids flickering upon recreating taskbar.
         updateStateForFlag(FLAG_IN_APP, true);
@@ -389,11 +388,11 @@
         return (hasAnyFlag(FLAG_IN_STASHED_LAUNCHER_STATE) && supportsVisualStashing());
     }
 
-    private boolean hasAnyFlag(int flagMask) {
+    private boolean hasAnyFlag(long flagMask) {
         return hasAnyFlag(mState, flagMask);
     }
 
-    private boolean hasAnyFlag(int flags, int flagMask) {
+    private boolean hasAnyFlag(long flags, long flagMask) {
         return (flags & flagMask) != 0;
     }
 
@@ -425,14 +424,15 @@
      * @see android.view.WindowInsets.Type#systemBars()
      */
     public int getContentHeightToReportToApps() {
-        if ((mActivity.isPhoneMode() && !mActivity.isThreeButtonNav())
-                || DisplayController.isTransientTaskbar(mActivity)) {
+        if (mActivity.isUserSetupComplete() && (mActivity.isPhoneGestureNavMode()
+                || DisplayController.isTransientTaskbar(mActivity))) {
             return getStashedHeight();
         }
 
         if (supportsVisualStashing() && hasAnyFlag(FLAGS_REPORT_STASHED_INSETS_TO_APP)) {
             DeviceProfile dp = mActivity.getDeviceProfile();
-            if (hasAnyFlag(FLAG_STASHED_IN_APP_SETUP) && dp.isTaskbarPresent) {
+            if (hasAnyFlag(FLAG_STASHED_IN_APP_SETUP) && (dp.isTaskbarPresent
+                    || mActivity.isPhoneGestureNavMode())) {
                 // We always show the back button in SUW but in portrait the SUW layout may not
                 // be wide enough to support overlapping the nav bar with its content.
                 // We're sending different res values in portrait vs landscape
@@ -547,11 +547,12 @@
      *                            sub-animations are properly coordinated. This duration should not
      *                            actually be used since this animation tracks a swipe progress.
      */
-    protected void addUnstashToHotseatAnimation(AnimatorSet animation, int placeholderDuration) {
+    protected void addUnstashToHotseatAnimationFromSuw(AnimatorSet animation,
+            int placeholderDuration) {
         // Defer any UI updates now to avoid the UI becoming stale when the animation plays.
         mControllers.taskbarViewController.setDeferUpdatesForSUW(true);
         createAnimToIsStashed(
-                /* isStashed= */ false,
+                /* isStashed= */ mActivity.isPhoneMode(),
                 placeholderDuration,
                 TRANSITION_UNSTASH_SUW_MANUAL,
                 /* jankTag= */ "SUW_MANUAL");
@@ -929,7 +930,7 @@
     }
 
     /** Called when some system ui state has changed. (See SYSUI_STATE_... in QuickstepContract) */
-    public void updateStateForSysuiFlags(int systemUiStateFlags, boolean skipAnim) {
+    public void updateStateForSysuiFlags(long systemUiStateFlags, boolean skipAnim) {
         long animDuration = TASKBAR_STASH_DURATION;
         long startDelay = 0;
 
@@ -1005,8 +1006,8 @@
      *                unstashed.
      * @return Whether the flag state changed.
      */
-    public boolean updateStateForFlag(int flag, boolean enabled) {
-        int oldState = mState;
+    public boolean updateStateForFlag(long flag, boolean enabled) {
+        long oldState = mState;
         if (enabled) {
             mState |= flag;
         } else {
@@ -1020,7 +1021,7 @@
      *
      * @param changedFlags The flags that have changed.
      */
-    private void onStateChangeApplied(int changedFlags) {
+    private void onStateChangeApplied(long changedFlags) {
         if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP)) {
             mControllers.uiController.onStashedInAppChanged();
         }
@@ -1151,7 +1152,7 @@
         pw.println(prefix + "\tmIsImeSwitcherShowing=" + mIsImeSwitcherShowing);
     }
 
-    private static String getStateString(int flags) {
+    private static String getStateString(long flags) {
         StringJoiner sj = new StringJoiner("|");
         appendFlag(sj, flags, FLAGS_IN_APP, "FLAG_IN_APP");
         appendFlag(sj, flags, FLAG_STASHED_IN_APP_SYSUI, "FLAG_STASHED_IN_APP_SYSUI");
@@ -1168,15 +1169,15 @@
     }
 
     private class StatePropertyHolder {
-        private final IntPredicate mStashCondition;
+        private final LongPredicate mStashCondition;
 
         private boolean mIsStashed;
         private @StashAnimation int mLastStartedTransitionType = TRANSITION_DEFAULT;
-        private int mPrevFlags;
+        private long mPrevFlags;
 
         private long mLastUnlockTransitionTimeout = 0;
 
-        StatePropertyHolder(IntPredicate stashCondition) {
+        StatePropertyHolder(LongPredicate stashCondition) {
             mStashCondition = stashCondition;
         }
 
@@ -1189,7 +1190,7 @@
          * @return mAnimator if mIsStashed changed, or {@code null} otherwise.
          */
         @Nullable
-        public Animator createSetStateAnimator(int flags, long duration) {
+        public Animator createSetStateAnimator(long flags, long duration) {
             boolean isStashed = mStashCondition.test(flags);
 
             if (DEBUG) {
@@ -1201,7 +1202,7 @@
                         + ", mIsStashed: " + mIsStashed);
             }
 
-            int changedFlags = mPrevFlags ^ flags;
+            long changedFlags = mPrevFlags ^ flags;
             if (mPrevFlags != flags) {
                 onStateChangeApplied(changedFlags);
                 mPrevFlags = flags;
@@ -1248,7 +1249,7 @@
         }
 
         /** Calculates the tag for CUJ_TASKBAR_EXPAND and CUJ_TASKBAR_COLLAPSE jank traces. */
-        private String computeTaskbarJankMonitorTag(int changedFlags) {
+        private String computeTaskbarJankMonitorTag(long changedFlags) {
             if (hasAnyFlag(changedFlags, FLAG_IN_APP)) {
                 // moving in or out of the app
                 if (hasAnyFlag(FLAG_IN_APP)) {
@@ -1268,7 +1269,7 @@
             return "";
         }
 
-        private @StashAnimation int computeTransitionType(int changedFlags) {
+        private @StashAnimation int computeTransitionType(long changedFlags) {
 
             boolean hotseatHiddenDuringAppLaunch =
                     !mControllers.uiController.isHotseatIconOnTopWhenAligned()
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 2e78489..2b68b52 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -44,8 +44,9 @@
 import com.android.quickstep.util.TISBindHelper;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
-import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
+import com.android.quickstep.views.TaskView.TaskContainer;
 import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 
 import java.io.PrintWriter;
 import java.util.Collections;
@@ -55,7 +56,6 @@
  * Base class for providing different taskbar UI
  */
 public class TaskbarUIController {
-
     public static final TaskbarUIController DEFAULT = new TaskbarUIController();
 
     // Initialized in init.
@@ -91,6 +91,10 @@
      */
     protected void onIconLayoutBoundsChanged() { }
 
+    protected String getTaskbarUIControllerName() {
+        return "TaskbarUIController";
+    }
+
     /** Called when an icon is launched. */
     @CallSuper
     public void onTaskbarIconLaunched(ItemInfo item) {
@@ -137,7 +141,7 @@
     /**
      * SysUI flags updated, see QuickStepContract.SYSUI_STATE_* values.
      */
-    public void updateStateForSysuiFlags(int sysuiFlags) {
+    public void updateStateForSysuiFlags(@SystemUiStateFlags long sysuiFlags) {
     }
 
     /**
@@ -207,7 +211,7 @@
         pw.println(String.format(
                 "%sTaskbarUIController: using an instance of %s",
                 prefix,
-                getClass().getSimpleName()));
+                getTaskbarUIControllerName()));
     }
 
     /**
@@ -259,14 +263,14 @@
                         if (foundTaskView != null) {
                             // There is already a running app of this type, use that as second app.
                             // Get index of task (0 or 1), in case it's a GroupedTaskView
-                            TaskIdAttributeContainer taskAttributes =
-                                    foundTaskView.getTaskAttributesById(foundTask.key.id);
+                            TaskContainer taskContainer =
+                                    foundTaskView.getTaskContainerById(foundTask.key.id);
                             recents.confirmSplitSelect(
                                     foundTaskView,
                                     foundTask,
-                                    taskAttributes.getIconView().getDrawable(),
-                                    taskAttributes.getThumbnailView(),
-                                    taskAttributes.getThumbnailView().getThumbnail(),
+                                    taskContainer.getIconView().getDrawable(),
+                                    taskContainer.getThumbnailViewDeprecated(),
+                                    taskContainer.getThumbnailViewDeprecated().getThumbnail(),
                                     null /* intent */,
                                     null /* user */,
                                     info);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index effef3c..570221c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -15,7 +15,6 @@
  */
 package com.android.launcher3.taskbar;
 
-import static android.content.pm.PackageManager.FEATURE_PC;
 import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
 
 import static com.android.launcher3.BubbleTextView.DISPLAY_TASKBAR;
@@ -25,6 +24,7 @@
 import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR;
 import static com.android.launcher3.config.FeatureFlags.enableTaskbarPinning;
 import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -37,6 +37,7 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
 
@@ -64,6 +65,8 @@
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.views.IconButtonView;
+import com.android.quickstep.DeviceConfigWrapper;
+import com.android.quickstep.util.AssistStateManager;
 
 import java.util.function.Predicate;
 
@@ -72,8 +75,6 @@
  */
 public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconParent, Insettable,
         DeviceProfile.OnDeviceProfileChangeListener {
-    private static final String TAG = TaskbarView.class.getSimpleName();
-
     private static final Rect sTmpRect = new Rect();
 
     private final int[] mTempOutLocation = new int[2];
@@ -96,6 +97,9 @@
 
     // Only non-null when device supports having an All Apps button.
     private @Nullable IconButtonView mAllAppsButton;
+    private Runnable mAllAppsTouchRunnable;
+    private long mAllAppsButtonTouchDelayMs;
+    private boolean mAllAppsTouchTriggered;
 
     // Only non-null when device supports having an All Apps button.
     private @Nullable IconButtonView mTaskbarDivider;
@@ -130,7 +134,6 @@
         mIsRtl = Utilities.isRtl(resources);
         mTransientTaskbarMinWidth = resources.getDimension(R.dimen.transient_taskbar_min_width);
 
-
         onDeviceProfileChanged(mActivityContext.getDeviceProfile());
 
         int actualMargin = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
@@ -157,27 +160,28 @@
         // Needed to draw folder leave-behind when opening one.
         setWillNotDraw(false);
 
-        if (!mActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
-            mAllAppsButton = (IconButtonView) LayoutInflater.from(context)
-                    .inflate(R.layout.taskbar_all_apps_button, this, false);
-            mAllAppsButton.setIconDrawable(resources.getDrawable(
-                    getAllAppsButton(isTransientTaskbar)));
-            mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
-            mAllAppsButton.setForegroundTint(
-                    mActivityContext.getColor(R.color.all_apps_button_color));
+        mAllAppsButton = (IconButtonView) LayoutInflater.from(context)
+                .inflate(R.layout.taskbar_all_apps_button, this, false);
+        mAllAppsButton.setIconDrawable(resources.getDrawable(
+                getAllAppsButton(isTransientTaskbar)));
+        mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
+        mAllAppsButton.setForegroundTint(
+                mActivityContext.getColor(R.color.all_apps_button_color));
 
-            if (enableTaskbarPinning()) {
-                mTaskbarDivider = (IconButtonView) LayoutInflater.from(context).inflate(
-                        R.layout.taskbar_divider,
-                        this, false);
-                mTaskbarDivider.setIconDrawable(
-                        resources.getDrawable(R.drawable.taskbar_divider_button));
-                mTaskbarDivider.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
-            }
+        if (enableTaskbarPinning()) {
+            mTaskbarDivider = (IconButtonView) LayoutInflater.from(context).inflate(
+                    R.layout.taskbar_divider,
+                    this, false);
+            mTaskbarDivider.setIconDrawable(
+                    resources.getDrawable(R.drawable.taskbar_divider_button));
+            mTaskbarDivider.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
         }
 
         // TODO: Disable touch events on QSB otherwise it can crash.
         mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false);
+
+        // Default long press (touch) delay = 400ms
+        mAllAppsButtonTouchDelayMs = ViewConfiguration.getLongPressTimeout();
     }
 
     @DrawableRes
@@ -268,11 +272,20 @@
         mIconLongClickListener = mControllerCallbacks.getIconOnLongClickListener();
 
         if (mAllAppsButton != null) {
-            mAllAppsButton.setOnClickListener(mControllerCallbacks.getAllAppsButtonClickListener());
-            mAllAppsButton.setOnLongClickListener(
-                    mControllerCallbacks.getAllAppsButtonLongClickListener());
+            mAllAppsButton.setOnClickListener(this::onAllAppsButtonClick);
+            mAllAppsButton.setOnLongClickListener(this::onAllAppsButtonLongClick);
+            mAllAppsButton.setOnTouchListener(this::onAllAppsButtonTouch);
             mAllAppsButton.setHapticFeedbackEnabled(
                     mControllerCallbacks.isAllAppsButtonHapticFeedbackEnabled());
+            mAllAppsTouchRunnable = () -> {
+                mControllerCallbacks.triggerAllAppsButtonLongClick();
+                mAllAppsTouchTriggered = true;
+            };
+            AssistStateManager assistStateManager = AssistStateManager.INSTANCE.get(mContext);
+            if (DeviceConfigWrapper.get().getCustomLpaaThresholds()
+                    && assistStateManager.getLPNHDurationMillis().isPresent()) {
+                mAllAppsButtonTouchDelayMs = assistStateManager.getLPNHDurationMillis().get();
+            }
         }
         if (mTaskbarDivider != null && !mActivityContext.isThreeButtonNav()) {
             mTaskbarDivider.setOnLongClickListener(
@@ -308,7 +321,6 @@
         }
         removeView(mQsb);
 
-
         for (int i = 0; i < hotseatItemInfos.length; i++) {
             ItemInfo hotseatItemInfo = hotseatItemInfos[i];
             if (hotseatItemInfo == null) {
@@ -692,4 +704,46 @@
         }
         return mAllAppsButton;
     }
+
+    private boolean onAllAppsButtonTouch(View view, MotionEvent ev) {
+        switch (ev.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                mAllAppsTouchTriggered = false;
+                MAIN_EXECUTOR.getHandler().postDelayed(
+                        mAllAppsTouchRunnable, mAllAppsButtonTouchDelayMs);
+                break;
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                cancelAllAppsButtonTouch();
+        }
+        return false;
+    }
+
+    private void cancelAllAppsButtonTouch() {
+        MAIN_EXECUTOR.getHandler().removeCallbacks(mAllAppsTouchRunnable);
+        // ACTION_UP is first triggered, then click listener / long-click listener is triggered on
+        // the next frame, so we need to post twice and delay the reset.
+        if (mAllAppsButton != null) {
+            mAllAppsButton.post(() -> {
+                mAllAppsButton.post(() -> {
+                    mAllAppsTouchTriggered = false;
+                });
+            });
+        }
+    }
+
+    private void onAllAppsButtonClick(View view) {
+        if (!mAllAppsTouchTriggered) {
+            mControllerCallbacks.triggerAllAppsButtonClick(view);
+        }
+    }
+
+    // Handle long click from Switch Access and Voice Access
+    private boolean onAllAppsButtonLongClick(View view) {
+        if (!MAIN_EXECUTOR.getHandler().hasCallbacks(mAllAppsTouchRunnable)
+                && !mAllAppsTouchTriggered) {
+            mControllerCallbacks.triggerAllAppsButtonLongClick();
+        }
+        return true;
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
index c841cac..3c646cb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
@@ -46,20 +46,17 @@
         return mActivity.getItemOnClickListener();
     }
 
-    public View.OnClickListener getAllAppsButtonClickListener() {
-        return v -> {
-            InteractionJankMonitorWrapper.begin(v, Cuj.CUJ_LAUNCHER_OPEN_ALL_APPS,
-                    /* tag= */ "TASKBAR_BUTTON");
-            mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP);
-            mControllers.taskbarAllAppsController.toggle();
-        };
+    /** Trigger All Apps button click action. */
+    protected void triggerAllAppsButtonClick(View v) {
+        InteractionJankMonitorWrapper.begin(v, Cuj.CUJ_LAUNCHER_OPEN_ALL_APPS,
+                /* tag= */ "TASKBAR_BUTTON");
+        mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP);
+        mControllers.taskbarAllAppsController.toggle();
     }
 
-    public View.OnLongClickListener getAllAppsButtonLongClickListener() {
-        return v -> {
-            mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_LONG_PRESS);
-            return true;
-        };
+    /** Trigger All Apps button long click action. */
+    protected void triggerAllAppsButtonLongClick() {
+        mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_LONG_PRESS);
     }
 
     public boolean isAllAppsButtonHapticFeedbackEnabled() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index e0b446e..23495ad 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -17,6 +17,7 @@
 
 import static com.android.app.animation.Interpolators.FINAL_FRAME;
 import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
@@ -79,7 +80,7 @@
  */
 public class TaskbarViewController implements TaskbarControllers.LoggableTaskbarController {
 
-    private static final String TAG = TaskbarViewController.class.getSimpleName();
+    private static final String TAG = "TaskbarViewController";
 
     private static final Runnable NO_OP = () -> { };
 
@@ -509,14 +510,30 @@
     }
 
     /** Updates which icons are marked as running given the Set of currently running packages. */
-    public void updateIconViewsRunningStates(Set<String> runningPackages) {
+    public void updateIconViewsRunningStates(Set<String> runningPackages,
+            Set<String> minimizedPackages) {
         for (View iconView : getIconViews()) {
             if (iconView instanceof BubbleTextView btv) {
-                btv.updateRunningState(runningPackages.contains(btv.getTargetPackageName()));
+                btv.updateRunningState(
+                        getRunningAppState(btv.getTargetPackageName(), runningPackages,
+                                minimizedPackages));
             }
         }
     }
 
+    private BubbleTextView.RunningAppState getRunningAppState(
+            String packageName,
+            Set<String> runningPackages,
+            Set<String> minimizedPackages) {
+        if (minimizedPackages.contains(packageName)) {
+            return BubbleTextView.RunningAppState.MINIMIZED;
+        }
+        if (runningPackages.contains(packageName)) {
+            return BubbleTextView.RunningAppState.RUNNING;
+        }
+        return BubbleTextView.RunningAppState.NOT_RUNNING;
+    }
+
     /**
      * Defers any updates to the UI for the setup wizard animation.
      */
@@ -689,6 +706,12 @@
                         && mIsStashed) {
                     // Prevent All Apps icon from appearing when going from hotseat to nav handle.
                     setter.setViewAlpha(child, 0, Interpolators.clampToProgress(LINEAR, 0f, 0f));
+                } else if (enableScalingRevealHomeAnimation()) {
+                    // Tighten clamp so that these icons do not linger as the spring settles.
+                    setter.setViewAlpha(child, 0,
+                            isToHome
+                                    ? Interpolators.clampToProgress(LINEAR, 0f, 0.07f)
+                                    : Interpolators.clampToProgress(LINEAR, 0.93f, 1f));
                 } else {
                     setter.setViewAlpha(child, 0,
                             isToHome
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index 8e05686..90ac872 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -17,6 +17,8 @@
 
 import static com.android.app.animation.Interpolators.EMPHASIZED;
 import static com.android.launcher3.Flags.enablePredictiveBackGesture;
+import static com.android.launcher3.touch.AllAppsSwipeController.ALL_APPS_FADE_MANUAL;
+import static com.android.launcher3.touch.AllAppsSwipeController.SCRIM_FADE_MANUAL;
 
 import android.animation.Animator;
 import android.content.Context;
@@ -32,6 +34,7 @@
 
 import androidx.annotation.Nullable;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
@@ -40,6 +43,7 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.taskbar.allapps.TaskbarAllAppsViewController.TaskbarAllAppsCallbacks;
 import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
+import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.AbstractSlideInView;
 
 /** Wrapper for taskbar all apps with slide-in behavior. */
@@ -113,8 +117,25 @@
 
     @Override
     protected void onOpenCloseAnimationPending(PendingAnimation animation) {
-        mAllAppsCallbacks.onAllAppsAnimationPending(
-                animation, mToTranslationShift == TRANSLATION_SHIFT_OPENED);
+        final boolean isOpening = mToTranslationShift == TRANSLATION_SHIFT_OPENED;
+
+        if (mActivityContext.getDeviceProfile().isPhone) {
+            final Interpolator allAppsFadeInterpolator =
+                    isOpening ? ALL_APPS_FADE_MANUAL : Interpolators.reverse(ALL_APPS_FADE_MANUAL);
+            animation.setViewAlpha(mAppsView, 1 - mToTranslationShift, allAppsFadeInterpolator);
+        }
+
+        mAllAppsCallbacks.onAllAppsAnimationPending(animation, isOpening);
+    }
+
+    @Override
+    protected Interpolator getScrimInterpolator() {
+        if (mActivityContext.getDeviceProfile().isTablet) {
+            return super.getScrimInterpolator();
+        }
+        return mToTranslationShift == TRANSLATION_SHIFT_OPENED
+                ? SCRIM_FADE_MANUAL
+                : Interpolators.reverse(SCRIM_FADE_MANUAL);
     }
 
     /** The apps container inside this view. */
@@ -154,6 +175,9 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mAppsView = findViewById(R.id.apps_view);
+        if (mActivityContext.getDeviceProfile().isPhone) {
+            mAppsView.setAlpha(0);
+        }
         mContent = mAppsView;
 
         // Setup header protection for search bar, if enabled.
@@ -214,7 +238,9 @@
 
     @Override
     protected int getScrimColor(Context context) {
-        return context.getColor(R.color.widgets_picker_scrim);
+        return mActivityContext.getDeviceProfile().isPhone
+                ? Themes.getAttrColor(context, R.attr.allAppsScrimColor)
+                : context.getColor(R.color.widgets_picker_scrim);
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
index ec47c4f..a59e81b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
@@ -131,21 +131,15 @@
 
         // Draw background.
         val radius = backgroundHeight / 2f
-        val left = if (anchorLeft) 0f else bounds.width().toFloat() - width
-        val right = if (anchorLeft) width else bounds.width().toFloat()
-        canvas.drawRoundRect(
-            left,
-            pointerVisibleHeight,
-            right,
-            bounds.height().toFloat(),
-            radius,
-            radius,
-            paint
-        )
+        val left = bounds.left + (if (anchorLeft) 0f else bounds.width().toFloat() - width)
+        val right = bounds.left + (if (anchorLeft) width else bounds.width().toFloat())
+        val top = bounds.top + pointerVisibleHeight
+        val bottom = bounds.top + bounds.height().toFloat()
+        canvas.drawRoundRect(left, top, right, bottom, radius, radius, paint)
 
         if (showingArrow) {
             // Draw arrow.
-            val transX = arrowPositionX - pointerWidth / 2f
+            val transX = bounds.left + arrowPositionX - pointerWidth / 2f
             canvas.translate(transX, 0f)
             arrowDrawable.draw(canvas)
         }
@@ -164,6 +158,7 @@
     override fun setAlpha(alpha: Int) {
         paint.alpha = alpha
         arrowDrawable.alpha = alpha
+        invalidateSelf()
     }
 
     override fun getAlpha(): Int {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index 981c9f9..046f5b6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -31,8 +31,6 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
 
-import static java.lang.Math.abs;
-
 import android.annotation.BinderThread;
 import android.annotation.Nullable;
 import android.app.Notification;
@@ -47,7 +45,6 @@
 import android.graphics.Matrix;
 import android.graphics.Path;
 import android.graphics.Point;
-import android.graphics.Rect;
 import android.graphics.drawable.AdaptiveIconDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -67,10 +64,9 @@
 import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.icons.BubbleIconFactory;
 import com.android.launcher3.shortcuts.ShortcutRequest;
-import com.android.launcher3.taskbar.TaskbarControllers;
-import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.Executors.SimpleThreadFactory;
 import com.android.quickstep.SystemUiProxy;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 import com.android.wm.shell.Flags;
 import com.android.wm.shell.bubbles.IBubblesListener;
 import com.android.wm.shell.common.bubbles.BubbleBarLocation;
@@ -94,7 +90,7 @@
  */
 public class BubbleBarController extends IBubblesListener.Stub {
 
-    private static final String TAG = BubbleBarController.class.getSimpleName();
+    private static final String TAG = "BubbleBarController";
     private static final boolean DEBUG = false;
 
     /**
@@ -117,7 +113,7 @@
                 || SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false);
     }
 
-    private static final int MASK_HIDE_BUBBLE_BAR = SYSUI_STATE_BOUNCER_SHOWING
+    private static final long MASK_HIDE_BUBBLE_BAR = SYSUI_STATE_BOUNCER_SHOWING
             | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
             | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
             | SYSUI_STATE_IME_SHOWING
@@ -125,11 +121,11 @@
             | SYSUI_STATE_QUICK_SETTINGS_EXPANDED
             | SYSUI_STATE_IME_SWITCHER_SHOWING;
 
-    private static final int MASK_HIDE_HANDLE_VIEW = SYSUI_STATE_BOUNCER_SHOWING
+    private static final long MASK_HIDE_HANDLE_VIEW = SYSUI_STATE_BOUNCER_SHOWING
             | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
             | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
 
-    private static final int MASK_SYSUI_LOCKED = SYSUI_STATE_BOUNCER_SHOWING
+    private static final long MASK_SYSUI_LOCKED = SYSUI_STATE_BOUNCER_SHOWING
             | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
             | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
 
@@ -147,12 +143,14 @@
     private BubbleBarItem mSelectedBubble;
     private BubbleBarOverflow mOverflowBubble;
 
+    private ImeVisibilityChecker mImeVisibilityChecker;
     private BubbleBarViewController mBubbleBarViewController;
     private BubbleStashController mBubbleStashController;
     private BubbleStashedHandleViewController mBubbleStashedHandleViewController;
+    private BubblePinController mBubblePinController;
 
-    // Keep track of bubble bar bounds sent to shell to avoid sending duplicate updates
-    private final Rect mLastSentBubbleBarBounds = new Rect();
+    // Cache last sent top coordinate to avoid sending duplicate updates to shell
+    private int mLastSentBubbleBarTop;
 
     /**
      * Similar to {@link BubbleBarUpdate} but rather than {@link BubbleInfo}s it uses
@@ -169,6 +167,7 @@
         BubbleBarLocation bubbleBarLocation;
         List<RemovedBubble> removedBubbles;
         List<String> bubbleKeysInOrder;
+        Point expandedViewDropTargetSize;
 
         // These need to be loaded in the background
         BubbleBarBubble addedBubble;
@@ -186,6 +185,7 @@
             bubbleBarLocation = update.bubbleBarLocation;
             removedBubbles = update.removedBubbles;
             bubbleKeysInOrder = update.bubbleKeysInOrder;
+            expandedViewDropTargetSize = update.expandedViewDropTargetSize;
         }
     }
 
@@ -212,10 +212,14 @@
         mSystemUiProxy.setBubblesListener(null);
     }
 
-    public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
+    /** Initializes controllers. */
+    public void init(BubbleControllers bubbleControllers,
+            ImeVisibilityChecker imeVisibilityChecker) {
+        mImeVisibilityChecker = imeVisibilityChecker;
         mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
         mBubbleStashController = bubbleControllers.bubbleStashController;
         mBubbleStashedHandleViewController = bubbleControllers.bubbleStashedHandleViewController;
+        mBubblePinController = bubbleControllers.bubblePinController;
 
         bubbleControllers.runAfterInit(() -> {
             mBubbleBarViewController.setHiddenForBubbles(
@@ -252,7 +256,7 @@
     /**
      * Updates the bubble bar, handle bar, and stash controllers based on sysui state flags.
      */
-    public void updateStateForSysuiFlags(int flags) {
+    public void updateStateForSysuiFlags(@SystemUiStateFlags long flags) {
         boolean hideBubbleBar = (flags & MASK_HIDE_BUBBLE_BAR) != 0;
         mBubbleBarViewController.setHiddenForSysui(hideBubbleBar);
 
@@ -316,9 +320,9 @@
         // enabling gesture nav. also suppress animation if the bubble bar is hidden for sysui e.g.
         // the shade is open, or we're locked.
         final boolean suppressAnimation =
-                update.initialState || mBubbleBarViewController.isHiddenForSysui();
+                update.initialState || mBubbleBarViewController.isHiddenForSysui()
+                        || mImeVisibilityChecker.isImeVisible();
 
-        BubbleBarItem previouslySelectedBubble = mSelectedBubble;
         BubbleBarBubble bubbleToSelect = null;
         if (!update.removedBubbles.isEmpty()) {
             for (int i = 0; i < update.removedBubbles.size(); i++) {
@@ -374,6 +378,7 @@
             BubbleBarBubble bb = mBubbles.get(update.updatedBubble.getKey());
             // If we're not stashed, we're visible so animate
             bb.getView().updateDotVisibility(!mBubbleStashController.isStashed() /* animate */);
+            mBubbleBarViewController.animateBubbleNotification(bb, /* isExpanding= */ false);
         }
         if (update.bubbleKeysInOrder != null && !update.bubbleKeysInOrder.isEmpty()) {
             // Create the new list
@@ -403,9 +408,6 @@
         }
         if (bubbleToSelect != null) {
             setSelectedBubbleInternal(bubbleToSelect);
-            if (previouslySelectedBubble == null) {
-                mBubbleStashController.animateToInitialState(update.expanded);
-            }
         }
         if (update.shouldShowEducation) {
             mBubbleBarViewController.prepareToShowEducation();
@@ -419,11 +421,12 @@
         }
         if (update.bubbleBarLocation != null) {
             if (update.bubbleBarLocation != mBubbleBarViewController.getBubbleBarLocation()) {
-                // Animate when receiving updates. Skip it if we received the initial state.
-                boolean animate = !update.initialState;
-                updateBubbleBarLocationInternal(update.bubbleBarLocation, animate);
+                updateBubbleBarLocationInternal(update.bubbleBarLocation);
             }
         }
+        if (update.expandedViewDropTargetSize != null) {
+            mBubblePinController.setDropTargetSize(update.expandedViewDropTargetSize);
+        }
     }
 
     /** Tells WMShell to show the currently selected bubble. */
@@ -438,9 +441,8 @@
                         info.getFlags() | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
                 mSelectedBubble.getView().updateDotVisibility(true /* animate */);
             }
-            Rect bounds = getExpandedBubbleBarDisplayBounds();
-            mLastSentBubbleBarBounds.set(bounds);
-            mSystemUiProxy.showBubble(getSelectedBubbleKey(), bounds);
+            mLastSentBubbleBarTop = mBarView.getRestingTopPositionOnScreen();
+            mSystemUiProxy.showBubble(getSelectedBubbleKey(), mLastSentBubbleBarTop);
         } else {
             Log.w(TAG, "Trying to show the selected bubble but it's null");
         }
@@ -483,15 +485,21 @@
      * Updates the value locally in Launcher and in WMShell.
      */
     public void updateBubbleBarLocation(BubbleBarLocation location) {
-        updateBubbleBarLocationInternal(location, false /* animate */);
+        updateBubbleBarLocationInternal(location);
         mSystemUiProxy.setBubbleBarLocation(location);
     }
 
-    private void updateBubbleBarLocationInternal(BubbleBarLocation location, boolean animate) {
-        mBubbleBarViewController.setBubbleBarLocation(location, animate);
+    private void updateBubbleBarLocationInternal(BubbleBarLocation location) {
+        mBubbleBarViewController.setBubbleBarLocation(location);
         mBubbleStashController.setBubbleBarLocation(location);
     }
 
+    @Override
+    public void animateBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
+        mMainExecutor.execute(
+                () -> mBubbleBarViewController.animateBubbleBarLocation(bubbleBarLocation));
+    }
+
     //
     // Loading data for the bubbles
     //
@@ -623,39 +631,17 @@
         return mIconFactory.createBadgedIconBitmap(drawable).icon;
     }
 
-    private void onBubbleBarBoundsChanged(Rect newBounds) {
-        Rect displayBounds = convertToDisplayBounds(newBounds);
-        // Only send bounds over if they changed
-        if (!displayBounds.equals(mLastSentBubbleBarBounds)) {
-            mLastSentBubbleBarBounds.set(displayBounds);
-            mSystemUiProxy.setBubbleBarBounds(displayBounds);
+    private void onBubbleBarBoundsChanged() {
+        int newTop = mBarView.getRestingTopPositionOnScreen();
+        if (newTop != mLastSentBubbleBarTop) {
+            mLastSentBubbleBarTop = newTop;
+            mSystemUiProxy.updateBubbleBarTopOnScreen(newTop);
         }
     }
 
-    /**
-     * Get bounds of the bubble bar as if it would be expanded.
-     * Calculates the bounds instead of retrieving current view location as the view may be
-     * animating.
-     */
-    private Rect getExpandedBubbleBarDisplayBounds() {
-        return convertToDisplayBounds(mBarView.getBubbleBarBounds());
-    }
-
-    private Rect convertToDisplayBounds(Rect currentBarBounds) {
-        Point displaySize = DisplayController.INSTANCE.get(mContext).getInfo().currentSize;
-        Rect displayBounds = new Rect();
-        // currentBarBounds is only useful for distance from left or right edge.
-        // It contains the current bounds, calculate the expanded bounds.
-        if (mBarView.getBubbleBarLocation().isOnLeft(mBarView.isLayoutRtl())) {
-            displayBounds.left = currentBarBounds.left;
-            displayBounds.right = (int) (currentBarBounds.left + mBarView.expandedWidth());
-        } else {
-            displayBounds.left = (int) (currentBarBounds.right - mBarView.expandedWidth());
-            displayBounds.right = currentBarBounds.right;
-        }
-        final int translation = (int) abs(mBubbleStashController.getBubbleBarTranslationY());
-        displayBounds.top = displaySize.y - currentBarBounds.height() - translation;
-        displayBounds.bottom = displaySize.y - translation;
-        return displayBounds;
+    /** Interface for checking whether the IME is visible. */
+    public interface ImeVisibilityChecker {
+        /** Whether the IME is visible. */
+        boolean isImeVisible();
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt
index 8ed9949..9e5ffc9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt
@@ -19,7 +19,6 @@
 import android.annotation.SuppressLint
 import android.content.Context
 import android.graphics.Point
-import android.graphics.RectF
 import android.view.Gravity.BOTTOM
 import android.view.Gravity.LEFT
 import android.view.Gravity.RIGHT
@@ -37,44 +36,29 @@
 class BubbleBarPinController(
     private val context: Context,
     private val container: FrameLayout,
-    private val screenSizeProvider: () -> Point
-) : BaseBubblePinController() {
+    screenSizeProvider: () -> Point
+) : BaseBubblePinController(screenSizeProvider) {
 
     private lateinit var bubbleBarViewController: BubbleBarViewController
     private lateinit var bubbleStashController: BubbleStashController
+    private var exclRectWidth: Float = 0f
+    private var exclRectHeight: Float = 0f
+
     private var dropTargetView: View? = null
 
     fun init(bubbleControllers: BubbleControllers) {
         bubbleBarViewController = bubbleControllers.bubbleBarViewController
         bubbleStashController = bubbleControllers.bubbleStashController
+        exclRectWidth = context.resources.getDimension(R.dimen.bubblebar_dismiss_zone_width)
+        exclRectHeight = context.resources.getDimension(R.dimen.bubblebar_dismiss_zone_height)
     }
 
-    override fun getScreenCenterX(): Int {
-        return screenSizeProvider.invoke().x / 2
+    override fun getExclusionRectWidth(): Float {
+        return exclRectWidth
     }
 
-    override fun getExclusionRect(): RectF {
-        val rect =
-            RectF(
-                0f,
-                0f,
-                context.resources.getDimension(R.dimen.bubblebar_dismiss_zone_width),
-                context.resources.getDimension(R.dimen.bubblebar_dismiss_zone_height)
-            )
-        val screenSize = screenSizeProvider.invoke()
-        val middleX = screenSize.x / 2
-        // Center it around the bottom center of the screen
-        rect.offsetTo(middleX - rect.width() / 2, screenSize.y - rect.height())
-        return rect
-    }
-
-    override fun createDropTargetView(): View {
-        return LayoutInflater.from(context)
-            .inflate(R.layout.bubble_bar_drop_target, container, false)
-            .also { view ->
-                dropTargetView = view
-                container.addView(view)
-            }
+    override fun getExclusionRectHeight(): Float {
+        return exclRectHeight
     }
 
     override fun getDropTargetView(): View? {
@@ -86,6 +70,15 @@
         dropTargetView = null
     }
 
+    override fun createDropTargetView(): View {
+        return LayoutInflater.from(context)
+            .inflate(R.layout.bubble_bar_drop_target, container, false)
+            .also { view ->
+                dropTargetView = view
+                container.addView(view)
+            }
+    }
+
     @SuppressLint("RtlHardcoded")
     override fun updateLocation(location: BubbleBarLocation) {
         val onLeft = location.isOnLeft(container.isLayoutRtl)
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index 5234936..23e52e6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -16,6 +16,7 @@
 package com.android.launcher3.taskbar.bubbles;
 
 import static com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
 
 import android.animation.Animator;
@@ -29,6 +30,7 @@
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.util.FloatProperty;
 import android.util.LayoutDirection;
 import android.util.Log;
 import android.view.Gravity;
@@ -41,6 +43,7 @@
 
 import com.android.launcher3.R;
 import com.android.launcher3.anim.SpringAnimationBuilder;
+import com.android.launcher3.util.DisplayController;
 import com.android.wm.shell.common.bubbles.BubbleBarLocation;
 
 import java.util.List;
@@ -74,11 +77,12 @@
  */
 public class BubbleBarView extends FrameLayout {
 
-    private static final String TAG = BubbleBarView.class.getSimpleName();
+    private static final String TAG = "BubbleBarView";
 
     // TODO: (b/273594744) calculate the amount of space we have and base the max on that
     //  if it's smaller than 5.
     private static final int MAX_BUBBLES = 5;
+    private static final int MAX_VISIBLE_BUBBLES_COLLAPSED = 2;
     private static final int ARROW_POSITION_ANIMATION_DURATION_MS = 200;
     private static final int WIDTH_ANIMATION_DURATION_MS = 200;
 
@@ -94,6 +98,23 @@
     // During fade in animation we shift the bubble bar 1/60th of the screen width
     private static final float FADE_IN_ANIM_POSITION_SHIFT = 1 / 60f;
 
+    /**
+     * Custom property to set alpha value for the bar view while a bubble is being dragged.
+     * Skips applying alpha to the dragged bubble.
+     */
+    private static final FloatProperty<BubbleBarView> BUBBLE_DRAG_ALPHA =
+            new FloatProperty<>("bubbleDragAlpha") {
+                @Override
+                public void setValue(BubbleBarView bubbleBarView, float alpha) {
+                    bubbleBarView.setAlphaDuringBubbleDrag(alpha);
+                }
+
+                @Override
+                public Float get(BubbleBarView bubbleBarView) {
+                    return bubbleBarView.mAlphaDuringDrag;
+                }
+            };
+
     private final BubbleBarBackground mBubbleBarBackground;
 
     private boolean mIsAnimatingNewBubble = false;
@@ -104,8 +125,6 @@
      * updates the bounds and accounts for translation.
      */
     private final Rect mBubbleBarBounds = new Rect();
-    /** The bounds of the animating bubble in the coordinate space of the BubbleBarView. */
-    private final Rect mAnimatingBubbleBounds = new Rect();
     // The amount the bubbles overlap when they are stacked in the bubble bar
     private final float mIconOverlapAmount;
     // The spacing between the bubbles when bubble bar is expanded
@@ -119,6 +138,8 @@
     private final float mDragElevation;
     private final int mPointerSize;
 
+    private final Rect mTempBackgroundBounds = new Rect();
+
     // Whether the bar is expanded (i.e. the bubble activity is being displayed).
     private boolean mIsBarExpanded = false;
     // The currently selected bubble view.
@@ -152,11 +173,12 @@
 
     @Nullable
     private BubbleView mDraggedBubbleView;
+    private float mAlphaDuringDrag = 1f;
+
+    private Controller mController;
 
     private int mPreviousLayoutDirection = LayoutDirection.UNDEFINED;
 
-    private boolean mLocationChangePending;
-
     public BubbleBarView(Context context) {
         this(context, null);
     }
@@ -185,12 +207,12 @@
 
         setClipToPadding(false);
 
-        mBubbleBarBackground = new BubbleBarBackground(context, getBubbleBarHeight());
+        mBubbleBarBackground = new BubbleBarBackground(context, getBubbleBarExpandedHeight());
         setBackgroundDrawable(mBubbleBarBackground);
 
         mWidthAnimator.setDuration(WIDTH_ANIMATION_DURATION_MS);
         mWidthAnimator.addUpdateListener(animation -> {
-            updateChildrenRenderNodeProperties();
+            updateChildrenRenderNodeProperties(mBubbleBarLocation);
             invalidate();
         });
         mWidthAnimator.addListener(new Animator.AnimatorListener() {
@@ -227,6 +249,17 @@
         });
     }
 
+    @Override
+    public void setTranslationX(float translationX) {
+        super.setTranslationX(translationX);
+        if (mDraggedBubbleView != null) {
+            // Apply reverse of the translation as an offset to the dragged view. This ensures
+            // that the dragged bubble stays at the current location on the screen and its
+            // position is not affected by the parent translation.
+            mDraggedBubbleView.setOffsetX(-translationX);
+        }
+    }
+
     /**
      * Sets new icon size and spacing between icons and bubble bar borders.
      *
@@ -246,7 +279,7 @@
             params.width = (int) mIconSize;
             childView.setLayoutParams(params);
         }
-        mBubbleBarBackground.setHeight(getBubbleBarHeight());
+        mBubbleBarBackground.setHeight(getBubbleBarExpandedHeight());
         updateLayoutParams();
     }
 
@@ -263,8 +296,10 @@
         setPivotX(mRelativePivotX * getWidth());
         setPivotY(mRelativePivotY * getHeight());
 
-        // Position the views
-        updateChildrenRenderNodeProperties();
+        if (!mDragging) {
+            // Position the views when not dragging
+            updateChildrenRenderNodeProperties(mBubbleBarLocation);
+        }
     }
 
     @Override
@@ -280,15 +315,12 @@
 
     @SuppressLint("RtlHardcoded")
     private void onBubbleBarLocationChanged() {
-        mLocationChangePending = false;
         final boolean onLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl());
         mBubbleBarBackground.setAnchorLeft(onLeft);
         mRelativePivotX = onLeft ? 0f : 1f;
-        if (getLayoutParams() instanceof LayoutParams lp) {
-            lp.gravity = Gravity.BOTTOM | (onLeft ? Gravity.LEFT : Gravity.RIGHT);
-            setLayoutParams(lp);
-        }
-        invalidate();
+        LayoutParams lp = (LayoutParams) getLayoutParams();
+        lp.gravity = Gravity.BOTTOM | (onLeft ? Gravity.LEFT : Gravity.RIGHT);
+        setLayoutParams(lp); // triggers a relayout
     }
 
     /**
@@ -301,16 +333,16 @@
     /**
      * Update {@link BubbleBarLocation}
      */
-    public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation, boolean animate) {
-        if (animate) {
-            animateToBubbleBarLocation(bubbleBarLocation);
-        } else {
-            setBubbleBarLocationInternal(bubbleBarLocation);
+    public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
+        resetDragAnimation();
+        if (bubbleBarLocation != mBubbleBarLocation) {
+            mBubbleBarLocation = bubbleBarLocation;
+            onBubbleBarLocationChanged();
         }
     }
 
     /**
-     * Set whether this view is being currently being dragged
+     * Set whether this view is currently being dragged
      */
     public void setIsDragging(boolean dragging) {
         if (mDragging == dragging) {
@@ -318,51 +350,69 @@
         }
         mDragging = dragging;
         setElevation(dragging ? mDragElevation : mBubbleElevation);
-        if (!dragging && mLocationChangePending) {
-            // During drag finish animation we may update the translation x value to shift the
-            // bubble to the new drop target. Clear the translation here.
-            setTranslationX(0f);
-            onBubbleBarLocationChanged();
+        if (!mDragging) {
+            // Relayout after dragging to ensure that the dragged bubble is positioned correctly
+            requestLayout();
         }
     }
 
     /**
-     * Adjust resting position for the bubble bar while it is being dragged.
-     * <p>
-     * Bubble bar is laid out on left or right side of the screen. When it is being dragged to
-     * the opposite side, the resting position should be on that side. Calculate any additional
-     * translation that may be required to move the bubble bar to the new side.
+     * Get translation for bubble bar when drag is released and it needs to animate back to the
+     * resting position.
+     * Resting position is based on the supplied location. If the supplied location is different
+     * from the internal location that was used during bubble bar layout, translation values are
+     * calculated to position the bar at the desired location.
      *
-     * @param restingPosition relative resting position of the bubble bar from the laid out position
+     * @param initialTranslation initial bubble bar translation at the start of drag
+     * @param location           desired location of the bubble bar when drag is released
+     * @return point with x and y values representing translation on x and y-axis
      */
-    @SuppressLint("RtlHardcoded")
-    void adjustRelativeRestingPosition(PointF restingPosition) {
-        final boolean locationOnLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl());
-        // Bubble bar is placed left or right with gravity. Check where it is currently.
-        final int absoluteGravity = Gravity.getAbsoluteGravity(
-                ((LayoutParams) getLayoutParams()).gravity, getLayoutDirection());
-        final boolean gravityOnLeft =
-                (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.LEFT;
-
-        // Bubble bar is pinned to the same side per gravity and the desired location.
-        // Resting translation does not need to be adjusted.
-        if (locationOnLeft == gravityOnLeft) {
-            return;
+    public PointF getBubbleBarDragReleaseTranslation(PointF initialTranslation,
+            BubbleBarLocation location) {
+        float dragEndTranslationX = initialTranslation.x;
+        if (getBubbleBarLocation().isOnLeft(isLayoutRtl()) != location.isOnLeft(isLayoutRtl())) {
+            // Bubble bar is laid out on left or right side of the screen. And the desired new
+            // location is on the other side. Calculate x translation value required to shift
+            // bubble bar from one side to the other.
+            final float shift = getDistanceFromOtherSide();
+            if (location.isOnLeft(isLayoutRtl())) {
+                // New location is on the left, shift left
+                // before -> |......ooo.| after -> |.ooo......|
+                dragEndTranslationX = -shift;
+            } else {
+                // New location is on the right, shift right
+                // before -> |.ooo......| after -> |......ooo.|
+                dragEndTranslationX = shift;
+            }
         }
+        return new PointF(dragEndTranslationX, mController.getBubbleBarTranslationY());
+    }
 
-        // Bubble bar is laid out on left or right side of the screen. And the desired new
-        // location is on the other side. Calculate x translation value required to shift the
-        // bubble bar from one side to the other.
-        float x = getDistanceFromOtherSide();
-        if (locationOnLeft) {
-            // New location is on the left, shift left
-            // before -> |......ooo.| after -> |.ooo......|
-            restingPosition.x = -x;
-        } else {
-            // New location is on the right, shift right
-            // before -> |.ooo......| after -> |......ooo.|
-            restingPosition.x = x;
+    /**
+     * Get translation for a bubble when drag is released and it needs to animate back to the
+     * resting position.
+     * Resting position is based on the supplied location. If the supplied location is different
+     * from the internal location that was used during bubble bar layout, translation values are
+     * calculated to position the bar at the desired location.
+     *
+     * @param initialTranslation initial bubble translation inside the bar at the start of drag
+     * @param location           desired location of the bubble bar when drag is released
+     * @return point with x and y values representing translation on x and y-axis
+     */
+    public PointF getDraggedBubbleReleaseTranslation(PointF initialTranslation,
+            BubbleBarLocation location) {
+        float dragEndTranslationX = initialTranslation.x;
+        boolean newLocationOnLeft = location.isOnLeft(isLayoutRtl());
+        if (getBubbleBarLocation().isOnLeft(isLayoutRtl()) != newLocationOnLeft) {
+            // Calculate translationX based on bar and bubble translations
+            float bubbleBarTx = getBubbleBarDragReleaseTranslation(initialTranslation, location).x;
+            float bubbleTx =
+                    getExpandedBubbleTranslationX(
+                            indexOfChild(mDraggedBubbleView), getChildCount(), newLocationOnLeft);
+            dragEndTranslationX = bubbleBarTx + bubbleTx;
         }
+        // translationY does not change during drag and can be reused
+        return new PointF(dragEndTranslationX, initialTranslation.y);
     }
 
     private float getDistanceFromOtherSide() {
@@ -376,55 +426,46 @@
         return (float) (displayWidth - getWidth() - margin);
     }
 
-    private void setBubbleBarLocationInternal(BubbleBarLocation bubbleBarLocation) {
-        if (bubbleBarLocation != mBubbleBarLocation) {
-            mBubbleBarLocation = bubbleBarLocation;
-            if (mDragging) {
-                mLocationChangePending = true;
-            } else {
-                onBubbleBarLocationChanged();
-                invalidate();
-            }
-        }
-    }
-
-    private void animateToBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
-        if (bubbleBarLocation == mBubbleBarLocation) {
-            // nothing to do, already at expected location
-            return;
-        }
+    /**
+     * Animate bubble bar to the given location transiently. Does not modify the layout or the value
+     * returned by {@link #getBubbleBarLocation()}.
+     */
+    public void animateToBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
         if (mBubbleBarLocationAnimator != null && mBubbleBarLocationAnimator.isRunning()) {
+            mBubbleBarLocationAnimator.removeAllListeners();
             mBubbleBarLocationAnimator.cancel();
         }
 
         // Location animation uses two separate animators.
         // First animator hides the bar.
-        // After it completes, location update is sent to layout the bar in the new location.
+        // After it completes, bubble positions in the bar and arrow position is updated.
         // Second animator is started to show the bar.
-        mBubbleBarLocationAnimator = getLocationUpdateFadeOutAnimator();
+        mBubbleBarLocationAnimator = getLocationUpdateFadeOutAnimator(bubbleBarLocation);
         mBubbleBarLocationAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                // Bubble bar is not visible, update the location
-                setBubbleBarLocationInternal(bubbleBarLocation);
+                updateChildrenRenderNodeProperties(bubbleBarLocation);
+                mBubbleBarBackground.setAnchorLeft(bubbleBarLocation.isOnLeft(isLayoutRtl()));
+
                 // Animate it in
-                mBubbleBarLocationAnimator = getLocationUpdateFadeInAnimator();
+                mBubbleBarLocationAnimator = getLocationUpdateFadeInAnimator(bubbleBarLocation);
                 mBubbleBarLocationAnimator.start();
             }
         });
         mBubbleBarLocationAnimator.start();
     }
 
-    private AnimatorSet getLocationUpdateFadeOutAnimator() {
+    private Animator getLocationUpdateFadeOutAnimator(BubbleBarLocation newLocation) {
         final float shift =
                 getResources().getDisplayMetrics().widthPixels * FADE_OUT_ANIM_POSITION_SHIFT;
-        final float tx = mBubbleBarLocation.isOnLeft(isLayoutRtl()) ? shift : -shift;
+        final boolean onLeft = newLocation.isOnLeft(isLayoutRtl());
+        final float tx = getTranslationX() + (onLeft ? -shift : shift);
 
-        ObjectAnimator positionAnim = ObjectAnimator.ofFloat(this, TRANSLATION_X, tx)
+        ObjectAnimator positionAnim = ObjectAnimator.ofFloat(this, VIEW_TRANSLATE_X, tx)
                 .setDuration(FADE_OUT_ANIM_POSITION_DURATION_MS);
         positionAnim.setInterpolator(EMPHASIZED_ACCELERATE);
 
-        ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(this, ALPHA, 0f)
+        ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(this, getLocationAnimAlphaProperty(), 0f)
                 .setDuration(FADE_OUT_ANIM_ALPHA_DURATION_MS);
         alphaAnim.setStartDelay(FADE_OUT_ANIM_ALPHA_DELAY_MS);
 
@@ -433,19 +474,36 @@
         return animatorSet;
     }
 
-    private Animator getLocationUpdateFadeInAnimator() {
+    private Animator getLocationUpdateFadeInAnimator(BubbleBarLocation newLocation) {
         final float shift =
                 getResources().getDisplayMetrics().widthPixels * FADE_IN_ANIM_POSITION_SHIFT;
-        final float startTx = mBubbleBarLocation.isOnLeft(isLayoutRtl()) ? shift : -shift;
+
+        final boolean onLeft = newLocation.isOnLeft(isLayoutRtl());
+        final float startTx;
+        final float finalTx;
+        if (newLocation == mBubbleBarLocation) {
+            // Animated location matches layout location.
+            finalTx = 0;
+        } else {
+            // We are animating in to a transient location, need to move the bar accordingly.
+            finalTx = getDistanceFromOtherSide() * (onLeft ? -1 : 1);
+        }
+        if (onLeft) {
+            // Bar will be shown on the left side. Start point is shifted right.
+            startTx = finalTx + shift;
+        } else {
+            // Bar will be shown on the right side. Start point is shifted left.
+            startTx = finalTx - shift;
+        }
 
         ValueAnimator positionAnim = new SpringAnimationBuilder(getContext())
                 .setStartValue(startTx)
-                .setEndValue(0)
+                .setEndValue(finalTx)
                 .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
                 .setStiffness(FADE_IN_ANIM_POSITION_SPRING_STIFFNESS)
                 .build(this, VIEW_TRANSLATE_X);
 
-        ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(this, ALPHA, 1f)
+        ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(this, getLocationAnimAlphaProperty(), 1f)
                 .setDuration(FADE_IN_ANIM_ALPHA_DURATION_MS);
 
         AnimatorSet animatorSet = new AnimatorSet();
@@ -454,6 +512,58 @@
     }
 
     /**
+     * Get property that can be used to animate the alpha value for the bar.
+     * When a bubble is being dragged, uses {@link #BUBBLE_DRAG_ALPHA}.
+     * Falls back to {@link com.android.launcher3.LauncherAnimUtils#VIEW_ALPHA} otherwise.
+     */
+    private FloatProperty<? super BubbleBarView> getLocationAnimAlphaProperty() {
+        return mDraggedBubbleView == null ? VIEW_ALPHA : BUBBLE_DRAG_ALPHA;
+    }
+
+    /**
+     * Set alpha value for the bar while a bubble is being dragged.
+     * We can not update the alpha on the bar directly because the dragged bubble would be affected
+     * as well. As it is a child view.
+     * Instead, while a bubble is being dragged, set alpha on each child view, that is not the
+     * dragged view. And set an alpha on the background.
+     * This allows for the dragged bubble to remain visible while the bar is hidden during
+     * animation.
+     */
+    private void setAlphaDuringBubbleDrag(float alpha) {
+        mAlphaDuringDrag = alpha;
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View view = getChildAt(i);
+            if (view != mDraggedBubbleView) {
+                view.setAlpha(alpha);
+            }
+        }
+        if (mBubbleBarBackground != null) {
+            mBubbleBarBackground.setAlpha((int) (255 * alpha));
+        }
+    }
+
+    private void resetDragAnimation() {
+        if (mBubbleBarLocationAnimator != null) {
+            mBubbleBarLocationAnimator.removeAllListeners();
+            mBubbleBarLocationAnimator.cancel();
+            mBubbleBarLocationAnimator = null;
+        }
+        setAlphaDuringBubbleDrag(1f);
+        setTranslationX(0f);
+        setAlpha(1f);
+    }
+
+    /**
+     * Get bubble bar top coordinate on screen when bar is resting
+     */
+    public int getRestingTopPositionOnScreen() {
+        int displayHeight = DisplayController.INSTANCE.get(getContext()).getInfo().currentSize.y;
+        int bubbleBarHeight = getBubbleBarBounds().height();
+        return displayHeight - bubbleBarHeight + (int) mController.getBubbleBarTranslationY();
+    }
+
+    /**
      * Updates the bounds with translation that may have been applied and returns the result.
      */
     public Rect getBubbleBarBounds() {
@@ -462,30 +572,6 @@
         return mBubbleBarBounds;
     }
 
-    /** Returns the bounds of the animating bubble, or {@code null} if no bubble is animating. */
-    @Nullable
-    public Rect getAnimatingBubbleBounds() {
-        if (mIsAnimatingNewBubble) {
-            return mAnimatingBubbleBounds;
-        }
-        return null;
-    }
-
-    /**
-     * Updates the animating bubble bounds. This should be called when the bubble is fully animated
-     * in so that we can include it in taskbar touchable region.
-     *
-     * <p>The bounds are adjusted to the coordinate space of BubbleBarView so that it can be used
-     * by taskbar.
-     */
-    public void updateAnimatingBubbleBounds(int left, int top, int width, int height) {
-        Rect bubbleBarBounds = getBubbleBarBounds();
-        mAnimatingBubbleBounds.left = bubbleBarBounds.left + left;
-        mAnimatingBubbleBounds.top = bubbleBarBounds.top + top;
-        mAnimatingBubbleBounds.right = mAnimatingBubbleBounds.left + width;
-        mAnimatingBubbleBounds.bottom = mAnimatingBubbleBounds.top + height;
-    }
-
     /**
      * Set bubble bar relative pivot value for X and Y, applied as a fraction of view width/height
      * respectively. If the value is not in range of 0 to 1 it will be normalized.
@@ -498,6 +584,11 @@
         requestLayout();
     }
 
+    /** Like {@link #setRelativePivot(float, float)} but only updates pivot y. */
+    public void setRelativePivotY(float y) {
+        setRelativePivot(mRelativePivotX, y);
+    }
+
     /**
      * Get current relative pivot for X axis
      */
@@ -512,38 +603,14 @@
         return mRelativePivotY;
     }
 
-    /** Prepares for animating a bubble while being stashed. */
-    public void prepareForAnimatingBubbleWhileStashed(String bubbleKey) {
+    /** Notifies the bubble bar that a new bubble animation is starting. */
+    public void onAnimatingBubbleStarted() {
         mIsAnimatingNewBubble = true;
-        // we're about to animate the new bubble in. the new bubble has already been added to this
-        // view, but we're currently stashed, so before we can start the animation we need make
-        // everything else in the bubble bar invisible, except for the bubble that's being animated.
-        setBackground(null);
-        for (int i = 0; i < getChildCount(); i++) {
-            final BubbleView view = (BubbleView) getChildAt(i);
-            final String key = view.getBubble().getKey();
-            if (!bubbleKey.equals(key)) {
-                view.setVisibility(INVISIBLE);
-            }
-        }
-        setVisibility(VISIBLE);
-        setAlpha(1);
-        setTranslationY(0);
-        setScaleX(1);
-        setScaleY(1);
     }
 
-    /** Resets the state after the bubble animation completed. */
+    /** Notifies the bubble bar that a new bubble animation is complete. */
     public void onAnimatingBubbleCompleted() {
         mIsAnimatingNewBubble = false;
-        // setting the background triggers relayout so no need to explicitly invalidate after the
-        // animation
-        setBackground(mBubbleBarBackground);
-        for (int i = 0; i < getChildCount(); i++) {
-            final BubbleView view = (BubbleView) getChildAt(i);
-            view.setVisibility(VISIBLE);
-            view.setAlpha(1f);
-        }
     }
 
     // TODO: (b/280605790) animate it
@@ -577,7 +644,7 @@
 
     private void updateLayoutParams() {
         LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
-        lp.height = getBubbleBarHeight();
+        lp.height = (int) getBubbleBarExpandedHeight();
         lp.width = (int) (mIsBarExpanded ? expandedWidth() : collapsedWidth());
         setLayoutParams(lp);
     }
@@ -592,13 +659,7 @@
      * Updates the z order, positions, and badge visibility of the bubble views in the bar based
      * on the expanded state.
      */
-    private void updateChildrenRenderNodeProperties() {
-        if (mIsAnimatingNewBubble) {
-            // don't update bubbles if a new bubble animation is playing.
-            // the bubble bar will redraw itself via onLayout after the animation.
-            return;
-        }
-
+    private void updateChildrenRenderNodeProperties(BubbleBarLocation bubbleBarLocation) {
         final float widthState = (float) mWidthAnimator.getAnimatedValue();
         final float currentWidth = getWidth();
         final float expandedWidth = expandedWidth();
@@ -606,35 +667,30 @@
         int bubbleCount = getChildCount();
         final float ty = (mBubbleBarBounds.height() - mIconSize) / 2f;
         final boolean animate = getVisibility() == VISIBLE;
-        final boolean onLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl());
+        final boolean onLeft = bubbleBarLocation.isOnLeft(isLayoutRtl());
         // elevation state is opposite to widthState - when expanded all icons are flat
         float elevationState = (1 - widthState);
         for (int i = 0; i < bubbleCount; i++) {
             BubbleView bv = (BubbleView) getChildAt(i);
+            if (bv == mDraggedBubbleView) {
+                // Skip the dragged bubble. Its translation is managed by the drag controller.
+                continue;
+            }
+            // Clear out drag translation and offset
+            bv.setDragTranslationX(0f);
+            bv.setOffsetX(0f);
+
             bv.setTranslationY(ty);
 
             // the position of the bubble when the bar is fully expanded
-            final float expandedX;
+            final float expandedX = getExpandedBubbleTranslationX(i, bubbleCount, onLeft);
             // the position of the bubble when the bar is fully collapsed
-            final float collapsedX;
-            if (onLeft) {
-                // If bar is on the left, bubbles are ordered right to left
-                expandedX = (bubbleCount - i - 1) * (mIconSize + mExpandedBarIconsSpacing);
-                // Shift the first bubble only if there are more bubbles in addition to overflow
-                collapsedX = i == 0 && bubbleCount > 2 ? mIconOverlapAmount : 0;
-            } else {
-                // Bubbles ordered left to right, don't move the first bubble
-                expandedX = i * (mIconSize + mExpandedBarIconsSpacing);
-                collapsedX = i == 0 ? 0 : mIconOverlapAmount;
-            }
-            if (bv == mDraggedBubbleView) {
-                // if bubble is dragged set the elevation to bubble drag elevation
-                bv.setZ(mDragElevation);
-            } else {
-                // otherwise slowly animate elevation while keeping correct Z ordering
-                float fullElevationForChild = (MAX_BUBBLES * mBubbleElevation) - i;
-                bv.setZ(fullElevationForChild * elevationState);
-            }
+            final float collapsedX = getCollapsedBubbleTranslationX(i, bubbleCount, onLeft);
+
+            // slowly animate elevation while keeping correct Z ordering
+            float fullElevationForChild = (MAX_BUBBLES * mBubbleElevation) - i;
+            bv.setZ(fullElevationForChild * elevationState);
+
             if (mIsBarExpanded) {
                 // If bar is on the right, account for bubble bar expanding and shifting left
                 final float expandedBarShift = onLeft ? 0 : currentWidth - expandedWidth;
@@ -654,9 +710,10 @@
                 // If we're fully collapsed, hide all bubbles except for the first 2. If there are
                 // only 2 bubbles, hide the second bubble as well because it's the overflow.
                 if (widthState == 0) {
-                    if (i > 1) {
+                    if (i > MAX_VISIBLE_BUBBLES_COLLAPSED - 1) {
                         bv.setAlpha(0);
-                    } else if (i == 1 && bubbleCount == 2) {
+                    } else if (i == MAX_VISIBLE_BUBBLES_COLLAPSED - 1
+                            && bubbleCount == MAX_VISIBLE_BUBBLES_COLLAPSED) {
                         bv.setAlpha(0);
                     }
                 }
@@ -664,8 +721,9 @@
         }
 
         // update the arrow position
-        final float collapsedArrowPosition = arrowPositionForSelectedWhenCollapsed();
-        final float expandedArrowPosition = arrowPositionForSelectedWhenExpanded();
+        final float collapsedArrowPosition = arrowPositionForSelectedWhenCollapsed(
+                bubbleBarLocation);
+        final float expandedArrowPosition = arrowPositionForSelectedWhenExpanded(bubbleBarLocation);
         final float interpolatedWidth =
                 widthState * (expandedWidth - collapsedWidth) + collapsedWidth;
         final float arrowPosition;
@@ -688,6 +746,34 @@
         mBubbleBarBackground.setWidth(interpolatedWidth);
     }
 
+    private float getExpandedBubbleTranslationX(int bubbleIndex, int bubbleCount,
+            boolean onLeft) {
+        if (bubbleIndex < 0 || bubbleIndex >= bubbleCount) {
+            return 0;
+        }
+        if (onLeft) {
+            // If bar is on the left, bubbles are ordered right to left
+            return (bubbleCount - bubbleIndex - 1) * (mIconSize + mExpandedBarIconsSpacing);
+        } else {
+            // Bubbles ordered left to right, don't move the first bubble
+            return bubbleIndex * (mIconSize + mExpandedBarIconsSpacing);
+        }
+    }
+
+    private float getCollapsedBubbleTranslationX(int bubbleIndex, int bubbleCount,
+            boolean onLeft) {
+        if (bubbleIndex < 0 || bubbleIndex >= bubbleCount) {
+            return 0;
+        }
+        if (onLeft) {
+            // Shift the first bubble only if there are more bubbles in addition to overflow
+            return bubbleIndex == 0 && bubbleCount > MAX_VISIBLE_BUBBLES_COLLAPSED
+                    ? mIconOverlapAmount : 0;
+        } else {
+            return bubbleIndex == 0 ? 0 : mIconOverlapAmount;
+        }
+    }
+
     /**
      * Reorders the views to match the provided list.
      */
@@ -712,7 +798,7 @@
                     addViewInLayout(child, i, child.getLayoutParams());
                 }
             }
-            updateChildrenRenderNodeProperties();
+            updateChildrenRenderNodeProperties(mBubbleBarLocation);
         }
     }
 
@@ -721,6 +807,10 @@
         mUpdateSelectedBubbleAfterCollapse = updateSelectedBubbleAfterCollapse;
     }
 
+    void setController(Controller controller) {
+        mController = controller;
+    }
+
     /**
      * Sets which bubble view should be shown as selected.
      */
@@ -737,8 +827,14 @@
      * Sets the dragged bubble view to correctly apply Z order. Dragged view should appear on top
      */
     public void setDraggedBubble(@Nullable BubbleView view) {
+        if (mDraggedBubbleView != null) {
+            mDraggedBubbleView.setZ(0);
+        }
         mDraggedBubbleView = view;
-        requestLayout();
+        if (view != null) {
+            view.setZ(mDragElevation);
+        }
+        setIsDragging(view != null);
     }
 
     /**
@@ -753,7 +849,7 @@
             return;
         }
         // Find the center of the bubble when it's expanded, set the arrow position to it.
-        final float tx = arrowPositionForSelectedWhenExpanded();
+        final float tx = arrowPositionForSelectedWhenExpanded(mBubbleBarLocation);
         final float currentArrowPosition = mBubbleBarBackground.getArrowPositionX();
         if (tx == currentArrowPosition) {
             // arrow position remains unchanged
@@ -778,10 +874,10 @@
         }
     }
 
-    private float arrowPositionForSelectedWhenExpanded() {
+    private float arrowPositionForSelectedWhenExpanded(BubbleBarLocation bubbleBarLocation) {
         final int index = indexOfChild(mSelectedBubbleView);
         final int bubblePosition;
-        if (mBubbleBarLocation.isOnLeft(isLayoutRtl())) {
+        if (bubbleBarLocation.isOnLeft(isLayoutRtl())) {
             // Bubble positions are reversed. First bubble is on the right.
             bubblePosition = getChildCount() - index - 1;
         } else {
@@ -791,13 +887,13 @@
                 + mIconSize / 2f;
     }
 
-    private float arrowPositionForSelectedWhenCollapsed() {
+    private float arrowPositionForSelectedWhenCollapsed(BubbleBarLocation bubbleBarLocation) {
         final int index = indexOfChild(mSelectedBubbleView);
         final int bubblePosition;
-        if (mBubbleBarLocation.isOnLeft(isLayoutRtl())) {
+        if (bubbleBarLocation.isOnLeft(isLayoutRtl())) {
             // Bubble positions are reversed. First bubble may be shifted, if there are more
             // bubbles than the current bubble and overflow.
-            bubblePosition = index == 0 && getChildCount() > 2 ? 1 : 0;
+            bubblePosition = index == 0 && getChildCount() > MAX_VISIBLE_BUBBLES_COLLAPSED ? 1 : 0;
         } else {
             bubblePosition = index;
         }
@@ -859,13 +955,18 @@
         final int horizontalPadding = getPaddingStart() + getPaddingEnd();
         // If there are more than 2 bubbles, the first 2 should be visible when collapsed.
         // Otherwise just the first bubble should be visible because we don't show the overflow.
-        return childCount > 2
+        return childCount > MAX_VISIBLE_BUBBLES_COLLAPSED
                 ? mIconSize + mIconOverlapAmount + horizontalPadding
                 : mIconSize + horizontalPadding;
     }
 
-    private int getBubbleBarHeight() {
-        return (int) (mIconSize + mBubbleBarPadding * 2 + mPointerSize);
+    private float getBubbleBarExpandedHeight() {
+        return getBubbleBarCollapsedHeight() + mPointerSize;
+    }
+
+    float getBubbleBarCollapsedHeight() {
+        // the pointer is invisible when collapsed
+        return mIconSize + mBubbleBarPadding * 2;
     }
 
     /**
@@ -882,7 +983,10 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (!mIsBarExpanded && !mIsAnimatingNewBubble) {
+        if (mIsAnimatingNewBubble) {
+            mController.onBubbleBarTouchedWhileAnimating();
+        }
+        if (!mIsBarExpanded) {
             // When the bar is collapsed, all taps on it should expand it.
             return true;
         }
@@ -893,4 +997,14 @@
     public boolean isAnimatingNewBubble() {
         return mIsAnimatingNewBubble;
     }
+
+    /** Interface for BubbleBarView to communicate with its controller. */
+    interface Controller {
+
+        /** Returns the translation Y that the bubble bar should have. */
+        float getBubbleBarTranslationY();
+
+        /** Notifies the controller that the bubble bar was touched while it was animating. */
+        void onBubbleBarTouchedWhileAnimating();
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index 3c46f32..f614dc6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -20,6 +20,7 @@
 
 import android.content.res.Resources;
 import android.graphics.Point;
+import android.graphics.PointF;
 import android.graphics.Rect;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -54,7 +55,7 @@
  */
 public class BubbleBarViewController {
 
-    private static final String TAG = BubbleBarViewController.class.getSimpleName();
+    private static final String TAG = "BubbleBarViewController";
     private static final float APP_ICON_SMALL_DP = 44f;
     private static final float APP_ICON_MEDIUM_DP = 48f;
     private static final float APP_ICON_LARGE_DP = 52f;
@@ -92,8 +93,6 @@
     @Nullable
     private BubbleBarBoundsChangeListener mBoundsChangeListener;
 
-    private final Rect mPreviousBubbleBarBounds = new Rect();
-
     public BubbleBarViewController(TaskbarActivityContext activity, BubbleBarView barView) {
         mActivity = activity;
         mBarView = barView;
@@ -121,16 +120,23 @@
         mBarView.addOnLayoutChangeListener(
                 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
                     mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
-                    Rect bubbleBarBounds = mBarView.getBubbleBarBounds();
-                    if (!bubbleBarBounds.equals(mPreviousBubbleBarBounds)) {
-                        mPreviousBubbleBarBounds.set(bubbleBarBounds);
-                        if (mBoundsChangeListener != null) {
-                            mBoundsChangeListener.onBoundsChanged(bubbleBarBounds);
-                        }
+                    if (mBoundsChangeListener != null) {
+                        mBoundsChangeListener.onBoundsChanged();
                     }
                 });
 
         mBubbleBarViewAnimator = new BubbleBarViewAnimator(mBarView, mBubbleStashController);
+        mBarView.setController(new BubbleBarView.Controller() {
+            @Override
+            public float getBubbleBarTranslationY() {
+                return mBubbleStashController.getBubbleBarTranslationY();
+            }
+
+            @Override
+            public void onBubbleBarTouchedWhileAnimating() {
+                BubbleBarViewController.this.onBubbleBarTouchedWhileAnimating();
+            }
+        });
     }
 
     private void onBubbleClicked(View v) {
@@ -139,14 +145,6 @@
             Log.e(TAG, "bubble click listener, bubble was null");
         }
 
-        if (mBarView.isAnimatingNewBubble()) {
-            mBubbleBarViewAnimator.onBubbleClickedWhileAnimating();
-            mBubbleStashController.showBubbleBarImmediate();
-            setExpanded(true);
-            mBubbleBarController.showAndSelectBubble(bubble);
-            return;
-        }
-
         final String currentlySelected = mBubbleBarController.getSelectedBubbleKey();
         if (mBarView.isExpanded() && Objects.equals(bubble.getKey(), currentlySelected)) {
             // Tapping the currently selected bubble while expanded collapses the view.
@@ -157,6 +155,11 @@
         }
     }
 
+    private void onBubbleBarTouchedWhileAnimating() {
+        mBubbleBarViewAnimator.onBubbleBarTouchedWhileAnimating();
+        mBubbleStashController.onNewBubbleAnimationInterrupted(false, mBarView.getTranslationY());
+    }
+
     private void onBubbleBarClicked() {
         if (mShouldShowEducation) {
             mShouldShowEducation = false;
@@ -168,10 +171,21 @@
             // Show user education relative to the reference point
             mSystemUiProxy.showUserEducation(position);
         } else {
+            // ensure that the bubble bar has the correct translation. we may have just interrupted
+            // the animation by touching the bubble bar.
+            mBubbleBarTranslationY.animateToValue(mBubbleStashController.getBubbleBarTranslationY())
+                    .start();
             setExpanded(true);
         }
     }
 
+    /** Notifies that the stash state is changing. */
+    public void onStashStateChanging() {
+        if (isAnimatingNewBubble()) {
+            mBubbleBarViewAnimator.onStashStateChangingWhileAnimating();
+        }
+    }
+
     //
     // The below animators are exposed to BubbleStashController so it can manage the stashing
     // animation.
@@ -189,6 +203,10 @@
         return mBubbleBarTranslationY;
     }
 
+    float getBubbleBarCollapsedHeight() {
+        return mBarView.getBubbleBarCollapsedHeight();
+    }
+
     /**
      * Whether the bubble bar is visible or not.
      */
@@ -211,8 +229,17 @@
     /**
      * Update bar {@link BubbleBarLocation}
      */
-    public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation, boolean animate) {
-        mBarView.setBubbleBarLocation(bubbleBarLocation, animate);
+    public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
+        mBarView.setBubbleBarLocation(bubbleBarLocation);
+    }
+
+    /**
+     * Animate bubble bar to the given location. The location change is transient. It does not
+     * update the state of the bubble bar.
+     * To update bubble bar pinned location, use {@link #setBubbleBarLocation(BubbleBarLocation)}.
+     */
+    public void animateBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
+        mBarView.animateToBubbleBarLocation(bubbleBarLocation);
     }
 
     /**
@@ -222,10 +249,9 @@
         return mBarView.getBubbleBarBounds();
     }
 
-    /** The bounds of the animating bubble, or {@code null} if no bubble is animating. */
-    @Nullable
-    public Rect getAnimatingBubbleBounds() {
-        return mBarView.getAnimatingBubbleBounds();
+    /** Whether a new bubble is animating. */
+    public boolean isAnimatingNewBubble() {
+        return mBarView.isAnimatingNewBubble();
     }
 
     /** The horizontal margin of the bubble bar from the edge of the screen. */
@@ -382,20 +408,31 @@
             b.getView().setOnClickListener(mBubbleClickListener);
             mBubbleDragController.setupBubbleView(b.getView());
 
-            if (suppressAnimation) {
+            if (suppressAnimation || !(b instanceof BubbleBarBubble bubble)) {
                 return;
             }
-
-            boolean isInApp = mTaskbarStashController.isInApp();
-            // only animate the new bubble if we're in an app and not auto expanding
-            if (b instanceof BubbleBarBubble && isInApp && !isExpanding && !isExpanded()) {
-                mBubbleBarViewAnimator.animateBubbleInForStashed((BubbleBarBubble) b);
-            }
+            animateBubbleNotification(bubble, isExpanding);
         } else {
             Log.w(TAG, "addBubble, bubble was null!");
         }
     }
 
+    /** Animates the bubble bar to notify the user about a bubble change. */
+    public void animateBubbleNotification(BubbleBarBubble bubble, boolean isExpanding) {
+        boolean isInApp = mTaskbarStashController.isInApp();
+        // if this is the first bubble, animate to the initial state. one bubble is the overflow
+        // so check for at most 2 children.
+        if (mBarView.getChildCount() <= 2) {
+            mBubbleBarViewAnimator.animateToInitialState(bubble, isInApp, isExpanding);
+            return;
+        }
+
+        // only animate the new bubble if we're in an app and not auto expanding
+        if (isInApp && !isExpanding && !isExpanded()) {
+            mBubbleBarViewAnimator.animateBubbleInForStashed(bubble);
+        }
+    }
+
     /**
      * Reorders the bubbles based on the provided list.
      */
@@ -454,34 +491,63 @@
      * that a bubble is being dragged to dismiss.
      * @param bubbleView dragged bubble view
      */
-    public void onDragStart(@NonNull BubbleView bubbleView) {
+    public void onBubbleDragStart(@NonNull BubbleView bubbleView) {
         if (bubbleView.getBubble() == null) return;
-        mSystemUiProxy.onBubbleDrag(bubbleView.getBubble().getKey(), /* isBeingDragged = */ true);
+
+        mSystemUiProxy.startBubbleDrag(bubbleView.getBubble().getKey());
         mBarView.setDraggedBubble(bubbleView);
     }
 
     /**
      * Notifies SystemUI to expand the selected bubble when the bubble is released.
-     * @param bubbleView dragged bubble view
      */
-    public void onDragRelease(@NonNull BubbleView bubbleView) {
-        if (bubbleView.getBubble() == null) return;
-        mSystemUiProxy.onBubbleDrag(bubbleView.getBubble().getKey(), /* isBeingDragged = */ false);
+    public void onBubbleDragRelease(BubbleBarLocation location) {
+        mSystemUiProxy.stopBubbleDrag(location, mBarView.getRestingTopPositionOnScreen());
     }
 
     /**
-     * Removes the dragged bubble view in the bubble bar view
+     * Notifies {@link BubbleBarView} that drag and all animations are finished.
      */
-    public void onDragEnd() {
+    public void onBubbleDragEnd() {
         mBarView.setDraggedBubble(null);
     }
 
+    /** Notifies that dragging the bubble bar ended. */
+    public void onBubbleBarDragEnd() {
+        // we may have changed the bubble bar translation Y value from the value it had at the
+        // beginning of the drag, so update the translation Y animator state
+        mBubbleBarTranslationY.updateValue(mBarView.getTranslationY());
+    }
+
+    /**
+     * Get translation for bubble bar when drag is released.
+     *
+     * @see BubbleBarView#getBubbleBarDragReleaseTranslation(PointF, BubbleBarLocation)
+     */
+    public PointF getBubbleBarDragReleaseTranslation(PointF initialTranslation,
+            BubbleBarLocation location) {
+        return mBarView.getBubbleBarDragReleaseTranslation(initialTranslation, location);
+    }
+
+    /**
+     * Get translation for bubble view when drag is released.
+     *
+     * @see BubbleBarView#getDraggedBubbleReleaseTranslation(PointF, BubbleBarLocation)
+     */
+    public PointF getDraggedBubbleReleaseTranslation(PointF initialTranslation,
+            BubbleBarLocation location) {
+        if (location == mBarView.getBubbleBarLocation()) {
+            return initialTranslation;
+        }
+        return mBarView.getDraggedBubbleReleaseTranslation(initialTranslation, location);
+    }
+
     /**
      * Called when bubble was dragged into the dismiss target. Notifies System
      * @param bubble dismissed bubble item
      */
     public void onDismissBubbleWhileDragging(@NonNull BubbleBarItem bubble) {
-        mSystemUiProxy.removeBubble(bubble.getKey());
+        mSystemUiProxy.dragBubbleToDismiss(bubble.getKey());
     }
 
     /**
@@ -503,6 +569,6 @@
      */
     public interface BubbleBarBoundsChangeListener {
         /** Called when bounds have changed */
-        void onBoundsChanged(Rect newBounds);
+        void onBoundsChanged();
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
index 90f1be3..32d6375 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
@@ -30,6 +30,7 @@
     public final BubbleDragController bubbleDragController;
     public final BubbleDismissController bubbleDismissController;
     public final BubbleBarPinController bubbleBarPinController;
+    public final BubblePinController bubblePinController;
 
     private final RunnableList mPostInitRunnables = new RunnableList();
 
@@ -45,7 +46,8 @@
             BubbleStashedHandleViewController bubbleStashedHandleViewController,
             BubbleDragController bubbleDragController,
             BubbleDismissController bubbleDismissController,
-            BubbleBarPinController bubbleBarPinController) {
+            BubbleBarPinController bubbleBarPinController,
+            BubblePinController bubblePinController) {
         this.bubbleBarController = bubbleBarController;
         this.bubbleBarViewController = bubbleBarViewController;
         this.bubbleStashController = bubbleStashController;
@@ -53,6 +55,7 @@
         this.bubbleDragController = bubbleDragController;
         this.bubbleDismissController = bubbleDismissController;
         this.bubbleBarPinController = bubbleBarPinController;
+        this.bubblePinController = bubblePinController;
     }
 
     /**
@@ -61,13 +64,15 @@
      * in constructors for now, as some controllers may still be waiting for init().
      */
     public void init(TaskbarControllers taskbarControllers) {
-        bubbleBarController.init(taskbarControllers, this);
+        bubbleBarController.init(this,
+                taskbarControllers.navbarButtonsViewController::isImeVisible);
         bubbleBarViewController.init(taskbarControllers, this);
         bubbleStashedHandleViewController.init(taskbarControllers, this);
         bubbleStashController.init(taskbarControllers, this);
         bubbleDragController.init(/* bubbleControllers = */ this);
         bubbleDismissController.init(/* bubbleControllers = */ this);
         bubbleBarPinController.init(this);
+        bubblePinController.init(this);
 
         mPostInitRunnables.executeAllAndDestroy();
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
index a40f33c..0e6fa3c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
@@ -40,7 +40,7 @@
  * @see BubbleDragController
  */
 public class BubbleDismissController {
-    private static final String TAG = BubbleDismissController.class.getSimpleName();
+    private static final String TAG = "BubbleDismissController";
     private static final float FLING_TO_DISMISS_MIN_VELOCITY = 6000f;
     private final TaskbarActivityContext mActivity;
     private final TaskbarDragLayer mDragLayer;
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
index 8b811d9..287e906 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
@@ -60,6 +60,7 @@
     private final float mBubbleFocusedScale;
     private final float mBubbleCapturedScale;
     private final float mDismissCapturedScale;
+    private final FloatPropertyCompat<View> mTranslationXProperty;
 
     /**
      * Should be initialised for each dragged view
@@ -81,9 +82,28 @@
         if (view instanceof BubbleBarView) {
             mBubbleFocusedScale = SCALE_BUBBLE_BAR_FOCUSED;
             mBubbleCapturedScale = mDismissCapturedScale;
+            mTranslationXProperty = DynamicAnimation.TRANSLATION_X;
         } else {
             mBubbleFocusedScale = SCALE_BUBBLE_FOCUSED;
             mBubbleCapturedScale = SCALE_BUBBLE_CAPTURED;
+            // Wrap BubbleView.DRAG_TRANSLATION_X as it can't be cast to FloatPropertyCompat<View>
+            mTranslationXProperty = new FloatPropertyCompat<>(
+                    BubbleView.DRAG_TRANSLATION_X.getName()) {
+                @Override
+                public float getValue(View object) {
+                    if (object instanceof BubbleView bubbleView) {
+                        return BubbleView.DRAG_TRANSLATION_X.get(bubbleView);
+                    }
+                    return 0;
+                }
+
+                @Override
+                public void setValue(View object, float value) {
+                    if (object instanceof BubbleView bubbleView) {
+                        BubbleView.DRAG_TRANSLATION_X.setValue(bubbleView, value);
+                    }
+                }
+            };
         }
     }
 
@@ -110,25 +130,25 @@
     /**
      * Animates the dragged bubble movement back to the initial position.
      *
-     * @param initialPosition the position to animate to
+     * @param restingPosition the position to animate to
      * @param velocity        the initial velocity to use for the spring animation
      * @param endActions      gets called when the animation completes or gets cancelled
      */
-    public void animateToInitialState(@NonNull PointF initialPosition, @NonNull PointF velocity,
+    public void animateToRestingState(@NonNull PointF restingPosition, @NonNull PointF velocity,
             @Nullable Runnable endActions) {
         mBubbleAnimator.cancel();
         mBubbleAnimator
                 .spring(DynamicAnimation.SCALE_X, 1f)
                 .spring(DynamicAnimation.SCALE_Y, 1f)
-                .spring(DynamicAnimation.TRANSLATION_X, initialPosition.x, velocity.x,
+                .spring(mTranslationXProperty, restingPosition.x, velocity.x,
                         mTranslationConfig)
-                .spring(DynamicAnimation.TRANSLATION_Y, initialPosition.y, velocity.y,
+                .spring(DynamicAnimation.TRANSLATION_Y, restingPosition.y, velocity.y,
                         mTranslationConfig)
                 .addEndListener((View target, @NonNull FloatPropertyCompat<? super View> property,
                         boolean wasFling, boolean canceled, float finalValue, float finalVelocity,
                         boolean allRelevantPropertyAnimationsEnded) -> {
                     if (canceled || allRelevantPropertyAnimationsEnded) {
-                        resetAnimatedViews(initialPosition);
+                        resetAnimatedViews(restingPosition);
                         if (endActions != null) {
                             endActions.run();
                         }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java
index 5ffc6d8..2ebc3e8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java
@@ -26,6 +26,8 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.taskbar.TaskbarActivityContext;
+import com.android.wm.shell.common.bubbles.BaseBubblePinController.LocationChangeListener;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
 
 /**
  * Controls bubble bar drag interactions.
@@ -37,9 +39,11 @@
  */
 public class BubbleDragController {
     private final TaskbarActivityContext mActivity;
+    private BubbleBarController mBubbleBarController;
     private BubbleBarViewController mBubbleBarViewController;
     private BubbleDismissController mBubbleDismissController;
     private BubbleBarPinController mBubbleBarPinController;
+    private BubblePinController mBubblePinController;
 
     public BubbleDragController(TaskbarActivityContext activity) {
         mActivity = activity;
@@ -51,13 +55,16 @@
      * controllers may still be waiting for init().
      */
     public void init(@NonNull BubbleControllers bubbleControllers) {
+        mBubbleBarController = bubbleControllers.bubbleBarController;
         mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
         mBubbleDismissController = bubbleControllers.bubbleDismissController;
         mBubbleBarPinController = bubbleControllers.bubbleBarPinController;
-        mBubbleBarPinController.setListener(
-                bubbleControllers.bubbleBarController::updateBubbleBarLocation);
+        mBubblePinController = bubbleControllers.bubblePinController;
         mBubbleDismissController.setListener(
-                stuck -> mBubbleBarPinController.setDropTargetHidden(stuck));
+                stuck -> {
+                    mBubbleBarPinController.setDropTargetHidden(stuck);
+                    mBubblePinController.setDropTargetHidden(stuck);
+                });
     }
 
     /**
@@ -71,19 +78,60 @@
         }
 
         bubbleView.setOnTouchListener(new BubbleTouchListener() {
+
+            private BubbleBarLocation mReleasedLocation = BubbleBarLocation.DEFAULT;
+
+            private final LocationChangeListener mLocationChangeListener =
+                    new LocationChangeListener() {
+                        @Override
+                        public void onChange(@NonNull BubbleBarLocation location) {
+                            mBubbleBarController.animateBubbleBarLocation(location);
+                        }
+
+                        @Override
+                        public void onRelease(@NonNull BubbleBarLocation location) {
+                            mReleasedLocation = location;
+                        }
+                    };
+
             @Override
             void onDragStart() {
-                mBubbleBarViewController.onDragStart(bubbleView);
+                mBubblePinController.setListener(mLocationChangeListener);
+                mBubbleBarViewController.onBubbleDragStart(bubbleView);
+                mBubblePinController.onDragStart(
+                        mBubbleBarViewController.getBubbleBarLocation().isOnLeft(
+                                bubbleView.isLayoutRtl()));
             }
 
             @Override
-            void onDragEnd() {
-                mBubbleBarViewController.onDragEnd();
+            protected void onDragUpdate(float x, float y, float newTx, float newTy) {
+                bubbleView.setDragTranslationX(newTx);
+                bubbleView.setTranslationY(newTy);
+                mBubblePinController.onDragUpdate(x, y);
             }
 
             @Override
             protected void onDragRelease() {
-                mBubbleBarViewController.onDragRelease(bubbleView);
+                mBubblePinController.onDragEnd();
+                mBubbleBarViewController.onBubbleDragRelease(mReleasedLocation);
+            }
+
+            @Override
+            protected void onDragDismiss() {
+                mBubblePinController.onDragEnd();
+            }
+
+            @Override
+            void onDragEnd() {
+                mBubbleBarController.updateBubbleBarLocation(mReleasedLocation);
+                mBubbleBarViewController.onBubbleDragEnd();
+                mBubblePinController.setListener(null);
+            }
+
+            @Override
+            protected PointF getRestingPosition() {
+                return mBubbleBarViewController.getDraggedBubbleReleaseTranslation(
+                        getInitialPosition(), mReleasedLocation);
             }
         });
     }
@@ -96,6 +144,11 @@
         PointF initialRelativePivot = new PointF();
         bubbleBarView.setOnTouchListener(new BubbleTouchListener() {
 
+            private BubbleBarLocation mReleasedLocation = BubbleBarLocation.DEFAULT;
+
+            private final LocationChangeListener mLocationChangeListener =
+                    location -> mReleasedLocation = location;
+
             @Override
             protected boolean onTouchDown(@NonNull View view, @NonNull MotionEvent event) {
                 if (bubbleBarView.isExpanded()) return false;
@@ -104,6 +157,7 @@
 
             @Override
             void onDragStart() {
+                mBubbleBarPinController.setListener(mLocationChangeListener);
                 initialRelativePivot.set(bubbleBarView.getRelativePivotX(),
                         bubbleBarView.getRelativePivotY());
                 // By default the bubble bar view pivot is in bottom right corner, while dragging
@@ -115,7 +169,9 @@
             }
 
             @Override
-            protected void onDragUpdate(float x, float y) {
+            protected void onDragUpdate(float x, float y, float newTx, float newTy) {
+                bubbleBarView.setTranslationX(newTx);
+                bubbleBarView.setTranslationY(newTy);
                 mBubbleBarPinController.onDragUpdate(x, y);
             }
 
@@ -131,16 +187,19 @@
 
             @Override
             void onDragEnd() {
+                // Make sure to update location as the first thing. Pivot update causes a relayout
+                mBubbleBarController.updateBubbleBarLocation(mReleasedLocation);
+                bubbleBarView.setIsDragging(false);
                 // Restoring the initial pivot for the bubble bar view
                 bubbleBarView.setRelativePivot(initialRelativePivot.x, initialRelativePivot.y);
-                bubbleBarView.setIsDragging(false);
+                mBubbleBarViewController.onBubbleBarDragEnd();
+                mBubbleBarPinController.setListener(null);
             }
 
             @Override
             protected PointF getRestingPosition() {
-                PointF restingPosition = super.getRestingPosition();
-                bubbleBarView.adjustRelativeRestingPosition(restingPosition);
-                return restingPosition;
+                return mBubbleBarViewController.getBubbleBarDragReleaseTranslation(
+                        getInitialPosition(), mReleasedLocation);
             }
         });
     }
@@ -206,8 +265,7 @@
          * Called when bubble is dragged to new coordinates.
          * Not called while bubble is stuck to the dismiss target.
          */
-        protected void onDragUpdate(float x, float y) {
-        }
+        protected abstract void onDragUpdate(float x, float y, float newTx, float newTy);
 
         /**
          * Called when the dragging interaction has ended and all the animations have completed
@@ -229,6 +287,13 @@
         }
 
         /**
+         * Get the initial position of the view when drag started
+         */
+        protected PointF getInitialPosition() {
+            return mViewInitialPosition;
+        }
+
+        /**
          * Get the resting position of the view when drag is released
          */
         protected PointF getRestingPosition() {
@@ -345,9 +410,9 @@
         private void drag(@NonNull View view, @NonNull MotionEvent event, float dx, float dy,
                 float x, float y) {
             if (mBubbleDismissController.handleTouchEvent(event)) return;
-            view.setTranslationX(mViewInitialPosition.x + dx);
-            view.setTranslationY(mViewInitialPosition.y + dy);
-            onDragUpdate(x, y);
+            final float newTx = mViewInitialPosition.x + dx;
+            final float newTy = mViewInitialPosition.y + dy;
+            onDragUpdate(x, y, newTx, newTy);
         }
 
         private void stopDragging(@NonNull View view, @NonNull MotionEvent event) {
@@ -362,7 +427,7 @@
                 mAnimator.animateDismiss(mViewInitialPosition, onComplete);
             } else {
                 onDragRelease();
-                mAnimator.animateToInitialState(getRestingPosition(), getCurrentVelocity(),
+                mAnimator.animateToRestingState(getRestingPosition(), getCurrentVelocity(),
                         onComplete);
             }
             mBubbleDismissController.hideDismissView();
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubblePinController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubblePinController.kt
new file mode 100644
index 0000000..a77e685
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubblePinController.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2024 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.taskbar.bubbles
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.Point
+import android.view.Gravity.BOTTOM
+import android.view.Gravity.LEFT
+import android.view.Gravity.RIGHT
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.FrameLayout
+import androidx.core.view.updateLayoutParams
+import com.android.launcher3.R
+import com.android.wm.shell.common.bubbles.BaseBubblePinController
+import com.android.wm.shell.common.bubbles.BubbleBarLocation
+
+/** Controller to manage pinning bubble bar to left or right when dragging starts from a bubble */
+class BubblePinController(
+    private val context: Context,
+    private val container: FrameLayout,
+    screenSizeProvider: () -> Point
+) : BaseBubblePinController(screenSizeProvider) {
+
+    var dropTargetSize: Point? = null
+
+    private lateinit var bubbleBarViewController: BubbleBarViewController
+    private lateinit var bubbleStashController: BubbleStashController
+    private var exclRectWidth: Float = 0f
+    private var exclRectHeight: Float = 0f
+
+    private var dropTargetView: View? = null
+    // Fallback width and height in case shell has not sent the size over
+    private var dropTargetDefaultWidth: Int = 0
+    private var dropTargetDefaultHeight: Int = 0
+    private var dropTargetMargin: Int = 0
+
+    fun init(bubbleControllers: BubbleControllers) {
+        bubbleBarViewController = bubbleControllers.bubbleBarViewController
+        bubbleStashController = bubbleControllers.bubbleStashController
+        exclRectWidth = context.resources.getDimension(R.dimen.bubblebar_dismiss_zone_width)
+        exclRectHeight = context.resources.getDimension(R.dimen.bubblebar_dismiss_zone_height)
+        dropTargetDefaultWidth =
+            context.resources.getDimensionPixelSize(
+                R.dimen.bubble_expanded_view_drop_target_default_width
+            )
+        dropTargetDefaultHeight =
+            context.resources.getDimensionPixelSize(
+                R.dimen.bubble_expanded_view_drop_target_default_height
+            )
+        dropTargetMargin =
+            context.resources.getDimensionPixelSize(R.dimen.bubble_expanded_view_drop_target_margin)
+    }
+
+    override fun getExclusionRectWidth(): Float {
+        return exclRectWidth
+    }
+
+    override fun getExclusionRectHeight(): Float {
+        return exclRectHeight
+    }
+
+    override fun getDropTargetView(): View? {
+        return dropTargetView
+    }
+
+    override fun removeDropTargetView(view: View) {
+        container.removeView(view)
+        dropTargetView = null
+    }
+
+    override fun createDropTargetView(): View {
+        return LayoutInflater.from(context)
+            .inflate(R.layout.bubble_expanded_view_drop_target, container, false)
+            .also { view ->
+                dropTargetView = view
+                container.addView(view)
+            }
+    }
+
+    @SuppressLint("RtlHardcoded")
+    override fun updateLocation(location: BubbleBarLocation) {
+        val onLeft = location.isOnLeft(container.isLayoutRtl)
+
+        val bubbleBarBounds = bubbleBarViewController.bubbleBarBounds
+        dropTargetView?.updateLayoutParams<FrameLayout.LayoutParams> {
+            gravity = BOTTOM or (if (onLeft) LEFT else RIGHT)
+            width = dropTargetSize?.x ?: dropTargetDefaultWidth
+            height = dropTargetSize?.y ?: dropTargetDefaultHeight
+            bottomMargin =
+                -bubbleStashController.bubbleBarTranslationY.toInt() +
+                    bubbleBarBounds.height() +
+                    dropTargetMargin
+        }
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
index bea0af8..5d01b9b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
@@ -25,6 +25,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 
+import com.android.launcher3.R;
 import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.taskbar.StashedHandleViewController;
 import com.android.launcher3.taskbar.TaskbarActivityContext;
@@ -41,7 +42,7 @@
  */
 public class BubbleStashController {
 
-    private static final String TAG = BubbleStashController.class.getSimpleName();
+    private static final String TAG = "BubbleStashController";
 
     /**
      * How long to stash/unstash.
@@ -77,11 +78,16 @@
     private boolean mBubblesShowingOnOverview;
     private boolean mIsSysuiLocked;
 
+    private final float mHandleCenterFromScreenBottom;
+
     @Nullable
     private AnimatorSet mAnimator;
 
     public BubbleStashController(TaskbarActivityContext activity) {
         mActivity = activity;
+        // the handle is centered within the stashed taskbar area
+        mHandleCenterFromScreenBottom =
+                mActivity.getResources().getDimensionPixelSize(R.dimen.bubblebar_stashed_size) / 2f;
     }
 
     public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
@@ -117,21 +123,17 @@
     }
 
     /**
-     * Animates the bubble bar and handle to their initial state, transitioning from the state where
-     * both views are invisible. Called when the first bubble is added or when the device is
+     * Animates the handle (or bubble bar depending on state) to be visible after the device is
      * unlocked.
      *
      * <p>Normally either the bubble bar or the handle is visible,
      * and {@link #showBubbleBar(boolean)} and {@link #stashBubbleBar()} are used to transition
      * between these two states. But the transition from the state where both the bar and handle
      * are invisible is slightly different.
-     *
-     * <p>The initial state will depend on the current state of the device, i.e. overview, home etc
-     * and whether bubbles are requested to be expanded.
      */
-    public void animateToInitialState(boolean expanding) {
+    private void animateAfterUnlock() {
         AnimatorSet animatorSet = new AnimatorSet();
-        if (expanding || mBubblesShowingOnHome || mBubblesShowingOnOverview) {
+        if (mBubblesShowingOnHome || mBubblesShowingOnOverview) {
             mIsStashed = false;
             animatorSet.playTogether(mIconScaleForStash.animateToValue(1),
                     mIconTranslationYForStash.animateToValue(getBubbleBarTranslationY()),
@@ -211,7 +213,7 @@
         if (isSysuiLocked != mIsSysuiLocked) {
             mIsSysuiLocked = isSysuiLocked;
             if (!mIsSysuiLocked && mBarViewController.hasBubbles()) {
-                animateToInitialState(false /* expanding */);
+                animateAfterUnlock();
             }
         }
     }
@@ -244,6 +246,11 @@
                 && !mBubblesShowingOnHome
                 && !mBubblesShowingOnOverview;
         if (mIsStashed != isStashed) {
+            // notify the view controller that the stash state is about to change so that it can
+            // cancel an ongoing animation if there is one.
+            // note that this has to be called before updating mIsStashed with the new value,
+            // otherwise interrupting an ongoing animation may update it again with the wrong state
+            mBarViewController.onStashStateChanging();
             mIsStashed = isStashed;
             if (mAnimator != null) {
                 mAnimator.cancel();
@@ -266,7 +273,6 @@
      */
     private AnimatorSet createStashAnimator(boolean isStashed, long duration) {
         AnimatorSet animatorSet = new AnimatorSet();
-        final float stashTranslation = (mUnstashedHeight - mStashedHeight) / 2f;
 
         AnimatorSet fullLengthAnimatorSet = new AnimatorSet();
         // Not exactly half and may overlap. See [first|second]HalfDurationScale below.
@@ -280,7 +286,8 @@
             firstHalfDurationScale = 0.75f;
             secondHalfDurationScale = 0.5f;
 
-            fullLengthAnimatorSet.play(mIconTranslationYForStash.animateToValue(stashTranslation));
+            fullLengthAnimatorSet.play(
+                    mIconTranslationYForStash.animateToValue(getStashTranslation()));
 
             firstHalfAnimatorSet.playTogether(
                     mIconAlphaForStash.animateToValue(0),
@@ -329,6 +336,10 @@
         return animatorSet;
     }
 
+    private float getStashTranslation() {
+        return (mUnstashedHeight - mStashedHeight) / 2f;
+    }
+
     private void onIsStashedChanged() {
         mControllers.runAfterInit(() -> {
             mHandleViewController.onIsStashedChanged();
@@ -336,7 +347,7 @@
         });
     }
 
-    private float getBubbleBarTranslationYForTaskbar() {
+    public float getBubbleBarTranslationYForTaskbar() {
         return -mActivity.getDeviceProfile().taskbarBottomMargin;
     }
 
@@ -355,6 +366,25 @@
                 : getBubbleBarTranslationYForTaskbar();
     }
 
+    /**
+     * The difference on the Y axis between the center of the handle and the center of the bubble
+     * bar.
+     */
+    public float getDiffBetweenHandleAndBarCenters() {
+        // the difference between the centers of the handle and the bubble bar is the difference
+        // between their distance from the bottom of the screen.
+
+        float barCenter = mBarViewController.getBubbleBarCollapsedHeight() / 2f;
+        return mHandleCenterFromScreenBottom - barCenter;
+    }
+
+    /** The distance the handle moves as part of the new bubble animation. */
+    public float getStashedHandleTranslationForNewBubbleAnimation() {
+        // the should move up to the top of the stashed taskbar area. it is centered within it so
+        // it should move the same distance as it is away from the bottom.
+        return -mHandleCenterFromScreenBottom;
+    }
+
     /** Checks whether the motion event is over the stash handle. */
     public boolean isEventOverStashHandle(MotionEvent ev) {
         return mHandleViewController.isEventOverHandle(ev);
@@ -365,11 +395,6 @@
         mHandleViewController.setBubbleBarLocation(bubbleBarLocation);
     }
 
-    /** Returns the x position of the center of the stashed handle. */
-    public float getStashedHandleCenterX() {
-        return mHandleViewController.getStashedHandleCenterX();
-    }
-
     /** Returns the [PhysicsAnimator] for the stashed handle view. */
     public PhysicsAnimator<View> getStashedHandlePhysicsAnimator() {
         return mHandleViewController.getPhysicsAnimator();
@@ -389,4 +414,44 @@
         mIsStashed = false;
         onIsStashedChanged();
     }
+
+    /** Stashes the bubble bar immediately without animation. */
+    public void stashBubbleBarImmediate() {
+        mHandleViewController.setTranslationYForSwipe(0);
+        mIconAlphaForStash.setValue(0);
+        mIconTranslationYForStash.updateValue(getStashTranslation());
+        mIconScaleForStash.updateValue(STASHED_BAR_SCALE);
+        mIsStashed = true;
+        onIsStashedChanged();
+    }
+
+    /**
+     * Updates the values of the internal animators after the new bubble animation was interrupted
+     *
+     * @param isStashed whether the current state should be stashed
+     * @param bubbleBarTranslationY the current bubble bar translation. this is only used if the
+     *                              bubble bar is showing to ensure that the stash animator runs
+     *                              smoothly.
+     */
+    public void onNewBubbleAnimationInterrupted(boolean isStashed, float bubbleBarTranslationY) {
+        if (isStashed) {
+            mBubbleStashedHandleAlpha.setValue(1);
+            mIconAlphaForStash.setValue(0);
+            mIconScaleForStash.updateValue(STASHED_BAR_SCALE);
+            mIconTranslationYForStash.updateValue(getStashTranslation());
+        } else {
+            mBubbleStashedHandleAlpha.setValue(0);
+            mHandleViewController.setTranslationYForSwipe(0);
+            mIconAlphaForStash.setValue(1);
+            mIconScaleForStash.updateValue(1);
+            mIconTranslationYForStash.updateValue(bubbleBarTranslationY);
+        }
+        mIsStashed = isStashed;
+        onIsStashedChanged();
+    }
+
+    /** Set the translation Y for the stashed handle. */
+    public void setHandleTranslationY(float ty) {
+        mHandleViewController.setTranslationYForSwipe(ty);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
index 6f1a093..91103d7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
@@ -251,11 +251,6 @@
         return mStashedHandleAlpha;
     }
 
-    /** Returns the x position of the center of the stashed handle. */
-    public float getStashedHandleCenterX() {
-        return mStashedHandleBounds.exactCenterX();
-    }
-
     /**
      * Creates and returns an Animator that updates the stashed handle  shape and size.
      * When stashed, the shape is a thin rounded pill. When unstashed, the shape morphs into
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
index bcdc718..61a6bce 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
@@ -22,11 +22,13 @@
 import android.graphics.Outline;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.util.FloatProperty;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewOutlineProvider;
 import android.widget.ImageView;
 
+import androidx.annotation.NonNull;
 import androidx.constraintlayout.widget.ConstraintLayout;
 
 import com.android.launcher3.R;
@@ -47,6 +49,25 @@
     public static final int DEFAULT_PATH_SIZE = 100;
 
     /**
+     * Property to update drag translation value.
+     *
+     * @see BubbleView#getDragTranslationX()
+     * @see BubbleView#setDragTranslationX(float)
+     */
+    public static final FloatProperty<BubbleView> DRAG_TRANSLATION_X = new FloatProperty<>(
+            "dragTranslationX") {
+        @Override
+        public void setValue(@NonNull BubbleView bubbleView, float value) {
+            bubbleView.setDragTranslationX(value);
+        }
+
+        @Override
+        public Float get(BubbleView bubbleView) {
+            return bubbleView.getDragTranslationX();
+        }
+    };
+
+    /**
      * Flags that suppress the visibility of the 'new' dot or the app badge, for one reason or
      * another. If any of these flags are set, the dot will not be shown.
      * If {@link SuppressionFlag#BEHIND_STACK} then the app badge will not be shown.
@@ -66,6 +87,9 @@
     private final ImageView mAppIcon;
     private final int mBubbleSize;
 
+    private float mDragTranslationX;
+    private float mOffsetX;
+
     private DotRenderer mDotRenderer;
     private DotRenderer.DrawParams mDrawParams;
     private int mDotColor;
@@ -126,6 +150,39 @@
         outline.setOval(inset, inset, inset + normalizedSize, inset + normalizedSize);
     }
 
+    /**
+     * Set translation-x while this bubble is being dragged.
+     * Translation applied to the view is a sum of {@code translationX} and offset defined by
+     * {@link #setOffsetX(float)}.
+     */
+    public void setDragTranslationX(float translationX) {
+        mDragTranslationX = translationX;
+        applyDragTranslation();
+    }
+
+    /**
+     * Get translation value applied via {@link #setDragTranslationX(float)}.
+     */
+    public float getDragTranslationX() {
+        return mDragTranslationX;
+    }
+
+    /**
+     * Set offset on x-axis while dragging.
+     * Used to counter parent translation in order to keep the dragged view at the current position
+     * on screen.
+     * Translation applied to the view is a sum of {@code offsetX} and translation defined by
+     * {@link #setDragTranslationX(float)}
+     */
+    public void setOffsetX(float offsetX) {
+        mOffsetX = offsetX;
+        applyDragTranslation();
+    }
+
+    private void applyDragTranslation() {
+        setTranslationX(mDragTranslationX + mOffsetX);
+    }
+
     @Override
     public void dispatchDraw(Canvas canvas) {
         super.dispatchDraw(canvas);
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
index da36944..d88e272 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
@@ -40,20 +40,10 @@
     private companion object {
         /** The time to show the flyout. */
         const val FLYOUT_DELAY_MS: Long = 2500
-        /** The translation Y the new bubble will animate to. */
-        const val BUBBLE_ANIMATION_BUBBLE_TRANSLATION_Y = -50f
-        /** The initial translation Y value the new bubble is set to before the animation starts. */
-        // TODO(liranb): get rid of this and calculate this based on the y-distance between the
-        // bubble and the stash handle.
-        const val BUBBLE_ANIMATION_TRANSLATION_Y_OFFSET = 50f
         /** The initial scale Y value that the new bubble is set to before the animation starts. */
         const val BUBBLE_ANIMATION_INITIAL_SCALE_Y = 0.3f
-        /**
-         * The distance the stashed handle will travel as it gets hidden as part of the new bubble
-         * animation.
-         */
-        // TODO(liranb): calculate this based on the position of the views
-        const val BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y = -20f
+        /** The minimum alpha value to make the bubble bar touchable. */
+        const val MIN_ALPHA_FOR_TOUCHABLE = 0.5f
     }
 
     /** Wrapper around the animating bubble with its show and hide animations. */
@@ -105,184 +95,253 @@
         if (animator.isRunning()) animator.cancel()
         // the animation of a new bubble is divided into 2 parts. The first part shows the bubble
         // and the second part hides it after a delay.
-        val showAnimation = buildShowAnimation(bubbleView, b.key)
-        val hideAnimation = buildHideAnimation(bubbleView)
+        val showAnimation = buildHandleToBubbleBarAnimation()
+        val hideAnimation = buildBubbleBarToHandleAnimation()
         animatingBubble = AnimatingBubble(bubbleView, showAnimation, hideAnimation)
         scheduler.post(showAnimation)
         scheduler.postDelayed(FLYOUT_DELAY_MS, hideAnimation)
     }
 
     /**
-     * Returns a lambda that starts the animation that shows the new bubble.
+     * Returns a [Runnable] that starts the animation that morphs the handle to the bubble bar.
      *
      * Visually, the animation is divided into 2 parts. The stash handle starts animating up and
-     * fading out and then the bubble starts animating up and fading in.
+     * fading out and then the bubble bar starts animating up and fading in.
      *
-     * To make the transition from the handle to the bubble smooth, the positions and movement of
-     * the 2 views must be synchronized. To do that we use a single spring path along the Y axis,
-     * starting from the handle's position to the eventual bubble's position. The path is split into
-     * 3 parts.
+     * To make the transition from the handle to the bar smooth, the positions and movement of the 2
+     * views must be synchronized. To do that we use a single spring path along the Y axis, starting
+     * from the handle's position to the eventual bar's position. The path is split into 3 parts.
      * 1. In the first part, we only animate the handle.
-     * 1. In the second part the handle is fully hidden, and the bubble is animating in.
-     * 1. The third part is the overshoot of the spring animation, where we make the bubble fully
+     * 2. In the second part the handle is fully hidden, and the bubble bar is animating in.
+     * 3. The third part is the overshoot of the spring animation, where we make the bubble fully
      *    visible which helps avoiding further updates when we re-enter the second part.
      */
-    private fun buildShowAnimation(
-        bubbleView: BubbleView,
-        key: String,
-    ) = Runnable {
-        bubbleBarView.prepareForAnimatingBubbleWhileStashed(key)
-        // calculate the initial translation x the bubble should have in order to align it with the
-        // stash handle.
-        val initialTranslationX =
-            bubbleStashController.stashedHandleCenterX - bubbleView.centerXOnScreen
-        // prepare the bubble for the animation
-        bubbleView.alpha = 0f
-        bubbleView.translationX = initialTranslationX
-        bubbleView.scaleY = BUBBLE_ANIMATION_INITIAL_SCALE_Y
-        bubbleView.visibility = VISIBLE
+    private fun buildHandleToBubbleBarAnimation() = Runnable {
+        // prepare the bubble bar for the animation
+        bubbleBarView.onAnimatingBubbleStarted()
+        bubbleBarView.visibility = VISIBLE
+        bubbleBarView.alpha = 0f
+        bubbleBarView.translationY = 0f
+        bubbleBarView.scaleX = 1f
+        bubbleBarView.scaleY = BUBBLE_ANIMATION_INITIAL_SCALE_Y
+        bubbleBarView.relativePivotY = 0.5f
+
+        // this is the offset between the center of the bubble bar and the center of the stash
+        // handle. when the handle becomes invisible and we start animating in the bubble bar,
+        // the translation y is offset by this value to make the transition from the handle to the
+        // bar smooth.
+        val offset = bubbleStashController.diffBetweenHandleAndBarCenters
+        val stashedHandleTranslationY =
+            bubbleStashController.stashedHandleTranslationForNewBubbleAnimation
 
         // this is the total distance that both the stashed handle and the bubble will be traveling
-        val totalTranslationY =
-            BUBBLE_ANIMATION_BUBBLE_TRANSLATION_Y + BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y
+        // at the end of the animation the bubble bar will be positioned in the same place when it
+        // shows while we're in an app.
+        val totalTranslationY = bubbleStashController.bubbleBarTranslationYForTaskbar + offset
         val animator = bubbleStashController.stashedHandlePhysicsAnimator
         animator.setDefaultSpringConfig(springConfig)
         animator.spring(DynamicAnimation.TRANSLATION_Y, totalTranslationY)
-        animator.addUpdateListener { target, values ->
+        animator.addUpdateListener { handle, values ->
             val ty = values[DynamicAnimation.TRANSLATION_Y]?.value ?: return@addUpdateListener
             when {
-                ty >= BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y -> {
+                ty >= stashedHandleTranslationY -> {
                     // we're in the first leg of the animation. only animate the handle. the bubble
-                    // remains hidden during this part of the animation
+                    // bar remains hidden during this part of the animation
 
-                    // map the path [0, BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y] to [0,1]
-                    val fraction = ty / BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y
-                    target.alpha = 1 - fraction
+                    // map the path [0, stashedHandleTranslationY] to [0,1]
+                    val fraction = ty / stashedHandleTranslationY
+                    handle.alpha = 1 - fraction
                 }
                 ty >= totalTranslationY -> {
                     // this is the second leg of the animation. the handle should be completely
-                    // hidden and the bubble should start animating in.
+                    // hidden and the bubble bar should start animating in.
                     // it's possible that we're re-entering this leg because this is a spring
-                    // animation, so only set the alpha and scale for the bubble if we didn't
+                    // animation, so only set the alpha and scale for the bubble bar if we didn't
                     // already fully animate in.
-                    target.alpha = 0f
-                    bubbleView.translationY = ty + BUBBLE_ANIMATION_TRANSLATION_Y_OFFSET
-                    if (bubbleView.alpha != 1f) {
-                        // map the path
-                        // [BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y, totalTranslationY]
-                        // to [0, 1]
+                    handle.alpha = 0f
+                    bubbleBarView.translationY = ty - offset
+                    if (bubbleBarView.alpha != 1f) {
+                        // map the path [stashedHandleTranslationY, totalTranslationY] to [0, 1]
                         val fraction =
-                            (ty - BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y) /
-                                BUBBLE_ANIMATION_BUBBLE_TRANSLATION_Y
-                        bubbleView.alpha = fraction
-                        bubbleView.scaleY =
+                            (ty - stashedHandleTranslationY) /
+                                (totalTranslationY - stashedHandleTranslationY)
+                        bubbleBarView.alpha = fraction
+                        bubbleBarView.scaleY =
                             BUBBLE_ANIMATION_INITIAL_SCALE_Y +
                                 (1 - BUBBLE_ANIMATION_INITIAL_SCALE_Y) * fraction
+                        if (bubbleBarView.alpha > MIN_ALPHA_FOR_TOUCHABLE) {
+                            bubbleStashController.updateTaskbarTouchRegion()
+                        }
                     }
                 }
                 else -> {
                     // we're past the target animated value, set the alpha and scale for the bubble
-                    // so that it's fully visible and no longer changing, but keep moving it along
-                    // the animation path
-                    bubbleView.alpha = 1f
-                    bubbleView.scaleY = 1f
-                    bubbleView.translationY = ty + BUBBLE_ANIMATION_TRANSLATION_Y_OFFSET
+                    // bar so that it's fully visible and no longer changing, but keep moving it
+                    // along the animation path
+                    bubbleBarView.alpha = 1f
+                    bubbleBarView.scaleY = 1f
+                    bubbleBarView.translationY = ty - offset
+                    bubbleStashController.updateTaskbarTouchRegion()
                 }
             }
         }
-        animator.addEndListener { _, _, _, _, _, _, _ ->
-            // the bubble is now fully settled in. make it touchable
-            bubbleBarView.updateAnimatingBubbleBounds(
-                bubbleView.left,
-                bubbleView.top,
-                bubbleView.width,
-                bubbleView.height
-            )
+        animator.addEndListener { _, _, _, canceled, _, _, _ ->
+            // if the show animation was canceled, also cancel the hide animation. this is typically
+            // canceled in this class, but could potentially be canceled elsewhere.
+            if (canceled) {
+                val hideAnimation = animatingBubble?.hideAnimation ?: return@addEndListener
+                scheduler.cancel(hideAnimation)
+                animatingBubble = null
+                bubbleBarView.onAnimatingBubbleCompleted()
+                bubbleBarView.relativePivotY = 1f
+                return@addEndListener
+            }
+            // the bubble bar is now fully settled in. update taskbar touch region so it's touchable
             bubbleStashController.updateTaskbarTouchRegion()
         }
         animator.start()
     }
 
     /**
-     * Returns a lambda that starts the animation that hides the new bubble.
+     * Returns a [Runnable] that starts the animation that hides the bubble bar and morphs it into
+     * the stashed handle.
      *
      * Similarly to the show animation, this is visually divided into 2 parts. We first animate the
-     * bubble out, and then animate the stash handle in. At the end of the animation we reset the
-     * values of the bubble.
+     * bubble bar out, and then animate the stash handle in. At the end of the animation we reset
+     * values of the bubble bar.
      *
      * This is a spring animation that goes along the same path of the show animation in the
      * opposite order, and is split into 3 parts:
      * 1. In the first part the bubble animates out.
-     * 1. In the second part the bubble is fully hidden and the handle animates in.
-     * 1. The third part is the overshoot. The handle is made fully visible.
+     * 2. In the second part the bubble bar is fully hidden and the handle animates in.
+     * 3. The third part is the overshoot. The handle is made fully visible.
      */
-    private fun buildHideAnimation(bubbleView: BubbleView) = Runnable {
-        // this is the total distance that both the stashed handle and the bubble will be traveling
-        val totalTranslationY =
-            BUBBLE_ANIMATION_BUBBLE_TRANSLATION_Y + BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y
+    private fun buildBubbleBarToHandleAnimation() = Runnable {
+        if (animatingBubble == null) return@Runnable
+        val offset = bubbleStashController.diffBetweenHandleAndBarCenters
+        val stashedHandleTranslationY =
+            bubbleStashController.stashedHandleTranslationForNewBubbleAnimation
+        // this is the total distance that both the stashed handle and the bar will be traveling
+        val totalTranslationY = bubbleStashController.bubbleBarTranslationYForTaskbar + offset
+        bubbleStashController.setHandleTranslationY(totalTranslationY)
         val animator = bubbleStashController.stashedHandlePhysicsAnimator
         animator.setDefaultSpringConfig(springConfig)
         animator.spring(DynamicAnimation.TRANSLATION_Y, 0f)
-        animator.addUpdateListener { target, values ->
+        animator.addUpdateListener { handle, values ->
             val ty = values[DynamicAnimation.TRANSLATION_Y]?.value ?: return@addUpdateListener
             when {
-                ty <= BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y -> {
-                    // this is the first leg of the animation. only animate the bubble. the handle
-                    // is hidden during this part
-                    bubbleView.translationY = ty + BUBBLE_ANIMATION_TRANSLATION_Y_OFFSET
-                    // map the path
-                    // [totalTranslationY, BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y]
-                    // to [0, 1]
-                    val fraction = (totalTranslationY - ty) / BUBBLE_ANIMATION_BUBBLE_TRANSLATION_Y
-                    bubbleView.alpha = 1 - fraction / 2
-                    bubbleView.scaleY = 1 - (1 - BUBBLE_ANIMATION_INITIAL_SCALE_Y) * fraction
+                ty <= stashedHandleTranslationY -> {
+                    // this is the first leg of the animation. only animate the bubble bar. the
+                    // handle is hidden during this part
+                    bubbleBarView.translationY = ty - offset
+                    // map the path [totalTranslationY, stashedHandleTranslationY] to [0, 1]
+                    val fraction =
+                        (totalTranslationY - ty) / (totalTranslationY - stashedHandleTranslationY)
+                    bubbleBarView.alpha = 1 - fraction
+                    bubbleBarView.scaleY = 1 - (1 - BUBBLE_ANIMATION_INITIAL_SCALE_Y) * fraction
+                    if (bubbleBarView.alpha > MIN_ALPHA_FOR_TOUCHABLE) {
+                        bubbleStashController.updateTaskbarTouchRegion()
+                    }
                 }
                 ty <= 0 -> {
-                    // this is the second part of the animation. make the bubble invisible and
+                    // this is the second part of the animation. make the bubble bar invisible and
                     // start fading in the handle, but don't update the alpha if it's already fully
                     // visible
-                    bubbleView.alpha = 0f
-                    if (target.alpha != 1f) {
-                        // map the path [BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y, 0] to [0, 1]
-                        val fraction =
-                            (BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y - ty) /
-                                BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y
-                        target.alpha = fraction
+                    bubbleBarView.alpha = 0f
+                    if (handle.alpha != 1f) {
+                        // map the path [stashedHandleTranslationY, 0] to [0, 1]
+                        val fraction = (stashedHandleTranslationY - ty) / stashedHandleTranslationY
+                        handle.alpha = fraction
                     }
                 }
                 else -> {
                     // we reached the target value. set the alpha of the handle to 1
-                    target.alpha = 1f
+                    handle.alpha = 1f
                 }
             }
         }
-        animator.addEndListener { _, _, _, _, _, _, _ ->
+        animator.addEndListener { _, _, _, canceled, _, _, _ ->
             animatingBubble = null
-            bubbleView.alpha = 0f
-            bubbleView.translationY = 0f
-            bubbleView.scaleY = 1f
-            if (bubbleStashController.isStashed) {
-                bubbleBarView.alpha = 0f
-            }
+            if (!canceled) bubbleStashController.stashBubbleBarImmediate()
             bubbleBarView.onAnimatingBubbleCompleted()
+            bubbleBarView.relativePivotY = 1f
             bubbleStashController.updateTaskbarTouchRegion()
         }
         animator.start()
     }
 
-    /** Handles clicking on the animating bubble while the animation is still playing. */
-    fun onBubbleClickedWhileAnimating() {
+    /** Animates to the initial state of the bubble bar, when there are no previous bubbles. */
+    fun animateToInitialState(b: BubbleBarBubble, isInApp: Boolean, isExpanding: Boolean) {
+        val bubbleView = b.view
+        val animator = PhysicsAnimator.getInstance(bubbleView)
+        if (animator.isRunning()) animator.cancel()
+        // the animation of a new bubble is divided into 2 parts. The first part shows the bubble
+        // and the second part hides it after a delay if we are in an app.
+        val showAnimation = buildBubbleBarBounceAnimation()
+        val hideAnimation =
+            if (isInApp && !isExpanding) {
+                buildBubbleBarToHandleAnimation()
+            } else {
+                // in this case the bubble bar remains visible so not much to do. once we implement
+                // the flyout we'll update this runnable to hide it.
+                Runnable {
+                    animatingBubble = null
+                    bubbleStashController.showBubbleBarImmediate()
+                    bubbleBarView.onAnimatingBubbleCompleted()
+                    bubbleStashController.updateTaskbarTouchRegion()
+                }
+            }
+        animatingBubble = AnimatingBubble(bubbleView, showAnimation, hideAnimation)
+        scheduler.post(showAnimation)
+        scheduler.postDelayed(FLYOUT_DELAY_MS, hideAnimation)
+    }
+
+    private fun buildBubbleBarBounceAnimation() = Runnable {
+        // prepare the bubble bar for the animation
+        bubbleBarView.onAnimatingBubbleStarted()
+        bubbleBarView.translationY = bubbleBarView.height.toFloat()
+        bubbleBarView.visibility = VISIBLE
+        bubbleBarView.alpha = 1f
+        bubbleBarView.scaleX = 1f
+        bubbleBarView.scaleY = 1f
+
+        val animator = PhysicsAnimator.getInstance(bubbleBarView)
+        animator.setDefaultSpringConfig(springConfig)
+        animator.spring(DynamicAnimation.TRANSLATION_Y, bubbleStashController.bubbleBarTranslationY)
+        animator.addUpdateListener { _, _ -> bubbleStashController.updateTaskbarTouchRegion() }
+        animator.addEndListener { _, _, _, _, _, _, _ ->
+            // the bubble bar is now fully settled in. update taskbar touch region so it's touchable
+            bubbleStashController.updateTaskbarTouchRegion()
+        }
+        animator.start()
+    }
+
+    /** Handles touching the animating bubble bar. */
+    fun onBubbleBarTouchedWhileAnimating() {
+        PhysicsAnimator.getInstance(bubbleBarView).cancelIfRunning()
+        bubbleStashController.stashedHandlePhysicsAnimator.cancelIfRunning()
         val hideAnimation = animatingBubble?.hideAnimation ?: return
         scheduler.cancel(hideAnimation)
         bubbleBarView.onAnimatingBubbleCompleted()
+        bubbleBarView.relativePivotY = 1f
         animatingBubble = null
     }
-}
 
-/** The X position in screen coordinates of the center of the bubble. */
-private val BubbleView.centerXOnScreen: Float
-    get() {
-        val screenCoordinates = IntArray(2)
-        getLocationOnScreen(screenCoordinates)
-        return screenCoordinates[0] + width / 2f
+    /** Notifies the animator that the taskbar area was touched during an animation. */
+    fun onStashStateChangingWhileAnimating() {
+        val hideAnimation = animatingBubble?.hideAnimation ?: return
+        scheduler.cancel(hideAnimation)
+        animatingBubble = null
+        bubbleStashController.stashedHandlePhysicsAnimator.cancel()
+        bubbleBarView.onAnimatingBubbleCompleted()
+        bubbleBarView.relativePivotY = 1f
+        bubbleStashController.onNewBubbleAnimationInterrupted(
+            /* isStashed= */ bubbleBarView.alpha == 0f,
+            bubbleBarView.translationY
+        )
     }
+
+    private fun <T> PhysicsAnimator<T>.cancelIfRunning() {
+        if (isRunning()) cancel()
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
index fe91362..e487f9f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
@@ -24,10 +24,11 @@
 import android.widget.ImageView
 import android.widget.LinearLayout
 import android.widget.Space
+import com.android.launcher3.DeviceProfile
 import com.android.launcher3.R
 import com.android.launcher3.Utilities
+import com.android.launcher3.taskbar.TaskbarActivityContext
 import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.NavButtonLayoutter
-import com.android.systemui.shared.rotation.RotationButton
 
 /**
  * Meant to be a simple container for data subclasses will need
@@ -41,14 +42,13 @@
  * @property startContextualContainer ViewGroup that holds the start contextual button (ex, A11y).
  */
 abstract class AbstractNavButtonLayoutter(
-        val resources: Resources,
-        val navButtonContainer: LinearLayout,
-        protected val endContextualContainer: ViewGroup,
-        protected val startContextualContainer: ViewGroup,
-        protected val imeSwitcher: ImageView?,
-        protected val rotationButton: RotationButton?,
-        protected val a11yButton: ImageView?,
-        protected val space: Space?
+    val resources: Resources,
+    val navButtonContainer: LinearLayout,
+    protected val endContextualContainer: ViewGroup,
+    protected val startContextualContainer: ViewGroup,
+    protected val imeSwitcher: ImageView?,
+    protected val a11yButton: ImageView?,
+    protected val space: Space?
 ) : NavButtonLayoutter {
     protected val homeButton: ImageView? = navButtonContainer.findViewById(R.id.home)
     protected val recentsButton: ImageView? = navButtonContainer.findViewById(R.id.recent_apps)
@@ -66,17 +66,41 @@
     }
 
     fun getParamsToCenterView(): FrameLayout.LayoutParams {
-        val params = FrameLayout.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
+        val params =
+            FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT
+            )
         params.gravity = Gravity.CENTER
-        return params;
+        return params
     }
 
-    open fun repositionContextualContainer(contextualContainer: ViewGroup, buttonSize: Int,
-                                           barAxisMarginStart: Int, barAxisMarginEnd: Int,
-                                           gravity: Int) {
-        val contextualContainerParams = FrameLayout.LayoutParams(
-                buttonSize, ViewGroup.LayoutParams.MATCH_PARENT)
+    fun adjustForSetupInPhoneMode(
+        navButtonsLayoutParams: FrameLayout.LayoutParams,
+        navButtonsViewLayoutParams: FrameLayout.LayoutParams,
+        deviceProfile: DeviceProfile
+    ) {
+        val phoneOrPortraitSetupMargin =
+            resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_margin)
+        navButtonsLayoutParams.marginStart = phoneOrPortraitSetupMargin
+        navButtonsLayoutParams.bottomMargin =
+            if (!deviceProfile.isLandscape) 0
+            else
+                phoneOrPortraitSetupMargin -
+                        resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size) / 2
+        navButtonsViewLayoutParams.height =
+            resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_height)
+    }
+
+    open fun repositionContextualContainer(
+        contextualContainer: ViewGroup,
+        buttonSize: Int,
+        barAxisMarginStart: Int,
+        barAxisMarginEnd: Int,
+        gravity: Int
+    ) {
+        val contextualContainerParams =
+            FrameLayout.LayoutParams(buttonSize, ViewGroup.LayoutParams.MATCH_PARENT)
         contextualContainerParams.apply {
             marginStart = barAxisMarginStart
             marginEnd = barAxisMarginEnd
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt
index 4368b95..aa8f5a3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt
@@ -29,27 +29,24 @@
 import com.android.launcher3.R
 import com.android.launcher3.taskbar.TaskbarActivityContext
 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.*
-import com.android.systemui.shared.rotation.RotationButton
 
 class KidsNavLayoutter(
-        resources: Resources,
-        navBarContainer: LinearLayout,
-        endContextualContainer: ViewGroup,
-        startContextualContainer: ViewGroup,
-        imeSwitcher: ImageView?,
-        rotationButton: RotationButton?,
-        a11yButton: ImageView?,
-        space: Space?
+    resources: Resources,
+    navBarContainer: LinearLayout,
+    endContextualContainer: ViewGroup,
+    startContextualContainer: ViewGroup,
+    imeSwitcher: ImageView?,
+    a11yButton: ImageView?,
+    space: Space?
 ) :
     AbstractNavButtonLayoutter(
-            resources,
-            navBarContainer,
-            endContextualContainer,
-            startContextualContainer,
-            imeSwitcher,
-            rotationButton,
-            a11yButton,
-            space
+        resources,
+        navBarContainer,
+        endContextualContainer,
+        startContextualContainer,
+        imeSwitcher,
+        a11yButton,
+        space
     ) {
 
     override fun layoutButtons(context: TaskbarActivityContext, isA11yButtonPersistent: Boolean) {
@@ -105,11 +102,16 @@
         endContextualContainer.removeAllViews()
         startContextualContainer.removeAllViews()
 
-        val contextualMargin = resources.getDimensionPixelSize(
-                R.dimen.taskbar_contextual_button_padding)
+        val contextualMargin =
+            resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_padding)
         repositionContextualContainer(endContextualContainer, WRAP_CONTENT, 0, 0, Gravity.END)
-        repositionContextualContainer(startContextualContainer, WRAP_CONTENT, contextualMargin,
-                contextualMargin, Gravity.START)
+        repositionContextualContainer(
+            startContextualContainer,
+            WRAP_CONTENT,
+            contextualMargin,
+            contextualMargin,
+            Gravity.START
+        )
 
         if (imeSwitcher != null) {
             startContextualContainer.addView(imeSwitcher)
@@ -119,9 +121,5 @@
             endContextualContainer.addView(a11yButton)
             a11yButton.layoutParams = getParamsToCenterView()
         }
-        if (rotationButton != null) {
-            endContextualContainer.addView(rotationButton.currentView)
-            rotationButton.currentView.layoutParams = getParamsToCenterView()
-        }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
index 5bfdce9..2497fbb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
@@ -25,10 +25,11 @@
 import android.widget.Space
 import com.android.launcher3.DeviceProfile
 import com.android.launcher3.taskbar.TaskbarActivityContext
-import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.*
+import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_END_CONTEXTUAL_BUTTONS
+import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_END_NAV_BUTTONS
+import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_START_CONTEXTUAL_BUTTONS
 import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.Companion
 import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.NavButtonLayoutter
-import com.android.systemui.shared.rotation.RotationButton
 
 /**
  * Select the correct layout for nav buttons
@@ -58,7 +59,6 @@
             deviceProfile: DeviceProfile,
             navButtonsView: NearestTouchFrame,
             imeSwitcher: ImageView?,
-            rotationButton: RotationButton?,
             a11yButton: ImageView?,
             space: Space?,
             resources: Resources,
@@ -86,7 +86,6 @@
                             endContextualContainer,
                             startContextualContainer,
                             imeSwitcher,
-                            rotationButton,
                             a11yButton,
                             space
                         )
@@ -98,7 +97,6 @@
                             endContextualContainer,
                             startContextualContainer,
                             imeSwitcher,
-                            rotationButton,
                             a11yButton,
                             space
                         )
@@ -110,7 +108,6 @@
                             endContextualContainer,
                             startContextualContainer,
                             imeSwitcher,
-                            rotationButton,
                             a11yButton,
                             space
                         )
@@ -119,11 +116,11 @@
                 isPhoneGestureMode -> {
                     PhoneGestureLayoutter(
                         resources,
+                        navButtonsView,
                         navButtonContainer,
                         endContextualContainer,
                         startContextualContainer,
                         imeSwitcher,
-                        rotationButton,
                         a11yButton,
                         space
                     )
@@ -138,7 +135,6 @@
                                 endContextualContainer,
                                 startContextualContainer,
                                 imeSwitcher,
-                                rotationButton,
                                 a11yButton,
                                 space
                             )
@@ -150,7 +146,6 @@
                                 endContextualContainer,
                                 startContextualContainer,
                                 imeSwitcher,
-                                rotationButton,
                                 a11yButton,
                                 space
                             )
@@ -162,7 +157,6 @@
                                 endContextualContainer,
                                 startContextualContainer,
                                 imeSwitcher,
-                                rotationButton,
                                 a11yButton,
                                 space
                             )
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt
index bf820c0..390ec34 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt
@@ -17,36 +17,60 @@
 package com.android.launcher3.taskbar.navbutton
 
 import android.content.res.Resources
+import android.view.Gravity
 import android.view.ViewGroup
+import android.widget.FrameLayout
 import android.widget.ImageView
 import android.widget.LinearLayout
 import android.widget.Space
+import com.android.launcher3.DeviceProfile
 import com.android.launcher3.taskbar.TaskbarActivityContext
-import com.android.systemui.shared.rotation.RotationButton
 
 /** Layoutter for showing gesture navigation on phone screen. No buttons here, no-op container */
 class PhoneGestureLayoutter(
-        resources: Resources,
-        navBarContainer: LinearLayout,
-        endContextualContainer: ViewGroup,
-        startContextualContainer: ViewGroup,
-        imeSwitcher: ImageView?,
-        rotationButton: RotationButton?,
-        a11yButton: ImageView?,
-        space: Space?
+    resources: Resources,
+    navButtonsView: NearestTouchFrame,
+    navBarContainer: LinearLayout,
+    endContextualContainer: ViewGroup,
+    startContextualContainer: ViewGroup,
+    imeSwitcher: ImageView?,
+    a11yButton: ImageView?,
+    space: Space?
 ) :
-        AbstractNavButtonLayoutter(
-                resources,
-                navBarContainer,
-                endContextualContainer,
-                startContextualContainer,
-                imeSwitcher,
-                rotationButton,
-                a11yButton,
-                space
-        ) {
+    AbstractNavButtonLayoutter(
+        resources,
+        navBarContainer,
+        endContextualContainer,
+        startContextualContainer,
+        imeSwitcher,
+        a11yButton,
+        space
+    ) {
+    private val mNavButtonsView = navButtonsView
 
     override fun layoutButtons(context: TaskbarActivityContext, isA11yButtonPersistent: Boolean) {
+        // TODO: look into if we should use SetupNavLayoutter instead.
+        if (!context.isUserSetupComplete) {
+            // Since setup wizard only has back button enabled, it looks strange to be
+            // end-aligned, so start-align instead.
+            val navButtonsLayoutParams = navButtonContainer.layoutParams as FrameLayout.LayoutParams
+            val navButtonsViewLayoutParams =
+                mNavButtonsView.layoutParams as FrameLayout.LayoutParams
+            val deviceProfile: DeviceProfile = context.deviceProfile
+
+            navButtonsLayoutParams.marginEnd = 0
+            navButtonsLayoutParams.gravity = Gravity.START
+            context.setTaskbarWindowSize(context.setupWindowSize)
+
+            adjustForSetupInPhoneMode(
+                navButtonsLayoutParams,
+                navButtonsViewLayoutParams,
+                deviceProfile
+            )
+            mNavButtonsView.layoutParams = navButtonsViewLayoutParams
+            navButtonContainer.layoutParams = navButtonsLayoutParams
+        }
+
         endContextualContainer.removeAllViews()
         startContextualContainer.removeAllViews()
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt
index 6a935f1..9f7f07e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt
@@ -26,35 +26,32 @@
 import android.widget.Space
 import com.android.launcher3.R
 import com.android.launcher3.taskbar.TaskbarActivityContext
-import com.android.systemui.shared.rotation.RotationButton
 
 open class PhoneLandscapeNavLayoutter(
-        resources: Resources,
-        navBarContainer: LinearLayout,
-        endContextualContainer: ViewGroup,
-        startContextualContainer: ViewGroup,
-        imeSwitcher: ImageView?,
-        rotationButton: RotationButton?,
-        a11yButton: ImageView?,
-        space: Space?
+    resources: Resources,
+    navBarContainer: LinearLayout,
+    endContextualContainer: ViewGroup,
+    startContextualContainer: ViewGroup,
+    imeSwitcher: ImageView?,
+    a11yButton: ImageView?,
+    space: Space?
 ) :
     AbstractNavButtonLayoutter(
-            resources,
-            navBarContainer,
-            endContextualContainer,
-            startContextualContainer,
-            imeSwitcher,
-            rotationButton,
-            a11yButton,
-            space
+        resources,
+        navBarContainer,
+        endContextualContainer,
+        startContextualContainer,
+        imeSwitcher,
+        a11yButton,
+        space
     ) {
 
     override fun layoutButtons(context: TaskbarActivityContext, isA11yButtonPersistent: Boolean) {
         val totalHeight = context.deviceProfile.heightPx
-        val homeButtonHeight = resources.getDimensionPixelSize(
-                R.dimen.taskbar_phone_home_button_size)
-        val roundedCornerContentMargin = resources.getDimensionPixelSize(
-                R.dimen.taskbar_phone_rounded_corner_content_margin)
+        val homeButtonHeight =
+            resources.getDimensionPixelSize(R.dimen.taskbar_phone_home_button_size)
+        val roundedCornerContentMargin =
+            resources.getDimensionPixelSize(R.dimen.taskbar_phone_rounded_corner_content_margin)
         val contentPadding = resources.getDimensionPixelSize(R.dimen.taskbar_phone_content_padding)
         val contentWidth = totalHeight - roundedCornerContentMargin * 2 - contentPadding * 2
 
@@ -63,13 +60,13 @@
         val sideButtonHeight = contextualButtonHeight * 2
         val navButtonContainerHeight = contentWidth - contextualButtonHeight * 2
 
-        val navContainerParams = FrameLayout.LayoutParams(
-                MATCH_PARENT, navButtonContainerHeight.toInt())
+        val navContainerParams =
+            FrameLayout.LayoutParams(MATCH_PARENT, navButtonContainerHeight.toInt())
         navContainerParams.apply {
             topMargin =
-                    (contextualButtonHeight + contentPadding + roundedCornerContentMargin).toInt()
+                (contextualButtonHeight + contentPadding + roundedCornerContentMargin).toInt()
             bottomMargin =
-                    (contextualButtonHeight + contentPadding + roundedCornerContentMargin).toInt()
+                (contextualButtonHeight + contentPadding + roundedCornerContentMargin).toInt()
             marginEnd = 0
             marginStart = 0
         }
@@ -84,8 +81,8 @@
         navButtonContainer.gravity = Gravity.CENTER
 
         // Add the spaces in between the nav buttons
-        val spaceInBetween = (navButtonContainerHeight - homeButtonHeight -
-                sideButtonHeight * 2) / 2.0f
+        val spaceInBetween =
+            (navButtonContainerHeight - homeButtonHeight - sideButtonHeight * 2) / 2.0f
         for (i in 0 until navButtonContainer.childCount) {
             val navButton = navButtonContainer.getChildAt(i)
             val buttonLayoutParams = navButton.layoutParams as LinearLayout.LayoutParams
@@ -124,13 +121,23 @@
         endContextualContainer.removeAllViews()
         startContextualContainer.removeAllViews()
 
-        val roundedCornerContentMargin = resources.getDimensionPixelSize(
-                R.dimen.taskbar_phone_rounded_corner_content_margin)
+        val roundedCornerContentMargin =
+            resources.getDimensionPixelSize(R.dimen.taskbar_phone_rounded_corner_content_margin)
         val contentPadding = resources.getDimensionPixelSize(R.dimen.taskbar_phone_content_padding)
-        repositionContextualContainer(startContextualContainer, buttonSize,
-                roundedCornerContentMargin + contentPadding, 0, Gravity.TOP)
-        repositionContextualContainer(endContextualContainer, buttonSize,
-                0, roundedCornerContentMargin + contentPadding, Gravity.BOTTOM)
+        repositionContextualContainer(
+            startContextualContainer,
+            buttonSize,
+            roundedCornerContentMargin + contentPadding,
+            0,
+            Gravity.TOP
+        )
+        repositionContextualContainer(
+            endContextualContainer,
+            buttonSize,
+            0,
+            roundedCornerContentMargin + contentPadding,
+            Gravity.BOTTOM
+        )
 
         if (imeSwitcher != null) {
             startContextualContainer.addView(imeSwitcher)
@@ -140,16 +147,16 @@
             startContextualContainer.addView(a11yButton)
             a11yButton.layoutParams = getParamsToCenterView()
         }
-        if (rotationButton != null) {
-            startContextualContainer.addView(rotationButton.currentView)
-            rotationButton.currentView.layoutParams = getParamsToCenterView()
-        }
         endContextualContainer.addView(space, MATCH_PARENT, MATCH_PARENT)
     }
 
-    override fun repositionContextualContainer(contextualContainer: ViewGroup, buttonSize: Int,
-                                               barAxisMarginTop: Int, barAxisMarginBottom: Int,
-                                               gravity: Int) {
+    override fun repositionContextualContainer(
+        contextualContainer: ViewGroup,
+        buttonSize: Int,
+        barAxisMarginTop: Int,
+        barAxisMarginBottom: Int,
+        gravity: Int
+    ) {
         val contextualContainerParams = FrameLayout.LayoutParams(MATCH_PARENT, buttonSize)
         contextualContainerParams.apply {
             marginStart = 0
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt
index 0672270..5b24ebf 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt
@@ -26,34 +26,32 @@
 import android.widget.Space
 import com.android.launcher3.R
 import com.android.launcher3.taskbar.TaskbarActivityContext
-import com.android.systemui.shared.rotation.RotationButton
 
 class PhonePortraitNavLayoutter(
-        resources: Resources,
-        navBarContainer: LinearLayout,
-        endContextualContainer: ViewGroup,
-        startContextualContainer: ViewGroup,
-        imeSwitcher: ImageView?,
-        rotationButton: RotationButton?,
-        a11yButton: ImageView?,
-        space: Space?
+    resources: Resources,
+    navBarContainer: LinearLayout,
+    endContextualContainer: ViewGroup,
+    startContextualContainer: ViewGroup,
+    imeSwitcher: ImageView?,
+    a11yButton: ImageView?,
+    space: Space?
 ) :
     AbstractNavButtonLayoutter(
-            resources,
-            navBarContainer,
-            endContextualContainer,
-            startContextualContainer,
-            imeSwitcher,
-            rotationButton,
-            a11yButton,
-            space
+        resources,
+        navBarContainer,
+        endContextualContainer,
+        startContextualContainer,
+        imeSwitcher,
+        a11yButton,
+        space
     ) {
 
     override fun layoutButtons(context: TaskbarActivityContext, isA11yButtonPersistent: Boolean) {
         val totalWidth = context.deviceProfile.widthPx
-        val homeButtonWidth = resources.getDimensionPixelSize(R.dimen.taskbar_phone_home_button_size)
-        val roundedCornerContentMargin = resources.getDimensionPixelSize(
-                R.dimen.taskbar_phone_rounded_corner_content_margin)
+        val homeButtonWidth =
+            resources.getDimensionPixelSize(R.dimen.taskbar_phone_home_button_size)
+        val roundedCornerContentMargin =
+            resources.getDimensionPixelSize(R.dimen.taskbar_phone_rounded_corner_content_margin)
         val contentPadding = resources.getDimensionPixelSize(R.dimen.taskbar_phone_content_padding)
         val contentWidth = totalWidth - roundedCornerContentMargin * 2 - contentPadding * 2
 
@@ -62,15 +60,18 @@
         val sideButtonWidth = contextualButtonWidth * 2
         val navButtonContainerWidth = contentWidth - contextualButtonWidth * 2
 
-        val navContainerParams = FrameLayout.LayoutParams(navButtonContainerWidth.toInt(),
-                ViewGroup.LayoutParams.MATCH_PARENT)
+        val navContainerParams =
+            FrameLayout.LayoutParams(
+                navButtonContainerWidth.toInt(),
+                ViewGroup.LayoutParams.MATCH_PARENT
+            )
         navContainerParams.apply {
             topMargin = 0
             bottomMargin = 0
             marginEnd =
-                    (contextualButtonWidth + contentPadding + roundedCornerContentMargin).toInt()
+                (contextualButtonWidth + contentPadding + roundedCornerContentMargin).toInt()
             marginStart =
-                    (contextualButtonWidth + contentPadding + roundedCornerContentMargin).toInt()
+                (contextualButtonWidth + contentPadding + roundedCornerContentMargin).toInt()
         }
 
         // Ensure order of buttons is correct
@@ -85,8 +86,8 @@
         navButtonContainer.gravity = Gravity.CENTER
 
         // Add the spaces in between the nav buttons
-        val spaceInBetween = (navButtonContainerWidth - homeButtonWidth -
-                sideButtonWidth * 2) / 2.0f
+        val spaceInBetween =
+            (navButtonContainerWidth - homeButtonWidth - sideButtonWidth * 2) / 2.0f
         for (i in 0 until navButtonContainer.childCount) {
             val navButton = navButtonContainer.getChildAt(i)
             val buttonLayoutParams = navButton.layoutParams as LinearLayout.LayoutParams
@@ -114,10 +115,20 @@
         endContextualContainer.removeAllViews()
         startContextualContainer.removeAllViews()
 
-        repositionContextualContainer(startContextualContainer, contextualButtonWidth.toInt(),
-                roundedCornerContentMargin + contentPadding, 0, Gravity.START)
-        repositionContextualContainer(endContextualContainer, contextualButtonWidth.toInt(), 0,
-                roundedCornerContentMargin + contentPadding, Gravity.END)
+        repositionContextualContainer(
+            startContextualContainer,
+            contextualButtonWidth.toInt(),
+            roundedCornerContentMargin + contentPadding,
+            0,
+            Gravity.START
+        )
+        repositionContextualContainer(
+            endContextualContainer,
+            contextualButtonWidth.toInt(),
+            0,
+            roundedCornerContentMargin + contentPadding,
+            Gravity.END
+        )
 
         startContextualContainer.addView(space, MATCH_PARENT, MATCH_PARENT)
         if (imeSwitcher != null) {
@@ -128,9 +139,5 @@
             endContextualContainer.addView(a11yButton)
             a11yButton.layoutParams = getParamsToCenterView()
         }
-        if (rotationButton != null) {
-            endContextualContainer.addView(rotationButton.currentView)
-            rotationButton.currentView.layoutParams = getParamsToCenterView()
-        }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt
index 869cc43..f0b47f4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt
@@ -1,18 +1,18 @@
 /*
-* Copyright (C) 2023 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
-*/
+ * Copyright (C) 2023 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.taskbar.navbutton
 
@@ -24,28 +24,25 @@
 import android.widget.LinearLayout
 import android.widget.Space
 import com.android.launcher3.R
-import com.android.systemui.shared.rotation.RotationButton
 
 class PhoneSeascapeNavLayoutter(
-        resources: Resources,
-        navBarContainer: LinearLayout,
-        endContextualContainer: ViewGroup,
-        startContextualContainer: ViewGroup,
-        imeSwitcher: ImageView?,
-        rotationButton: RotationButton?,
-        a11yButton: ImageView?,
-        space: Space?
+    resources: Resources,
+    navBarContainer: LinearLayout,
+    endContextualContainer: ViewGroup,
+    startContextualContainer: ViewGroup,
+    imeSwitcher: ImageView?,
+    a11yButton: ImageView?,
+    space: Space?
 ) :
-        PhoneLandscapeNavLayoutter(
-                resources,
-                navBarContainer,
-                endContextualContainer,
-                startContextualContainer,
-                imeSwitcher,
-                rotationButton,
-                a11yButton,
-                space
-        ) {
+    PhoneLandscapeNavLayoutter(
+        resources,
+        navBarContainer,
+        endContextualContainer,
+        startContextualContainer,
+        imeSwitcher,
+        a11yButton,
+        space
+    ) {
 
     override fun addThreeButtons() {
         // Flip ordering of back and recents buttons
@@ -58,13 +55,23 @@
         endContextualContainer.removeAllViews()
         startContextualContainer.removeAllViews()
 
-        val roundedCornerContentMargin = resources.getDimensionPixelSize(
-                R.dimen.taskbar_phone_rounded_corner_content_margin)
+        val roundedCornerContentMargin =
+            resources.getDimensionPixelSize(R.dimen.taskbar_phone_rounded_corner_content_margin)
         val contentPadding = resources.getDimensionPixelSize(R.dimen.taskbar_phone_content_padding)
-        repositionContextualContainer(startContextualContainer, buttonSize,
-                roundedCornerContentMargin + contentPadding, 0, Gravity.TOP)
-        repositionContextualContainer(endContextualContainer, buttonSize, 0,
-                roundedCornerContentMargin + contentPadding,  Gravity.BOTTOM)
+        repositionContextualContainer(
+            startContextualContainer,
+            buttonSize,
+            roundedCornerContentMargin + contentPadding,
+            0,
+            Gravity.TOP
+        )
+        repositionContextualContainer(
+            endContextualContainer,
+            buttonSize,
+            0,
+            roundedCornerContentMargin + contentPadding,
+            Gravity.BOTTOM
+        )
 
         startContextualContainer.addView(space, MATCH_PARENT, MATCH_PARENT)
         if (imeSwitcher != null) {
@@ -75,9 +82,5 @@
             endContextualContainer.addView(a11yButton)
             a11yButton.layoutParams = getParamsToCenterView()
         }
-        if (rotationButton != null) {
-            endContextualContainer.addView(rotationButton.currentView)
-            rotationButton.currentView.layoutParams = getParamsToCenterView()
-        }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
index 8eff95c..22a3630 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
@@ -27,7 +27,6 @@
 import com.android.launcher3.DeviceProfile
 import com.android.launcher3.R
 import com.android.launcher3.taskbar.TaskbarActivityContext
-import com.android.systemui.shared.rotation.RotationButton
 
 const val SQUARE_ASPECT_RATIO_BOTTOM_BOUND = 0.95
 const val SQUARE_ASPECT_RATIO_UPPER_BOUND = 1.05
@@ -39,7 +38,6 @@
     endContextualContainer: ViewGroup,
     startContextualContainer: ViewGroup,
     imeSwitcher: ImageView?,
-    rotationButton: RotationButton?,
     a11yButton: ImageView?,
     space: Space?
 ) :
@@ -49,7 +47,6 @@
         endContextualContainer,
         startContextualContainer,
         imeSwitcher,
-        rotationButton,
         a11yButton,
         space
     ) {
@@ -80,16 +77,11 @@
             navButtonsLayoutParams.height =
                 resources.getDimensionPixelSize(R.dimen.taskbar_back_button_suw_height)
         } else {
-            val phoneOrPortraitSetupMargin =
-                resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_margin)
-            navButtonsLayoutParams.marginStart = phoneOrPortraitSetupMargin
-            navButtonsLayoutParams.bottomMargin =
-                if (!deviceProfile.isLandscape) 0
-                else
-                    phoneOrPortraitSetupMargin -
-                        resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size) / 2
-            navButtonsViewLayoutParams.height =
-                resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_height)
+            adjustForSetupInPhoneMode(
+                navButtonsLayoutParams,
+                navButtonsViewLayoutParams,
+                deviceProfile
+            )
         }
         mNavButtonsView.layoutParams = navButtonsViewLayoutParams
         navButtonContainer.layoutParams = navButtonsLayoutParams
@@ -116,9 +108,5 @@
             endContextualContainer.addView(a11yButton)
             a11yButton.layoutParams = getParamsToCenterView()
         }
-        if (rotationButton != null) {
-            endContextualContainer.addView(rotationButton.currentView)
-            rotationButton.currentView.layoutParams = getParamsToCenterView()
-        }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
index 34d3fad..a59e8a8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
@@ -26,7 +26,6 @@
 import android.widget.Space
 import com.android.launcher3.R
 import com.android.launcher3.taskbar.TaskbarActivityContext
-import com.android.systemui.shared.rotation.RotationButton
 
 /** Layoutter for rendering task bar in large screen, both in 3-button and gesture nav mode. */
 class TaskbarNavLayoutter(
@@ -35,7 +34,6 @@
     endContextualContainer: ViewGroup,
     startContextualContainer: ViewGroup,
     imeSwitcher: ImageView?,
-    rotationButton: RotationButton?,
     a11yButton: ImageView?,
     space: Space?
 ) :
@@ -45,7 +43,6 @@
         endContextualContainer,
         startContextualContainer,
         imeSwitcher,
-        rotationButton,
         a11yButton,
         space
     ) {
@@ -137,10 +134,6 @@
                 endContextualContainer.addView(a11yButton)
                 a11yButton.layoutParams = getParamsToCenterView()
             }
-            if (rotationButton != null) {
-                endContextualContainer.addView(rotationButton.currentView)
-                rotationButton.currentView.layoutParams = getParamsToCenterView()
-            }
         }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
index 9c3e8af..773b0b9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
@@ -30,7 +30,7 @@
 
 import androidx.annotation.NonNull;
 
-import com.android.app.viewcapture.SettingsAwareViewCapture;
+import com.android.app.viewcapture.ViewCaptureFactory;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
@@ -59,7 +59,7 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         getViewTreeObserver().addOnComputeInternalInsetsListener(this);
-        mViewCaptureCloseable = SettingsAwareViewCapture.getInstance(getContext())
+        mViewCaptureCloseable = ViewCaptureFactory.getInstance(getContext())
                 .startCapture(getRootView(), ".TaskbarOverlay");
     }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index 2eced74..14d391b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -71,7 +71,7 @@
         ADJACENT_PAGE_HORIZONTAL_OFFSET.set(mRecentsView, scaleAndOffset[1]);
         TASK_SECONDARY_TRANSLATION.set(mRecentsView, 0f);
 
-        getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0);
+        getContentAlphaProperty().set(mRecentsView, state.isRecentsViewVisible ? 1f : 0);
         getTaskModalnessProperty().set(mRecentsView, state.getOverviewModalness());
         RECENTS_GRID_PROGRESS.set(mRecentsView,
                 state.displayOverviewTasksAsGrid(mLauncher.getDeviceProfile()) ? 1f : 0f);
@@ -109,7 +109,8 @@
         setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f,
                 config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
 
-        boolean exitingOverview = !FeatureFlags.enableSplitContextually() && !toState.overviewUi;
+        boolean exitingOverview =
+                !FeatureFlags.enableSplitContextually() && !toState.isRecentsViewVisible;
         if (mRecentsView.isSplitSelectionActive() && exitingOverview) {
             setter.add(mRecentsView.getSplitSelectController().getSplitAnimationController()
                     .createPlaceholderDismissAnim(mLauncher, LAUNCHER_SPLIT_SELECTION_EXIT_HOME,
@@ -124,7 +125,8 @@
             );
         }
 
-        setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
+        setter.setFloat(mRecentsView, getContentAlphaProperty(),
+                toState.isRecentsViewVisible ? 1 : 0,
                 config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
 
         setter.setFloat(
@@ -145,7 +147,7 @@
     private Interpolator getOverviewInterpolator(LauncherState fromState, LauncherState toState) {
         return fromState == QUICK_SWITCH_FROM_HOME
                 ? ACCELERATE_DECELERATE
-                : toState.overviewUi ? INSTANT : FINAL_FRAME;
+                : toState.isRecentsViewVisible ? INSTANT : FINAL_FRAME;
     }
 
     abstract FloatProperty getTaskModalnessProperty();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 4acddee..046dbd5 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -103,7 +103,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 
-import com.android.app.viewcapture.SettingsAwareViewCapture;
+import com.android.app.viewcapture.ViewCaptureFactory;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Flags;
@@ -166,6 +166,8 @@
 import com.android.launcher3.util.TouchController;
 import com.android.launcher3.widget.LauncherWidgetHolder;
 import com.android.quickstep.OverviewCommandHelper;
+import com.android.quickstep.OverviewComponentObserver;
+import com.android.quickstep.RecentsAnimationDeviceState;
 import com.android.quickstep.RecentsModel;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TaskUtils;
@@ -192,9 +194,12 @@
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
 import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig;
 import com.android.systemui.unfold.config.UnfoldTransitionConfig;
+import com.android.systemui.unfold.dagger.UnfoldMain;
 import com.android.systemui.unfold.progress.RemoteUnfoldTransitionReceiver;
 import com.android.systemui.unfold.updates.RotationChangeProvider;
 
+import kotlin.Unit;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -264,6 +269,10 @@
                         getDepthController(), getStatsLogManager(),
                         systemUiProxy, RecentsModel.INSTANCE.get(this),
                         () -> onStateBack());
+        RecentsAnimationDeviceState deviceState = new RecentsAnimationDeviceState(asContext());
+        // TODO(b/337863494): Explore use of the same OverviewComponentObserver across launcher
+        OverviewComponentObserver overviewComponentObserver = new OverviewComponentObserver(
+                asContext(), deviceState);
         if (enableDesktopWindowingMode()) {
             mDesktopRecentsTransitionController = new DesktopRecentsTransitionController(
                     getStateManager(), systemUiProxy, getIApplicationThread(),
@@ -272,7 +281,7 @@
         overviewPanel.init(mActionsView, mSplitSelectStateController,
                 mDesktopRecentsTransitionController);
         mSplitWithKeyboardShortcutController = new SplitWithKeyboardShortcutController(this,
-                mSplitSelectStateController);
+                mSplitSelectStateController, overviewComponentObserver, deviceState);
         mSplitToWorkspaceController = new SplitToWorkspaceController(this,
                 mSplitSelectStateController);
         mActionsView.updateDimension(getDeviceProfile(), overviewPanel.getLastComputedTaskSize());
@@ -287,7 +296,8 @@
         if (enableDesktopWindowingMode()) {
             mDesktopVisibilityController = new DesktopVisibilityController(this);
             mDesktopVisibilityController.registerSystemUiListener();
-            mSplitSelectStateController.initSplitFromDesktopController(this);
+            mSplitSelectStateController.initSplitFromDesktopController(this,
+                    overviewComponentObserver);
         }
         mHotseatPredictionController = new HotseatPredictionController(this);
 
@@ -391,6 +401,12 @@
     }
 
     @Override
+    public void startBinding() {
+        super.startBinding();
+        mHotseatPredictionController.verifyUIUpdateNotPaused();
+    }
+
+    @Override
     protected void onActivityFlagsChanged(int changeBits) {
         if ((changeBits & ACTIVITY_STATE_STARTED) != 0) {
             mDepthController.setActivityStarted(isStarted());
@@ -573,6 +589,7 @@
                         } else {
                             getStateManager().moveToRestState();
                         }
+                        return Unit.INSTANCE;
                     });
                 } else {
                     getStateManager().goToState(NORMAL);
@@ -655,7 +672,7 @@
         addMultiWindowModeChangedListener(mDepthController);
         initUnfoldTransitionProgressProvider();
         if (FeatureFlags.CONTINUOUS_VIEW_TREE_CAPTURE.get()) {
-            mViewCapture = SettingsAwareViewCapture.getInstance(this).startCapture(getWindow());
+            mViewCapture = ViewCaptureFactory.getInstance(this).startCapture(getWindow());
         }
         getWindow().addPrivateFlags(PRIVATE_FLAG_OPTIMIZE_MEASURE);
         QuickstepOnboardingPrefs.setup(this);
@@ -1031,6 +1048,7 @@
                         getMainExecutor(),
                         getMainThreadHandler(),
                         /* backgroundExecutor= */ UI_HELPER_EXECUTOR,
+                        /* bgHandler= */ UI_HELPER_EXECUTOR.getHandler(),
                         /* tracingTagPrefix= */ "launcher",
                         getSystemService(DisplayManager.class)
                 );
@@ -1050,7 +1068,7 @@
     }
 
     private void initUnfoldAnimationController(UnfoldTransitionProgressProvider progressProvider,
-            RotationChangeProvider rotationChangeProvider) {
+            @UnfoldMain RotationChangeProvider rotationChangeProvider) {
         mLauncherUnfoldAnimationController = new LauncherUnfoldAnimationController(
                 /* launcher= */ this,
                 getWindowManager(),
@@ -1255,7 +1273,7 @@
         if ((flags & CHANGE_NAVIGATION_MODE) != 0) {
             getDragLayer().recreateControllers();
             if (mActionsView != null) {
-                mActionsView.updateVerticalMargin(info.navigationMode);
+                mActionsView.updateVerticalMargin(info.getNavigationMode());
             }
         }
     }
@@ -1464,4 +1482,9 @@
         }
         return super.onCreateView(parent, name, context, attrs);
     }
+
+    @Override
+    public boolean isRecentsViewVisible() {
+        return getStateManager().getState().isRecentsViewVisible;
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 6c1d4b1..235ec7b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -21,7 +21,6 @@
 import static com.android.launcher3.LauncherState.OVERVIEW_ACTIONS;
 import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
-import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
 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.TASK_MODALNESS;
@@ -41,6 +40,7 @@
 
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.AnimatorListeners;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.anim.PropertySetter;
@@ -67,7 +67,7 @@
     @Override
     public void setState(@NonNull LauncherState state) {
         super.setState(state);
-        if (state.overviewUi) {
+        if (state.isRecentsViewVisible) {
             mRecentsView.updateEmptyMessage();
         } else {
             mRecentsView.resetTaskVisuals();
@@ -76,7 +76,7 @@
         mRecentsView.setFullscreenProgress(state.getOverviewFullscreenProgress());
         // In Overview, we may be layering app surfaces behind Launcher, so we need to notify
         // DepthController to prevent optimizations which might occlude the layers behind
-        mLauncher.getDepthController().setHasContentBehindLauncher(state.overviewUi);
+        mLauncher.getDepthController().setHasContentBehindLauncher(state.isRecentsViewVisible);
 
         PendingAnimation builder =
                 new PendingAnimation(state.getTransitionDuration(mLauncher, true));
@@ -89,7 +89,7 @@
             @NonNull StateAnimationConfig config, @NonNull PendingAnimation builder) {
         super.setStateWithAnimationInternal(toState, config, builder);
 
-        if (toState.overviewUi) {
+        if (toState.isRecentsViewVisible) {
             // While animating into recents, update the visible task data as needed
             builder.addOnFrameCallback(() -> mRecentsView.loadVisibleTaskData(FLAG_UPDATE_ALL));
             mRecentsView.updateEmptyMessage();
@@ -107,7 +107,8 @@
         // In Overview, we may be layering app surfaces behind Launcher, so we need to notify
         // DepthController to prevent optimizations which might occlude the layers behind
         builder.addListener(AnimatorListeners.forSuccessCallback(() ->
-                mLauncher.getDepthController().setHasContentBehindLauncher(toState.overviewUi)));
+                mLauncher.getDepthController().setHasContentBehindLauncher(
+                        toState.isRecentsViewVisible)));
 
         handleSplitSelectionState(toState, builder, /* animate */true);
 
@@ -168,7 +169,7 @@
                 clearAllButtonAlpha, LINEAR);
         float overviewButtonAlpha = state.areElementsVisible(mLauncher, OVERVIEW_ACTIONS) ? 1 : 0;
         propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(),
-                MULTI_PROPERTY_VALUE, overviewButtonAlpha, config.getInterpolator(
+                AnimatedFloat.VALUE, overviewButtonAlpha, config.getInterpolator(
                         ANIM_OVERVIEW_ACTIONS_FADE, LINEAR));
     }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt
index 535b4c2..146ff3d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt
+++ b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt
@@ -40,7 +40,7 @@
 import com.android.quickstep.util.FadeOutRemoteTransition
 
 /** A wrapper for the hidden API calls */
-class SystemApiWrapper(context: Context?) : ApiWrapper(context) {
+open class SystemApiWrapper(context: Context?) : ApiWrapper(context) {
 
     override fun getPersons(si: ShortcutInfo) = si.persons ?: Utilities.EMPTY_PERSON_ARRAY
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt b/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt
index 3881e9a..dc6365b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt
@@ -16,14 +16,28 @@
 
 package com.android.launcher3.uioverrides.flags
 
+import android.app.PendingIntent
+import android.app.blob.BlobHandle.createWithSha256
+import android.app.blob.BlobStoreManager
 import android.content.Context
+import android.content.IIntentReceiver
+import android.content.IIntentSender.Stub
 import android.content.Intent
+import android.content.Intent.ACTION_CREATE_DOCUMENT
+import android.content.Intent.ACTION_OPEN_DOCUMENT
 import android.content.pm.PackageManager
 import android.net.Uri
+import android.os.Bundle
+import android.os.IBinder
+import android.os.ParcelFileDescriptor.AutoCloseOutputStream
 import android.provider.DeviceConfig
 import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
+import android.provider.Settings.Secure
 import android.text.Html
 import android.util.AttributeSet
+import android.util.Base64
+import android.util.Base64.NO_PADDING
+import android.util.Base64.NO_WRAP
 import android.view.inputmethod.EditorInfo
 import android.widget.TextView
 import android.widget.Toast
@@ -33,11 +47,32 @@
 import androidx.preference.PreferenceGroup
 import androidx.preference.PreferenceViewHolder
 import androidx.preference.SwitchPreference
+import com.android.launcher3.AutoInstallsLayout
 import com.android.launcher3.ExtendedEditText
+import com.android.launcher3.LauncherAppState
 import com.android.launcher3.LauncherPrefs
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER
+import com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_KEY
+import com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_LABEL
+import com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_TAG
 import com.android.launcher3.R
+import com.android.launcher3.model.data.FolderInfo
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.LauncherAppWidgetInfo
+import com.android.launcher3.pm.UserCache
+import com.android.launcher3.proxy.ProxyActivityStarter
 import com.android.launcher3.secondarydisplay.SecondaryDisplayLauncher
+import com.android.launcher3.shortcuts.ShortcutKey
 import com.android.launcher3.uioverrides.plugins.PluginManagerWrapperImpl
+import com.android.launcher3.util.Executors.MAIN_EXECUTOR
+import com.android.launcher3.util.Executors.MODEL_EXECUTOR
+import com.android.launcher3.util.Executors.ORDERED_BG_EXECUTOR
+import com.android.launcher3.util.LauncherLayoutBuilder
 import com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT
 import com.android.launcher3.util.OnboardingPrefs.HOME_BOUNCE_COUNT
 import com.android.launcher3.util.OnboardingPrefs.HOME_BOUNCE_SEEN
@@ -45,12 +80,17 @@
 import com.android.launcher3.util.OnboardingPrefs.HOTSEAT_LONGPRESS_TIP_SEEN
 import com.android.launcher3.util.OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP
 import com.android.launcher3.util.PluginManagerWrapper
+import com.android.launcher3.util.StartActivityParams
+import com.android.launcher3.util.UserIconInfo
 import com.android.quickstep.util.DeviceConfigHelper
 import com.android.quickstep.util.DeviceConfigHelper.Companion.NAMESPACE_LAUNCHER
 import com.android.quickstep.util.DeviceConfigHelper.DebugInfo
 import com.android.systemui.shared.plugins.PluginEnabler
 import com.android.systemui.shared.plugins.PluginPrefs
+import java.io.OutputStreamWriter
+import java.security.MessageDigest
 import java.util.Locale
+import java.util.concurrent.Executor
 
 /** Helper class to generate UI for Device Config */
 class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, attr) {
@@ -67,6 +107,9 @@
         (holder.findViewById(R.id.filter_box) as TextView?)?.doAfterTextChanged {
             val query: String = it.toString().lowercase(Locale.getDefault()).replace("_", " ")
             filterPreferences(query, this)
+
+            // Always keep myself visible
+            this@DevOptionsUiHelper.isVisible = true
         }
     }
 
@@ -97,6 +140,7 @@
         }
         addIntentTargets()
         addOnboardingPrefsCategory()
+        addLayoutSharePref()
     }
 
     private fun newCategory(titleText: String, subTitleText: String? = null) =
@@ -359,7 +403,7 @@
             Preference(context).also {
                 it.title = title
                 it.summary = "Tap to reset"
-                setOnPreferenceClickListener { _ ->
+                it.setOnPreferenceClickListener { _ ->
                     LauncherPrefs.getPrefs(context)
                         .edit()
                         .apply { keys.forEach { key -> remove(key) } }
@@ -370,6 +414,137 @@
             }
         )
 
+    private fun addLayoutSharePref() {
+        val model = LauncherAppState.getInstance(context).model
+        val category = newCategory("Workspace grid layout")
+        Preference(context).apply {
+            title = "Export"
+            intent =
+                createUriPickerIntent(ACTION_CREATE_DOCUMENT, MAIN_EXECUTOR) { uri ->
+                    model.enqueueModelUpdateTask { _, dataModel, _ ->
+                        val builder = LauncherLayoutBuilder()
+                        dataModel.workspaceItems.forEach { info ->
+                            val loc =
+                                when (info.container) {
+                                    CONTAINER_DESKTOP ->
+                                        builder.atWorkspace(info.cellX, info.cellY, info.screenId)
+                                    CONTAINER_HOTSEAT -> builder.atHotseat(info.screenId)
+                                    else -> return@forEach
+                                }
+                            loc.addItem(info)
+                        }
+                        dataModel.appWidgets.forEach { info ->
+                            builder.atWorkspace(info.cellX, info.cellY, info.screenId).addItem(info)
+                        }
+
+                        context.contentResolver.openOutputStream(uri).use { os ->
+                            builder.build(OutputStreamWriter(os))
+                        }
+
+                        MAIN_EXECUTOR.execute {
+                            Toast.makeText(context, "File saved", Toast.LENGTH_LONG).show()
+                        }
+                    }
+                }
+            category.addPreference(this)
+        }
+
+        Preference(context).apply {
+            title = "Import"
+            intent =
+                createUriPickerIntent(ACTION_OPEN_DOCUMENT, ORDERED_BG_EXECUTOR) { uri ->
+                    val resolver = context.contentResolver
+                    val data =
+                        resolver.openInputStream(uri).use { stream ->
+                            stream?.readAllBytes() ?: return@createUriPickerIntent
+                        }
+
+                    val digest = MessageDigest.getInstance("SHA-256").digest(data)
+                    val handle = createWithSha256(digest, LAYOUT_DIGEST_LABEL, 0, LAYOUT_DIGEST_TAG)
+                    val blobManager = context.getSystemService(BlobStoreManager::class.java)!!
+
+                    blobManager.openSession(blobManager.createSession(handle)).use { session ->
+                        AutoCloseOutputStream(session.openWrite(0, -1)).use { it.write(data) }
+                        session.allowPublicAccess()
+
+                        session.commit(ORDERED_BG_EXECUTOR) {
+                            val key = Base64.encodeToString(digest, NO_WRAP or NO_PADDING)
+                            Secure.putString(resolver, LAYOUT_DIGEST_KEY, key)
+
+                            MODEL_EXECUTOR.submit { model.modelDbController.createEmptyDB() }.get()
+                            MAIN_EXECUTOR.submit { model.forceReload() }.get()
+                            MODEL_EXECUTOR.submit {}.get()
+                            Secure.putString(resolver, LAYOUT_DIGEST_KEY, null)
+                        }
+                    }
+                }
+            category.addPreference(this)
+        }
+    }
+
+    private fun LauncherLayoutBuilder.ItemTarget.addItem(info: ItemInfo) {
+        val userType: String? =
+            when (UserCache.INSTANCE.get(context).getUserInfo(info.user).type) {
+                UserIconInfo.TYPE_WORK -> AutoInstallsLayout.USER_TYPE_WORK
+                UserIconInfo.TYPE_CLONED -> AutoInstallsLayout.USER_TYPE_CLONED
+                else -> null
+            }
+        when (info.itemType) {
+            ITEM_TYPE_APPLICATION ->
+                info.targetComponent?.let { c -> putApp(c.packageName, c.className, userType) }
+            ITEM_TYPE_DEEP_SHORTCUT ->
+                ShortcutKey.fromItemInfo(info).let { key ->
+                    putShortcut(key.packageName, key.id, userType)
+                }
+            ITEM_TYPE_FOLDER ->
+                (info as FolderInfo).let { folderInfo ->
+                    putFolder(folderInfo.title?.toString() ?: "").also { folderBuilder ->
+                        folderInfo.getContents().forEach { folderContent ->
+                            folderBuilder.addItem(folderContent)
+                        }
+                    }
+                }
+            ITEM_TYPE_APPWIDGET ->
+                putWidget(
+                    (info as LauncherAppWidgetInfo).providerName.packageName,
+                    info.providerName.className,
+                    info.spanX,
+                    info.spanY,
+                    userType
+                )
+        }
+    }
+
+    private fun createUriPickerIntent(
+        action: String,
+        executor: Executor,
+        callback: (uri: Uri) -> Unit
+    ): Intent {
+        val pendingIntent =
+            PendingIntent(
+                object : Stub() {
+                    override fun send(
+                        code: Int,
+                        intent: Intent,
+                        resolvedType: String?,
+                        allowlistToken: IBinder?,
+                        finishedReceiver: IIntentReceiver?,
+                        requiredPermission: String?,
+                        options: Bundle?
+                    ) {
+                        intent.data?.let { uri -> executor.execute { callback(uri) } }
+                    }
+                }
+            )
+        val params = StartActivityParams(pendingIntent, 0)
+        params.intent =
+            Intent(action)
+                .addCategory(Intent.CATEGORY_OPENABLE)
+                .setType("text/xml")
+                .putExtra(Intent.EXTRA_TITLE, "launcher_grid.xml")
+        return ProxyActivityStarter.getLaunchIntent(context, params)
+    }
+
     private inner class CustomSwitchPref(
         private val bindCallback: (holder: PreferenceViewHolder, pref: SwitchPreference) -> Unit
     ) : SwitchPreference(context) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index 7fa121d..2625646 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -34,7 +34,7 @@
  */
 public class BackgroundAppState extends OverviewState {
 
-    private static final int STATE_FLAGS = FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI
+    private static final int STATE_FLAGS = FLAG_DISABLE_RESTORE | FLAG_RECENTS_VIEW_VISIBLE
             | FLAG_WORKSPACE_INACCESSIBLE | FLAG_NON_INTERACTIVE | FLAG_CLOSE_POPUPS;
 
     public BackgroundAppState(int id) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
index 3c291e6..932d241 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
@@ -32,7 +32,7 @@
 public class OverviewModalTaskState extends OverviewState {
 
     private static final int STATE_FLAGS =
-            FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_WORKSPACE_INACCESSIBLE;
+            FLAG_DISABLE_RESTORE | FLAG_RECENTS_VIEW_VISIBLE | FLAG_WORKSPACE_INACCESSIBLE;
 
     public OverviewModalTaskState(int id) {
         super(id, LAUNCHER_STATE_OVERVIEW, STATE_FLAGS);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index d0eef8e..7173298 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -47,7 +47,7 @@
     protected static final Rect sTempRect = new Rect();
 
     private static final int STATE_FLAGS = FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED
-            | FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_WORKSPACE_INACCESSIBLE
+            | FLAG_DISABLE_RESTORE | FLAG_RECENTS_VIEW_VISIBLE | FLAG_WORKSPACE_INACCESSIBLE
             | FLAG_CLOSE_POPUPS;
 
     public OverviewState(int id) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 3ed2d0b..11e0ed5 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -118,7 +118,7 @@
         if (!cameFromNavBar) {
             return false;
         }
-        if (mStartState.overviewUi || mStartState == ALL_APPS) {
+        if (mStartState.isRecentsViewVisible || mStartState == ALL_APPS) {
             return true;
         }
         int typeToClose = TYPE_ALL & ~TYPE_ALL_APPS_EDU;
@@ -145,7 +145,7 @@
     private void initCurrentAnimation() {
         long accuracy = (long) (getShiftRange() * 2);
         final PendingAnimation builder = new PendingAnimation(accuracy);
-        if (mStartState.overviewUi) {
+        if (mStartState.isRecentsViewVisible) {
             RecentsView recentsView = mLauncher.getOverviewPanel();
             AnimatorControllerWithResistance.createRecentsResistanceFromOverviewAnim(mLauncher,
                     builder);
@@ -194,7 +194,7 @@
             RecentsView recentsView = mLauncher.getOverviewPanel();
             recentsView.switchToScreenshot(null,
                     () -> recentsView.finishRecentsAnimation(true /* toRecents */, null));
-            if (mStartState.overviewUi) {
+            if (mStartState.isRecentsViewVisible) {
                 Runnable onReachedHome = () -> {
                     StateManager.StateListener<LauncherState> listener =
                             new StateManager.StateListener<>() {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index 42be52f..3325009 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -249,7 +249,7 @@
     }
 
     private boolean handlingOverviewAnim() {
-        int stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
+        long stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
         return mDidTouchStartInNavBar && mStartState == NORMAL
                 && (stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0;
     }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 527a776..ab277b6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -172,7 +172,7 @@
         if ((ev.getEdgeFlags() & Utilities.EDGE_NAV_BAR) == 0) {
             return false;
         }
-        int stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
+        long stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
         if ((stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0) {
             return false;
         }
@@ -248,7 +248,7 @@
         TASK_THUMBNAIL_SPLASH_ALPHA.set(mRecentsView, fromState.showTaskThumbnailSplash() ? 1f : 0);
         mRecentsView.setContentAlpha(1);
         mRecentsView.setFullscreenProgress(fromState.getOverviewFullscreenProgress());
-        mLauncher.getActionsView().getVisibilityAlpha().setValue(
+        mLauncher.getActionsView().getVisibilityAlpha().updateValue(
                 (fromState.getVisibleElements(mLauncher) & OVERVIEW_ACTIONS) != 0 ? 1f : 0f);
         mRecentsView.setTaskIconScaledDown(true);
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index 05a55d0..93e4fbd 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -84,7 +84,7 @@
 
     @Override
     protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) {
-        int stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
+        long stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
         if ((stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0) {
             return NORMAL;
         }
@@ -151,7 +151,7 @@
             int sysuiFlags = 0;
             TaskView tv = mOverviewPanel.getTaskViewAt(0);
             if (tv != null) {
-                sysuiFlags = tv.getThumbnail().getSysUiStatusNavFlags();
+                sysuiFlags = tv.getFirstThumbnailViewDeprecated().getSysUiStatusNavFlags();
             }
             mLauncher.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, sysuiFlags);
         } else {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index 300d697..4bc3c16 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -252,7 +252,7 @@
                     mTaskBeingDragged, maxDuration, currentInterpolator);
 
             // Since the thumbnail is what is filling the screen, based the end displacement on it.
-            View thumbnailView = mTaskBeingDragged.getThumbnail();
+            View thumbnailView = mTaskBeingDragged.getFirstThumbnailViewDeprecated();
             mTempCords[1] = orientationHandler.getSecondaryDimension(thumbnailView);
             dl.getDescendantCoordRelativeToSelf(thumbnailView, mTempCords);
             mEndDisplacement = secondaryLayerDimension - mTempCords[1];
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 8e4dde2..463222d 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -30,6 +30,7 @@
 import static com.android.launcher3.BaseActivity.EVENT_STARTED;
 import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
 import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
+import static com.android.launcher3.Flags.enableAdditionalHomeAnimations;
 import static com.android.launcher3.Flags.enableGridOnlyOverview;
 import static com.android.launcher3.PagedView.INVALID_PAGE;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
@@ -106,7 +107,6 @@
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.logging.StatsLogManager.StatsLogger;
-import com.android.launcher3.statehandlers.DesktopVisibilityController;
 import com.android.launcher3.statemanager.BaseState;
 import com.android.launcher3.taskbar.TaskbarThresholdUtils;
 import com.android.launcher3.taskbar.TaskbarUIController;
@@ -134,10 +134,11 @@
 import com.android.quickstep.util.SwipePipToHomeAnimator;
 import com.android.quickstep.util.TaskViewSimulator;
 import com.android.quickstep.util.TransformParams;
+import com.android.quickstep.views.DesktopTaskView;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.RecentsViewContainer;
 import com.android.quickstep.views.TaskView;
-import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
+import com.android.quickstep.views.TaskView.TaskContainer;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -146,12 +147,16 @@
 import com.android.systemui.shared.system.SysUiStatsLog;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.TaskStackChangeListeners;
+import com.android.window.flags.Flags;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.startingsurface.SplashScreenExitAnimationUtils;
 
+import kotlin.Unit;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.OptionalInt;
@@ -920,7 +925,7 @@
             TaskView runningTask = mRecentsView.getRunningTaskView();
             TaskView centermostTask = mRecentsView.getTaskViewNearestToCenterOfScreen();
             int centermostTaskFlags = centermostTask == null ? 0
-                    : centermostTask.getThumbnail().getSysUiStatusNavFlags();
+                    : centermostTask.getFirstThumbnailViewDeprecated().getSysUiStatusNavFlags();
             boolean swipeUpThresholdPassed = windowProgress > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD;
             boolean quickswitchThresholdPassed = centermostTask != runningTask;
 
@@ -1169,12 +1174,6 @@
                 mStateCallback.setState(STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT);
                 // Notify the SysUI to use fade-in animation when entering PiP
                 SystemUiProxy.INSTANCE.get(mContext).setPipAnimationTypeToAlpha();
-                DesktopVisibilityController desktopVisibilityController =
-                        mContainerInterface.getDesktopVisibilityController();
-                if (desktopVisibilityController != null) {
-                    // Notify the SysUI to stash desktop apps if they are visible
-                    desktopVisibilityController.onHomeActionTriggered();
-                }
                 break;
             case RECENTS:
                 mStateCallback.setState(STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
@@ -1256,13 +1255,16 @@
                 ? mRecentsView.getNextPageTaskView() : null;
         TaskView currentPageTaskView = mRecentsView != null
                 ? mRecentsView.getCurrentPageTaskView() : null;
-        if (((nextPageTaskView != null && nextPageTaskView.isDesktopTask())
-                || (currentPageTaskView != null && currentPageTaskView.isDesktopTask()))
-                && endTarget == NEW_TASK) {
-            // TODO(b/268075592): add support for quickswitch to/from desktop
-            return LAST_TASK;
-        }
 
+        if (Flags.enableDesktopWindowingMode()
+                && !(Flags.enableDesktopWindowingWallpaperActivity()
+                && Flags.enableDesktopWindowingQuickSwitch())) {
+            if ((nextPageTaskView instanceof DesktopTaskView
+                    || currentPageTaskView instanceof DesktopTaskView)
+                    && endTarget == NEW_TASK) {
+                return LAST_TASK;
+            }
+        }
         return endTarget;
     }
 
@@ -1419,14 +1421,27 @@
             mGestureState.setState(STATE_RECENTS_SCROLLING_FINISHED);
             setClampScrollOffset(false);
         };
-        if (mRecentsView != null && (mRecentsView.getCurrentPageTaskView() != null
-                && !mRecentsView.getCurrentPageTaskView().isDesktopTask())) {
-            ActiveGestureLog.INSTANCE.trackEvent(ActiveGestureErrorDetector.GestureEvent
-                    .SET_ON_PAGE_TRANSITION_END_CALLBACK);
-            // TODO(b/268075592): add support for quickswitch to/from desktop
-            mRecentsView.setOnPageTransitionEndCallback(onPageTransitionEnd);
+
+        if (Flags.enableDesktopWindowingMode()
+                && !(Flags.enableDesktopWindowingWallpaperActivity()
+                && Flags.enableDesktopWindowingQuickSwitch())) {
+            if (mRecentsView != null && (mRecentsView.getCurrentPageTaskView() != null
+                    && !(mRecentsView.getCurrentPageTaskView() instanceof DesktopTaskView))) {
+                ActiveGestureLog.INSTANCE.trackEvent(ActiveGestureErrorDetector.GestureEvent
+                        .SET_ON_PAGE_TRANSITION_END_CALLBACK);
+                mRecentsView.setOnPageTransitionEndCallback(onPageTransitionEnd);
+            } else {
+                onPageTransitionEnd.run();
+            }
         } else {
-            onPageTransitionEnd.run();
+            if (mRecentsView != null) {
+                ActiveGestureLog.INSTANCE.trackEvent(
+                        ActiveGestureErrorDetector
+                                .GestureEvent.SET_ON_PAGE_TRANSITION_END_CALLBACK);
+                mRecentsView.setOnPageTransitionEndCallback(onPageTransitionEnd);
+            } else {
+                onPageTransitionEnd.run();
+            }
         }
 
         animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs);
@@ -1454,14 +1469,15 @@
             default:
                 event = IGNORE;
         }
-        StatsLogger logger = StatsLogManager.newInstance(mContext).logger()
+        StatsLogger logger = StatsLogManager.newInstance(
+                        mContainer != null ? mContainer.asContext() : mContext).logger()
                 .withSrcState(LAUNCHER_STATE_BACKGROUND)
                 .withDstState(endTarget.containerType)
                 .withInputType(mGestureState.isTrackpadGesture()
                         ? SysUiStatsLog.LAUNCHER_UICHANGED__INPUT_TYPE__TRACKPAD
                         : SysUiStatsLog.LAUNCHER_UICHANGED__INPUT_TYPE__TOUCH);
         if (targetTask != null) {
-            logger.withItemInfo(targetTask.getItemInfo());
+            logger.withItemInfo(targetTask.getFirstItemInfo());
         }
 
         int pageIndex = endTarget == LAST_TASK || mRecentsView == null
@@ -1480,8 +1496,12 @@
     }
 
     protected abstract HomeAnimationFactory createHomeAnimationFactory(
-            ArrayList<IBinder> launchCookies, long duration, boolean isTargetTranslucent,
-            boolean appCanEnterPip, RemoteAnimationTarget runningTaskTarget);
+            List<IBinder> launchCookies,
+            long duration,
+            boolean isTargetTranslucent,
+            boolean appCanEnterPip,
+            RemoteAnimationTarget runningTaskTarget,
+            @Nullable TaskView targetTaskView);
 
     private final TaskStackChangeListener mActivityRestartListener = new TaskStackChangeListener() {
         @Override
@@ -1555,9 +1575,16 @@
                     && runningTaskTarget.allowEnterPip
                     && runningTaskTarget.taskInfo.pictureInPictureParams != null
                     && runningTaskTarget.taskInfo.pictureInPictureParams.isAutoEnterEnabled();
-            HomeAnimationFactory homeAnimFactory =
-                    createHomeAnimationFactory(cookies, duration, isTranslucent, appCanEnterPip,
-                            runningTaskTarget);
+            HomeAnimationFactory homeAnimFactory = createHomeAnimationFactory(
+                    cookies,
+                    duration,
+                    isTranslucent,
+                    appCanEnterPip,
+                    runningTaskTarget,
+                    !enableAdditionalHomeAnimations()
+                            || mRecentsView == null
+                            || mRecentsView.getCurrentPage() == mRecentsView.getRunningTaskIndex()
+                                    ? null : mRecentsView.getCurrentPageTaskView());
             SwipePipToHomeAnimator swipePipToHomeAnimator = !mIsSwipeForSplit && appCanEnterPip
                     ? createWindowAnimationToPip(homeAnimFactory, runningTaskTarget, start)
                     : null;
@@ -2237,13 +2264,14 @@
                     mRecentsAnimationController, mRecentsAnimationTargets);
         });
 
-        if ((mRecentsView.getNextPageTaskView() != null
-                && mRecentsView.getNextPageTaskView().isDesktopTask())
-                || (mRecentsView.getCurrentPageTaskView() != null
-                && mRecentsView.getCurrentPageTaskView().isDesktopTask())) {
-            // TODO(b/268075592): add support for quickswitch to/from desktop
-            mRecentsViewScrollLinked = false;
-            return;
+        if (Flags.enableDesktopWindowingMode()
+                && !(Flags.enableDesktopWindowingWallpaperActivity()
+                        && Flags.enableDesktopWindowingQuickSwitch())) {
+            if (mRecentsView.getNextPageTaskView() instanceof DesktopTaskView
+                    || mRecentsView.getCurrentPageTaskView() instanceof DesktopTaskView) {
+                mRecentsViewScrollLinked = false;
+                return;
+            }
         }
 
         // Disable scrolling in RecentsView for trackpad 3-finger swipe up gesture.
@@ -2274,15 +2302,15 @@
                 int[] taskIds = nextTask.getTaskIds();
                 ActiveGestureLog.CompoundString nextTaskLog = new ActiveGestureLog.CompoundString(
                         "Launching task: ");
-                for (TaskIdAttributeContainer c : nextTask.getTaskIdAttributeContainers()) {
-                    if (c == null) {
+                for (TaskContainer container : nextTask.getTaskContainers()) {
+                    if (container == null) {
                         continue;
                     }
                     nextTaskLog
                             .append("[id: ")
-                            .append(c.getTask().key.id)
+                            .append(container.getTask().key.id)
                             .append(", pkg: ")
-                            .append(c.getTask().key.getPackageName())
+                            .append(container.getTask().key.getPackageName())
                             .append("] | ");
                 }
                 mGestureState.updateLastStartedTaskIds(taskIds);
@@ -2305,6 +2333,7 @@
                             mRecentsAnimationController.finish(true /* toRecents */, null);
                         }
                     }
+                    return Unit.INSTANCE;
                 }, true /* freezeTaskList */);
             } else {
                 mContainerInterface.onLaunchTaskFailed();
@@ -2394,7 +2423,8 @@
         RemoteAnimationTarget taskTarget = taskTargetOptional.get();
         TaskView taskView = mRecentsView == null
                 ? null : mRecentsView.getTaskViewByTaskId(taskTarget.taskId);
-        if (taskView == null || !taskView.getThumbnail().shouldShowSplashView()) {
+        if (taskView == null
+                || !taskView.getFirstThumbnailViewDeprecated().shouldShowSplashView()) {
             ActiveGestureLog.INSTANCE.addLog("Invalid task view splash state");
             finishRecentsAnimationOnTasksAppeared(null /* onFinishComplete */);
             return;
diff --git a/quickstep/src/com/android/quickstep/DesktopModeStatus.java b/quickstep/src/com/android/quickstep/DesktopModeStatus.java
deleted file mode 100644
index b1aae16..0000000
--- a/quickstep/src/com/android/quickstep/DesktopModeStatus.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2024 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;
-
-import android.content.Context;
-import android.os.SystemProperties;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.window.flags.Flags;
-
-// TODO(b/335401172): Explore unifying logic across core and shell
-public class DesktopModeStatus {
-
-    /**
-     * Flag to indicate whether to restrict desktop mode to supported devices.
-     */
-    private static final boolean ENFORCE_DEVICE_RESTRICTIONS = SystemProperties.getBoolean(
-            "persist.wm.debug.desktop_mode_enforce_device_restrictions", true);
-
-    /**
-     * Return {@code true} if desktop mode should be restricted to supported devices.
-     */
-    @VisibleForTesting
-    public static boolean enforceDeviceRestrictions() {
-        return ENFORCE_DEVICE_RESTRICTIONS;
-    }
-
-    /**
-     * Return {@code true} if the current device supports desktop mode.
-     */
-    @VisibleForTesting
-    public static boolean isDesktopModeSupported(Context context) {
-        return context.getResources().getBoolean(
-                com.android.internal.R.bool.config_isDesktopModeSupported);
-    }
-
-    /**
-     * Return {@code true} if desktop mode can be entered on the current device.
-     */
-    public static boolean canEnterDesktopMode(Context context) {
-        return Flags.enableDesktopWindowingMode()
-                && (!enforceDeviceRestrictions() || isDesktopModeSupported(context));
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
index aab6aa1..50a06fc 100644
--- a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
+++ b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
@@ -23,29 +23,30 @@
 import com.android.launcher3.popup.SystemShortcut
 import com.android.quickstep.views.RecentsView
 import com.android.quickstep.views.RecentsViewContainer
-import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
+import com.android.quickstep.views.TaskView.TaskContainer
+import com.android.wm.shell.shared.DesktopModeStatus
 
 /** A menu item, "Desktop", that allows the user to bring the current app into Desktop Windowing. */
 class DesktopSystemShortcut(
     container: RecentsViewContainer,
-    private val mTaskContainer: TaskIdAttributeContainer,
+    private val taskContainer: TaskContainer,
     abstractFloatingViewHelper: AbstractFloatingViewHelper
 ) :
     SystemShortcut<RecentsViewContainer>(
         R.drawable.ic_caption_desktop_button_foreground,
         R.string.recent_task_option_desktop,
         container,
-        mTaskContainer.itemInfo,
-        mTaskContainer.taskView,
+        taskContainer.itemInfo,
+        taskContainer.taskView,
         abstractFloatingViewHelper
     ) {
     override fun onClick(view: View) {
         dismissTaskMenuView()
-        val recentsView = mTarget!!.getOverviewPanel<RecentsView<*, *>>()
-        recentsView.moveTaskToDesktop(mTaskContainer) {
+        val recentsView = mTarget.getOverviewPanel<RecentsView<*, *>>()
+        recentsView.moveTaskToDesktop(taskContainer) {
             mTarget.statsLogManager
                 .logger()
-                .withItemInfo(mTaskContainer.itemInfo)
+                .withItemInfo(taskContainer.itemInfo)
                 .log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DESKTOP_TAP)
         }
     }
@@ -59,7 +60,7 @@
             return object : TaskShortcutFactory {
                 override fun getShortcuts(
                     container: RecentsViewContainer,
-                    taskContainer: TaskIdAttributeContainer
+                    taskContainer: TaskContainer
                 ): List<DesktopSystemShortcut>? {
                     return if (!DesktopModeStatus.canEnterDesktopMode(container.asContext())) null
                     else if (!taskContainer.task.isDockable) null
diff --git a/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt b/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt
index f68f793..3549a12 100644
--- a/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt
+++ b/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt
@@ -37,6 +37,13 @@
             "Server side control to customize LPH timeout and touch slop"
         )
 
+    val customLpaaThresholds =
+        propReader.get(
+            "CUSTOM_LPAA_THRESHOLDS",
+            false,
+            "Server side control to customize LPAA timeout and touch slop"
+        )
+
     val overrideLpnhLphThresholds =
         propReader.get(
             "OVERRIDE_LPNH_LPH_THRESHOLDS",
@@ -154,7 +161,7 @@
     }
 
     companion object {
-        val configHelper by lazy { DeviceConfigHelper(::DeviceConfigWrapper) }
+        @JvmStatic val configHelper by lazy { DeviceConfigHelper(::DeviceConfigWrapper) }
 
         @JvmStatic fun get() = configHelper.config
     }
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index 92cdf72..625b6c6 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -68,11 +68,12 @@
 import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
 import com.android.quickstep.util.TransformParams;
 import com.android.quickstep.util.TransformParams.BuilderProxy;
+import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task.TaskKey;
 import com.android.systemui.shared.system.InputConsumerController;
 
 import java.lang.ref.WeakReference;
-import java.util.ArrayList;
+import java.util.List;
 import java.util.UUID;
 import java.util.function.Consumer;
 
@@ -140,9 +141,13 @@
     }
 
     @Override
-    protected HomeAnimationFactory createHomeAnimationFactory(ArrayList<IBinder> launchCookies,
-            long duration, boolean isTargetTranslucent, boolean appCanEnterPip,
-            RemoteAnimationTarget runningTaskTarget) {
+    protected HomeAnimationFactory createHomeAnimationFactory(
+            List<IBinder> launchCookies,
+            long duration,
+            boolean isTargetTranslucent,
+            boolean appCanEnterPip,
+            RemoteAnimationTarget runningTaskTarget,
+            @Nullable TaskView targetTaskView) {
         mAppCanEnterPip = appCanEnterPip;
         if (appCanEnterPip) {
             return new FallbackPipToHomeAnimationFactory();
@@ -380,7 +385,7 @@
         }
 
         @Override
-        public void update(RectF currentRect, float progress, float radius) {
+        public void update(RectF currentRect, float progress, float radius, int overlayAlpha) {
             if (mSurfaceControl != null) {
                 currentRect.roundOut(mTempRect);
                 Transaction t = new Transaction();
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index c8a91df..81c9d4a 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -186,6 +186,7 @@
     private final long mSwipeUpStartTimeMs = SystemClock.uptimeMillis();
 
     private boolean mHandlingAtomicEvent;
+    private boolean mIsInExtendedSlopRegion;
 
     public GestureState(OverviewComponentObserver componentObserver, int gestureId) {
         mHomeIntent = componentObserver.getHomeIntent();
@@ -494,6 +495,25 @@
     }
 
     /**
+     * Set whether it's in long press nav handle (LPNH)'s extended touch slop region, e.g., second
+     * stage region in order to continue respect LPNH and ignore other touch slop logic.
+     * This will only be set to true when flag ENABLE_LPNH_TWO_STAGES is turned on.
+     */
+    public void setIsInExtendedSlopRegion(boolean isInExtendedSlopRegion) {
+        if (DeviceConfigWrapper.get().getEnableLpnhTwoStages()) {
+            mIsInExtendedSlopRegion = isInExtendedSlopRegion;
+        }
+    }
+
+    /**
+     * Returns whether it's in LPNH's extended touch slop region. This is only valid when flag
+     * ENABLE_LPNH_TWO_STAGES is turned on.
+     */
+    public boolean isInExtendedSlopRegion() {
+        return mIsInExtendedSlopRegion;
+    }
+
+    /**
      * Returns and clears the canceled animation thumbnail data. This call only returns a value
      * while STATE_RECENTS_ANIMATION_CANCELED state is being set, and the caller is responsible for
      * calling {@link RecentsAnimationController#cleanupScreenshot()}.
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 7655c59..811b9fd 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -192,7 +192,7 @@
     public RecentsView getVisibleRecentsView() {
         QuickstepLauncher launcher = getVisibleLauncher();
         RecentsView recentsView =
-                launcher != null && launcher.getStateManager().getState().overviewUi
+                launcher != null && launcher.getStateManager().getState().isRecentsViewVisible
                         ? launcher.getOverviewPanel() : null;
         if (recentsView == null || (!launcher.hasBeenResumed()
                 && recentsView.getRunningTaskViewId() == -1)) {
diff --git a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
index 225b127..b720382 100644
--- a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
+++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
@@ -53,6 +53,7 @@
 import android.window.IOnBackInvokedCallback;
 
 import com.android.app.animation.Interpolators;
+import com.android.internal.policy.SystemBarUtils;
 import com.android.internal.view.AppearanceRegion;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BubbleTextView;
@@ -88,7 +89,6 @@
     private static final float MIN_WINDOW_SCALE = 0.85f;
     private static final float MAX_SCRIM_ALPHA_DARK = 0.8f;
     private static final float MAX_SCRIM_ALPHA_LIGHT = 0.2f;
-    private static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.20f;
 
     private final QuickstepTransitionManager mQuickstepTransitionManager;
     private final Matrix mTransformMatrix = new Matrix();
@@ -100,6 +100,7 @@
     private final int mWindowScaleMarginX;
     private float mWindowScaleEndCornerRadius;
     private float mWindowScaleStartCornerRadius;
+    private int mStatusBarHeight;
     private final Interpolator mProgressInterpolator = Interpolators.BACK_GESTURE;
     private final Interpolator mVerticalMoveInterpolator = new DecelerateInterpolator();
     private final PointF mInitialTouchPos = new PointF();
@@ -123,7 +124,7 @@
     private final ComponentCallbacks mComponentCallbacks = new ComponentCallbacks() {
         @Override
         public void onConfigurationChanged(Configuration newConfig) {
-            loadCornerRadius();
+            loadResources();
         }
 
         @Override
@@ -135,7 +136,7 @@
             QuickstepTransitionManager quickstepTransitionManager) {
         mLauncher = launcher;
         mQuickstepTransitionManager = quickstepTransitionManager;
-        loadCornerRadius();
+        loadResources();
         mWindowScaleMarginX = mLauncher.getResources().getDimensionPixelSize(
                 R.dimen.swipe_back_window_scale_x_margin);
     }
@@ -388,7 +389,7 @@
                 progress, mWindowScaleStartCornerRadius, mWindowScaleEndCornerRadius);
         applyTransform(mCurrentRect, cornerRadius);
 
-        customizeStatusBarAppearance(progress > UPDATE_SYSUI_FLAGS_THRESHOLD);
+        customizeStatusBarAppearance(top > mStatusBarHeight / 2);
     }
 
     /** Transform the target window to match the target rect. */
@@ -535,13 +536,14 @@
         anim.start();
     }
 
-    private void loadCornerRadius() {
+    private void loadResources() {
         mWindowScaleEndCornerRadius = QuickStepContract.supportsRoundedCornersOnWindows(
                 mLauncher.getResources())
                 ? mLauncher.getResources().getDimensionPixelSize(
                 R.dimen.swipe_back_window_corner_radius)
                 : 0;
         mWindowScaleStartCornerRadius = QuickStepContract.getWindowCornerRadius(mLauncher);
+        mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mLauncher);
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index af02ccf..080e03a 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -43,6 +43,7 @@
 import com.android.launcher3.states.StateAnimationConfig;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.launcher3.util.ObjectWrapper;
+import com.android.launcher3.views.ClipIconView;
 import com.android.launcher3.views.FloatingIconView;
 import com.android.launcher3.views.FloatingView;
 import com.android.launcher3.widget.LauncherAppWidgetHostView;
@@ -55,7 +56,8 @@
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.system.InputConsumerController;
 
-import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * Temporary class to allow easier refactoring
@@ -72,9 +74,13 @@
 
 
     @Override
-    protected HomeAnimationFactory createHomeAnimationFactory(ArrayList<IBinder> launchCookies,
-            long duration, boolean isTargetTranslucent, boolean appCanEnterPip,
-            RemoteAnimationTarget runningTaskTarget) {
+    protected HomeAnimationFactory createHomeAnimationFactory(
+            List<IBinder> launchCookies,
+            long duration,
+            boolean isTargetTranslucent,
+            boolean appCanEnterPip,
+            RemoteAnimationTarget runningTaskTarget,
+            @Nullable TaskView targetTaskView) {
         if (mContainer == null) {
             mStateCallback.addChangeListener(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
                     isPresent -> mRecentsView.startHome());
@@ -86,8 +92,14 @@
             };
         }
 
-        final View workspaceView = findWorkspaceView(launchCookies,
-                mRecentsView.getRunningTaskView());
+        TaskView sourceTaskView = mRecentsView == null && targetTaskView == null
+                ? null
+                : targetTaskView == null
+                        ? mRecentsView.getRunningTaskView()
+                        : targetTaskView;
+        final View workspaceView = findWorkspaceView(
+                targetTaskView == null ? launchCookies : Collections.emptyList(),
+                sourceTaskView);
         boolean canUseWorkspaceView = workspaceView != null
                 && workspaceView.isAttachedToWindow()
                 && workspaceView.getHeight() > 0
@@ -100,16 +112,24 @@
         }
 
         if (!canUseWorkspaceView || appCanEnterPip || mIsSwipeForSplit) {
-            return new LauncherHomeAnimationFactory();
+            return new LauncherHomeAnimationFactory() {
+
+                @Nullable
+                @Override
+                public TaskView getTargetTaskView() {
+                    return targetTaskView;
+                }
+            };
         }
         if (workspaceView instanceof LauncherAppWidgetHostView) {
             return createWidgetHomeAnimationFactory((LauncherAppWidgetHostView) workspaceView,
                     isTargetTranslucent, runningTaskTarget);
         }
-        return createIconHomeAnimationFactory(workspaceView);
+        return createIconHomeAnimationFactory(workspaceView, targetTaskView);
     }
 
-    private HomeAnimationFactory createIconHomeAnimationFactory(View workspaceView) {
+    private HomeAnimationFactory createIconHomeAnimationFactory(
+            View workspaceView, @Nullable TaskView targetTaskView) {
         RectF iconLocation = new RectF();
         FloatingIconView floatingIconView = getFloatingIconView(mContainer, workspaceView, null,
                 mContainer.getTaskbarUIController() == null
@@ -175,10 +195,35 @@
             }
 
             @Override
-            public void update(RectF currentRect, float progress, float radius) {
-                super.update(currentRect, progress, radius);
+            public void update(
+                    RectF currentRect,
+                    float progress,
+                    float radius,
+                    int overlayAlpha) {
                 floatingIconView.update(1f /* alpha */, currentRect, progress, windowAlphaThreshold,
-                        radius, false);
+                        radius, false, overlayAlpha);
+            }
+
+            @Override
+            public boolean isAnimationReady() {
+                return floatingIconView.isLaidOut();
+            }
+
+            @Override
+            public void setTaskViewArtist(ClipIconView.TaskViewArtist taskViewArtist) {
+                super.setTaskViewArtist(taskViewArtist);
+                floatingIconView.setOverlayArtist(taskViewArtist);
+            }
+
+            @Override
+            public boolean isAnimatingIntoIcon() {
+                return true;
+            }
+
+            @Nullable
+            @Override
+            public TaskView getTargetTaskView() {
+                return targetTaskView;
             }
         };
     }
@@ -232,8 +277,8 @@
             }
 
             @Override
-            public void update(RectF currentRect, float progress, float radius) {
-                super.update(currentRect, progress, radius);
+            public void update(RectF currentRect, float progress, float radius, int overlayAlpha) {
+                super.update(currentRect, progress, radius, overlayAlpha);
                 final float fallbackBackgroundAlpha =
                         1 - mapBoundToRange(progress, 0.8f, 1, 0, 1, EXAGGERATED_EASE);
                 final float foregroundAlpha =
@@ -254,13 +299,12 @@
      * associated with the running task.
      */
     @Nullable
-    private View findWorkspaceView(ArrayList<IBinder> launchCookies, TaskView runningTaskView) {
+    private View findWorkspaceView(List<IBinder> launchCookies, TaskView sourceTaskView) {
         if (mIsSwipingPipToHome) {
             // Disable if swiping to PIP
             return null;
         }
-        if (runningTaskView == null || runningTaskView.getTask() == null
-                || runningTaskView.getTask().key.getComponent() == null) {
+        if (sourceTaskView == null || sourceTaskView.getFirstTask().key.getComponent() == null) {
             // Disable if it's an invalid task
             return null;
         }
@@ -277,8 +321,8 @@
         }
 
         return mContainer.getFirstMatchForAppClose(launchCookieItemId,
-                runningTaskView.getTask().key.getComponent().getPackageName(),
-                UserHandle.of(runningTaskView.getTask().key.userId),
+                sourceTaskView.getFirstTask().key.getComponent().getPackageName(),
+                UserHandle.of(sourceTaskView.getFirstTask().key.userId),
                 false /* supportsAllAppsState */);
     }
 
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 68923ee..3091e3d 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -16,6 +16,9 @@
 package com.android.quickstep;
 
 import static com.android.launcher3.PagedView.INVALID_PAGE;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_3_BUTTON;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_QUICK_SWITCH;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_SHORTCUT;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
 
@@ -34,6 +37,8 @@
 import com.android.internal.jank.Cuj;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.logger.LauncherAtom;
+import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.taskbar.TaskbarUIController;
 import com.android.launcher3.util.RunnableList;
@@ -171,7 +176,7 @@
         RunnableList callbackList = null;
         if (taskView != null) {
             mWaitForToggleCommandComplete = true;
-            taskView.setEndQuickswitchCuj(true);
+            taskView.setEndQuickSwitchCuj(true);
             callbackList = taskView.launchTasks();
         }
 
@@ -285,6 +290,7 @@
             public void onAnimationStart(Animator animation) {
                 super.onAnimationStart(animation);
                 updateRecentsViewFocus(cmd);
+                logShowOverviewFrom(cmd.type);
             }
             @Override
             public void onAnimationEnd(Animator animation) {
@@ -319,6 +325,7 @@
             public void onRecentsAnimationStart(RecentsAnimationController controller,
                     RecentsAnimationTargets targets) {
                 updateRecentsViewFocus(cmd);
+                logShowOverviewFrom(cmd.type);
                 activityInterface.runOnInitBackgroundStateUI(() ->
                         interactionHandler.onGestureEnded(0, new PointF()));
                 cmd.removeListener(this);
@@ -420,6 +427,33 @@
         return true;
     }
 
+    private <T extends StatefulActivity<?> & RecentsViewContainer>
+            void logShowOverviewFrom(int cmdType) {
+        BaseActivityInterface<?, T> activityInterface =
+                mOverviewComponentObserver.getActivityInterface();
+        var container = activityInterface.getCreatedContainer();
+        if (container != null) {
+            StatsLogManager.LauncherEvent event;
+            switch (cmdType) {
+                case TYPE_SHOW -> event = LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_SHORTCUT;
+                case TYPE_HIDE ->
+                        event = LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_QUICK_SWITCH;
+                case TYPE_TOGGLE -> event = LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_3_BUTTON;
+                default -> {
+                    return;
+                }
+            }
+
+            StatsLogManager.newInstance(container.asContext())
+                    .logger()
+                    .withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
+                            .setTaskSwitcherContainer(
+                                    LauncherAtom.TaskSwitcherContainer.getDefaultInstance())
+                            .build())
+                    .log(event);
+        }
+    }
+
     public void dump(PrintWriter pw) {
         pw.println("OverviewCommandHelper:");
         pw.println("  mPendingCommands=" + mPendingCommands.size());
diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
index 0a02e99..a71e314 100644
--- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
+++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
@@ -109,6 +109,8 @@
      * Sets a listener for changes in {@link #isHomeAndOverviewSame()}
      */
     public void setOverviewChangeListener(Consumer<Boolean> overviewChangeListener) {
+        // TODO(b/337861962): This method should be able to support multiple listeners instead of
+        // one so that we can reuse the same instance of this class across multiple places
         mOverviewChangeListener = overviewChangeListener;
     }
 
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index 711882c..37b4dca 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -31,6 +31,7 @@
 import android.os.RemoteException;
 import android.util.SparseBooleanArray;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import com.android.launcher3.util.LooperExecutor;
@@ -44,6 +45,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -137,7 +139,7 @@
      * @return The change id of the current task list
      */
     public synchronized int getTasks(boolean loadKeysOnly,
-            Consumer<ArrayList<GroupTask>> callback, Predicate<GroupTask> filter) {
+            @Nullable Consumer<List<GroupTask>> callback, Predicate<GroupTask> filter) {
         final int requestLoadId = mChangeId;
         if (mResultsUi.isValidForRequest(requestLoadId, loadKeysOnly)) {
             // The list is up to date, send the callback on the next frame,
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index f57f4c8..97a0b3f 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -33,7 +33,6 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.app.ActivityOptions;
-import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.os.Bundle;
@@ -507,4 +506,9 @@
     public TISBindHelper getTISBindHelper() {
         return mTISBindHelper;
     }
+
+    @Override
+    public boolean isRecentsViewVisible() {
+        return getStateManager().getState().isRecentsViewVisible();
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 4b4f914..8bcdaa3 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -33,6 +33,7 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DIALOG_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP;
@@ -107,7 +108,7 @@
 
     private final ArrayList<Runnable> mOnDestroyActions = new ArrayList<>();
 
-    private @SystemUiStateFlags int mSystemUiStateFlags = QuickStepContract.SYSUI_STATE_AWAKE;
+    private @SystemUiStateFlags long mSystemUiStateFlags = QuickStepContract.SYSUI_STATE_AWAKE;
     private NavigationMode mMode = THREE_BUTTONS;
     private NavBarPosition mNavBarPosition;
 
@@ -351,7 +352,7 @@
     /**
      * Updates the system ui state flags from SystemUI.
      */
-    public void setSystemUiFlags(int stateFlags) {
+    public void setSystemUiFlags(@SystemUiStateFlags long stateFlags) {
         mSystemUiStateFlags = stateFlags;
     }
 
@@ -359,7 +360,8 @@
      * @return the system ui state flags.
      */
     // TODO(141886704): See if we can remove this
-    public int getSystemUiStateFlags() {
+    @SystemUiStateFlags
+    public long getSystemUiStateFlags() {
         return mSystemUiStateFlags;
     }
 
@@ -399,7 +401,8 @@
                 && (mSystemUiStateFlags & SYSUI_STATE_MAGNIFICATION_OVERLAP) == 0
                 && ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0
                         || (mSystemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0)
-                && (mSystemUiStateFlags & SYSUI_STATE_DEVICE_DREAMING) == 0;
+                && (mSystemUiStateFlags & SYSUI_STATE_DEVICE_DREAMING) == 0
+                && (mSystemUiStateFlags & SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION) == 0;
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index 89351aa..98c1eb4 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -33,6 +33,7 @@
 import android.os.Process;
 import android.os.UserHandle;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import com.android.launcher3.icons.IconProvider;
@@ -40,6 +41,7 @@
 import com.android.launcher3.util.Executors.SimpleThreadFactory;
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.SafeCloseable;
+import com.android.quickstep.recents.data.RecentTasksDataSource;
 import com.android.quickstep.util.GroupTask;
 import com.android.quickstep.util.TaskVisualsChangeListener;
 import com.android.systemui.shared.recents.model.Task;
@@ -60,8 +62,8 @@
  * Singleton class to load and manage recents model.
  */
 @TargetApi(Build.VERSION_CODES.O)
-public class RecentsModel implements IconChangeListener, TaskStackChangeListener,
-        TaskVisualsChangeListener, SafeCloseable {
+public class RecentsModel implements RecentTasksDataSource, IconChangeListener,
+        TaskStackChangeListener, TaskVisualsChangeListener, SafeCloseable {
 
     // We do not need any synchronization for this variable as its only written on UI thread.
     public static final MainThreadInitializedObject<RecentsModel> INSTANCE =
@@ -141,7 +143,8 @@
      *                always called on the UI thread.
      * @return the request id associated with this call.
      */
-    public int getTasks(Consumer<ArrayList<GroupTask>> callback) {
+    @Override
+    public int getTasks(@Nullable Consumer<List<GroupTask>> callback) {
         return mTaskList.getTasks(false /* loadKeysOnly */, callback,
                 RecentsFilterState.DEFAULT_FILTER);
     }
@@ -155,7 +158,7 @@
      *                callback.
      * @return the request id associated with this call.
      */
-    public int getTasks(Consumer<ArrayList<GroupTask>> callback, Predicate<GroupTask> filter) {
+    public int getTasks(@Nullable Consumer<List<GroupTask>> callback, Predicate<GroupTask> filter) {
         return mTaskList.getTasks(false /* loadKeysOnly */, callback, filter);
     }
 
diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
index 3380291..6f1ab7d 100644
--- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java
+++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
@@ -157,7 +157,7 @@
         // Register for navigation mode changes
         mDisplayController.addChangeListener(this);
         DisplayController.Info info = mDisplayController.getInfo();
-        onDisplayInfoChangedInternal(info, CHANGE_ALL, info.navigationMode.hasGestures);
+        onDisplayInfoChangedInternal(info, CHANGE_ALL, info.getNavigationMode().hasGestures);
         runOnDestroy(() -> mDisplayController.removeChangeListener(this));
 
         mOrientationListener = new OrientationEventListener(mContext) {
@@ -291,7 +291,7 @@
         }
 
         if ((flags & CHANGE_NAVIGATION_MODE) != 0) {
-            NavigationMode newMode = info.navigationMode;
+            NavigationMode newMode = info.getNavigationMode();
             mOrientationTouchTransformer.setNavigationMode(newMode, mDisplayController.getInfo(),
                     mContext.getResources());
 
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index 5ff9787..fb54241 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -17,6 +17,7 @@
 
 import static com.android.app.animation.Interpolators.ACCELERATE_1_5;
 import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.launcher3.PagedView.INVALID_PAGE;
 
 import android.animation.Animator;
 import android.content.Context;
@@ -27,6 +28,7 @@
 import android.view.RemoteAnimationTarget;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
 
 import com.android.launcher3.DeviceProfile;
@@ -36,6 +38,7 @@
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.touch.PagedOrientationHandler;
+import com.android.launcher3.views.ClipIconView;
 import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
 import com.android.quickstep.util.AnimatorControllerWithResistance;
@@ -46,6 +49,8 @@
 import com.android.quickstep.util.TaskViewSimulator;
 import com.android.quickstep.util.TransformParams;
 import com.android.quickstep.util.TransformParams.BuilderProxy;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskView;
 
 import java.util.Arrays;
 import java.util.function.Consumer;
@@ -201,7 +206,7 @@
 
         public void setAnimation(RectFSpringAnim anim) { }
 
-        public void update(RectF currentRect, float progress, float radius) { }
+        public void update(RectF currentRect, float progress, float radius, int overlayAlpha) { }
 
         public void onCancel() { }
 
@@ -222,6 +227,33 @@
             }
             return Utilities.mapToRange(progress, start, end, 1, 0, ACCELERATE_1_5);
         }
+
+        /**
+         * Sets a {@link com.android.launcher3.views.ClipIconView.TaskViewArtist} that should be
+         * used draw a {@link TaskView} during this home animation.
+         */
+        public void setTaskViewArtist(ClipIconView.TaskViewArtist taskViewArtist) { }
+
+        public boolean isAnimationReady() {
+            return true;
+        }
+
+        public boolean isAnimatingIntoIcon() {
+            return false;
+        }
+
+        @Nullable
+        public TaskView getTargetTaskView() {
+            return null;
+        }
+
+        public boolean isRtl() {
+            return Utilities.isRtl(mContext.getResources());
+        }
+
+        public boolean isPortrait() {
+            return !mDp.isLandscape && !mDp.isSeascape();
+        }
     }
 
     /**
@@ -276,9 +308,13 @@
         for (int i = 0, mRemoteTargetHandlesLength = mRemoteTargetHandles.length;
                 i < mRemoteTargetHandlesLength; i++) {
             RemoteTargetHandle remoteHandle = mRemoteTargetHandles[i];
-            out[i] = getWindowAnimationToHomeInternal(homeAnimationFactory,
-                    targetRect, remoteHandle.getTransformParams(),
-                    remoteHandle.getTaskViewSimulator(), startRects[i], homeToWindowPositionMap[i]);
+            out[i] = getWindowAnimationToHomeInternal(
+                    homeAnimationFactory,
+                    targetRect,
+                    remoteHandle.getTransformParams(),
+                    remoteHandle.getTaskViewSimulator(),
+                    startRects[i],
+                    homeToWindowPositionMap[i]);
         }
         return out;
     }
@@ -288,21 +324,39 @@
     }
 
     private RectFSpringAnim getWindowAnimationToHomeInternal(
-            HomeAnimationFactory homeAnimationFactory, RectF targetRect,
-            TransformParams transformParams, TaskViewSimulator taskViewSimulator,
-            RectF startRect, Matrix homeToWindowPositionMap) {
+            HomeAnimationFactory homeAnimationFactory,
+            RectF targetRect,
+            TransformParams transformParams,
+            TaskViewSimulator taskViewSimulator,
+            RectF startRect,
+            Matrix homeToWindowPositionMap) {
         RectF cropRectF = new RectF(taskViewSimulator.getCurrentCropRect());
         // Move the startRect to Launcher space as floatingIconView runs in Launcher
         Matrix windowToHomePositionMap = new Matrix();
 
-        // If the start rect ends up overshooting too much to the left/right offscreen, bring it
-        // back to fullscreen. This can happen when the recentsScroll value isn't aligned with
-        // the pageScroll value for a given taskView, see b/228829958#comment12
-        mRemoteTargetHandles[0].getTaskViewSimulator().getOrientationState().getOrientationHandler()
-                .fixBoundsForHomeAnimStartRect(startRect, mDp);
+        TaskView targetTaskView = homeAnimationFactory.getTargetTaskView();
+        if (targetTaskView == null) {
+            // If the start rect ends up overshooting too much to the left/right offscreen, bring it
+            // back to fullscreen. This can happen when the recentsScroll value isn't aligned with
+            // the pageScroll value for a given taskView, see b/228829958#comment12
+            mRemoteTargetHandles[0].getTaskViewSimulator()
+                    .getOrientationState()
+                    .getOrientationHandler()
+                    .fixBoundsForHomeAnimStartRect(startRect, mDp);
 
+        }
         homeToWindowPositionMap.invert(windowToHomePositionMap);
         windowToHomePositionMap.mapRect(startRect);
+        RectF invariantStartRect = new RectF(startRect);
+
+        if (targetTaskView != null) {
+            Rect thumbnailBounds = new Rect();
+            targetTaskView.getThumbnailBounds(thumbnailBounds, /* relativeToDragLayer= */ true);
+
+            invariantStartRect = new RectF(thumbnailBounds);
+            invariantStartRect.offsetTo(startRect.left, thumbnailBounds.top);
+            startRect = new RectF(thumbnailBounds);
+        }
 
         boolean useTaskbarHotseatParams = mDp.isTaskbarPresent
                 && homeAnimationFactory.isInHotseat();
@@ -312,8 +366,12 @@
         homeAnimationFactory.setAnimation(anim);
 
         SpringAnimationRunner runner = new SpringAnimationRunner(
-                homeAnimationFactory, cropRectF, homeToWindowPositionMap,
-                transformParams, taskViewSimulator);
+                homeAnimationFactory,
+                cropRectF,
+                homeToWindowPositionMap,
+                transformParams,
+                taskViewSimulator,
+                invariantStartRect);
         anim.addAnimatorListener(runner);
         anim.addOnUpdateListener(runner);
         return anim;
@@ -336,9 +394,30 @@
         final float mStartRadius;
         final float mEndRadius;
 
-        SpringAnimationRunner(HomeAnimationFactory factory, RectF cropRectF,
-                Matrix homeToWindowPositionMap, TransformParams transformParams,
-                TaskViewSimulator taskViewSimulator) {
+        final RectF mRunningTaskViewStartRectF;
+        @Nullable
+        final TaskView mTargetTaskView;
+        final float mRunningTaskViewScrollOffset;
+        final float mTaskViewWidth;
+        final float mTaskViewHeight;
+        final boolean mIsPortrait;
+        final Rect mThumbnailStartBounds = new Rect();
+
+        // Store the mTargetTaskView view properties onAnimationStart so that we can reset them
+        // when cleaning up.
+        float mTaskViewAlpha;
+        float mTaskViewTranslationX;
+        float mTaskViewTranslationY;
+        float mTaskViewScaleX;
+        float mTaskViewScaleY;
+
+        SpringAnimationRunner(
+                HomeAnimationFactory factory,
+                RectF cropRectF,
+                Matrix homeToWindowPositionMap,
+                TransformParams transformParams,
+                TaskViewSimulator taskViewSimulator,
+                RectF invariantStartRect) {
             mAnimationFactory = factory;
             mHomeAnim = factory.createActivityAnimationToHome();
             mCropRectF = cropRectF;
@@ -351,22 +430,62 @@
             // rounding at the end of the animation.
             mStartRadius = taskViewSimulator.getCurrentCornerRadius();
             mEndRadius = factory.getEndRadius(cropRectF);
+
+            mRunningTaskViewStartRectF = invariantStartRect;
+            mTargetTaskView = factory.getTargetTaskView();
+            mTaskViewWidth = mTargetTaskView == null ? 0 : mTargetTaskView.getWidth();
+            mTaskViewHeight = mTargetTaskView == null ? 0 : mTargetTaskView.getHeight();
+            mIsPortrait = factory.isPortrait();
+            // Use the running task's start position to determine how much it needs to be offset
+            // to end up offscreen.
+            mRunningTaskViewScrollOffset = factory.isRtl()
+                    ? (Math.min(0, -invariantStartRect.right))
+                    : (Math.max(0, mDp.widthPx - invariantStartRect.left));
         }
 
         @Override
         public void onUpdate(RectF currentRect, float progress) {
-            mHomeAnim.setPlayFraction(progress);
-            mHomeToWindowPositionMap.mapRect(mWindowCurrentRect, currentRect);
-
-            mMatrix.setRectToRect(mCropRectF, mWindowCurrentRect, ScaleToFit.FILL);
             float cornerRadius = Utilities.mapRange(progress, mStartRadius, mEndRadius);
             float alpha = mAnimationFactory.getWindowAlpha(progress);
-            mLocalTransformParams
-                    .setTargetAlpha(alpha)
-                    .setCornerRadius(cornerRadius);
-            mLocalTransformParams.applySurfaceParams(mLocalTransformParams
-                    .createSurfaceParams(this));
-            mAnimationFactory.update(currentRect, progress, mMatrix.mapRadius(cornerRadius));
+
+            mHomeAnim.setPlayFraction(progress);
+            if (mTargetTaskView == null) {
+                mHomeToWindowPositionMap.mapRect(mWindowCurrentRect, currentRect);
+                mMatrix.setRectToRect(mCropRectF, mWindowCurrentRect, ScaleToFit.FILL);
+                mLocalTransformParams
+                        .setTargetAlpha(alpha)
+                        .setCornerRadius(cornerRadius);
+            } else {
+                mHomeToWindowPositionMap.mapRect(mWindowCurrentRect, mRunningTaskViewStartRectF);
+                mWindowCurrentRect.offset(mRunningTaskViewScrollOffset * progress, 0f);
+                mMatrix.setRectToRect(mCropRectF, mWindowCurrentRect, ScaleToFit.FILL);
+                mLocalTransformParams.setCornerRadius(mStartRadius);
+            }
+
+            mLocalTransformParams.applySurfaceParams(
+                    mLocalTransformParams.createSurfaceParams(this));
+            mAnimationFactory.update(
+                    currentRect, progress, mMatrix.mapRadius(cornerRadius), (int) (alpha * 255));
+
+            if (mTargetTaskView == null) {
+                return;
+            }
+            if (mAnimationFactory.isAnimatingIntoIcon() && mAnimationFactory.isAnimationReady()) {
+                mTargetTaskView.setAlpha(0f);
+                return;
+            }
+            mTargetTaskView.setAlpha(mAnimationFactory.isAnimatingIntoIcon() ? 1f : alpha);
+            float width = mThumbnailStartBounds.width();
+            float height =  mThumbnailStartBounds.height();
+            float scale = Math.min(currentRect.width(), currentRect.height())
+                    / Math.min(width, height);
+
+            mTargetTaskView.setScaleX(scale);
+            mTargetTaskView.setScaleY(scale);
+            mTargetTaskView.setTranslationX(
+                    currentRect.centerX() - mThumbnailStartBounds.centerX());
+            mTargetTaskView.setTranslationY(
+                    currentRect.centerY() - mThumbnailStartBounds.centerY());
         }
 
         @Override
@@ -379,16 +498,71 @@
 
         @Override
         public void onCancel() {
+            cleanUp();
             mAnimationFactory.onCancel();
         }
 
         @Override
         public void onAnimationStart(Animator animation) {
+            setUp();
             mHomeAnim.dispatchOnStart();
+            if (mTargetTaskView == null) {
+                return;
+            }
+            Rect thumbnailBounds = new Rect();
+            // Use bounds relative to mTargetTaskView since it will be scaled afterwards
+            mTargetTaskView.getThumbnailBounds(thumbnailBounds);
+            mAnimationFactory.setTaskViewArtist(new ClipIconView.TaskViewArtist(
+                    mTargetTaskView::draw,
+                    0f,
+                    -thumbnailBounds.top,
+                    Math.min(mTaskViewHeight, mTaskViewWidth),
+                    mIsPortrait));
+        }
+
+        private void setUp() {
+            if (mTargetTaskView == null) {
+                return;
+            }
+            RecentsView recentsView = mTargetTaskView.getRecentsView();
+            if (recentsView != null) {
+                recentsView.setOffsetMidpointIndexOverride(
+                        recentsView.indexOfChild(mTargetTaskView));
+            }
+            mTargetTaskView.getThumbnailBounds(
+                    mThumbnailStartBounds, /* relativeToDragLayer= */ true);
+            mTaskViewAlpha = mTargetTaskView.getAlpha();
+            if (mAnimationFactory.isAnimatingIntoIcon()) {
+                return;
+            }
+            mTaskViewTranslationX = mTargetTaskView.getTranslationX();
+            mTaskViewTranslationY = mTargetTaskView.getTranslationY();
+            mTaskViewScaleX = mTargetTaskView.getScaleX();
+            mTaskViewScaleY = mTargetTaskView.getScaleY();
+        }
+
+        private void cleanUp() {
+            if (mTargetTaskView == null) {
+                return;
+            }
+            RecentsView recentsView = mTargetTaskView.getRecentsView();
+            if (recentsView != null) {
+                recentsView.setOffsetMidpointIndexOverride(INVALID_PAGE);
+            }
+            mTargetTaskView.setAlpha(mTaskViewAlpha);
+            if (!mAnimationFactory.isAnimatingIntoIcon()) {
+                mTargetTaskView.setTranslationX(mTaskViewTranslationX);
+                mTargetTaskView.setTranslationY(mTaskViewTranslationY);
+                mTargetTaskView.setScaleX(mTaskViewScaleX);
+                mTargetTaskView.setScaleY(mTaskViewScaleY);
+                return;
+            }
+            mAnimationFactory.setTaskViewArtist(null);
         }
 
         @Override
         public void onAnimationSuccess(Animator animator) {
+            cleanUp();
             mHomeAnim.getAnimationPlayer().end();
         }
     }
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index b0b2589..0ac3ec7 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -16,7 +16,6 @@
 package com.android.quickstep;
 
 import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
-import static android.content.pm.PackageManager.FEATURE_PC;
 
 import static com.android.launcher3.Flags.enableUnfoldStateAnimation;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -73,6 +72,7 @@
 import com.android.quickstep.util.unfold.ProxyUnfoldTransitionProvider;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
 import com.android.systemui.shared.system.RecentsAnimationListener;
 import com.android.systemui.shared.system.smartspace.ILauncherUnlockAnimationController;
@@ -112,7 +112,7 @@
  * Holds the reference to SystemUI.
  */
 public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable {
-    private static final String TAG = SystemUiProxy.class.getSimpleName();
+    private static final String TAG = "SystemUiProxy";
 
     public static final MainThreadInitializedObject<SystemUiProxy> INSTANCE =
             new MainThreadInitializedObject<>(SystemUiProxy::new);
@@ -173,7 +173,8 @@
     private final Handler mAsyncHandler;
 
     // TODO(141886704): Find a way to remove this
-    private int mLastSystemUiStateFlags;
+    @SystemUiStateFlags
+    private long mLastSystemUiStateFlags;
 
     /**
      * This is a singleton pending intent that is used to start recents via Shell (which is a
@@ -325,12 +326,13 @@
     }
 
     // TODO(141886704): Find a way to remove this
-    public void setLastSystemUiStateFlags(int stateFlags) {
+    public void setLastSystemUiStateFlags(@SystemUiStateFlags long stateFlags) {
         mLastSystemUiStateFlags = stateFlags;
     }
 
     // TODO(141886704): Find a way to remove this
-    public int getLastSystemUiStateFlags() {
+    @SystemUiStateFlags
+    public long getLastSystemUiStateFlags() {
         return mLastSystemUiStateFlags;
     }
 
@@ -576,6 +578,17 @@
         }
     }
 
+    @Override
+    public void toggleQuickSettingsPanel() {
+        if (mSystemUiProxy != null) {
+            try {
+                mSystemUiProxy.toggleQuickSettingsPanel();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call toggleQuickSettingsPanel", e);
+            }
+        }
+    }
+
     //
     // Pip
     //
@@ -748,12 +761,12 @@
     /**
      * Tells SysUI to show the bubble with the provided key.
      * @param key the key of the bubble to show.
-     * @param bubbleBarBounds bounds of the bubble bar in display coordinates
+     * @param top top coordinate of bubble bar on screen
      */
-    public void showBubble(String key, Rect bubbleBarBounds) {
+    public void showBubble(String key, int top) {
         if (mBubbles != null) {
             try {
-                mBubbles.showBubble(key, bubbleBarBounds);
+                mBubbles.showBubble(key, top);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed call showBubble");
             }
@@ -761,19 +774,6 @@
     }
 
     /**
-     * Tells SysUI to remove the bubble with the provided key.
-     * @param key the key of the bubble to show.
-     */
-    public void removeBubble(String key) {
-        if (mBubbles == null) return;
-        try {
-            mBubbles.removeBubble(key);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed call removeBubble");
-        }
-    }
-
-    /**
      * Tells SysUI to remove all bubbles.
      */
     public void removeAllBubbles() {
@@ -801,15 +801,43 @@
     /**
      * Tells SysUI when the bubble is being dragged.
      * Should be called only when the bubble bar is expanded.
-     * @param bubbleKey the key of the bubble to collapse/expand
-     * @param isBeingDragged whether the bubble is being dragged
+     * @param bubbleKey key of the bubble being dragged
      */
-    public void onBubbleDrag(@Nullable String bubbleKey, boolean isBeingDragged) {
+    public void startBubbleDrag(@Nullable String bubbleKey) {
         if (mBubbles == null) return;
         try {
-            mBubbles.onBubbleDrag(bubbleKey, isBeingDragged);
+            mBubbles.startBubbleDrag(bubbleKey);
         } catch (RemoteException e) {
-            Log.w(TAG, "Failed call onBubbleDrag");
+            Log.w(TAG, "Failed call startBubbleDrag");
+        }
+    }
+
+    /**
+     * Tells SysUI when the bubble stops being dragged.
+     * Should be called only when the bubble bar is expanded.
+     *
+     * @param location location of the bubble bar
+     * @param top      new top coordinate for bubble bar on screen
+     */
+    public void stopBubbleDrag(BubbleBarLocation location, int top) {
+        if (mBubbles == null) return;
+        try {
+            mBubbles.stopBubbleDrag(location, top);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed call stopBubbleDrag");
+        }
+    }
+
+    /**
+     * Tells SysUI to dismiss the bubble with the provided key.
+     * @param key the key of the bubble to dismiss.
+     */
+    public void dragBubbleToDismiss(String key) {
+        if (mBubbles == null) return;
+        try {
+            mBubbles.dragBubbleToDismiss(key);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed call dragBubbleToDismiss");
         }
     }
 
@@ -838,16 +866,17 @@
     }
 
     /**
-     * Tells SysUI the bounds for the bubble bar
-     * @param bubbleBarBounds bounds of the bubble bar in display coordinates
+     * Tells SysUI the top coordinate of bubble bar on screen
+     *
+     * @param topOnScreen top coordinate for bubble bar on screen
      */
-    public void setBubbleBarBounds(Rect bubbleBarBounds) {
+    public void updateBubbleBarTopOnScreen(int topOnScreen) {
         try {
             if (mBubbles != null) {
-                mBubbles.setBubbleBarBounds(bubbleBarBounds);
+                mBubbles.updateBubbleBarTopOnScreen(topOnScreen);
             }
         } catch (RemoteException e) {
-            Log.w(TAG, "Failed call setBubbleBarBounds");
+            Log.w(TAG, "Failed call updateBubbleBarTopOnScreen");
         }
     }
 
@@ -1385,8 +1414,7 @@
 
     private boolean shouldEnableRunningTasksForDesktopMode() {
         // TODO(b/335401172): unify DesktopMode checks in Launcher
-        return (enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps())
-                || mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
+        return enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps();
     }
 
     private boolean handleMessageAsync(Message msg) {
@@ -1417,28 +1445,6 @@
         }
     }
 
-    /** Call shell to stash desktop apps */
-    public void stashDesktopApps(int displayId) {
-        if (mDesktopMode != null) {
-            try {
-                mDesktopMode.stashDesktopApps(displayId);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed call stashDesktopApps", e);
-            }
-        }
-    }
-
-    /** Call shell to hide desktop apps that may be stashed */
-    public void hideStashedDesktopApps(int displayId) {
-        if (mDesktopMode != null) {
-            try {
-                mDesktopMode.hideStashedDesktopApps(displayId);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed call hideStashedDesktopApps", e);
-            }
-        }
-    }
-
     /**
      * If task with the given id is on the desktop, bring it to front
      */
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index d32c7a6..b183ae3 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -46,7 +46,7 @@
 import com.android.quickstep.views.RecentsViewContainer;
 import com.android.quickstep.views.TaskThumbnailViewDeprecated;
 import com.android.quickstep.views.TaskView;
-import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
+import com.android.quickstep.views.TaskView.TaskContainer;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 
@@ -59,7 +59,7 @@
 public class TaskOverlayFactory implements ResourceBasedOverride {
 
     public static List<SystemShortcut> getEnabledShortcuts(TaskView taskView,
-            TaskIdAttributeContainer taskContainer) {
+            TaskContainer taskContainer) {
         final ArrayList<SystemShortcut> shortcuts = new ArrayList<>();
         final RecentsViewContainer container =
                 RecentsViewContainer.containerFromContext(taskView.getContext());
@@ -80,8 +80,9 @@
         return shortcuts;
     }
 
-    public TaskOverlay createOverlay(TaskThumbnailViewDeprecated thumbnailView) {
-        return new TaskOverlay(thumbnailView);
+    /** Creates a {@link TaskOverlay} associated with the provide {@link TaskContainer}. */
+    public TaskOverlay<?> createOverlay(TaskContainer taskContainer) {
+        return new TaskOverlay<>(taskContainer);
     }
 
     /**
@@ -124,28 +125,29 @@
     public static class TaskOverlay<T extends OverviewActionsView> {
 
         protected final Context mApplicationContext;
-        protected final TaskThumbnailViewDeprecated mThumbnailView;
+        protected final TaskContainer mTaskContainer;
 
         private T mActionsView;
         protected ImageActionsApi mImageApi;
 
-        protected TaskOverlay(TaskThumbnailViewDeprecated taskThumbnailViewDeprecated) {
-            mApplicationContext = taskThumbnailViewDeprecated.getContext().getApplicationContext();
-            mThumbnailView = taskThumbnailViewDeprecated;
+        protected TaskOverlay(TaskContainer taskContainer) {
+            mApplicationContext = taskContainer.getTaskView().getContext().getApplicationContext();
+            mTaskContainer = taskContainer;
             mImageApi = new ImageActionsApi(
-                    mApplicationContext, mThumbnailView::getThumbnail);
+                    mApplicationContext, mTaskContainer.getThumbnailViewDeprecated()::getThumbnail);
         }
 
         protected T getActionsView() {
             if (mActionsView == null) {
-                mActionsView = BaseActivity.fromContext(mThumbnailView.getContext()).findViewById(
+                mActionsView = BaseActivity.fromContext(
+                        mTaskContainer.getThumbnailViewDeprecated().getContext()).findViewById(
                         R.id.overview_actions_view);
             }
             return mActionsView;
         }
 
         public TaskThumbnailViewDeprecated getThumbnailView() {
-            return mThumbnailView;
+            return mTaskContainer.getThumbnailViewDeprecated();
         }
 
         /**
@@ -157,7 +159,8 @@
 
             if (thumbnail != null) {
                 getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated);
-                boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot();
+                boolean isAllowedByPolicy =
+                        mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot();
                 getActionsView().setCallbacks(new OverlayUICallbacksImpl(isAllowedByPolicy, task));
             }
         }
@@ -168,7 +171,8 @@
          * @param callback callback to run, after switching to screenshot
          */
         public void endLiveTileMode(@NonNull Runnable callback) {
-            RecentsView recentsView = mThumbnailView.getTaskView().getRecentsView();
+            RecentsView recentsView =
+                    mTaskContainer.getThumbnailViewDeprecated().getTaskView().getRecentsView();
             // Task has already been dismissed
             if (recentsView == null) return;
             recentsView.switchToScreenshot(
@@ -181,8 +185,8 @@
          */
         @SuppressLint("NewApi")
         protected void saveScreenshot(Task task) {
-            if (mThumbnailView.isRealSnapshot()) {
-                mImageApi.saveScreenshot(mThumbnailView.getThumbnail(),
+            if (mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot()) {
+                mImageApi.saveScreenshot(mTaskContainer.getThumbnailViewDeprecated().getThumbnail(),
                         getTaskSnapshotBounds(), getTaskSnapshotInsets(), task.key);
             } else {
                 showBlockedByPolicyMessage();
@@ -190,14 +194,17 @@
         }
 
         protected void enterSplitSelect() {
-            RecentsView overviewPanel = mThumbnailView.getTaskView().getRecentsView();
+            RecentsView overviewPanel =
+                    mTaskContainer.getThumbnailViewDeprecated().getTaskView().getRecentsView();
             // Task has already been dismissed
             if (overviewPanel == null) return;
-            overviewPanel.initiateSplitSelect(mThumbnailView.getTaskView());
+            overviewPanel.initiateSplitSelect(
+                    mTaskContainer.getThumbnailViewDeprecated().getTaskView());
         }
 
         protected void saveAppPair() {
-            GroupedTaskView taskView = (GroupedTaskView) mThumbnailView.getTaskView();
+            GroupedTaskView taskView =
+                    (GroupedTaskView) mTaskContainer.getThumbnailViewDeprecated().getTaskView();
             taskView.getRecentsView().getSplitSelectController().getAppPairsController()
                     .saveAppPair(taskView);
         }
@@ -243,10 +250,11 @@
          */
         public Rect getTaskSnapshotBounds() {
             int[] location = new int[2];
-            mThumbnailView.getLocationOnScreen(location);
+            mTaskContainer.getThumbnailViewDeprecated().getLocationOnScreen(location);
 
-            return new Rect(location[0], location[1], mThumbnailView.getWidth() + location[0],
-                    mThumbnailView.getHeight() + location[1]);
+            return new Rect(location[0], location[1],
+                    mTaskContainer.getThumbnailViewDeprecated().getWidth() + location[0],
+                    mTaskContainer.getThumbnailViewDeprecated().getHeight() + location[1]);
         }
 
         /**
@@ -256,7 +264,7 @@
          */
         @RequiresApi(api = Build.VERSION_CODES.Q)
         public Insets getTaskSnapshotInsets() {
-            return mThumbnailView.getScaledInsets();
+            return mTaskContainer.getThumbnailViewDeprecated().getScaledInsets();
         }
 
         /**
@@ -267,17 +275,21 @@
 
         protected void showBlockedByPolicyMessage() {
             ActivityContext activityContext = ActivityContext.lookupContext(
-                    mThumbnailView.getContext());
+                    mTaskContainer.getThumbnailViewDeprecated().getContext());
             String message = activityContext.getStringCache() != null
                     ? activityContext.getStringCache().disabledByAdminMessage
-                    : mThumbnailView.getContext().getString(R.string.blocked_by_policy);
+                    : mTaskContainer.getThumbnailViewDeprecated().getContext().getString(
+                            R.string.blocked_by_policy);
 
-            Snackbar.show(BaseActivity.fromContext(mThumbnailView.getContext()), message, null);
+            Snackbar.show(BaseActivity.fromContext(
+                    mTaskContainer.getThumbnailViewDeprecated().getContext()), message, null);
         }
 
         /** Called when the snapshot has updated its full screen drawing parameters. */
-        public void setFullscreenParams(TaskView.FullscreenDrawParams fullscreenParams) {
-        }
+        public void setFullscreenParams(TaskView.FullscreenDrawParams fullscreenParams) {}
+
+        /** Sets visibility for the overlay associated elements. */
+        public void setVisibility(int visibility) {}
 
         private class ScreenshotSystemShortcut extends SystemShortcut {
 
@@ -292,7 +304,8 @@
 
             @Override
             public void onClick(View view) {
-                saveScreenshot(mThumbnailView.getTaskView().getTask());
+                saveScreenshot(
+                        mTaskContainer.getThumbnailViewDeprecated().getTaskView().getFirstTask());
                 dismissTaskMenuView();
             }
         }
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index 8df4bdd..4b5c826 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -42,10 +42,8 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Flags;
 import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
 import com.android.launcher3.model.WellbeingModel;
-import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.popup.SystemShortcut;
 import com.android.launcher3.popup.SystemShortcut.AppInfo;
 import com.android.launcher3.util.InstantAppResolver;
@@ -58,14 +56,13 @@
 import com.android.quickstep.views.RecentsViewContainer;
 import com.android.quickstep.views.TaskThumbnailViewDeprecated;
 import com.android.quickstep.views.TaskView;
-import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
+import com.android.quickstep.views.TaskView.TaskContainer;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
 import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
 import com.android.systemui.shared.recents.view.RecentsTransition;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.function.Function;
@@ -78,7 +75,7 @@
 public interface TaskShortcutFactory {
     @Nullable
     default List<SystemShortcut> getShortcuts(RecentsViewContainer container,
-            TaskIdAttributeContainer taskContainer) {
+            TaskContainer taskContainer) {
         return null;
     }
 
@@ -108,7 +105,7 @@
     TaskShortcutFactory APP_INFO = new TaskShortcutFactory() {
         @Override
         public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
-                TaskIdAttributeContainer taskContainer) {
+                TaskContainer taskContainer) {
             TaskView taskView = taskContainer.getTaskView();
             AppInfo.SplitAccessibilityInfo accessibilityInfo =
                     new AppInfo.SplitAccessibilityInfo(taskView.containsMultipleTasks(),
@@ -131,7 +128,8 @@
 
         public SplitSelectSystemShortcut(RecentsViewContainer container, TaskView taskView,
                 SplitPositionOption option) {
-            super(option.iconResId, option.textResId, container, taskView.getItemInfo(), taskView);
+            super(option.iconResId, option.textResId, container, taskView.getFirstItemInfo(),
+                    taskView);
             mTaskView = taskView;
             mSplitPositionOption = option;
         }
@@ -152,8 +150,8 @@
 
         public SaveAppPairSystemShortcut(RecentsViewContainer container, GroupedTaskView taskView,
             int iconResId) {
-                super(iconResId, R.string.save_app_pair, container,
-                    taskView.getItemInfo(), taskView);
+            super(iconResId, R.string.save_app_pair, container, taskView.getFirstItemInfo(),
+                    taskView);
             mTaskView = taskView;
         }
 
@@ -176,14 +174,14 @@
         private final LauncherEvent mLauncherEvent;
 
         public FreeformSystemShortcut(int iconRes, int textRes, RecentsViewContainer container,
-                TaskIdAttributeContainer taskContainer, LauncherEvent launcherEvent) {
+                TaskContainer taskContainer, LauncherEvent launcherEvent) {
             super(iconRes, textRes, container, taskContainer.getItemInfo(),
                     taskContainer.getTaskView());
             mLauncherEvent = launcherEvent;
             mHandler = new Handler(Looper.getMainLooper());
             mTaskView = taskContainer.getTaskView();
             mRecentsView = container.getOverviewPanel();
-            mThumbnailView = taskContainer.getThumbnailView();
+            mThumbnailView = taskContainer.getThumbnailViewDeprecated();
         }
 
         @Override
@@ -199,7 +197,7 @@
         }
 
         private void startActivity() {
-            final Task.TaskKey taskKey = mTaskView.getTask().key;
+            final Task.TaskKey taskKey = mTaskView.getFirstTask().key;
             final int taskId = taskKey.id;
             final ActivityOptions options = makeLaunchOptions(mTarget);
             if (options != null) {
@@ -243,7 +241,7 @@
                 overridePendingAppTransitionMultiThumbFuture(
                         future, animStartedListener, mHandler, true /* scaleUp */,
                         taskKey.displayId);
-                mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getItemInfo())
+                mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getFirstItemInfo())
                         .log(mLauncherEvent);
             }
         }
@@ -292,7 +290,7 @@
     TaskShortcutFactory SPLIT_SELECT = new TaskShortcutFactory() {
         @Override
         public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
-                TaskIdAttributeContainer taskContainer) {
+                TaskContainer taskContainer) {
             DeviceProfile deviceProfile = container.getDeviceProfile();
             final Task task = taskContainer.getTask();
             final int intentFlags = task.key.baseIntent.getFlags();
@@ -327,7 +325,7 @@
         @Nullable
         @Override
         public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
-                TaskIdAttributeContainer taskContainer) {
+                TaskContainer taskContainer) {
             DeviceProfile deviceProfile = container.getDeviceProfile();
             final TaskView taskView = taskContainer.getTaskView();
             final RecentsView recentsView = taskView.getRecentsView();
@@ -336,24 +334,15 @@
                     recentsView.isTaskInExpectedScrollPosition(recentsView.indexOfChild(taskView));
             boolean shouldShowActionsButtonInstead =
                     isLargeTileFocusedTask && isInExpectedScrollPosition;
-            boolean hasUnpinnableApp = Arrays.stream(taskView.getTaskIdAttributeContainers())
-                    .anyMatch(att -> att != null && att.getItemInfo() != null
-                            && ((att.getItemInfo().runtimeStatusFlags
-                                & ItemInfoWithIcon.FLAG_NOT_PINNABLE) != 0));
 
             // No "save app pair" menu item if:
-            // - app pairs feature is not enabled
             // - we are in 3p launcher
-            // - the task in question is a single task
-            // - at least one app in app pair is unpinnable
             // - the Overview Actions Button should be visible
-            // - the task is not a GroupedTaskView
-            if (!FeatureFlags.enableAppPairs()
-                    || !recentsView.supportsAppPairs()
-                    || !taskView.containsMultipleTasks()
-                    || hasUnpinnableApp
+            // - the task view is not a valid save-able split pair
+            if (!recentsView.supportsAppPairs()
                     || shouldShowActionsButtonInstead
-                    || !(taskView instanceof GroupedTaskView)) {
+                    || !recentsView.getSplitSelectController().getAppPairsController()
+                            .canSaveAppPair(taskView)) {
                 return null;
             }
 
@@ -375,7 +364,7 @@
     TaskShortcutFactory FREE_FORM = new TaskShortcutFactory() {
         @Override
         public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
-                TaskIdAttributeContainer taskContainer) {
+                TaskContainer taskContainer) {
             final Task task = taskContainer.getTask();
             if (!task.isDockable) {
                 return null;
@@ -401,7 +390,7 @@
     TaskShortcutFactory PIN = new TaskShortcutFactory() {
         @Override
         public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
-                TaskIdAttributeContainer taskContainer) {
+                TaskContainer taskContainer) {
             if (!SystemUiProxy.INSTANCE.get(container.asContext()).isActive()) {
                 return null;
             }
@@ -423,7 +412,7 @@
         private final TaskView mTaskView;
 
         public PinSystemShortcut(RecentsViewContainer target,
-                TaskIdAttributeContainer taskContainer) {
+                TaskContainer taskContainer) {
             super(R.drawable.ic_pin, R.string.recent_task_option_pin, target,
                     taskContainer.getItemInfo(), taskContainer.getTaskView());
             mTaskView = taskContainer.getTaskView();
@@ -433,10 +422,10 @@
         public void onClick(View view) {
             if (mTaskView.launchTaskAnimated() != null) {
                 SystemUiProxy.INSTANCE.get(mTarget.asContext()).startScreenPinning(
-                        mTaskView.getTask().key.id);
+                        mTaskView.getFirstTask().key.id);
             }
             dismissTaskMenuView();
-            mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getItemInfo())
+            mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getFirstItemInfo())
                     .log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP);
         }
     }
@@ -444,7 +433,7 @@
     TaskShortcutFactory INSTALL = new TaskShortcutFactory() {
         @Override
         public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
-                TaskIdAttributeContainer taskContainer) {
+                TaskContainer taskContainer) {
             Task t = taskContainer.getTask();
             return InstantAppResolver.newInstance(container.asContext()).isInstantApp(
                     t.getTopComponent().getPackageName(), t.getKey().userId)
@@ -457,7 +446,7 @@
     TaskShortcutFactory WELLBEING = new TaskShortcutFactory() {
         @Override
         public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
-                TaskIdAttributeContainer taskContainer) {
+                TaskContainer taskContainer) {
             SystemShortcut<ActivityContext> wellbeingShortcut =
                     WellbeingModel.SHORTCUT_FACTORY.getShortcut(container,
                             taskContainer.getItemInfo(), taskContainer.getTaskView());
@@ -468,13 +457,12 @@
     TaskShortcutFactory SCREENSHOT = new TaskShortcutFactory() {
         @Override
         public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
-                TaskIdAttributeContainer taskContainer) {
+                TaskContainer taskContainer) {
             boolean isTablet = container.getDeviceProfile().isTablet;
             boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview();
             // Extra conditions if it's not grid-only overview
             if (!isGridOnlyOverview) {
-                RecentsOrientedState orientedState =
-                        taskContainer.getTaskView().getRecentsView().getPagedViewOrientedState();
+                RecentsOrientedState orientedState = taskContainer.getTaskView().getOrientedState();
                 boolean isFakeLandscape = !orientedState.isRecentsActivityRotationAllowed()
                         && orientedState.getTouchRotation() != ROTATION_0;
                 if (!isFakeLandscape) {
@@ -482,10 +470,8 @@
                 }
             }
 
-            SystemShortcut screenshotShortcut =
-                    taskContainer.getThumbnailView().getTaskOverlay()
-                            .getScreenshotShortcut(container, taskContainer.getItemInfo(),
-                                    taskContainer.getTaskView());
+            SystemShortcut screenshotShortcut = taskContainer.getOverlay().getScreenshotShortcut(
+                    container, taskContainer.getItemInfo(), taskContainer.getTaskView());
             return createSingletonShortcutList(screenshotShortcut);
         }
 
@@ -498,13 +484,12 @@
     TaskShortcutFactory MODAL = new TaskShortcutFactory() {
         @Override
         public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
-                TaskIdAttributeContainer taskContainer) {
+                TaskContainer taskContainer) {
             boolean isTablet = container.getDeviceProfile().isTablet;
             boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview();
             // Extra conditions if it's not grid-only overview
             if (!isGridOnlyOverview) {
-                RecentsOrientedState orientedState =
-                        taskContainer.getTaskView().getRecentsView().getPagedViewOrientedState();
+                RecentsOrientedState orientedState = taskContainer.getTaskView().getOrientedState();
                 boolean isFakeLandscape = !orientedState.isRecentsActivityRotationAllowed()
                         && orientedState.getTouchRotation() != ROTATION_0;
                 if (!isFakeLandscape) {
@@ -517,9 +502,8 @@
             }
 
             SystemShortcut modalStateSystemShortcut =
-                    taskContainer.getThumbnailView().getTaskOverlay()
-                            .getModalStateSystemShortcut(
-                                    taskContainer.getItemInfo(), taskContainer.getTaskView());
+                    taskContainer.getOverlay().getModalStateSystemShortcut(
+                            taskContainer.getItemInfo(), taskContainer.getTaskView());
             return createSingletonShortcutList(modalStateSystemShortcut);
         }
     };
diff --git a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
index b7cbb47..38e927f 100644
--- a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
+++ b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
@@ -21,11 +21,13 @@
 import android.content.Context;
 import android.content.res.Resources;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
 import com.android.launcher3.R;
 import com.android.launcher3.util.CancellableTask;
 import com.android.launcher3.util.Preconditions;
+import com.android.quickstep.task.thumbnail.data.TaskThumbnailDataSource;
 import com.android.quickstep.util.TaskKeyByLastActiveTimeCache;
 import com.android.quickstep.util.TaskKeyCache;
 import com.android.quickstep.util.TaskKeyLruCache;
@@ -38,7 +40,7 @@
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 
-public class TaskThumbnailCache {
+public class TaskThumbnailCache implements TaskThumbnailDataSource {
 
     private final Executor mBgExecutor;
     private final TaskKeyCache<ThumbnailData> mCache;
@@ -148,12 +150,13 @@
      * @param callback The callback to receive the task after its data has been populated.
      * @return A cancelable handle to the request
      */
-    public CancellableTask updateThumbnailInBackground(
-            Task task, Consumer<ThumbnailData> callback) {
+    @Override
+    public CancellableTask<ThumbnailData> updateThumbnailInBackground(
+            Task task, @NonNull Consumer<ThumbnailData> callback) {
         Preconditions.assertUIThread();
 
         boolean lowResolution = !mHighResLoadingState.isEnabled();
-        if (task.thumbnail != null && task.thumbnail.thumbnail != null
+        if (task.thumbnail != null && task.thumbnail.getThumbnail() != null
                 && (!task.thumbnail.reducedResolution || lowResolution)) {
             // Nothing to load, the thumbnail is already high-resolution or matches what the
             // request, so just callback
@@ -184,12 +187,12 @@
         return newSize > oldSize;
     }
 
-    private CancellableTask updateThumbnailInBackground(TaskKey key, boolean lowResolution,
-            Consumer<ThumbnailData> callback) {
+    private CancellableTask<ThumbnailData> updateThumbnailInBackground(TaskKey key,
+            boolean lowResolution, Consumer<ThumbnailData> callback) {
         Preconditions.assertUIThread();
 
         ThumbnailData cachedThumbnail = mCache.getAndInvalidateIfModified(key);
-        if (cachedThumbnail != null &&  cachedThumbnail.thumbnail != null
+        if (cachedThumbnail != null &&  cachedThumbnail.getThumbnail() != null
                 && (!cachedThumbnail.reducedResolution || lowResolution)) {
             // Already cached, lets use that thumbnail
             callback.accept(cachedThumbnail);
@@ -200,7 +203,7 @@
                 () -> {
                     ThumbnailData thumbnailData = ActivityManagerWrapper.getInstance()
                             .getTaskThumbnail(key.id, lowResolution);
-                    return thumbnailData.thumbnail != null ? thumbnailData
+                    return thumbnailData.getThumbnail() != null ? thumbnailData
                             : ActivityManagerWrapper.getInstance().takeTaskThumbnail(key.id);
                 },
                 MAIN_EXECUTOR,
@@ -210,7 +213,7 @@
                     if (enableGridOnlyOverview() && result.reducedResolution
                             && getHighResLoadingState().isEnabled()) {
                         ThumbnailData newCachedThumbnail = mCache.getAndInvalidateIfModified(key);
-                        if (newCachedThumbnail != null && newCachedThumbnail.thumbnail != null
+                        if (newCachedThumbnail != null && newCachedThumbnail.getThumbnail() != null
                                 && !newCachedThumbnail.reducedResolution) {
                             return;
                         }
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index d89d399..ecd84f8 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -121,7 +121,7 @@
                 for (int i = 0; i < recentsView.getTaskViewCount(); i++) {
                     TaskView taskView = recentsView.getTaskViewAt(i);
                     if (recentsView.isTaskViewVisible(taskView)) {
-                        Task.TaskKey key = taskView.getTask().key;
+                        Task.TaskKey key = taskView.getFirstTask().key;
                         if (componentName.equals(key.getComponent()) && userId == key.userId) {
                             return taskView;
                         }
@@ -165,8 +165,8 @@
             @NonNull RemoteAnimationTarget[] nonAppTargets,
             @Nullable DepthController depthController,
             PendingAnimation out) {
-        boolean isQuickSwitch = v.isEndQuickswitchCuj();
-        v.setEndQuickswitchCuj(false);
+        boolean isQuickSwitch = v.isEndQuickSwitchCuj();
+        v.setEndQuickSwitchCuj(false);
 
         final RemoteAnimationTargets targets =
                 new RemoteAnimationTargets(appTargets, wallpaperTargets, nonAppTargets,
@@ -334,7 +334,7 @@
             // During animation we apply transformation on the thumbnailView (and not the rootView)
             // to follow the TaskViewSimulator. So the final matrix applied on the thumbnailView is:
             //    Mt K(0)` K(t) Mt`
-            TaskThumbnailViewDeprecated[] thumbnails = v.getThumbnails();
+            TaskThumbnailViewDeprecated[] thumbnails = v.getThumbnailViews();
 
             // In case simulator copies and thumbnail size do no match, ensure we get the lesser.
             // This ensures we do not create arrays with empty elements or attempt to references
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 832f4e1..4599f18 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -129,6 +129,7 @@
 import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
 import com.android.systemui.shared.system.InputConsumerController;
 import com.android.systemui.shared.system.InputMonitorCompat;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
 import com.android.systemui.unfold.progress.IUnfoldAnimation;
 import com.android.wm.shell.back.IBackAnimation;
@@ -301,9 +302,9 @@
         }
 
         @BinderThread
-        public void onSystemUiStateChanged(int stateFlags) {
+        public void onSystemUiStateChanged(@SystemUiStateFlags long stateFlags) {
             MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> {
-                int lastFlags = tis.mDeviceState.getSystemUiStateFlags();
+                long lastFlags = tis.mDeviceState.getSystemUiStateFlags();
                 tis.mDeviceState.setSystemUiFlags(stateFlags);
                 tis.onSystemUiFlagsChanged(lastFlags);
             }));
@@ -636,14 +637,14 @@
     }
 
     @UiThread
-    private void onSystemUiFlagsChanged(int lastSysUIFlags) {
+    private void onSystemUiFlagsChanged(@SystemUiStateFlags long lastSysUIFlags) {
         if (LockedUserState.get(this).isUserUnlocked()) {
-            int systemUiStateFlags = mDeviceState.getSystemUiStateFlags();
+            long systemUiStateFlags = mDeviceState.getSystemUiStateFlags();
             SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(systemUiStateFlags);
             mOverviewComponentObserver.onSystemUiStateChanged();
             mTaskbarManager.onSystemUiFlagsChanged(systemUiStateFlags);
 
-            int isShadeExpandedFlag =
+            long isShadeExpandedFlag =
                     SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
             boolean wasExpanded = (lastSysUIFlags & isShadeExpandedFlag) != 0;
             boolean isExpanded = (systemUiStateFlags & isShadeExpandedFlag) != 0;
@@ -1018,7 +1019,7 @@
                             .append("TaskbarActivityContext != null, ")
                             .append("using TaskbarUnstashInputConsumer");
                     base = new TaskbarUnstashInputConsumer(this, base, mInputMonitorCompat, tac,
-                            mOverviewCommandHelper);
+                            mOverviewCommandHelper, mGestureState);
                 }
             }
             if (enableBubblesLongPressNavHandle()) {
@@ -1046,7 +1047,7 @@
                 }
                 reasonString.append("using NavHandleLongPressInputConsumer");
                 base = new NavHandleLongPressInputConsumer(this, base, mInputMonitorCompat,
-                        mDeviceState, navHandle);
+                        mDeviceState, navHandle, mGestureState);
             }
 
             if (!enableBubblesLongPressNavHandle()) {
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 2e76356..94764a5 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -42,16 +42,14 @@
 
 import androidx.annotation.NonNull;
 
+import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.anim.PropertySetter;
 import com.android.launcher3.statemanager.StateManager.StateHandler;
 import com.android.launcher3.states.StateAnimationConfig;
-import com.android.launcher3.util.MultiPropertyFactory;
 import com.android.quickstep.RecentsActivity;
 import com.android.quickstep.views.ClearAllButton;
-import com.android.quickstep.views.OverviewActionsView;
 import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.RecentsViewContainer;
 
 /**
  * State controller for fallback recents activity
@@ -99,7 +97,7 @@
                 clearAllButtonAlpha, LINEAR);
         float overviewButtonAlpha = state.hasOverviewActions() ? 1 : 0;
         setter.setFloat(mActivity.getActionsView().getVisibilityAlpha(),
-                MultiPropertyFactory.MULTI_PROPERTY_VALUE, overviewButtonAlpha, LINEAR);
+                AnimatedFloat.VALUE, overviewButtonAlpha, LINEAR);
 
         float[] scaleAndOffset = state.getOverviewScaleAndOffset(mActivity);
         setter.setFloat(mRecentsView, RECENTS_SCALE_PROPERTY, scaleAndOffset[0],
@@ -138,7 +136,7 @@
     }
 
     private Interpolator getOverviewInterpolator(RecentsState toState) {
-        return toState.overviewUi() ? INSTANT : FINAL_FRAME;
+        return toState.isRecentsViewVisible() ? INSTANT : FINAL_FRAME;
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index d881a1f..485d6c4 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -53,6 +53,8 @@
 import com.android.systemui.shared.recents.model.Task;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsState>
         implements StateListener<RecentsState> {
@@ -144,8 +146,9 @@
     @Override
     public void setCurrentTask(int runningTaskViewId) {
         super.setCurrentTask(runningTaskViewId);
-        int runningTaskId = getTaskIdsForRunningTaskView()[0];
-        if (mHomeTask != null && mHomeTask.key.id != runningTaskId) {
+        int[] runningTaskIds = getTaskIdsForRunningTaskView();
+        if (mHomeTask != null
+                && Arrays.stream(runningTaskIds).noneMatch(taskId -> taskId == mHomeTask.key.id)) {
             mHomeTask = null;
             setRunningTaskHidden(false);
         }
@@ -177,18 +180,19 @@
     }
 
     @Override
-    protected void applyLoadPlan(ArrayList<GroupTask> taskGroups) {
+    protected void applyLoadPlan(List<GroupTask> taskGroups) {
         // When quick-switching on 3p-launcher, we add a "stub" tile corresponding to Launcher
         // as well. This tile is never shown as we have setCurrentTaskHidden, but allows use to
         // track the index of the next task appropriately, as if we are switching on any other app.
         // TODO(b/195607777) Confirm home task info is front-most task and not mixed in with others
-        int runningTaskId = getTaskIdsForRunningTaskView()[0];
-        if (mHomeTask != null && mHomeTask.key.id == runningTaskId
+        int[] runningTaskIds = getTaskIdsForRunningTaskView();
+        if (mHomeTask != null
+                && Arrays.stream(runningTaskIds).allMatch(taskId -> taskId == mHomeTask.key.id)
                 && !taskGroups.isEmpty()) {
             // Check if the task list has running task
             boolean found = false;
             for (GroupTask group : taskGroups) {
-                if (group.containsTask(runningTaskId)) {
+                if (Arrays.stream(runningTaskIds).allMatch(group::containsTask)) {
                     found = true;
                     break;
                 }
@@ -244,7 +248,7 @@
         }
 
         // Set border after select mode changes to avoid showing border during state transition
-        if (!toState.overviewUi() || toState == MODAL_TASK) {
+        if (!toState.isRecentsViewVisible() || toState == MODAL_TASK) {
             setTaskBorderEnabled(false);
         }
 
@@ -264,7 +268,7 @@
             setOverviewSelectEnabled(false);
         }
 
-        if (finalState.overviewUi() && finalState != MODAL_TASK) {
+        if (finalState.isRecentsViewVisible() && finalState != MODAL_TASK) {
             setTaskBorderEnabled(true);
         }
 
@@ -295,7 +299,7 @@
     public boolean onTouchEvent(MotionEvent ev) {
         boolean result = super.onTouchEvent(ev);
         // Do not let touch escape to siblings below this view.
-        return result || mContainer.getStateManager().getState().overviewUi();
+        return result || mContainer.getStateManager().getState().isRecentsViewVisible();
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsState.java b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
index 84937a2..ca9753f 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsState.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
@@ -26,7 +26,6 @@
 import com.android.launcher3.R;
 import com.android.launcher3.statemanager.BaseState;
 import com.android.launcher3.util.Themes;
-import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.RecentsViewContainer;
 
 /**
@@ -41,22 +40,23 @@
     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);
-    private static final int FLAG_OVERVIEW_UI = BaseState.getFlag(7);
+    private static final int FLAG_RECENTS_VIEW_VISIBLE = BaseState.getFlag(7);
     private static final int FLAG_TASK_THUMBNAIL_SPLASH = BaseState.getFlag(8);
 
     public static final RecentsState DEFAULT = new RecentsState(0,
             FLAG_DISABLE_RESTORE | FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_SHOW_AS_GRID
-                    | FLAG_SCRIM | FLAG_LIVE_TILE | FLAG_OVERVIEW_UI);
+                    | FLAG_SCRIM | FLAG_LIVE_TILE | FLAG_RECENTS_VIEW_VISIBLE);
     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_LIVE_TILE | FLAG_OVERVIEW_UI);
+                    | FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_LIVE_TILE | FLAG_RECENTS_VIEW_VISIBLE);
     public static final RecentsState BACKGROUND_APP = new BackgroundAppState(2,
-            FLAG_DISABLE_RESTORE | FLAG_NON_INTERACTIVE | FLAG_FULL_SCREEN | FLAG_OVERVIEW_UI
+            FLAG_DISABLE_RESTORE | FLAG_NON_INTERACTIVE | FLAG_FULL_SCREEN
+                    | FLAG_RECENTS_VIEW_VISIBLE
                     | FLAG_TASK_THUMBNAIL_SPLASH);
     public static final RecentsState HOME = new RecentsState(3, 0);
     public static final RecentsState BG_LAUNCHER = new LauncherState(4, 0);
     public static final RecentsState OVERVIEW_SPLIT_SELECT = new RecentsState(5,
-            FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_OVERVIEW_UI | FLAG_CLOSE_POPUPS
+            FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_RECENTS_VIEW_VISIBLE | FLAG_CLOSE_POPUPS
                     | FLAG_DISABLE_RESTORE);
 
     public final int ordinal;
@@ -152,8 +152,8 @@
     /**
      * True if the state has overview panel visible.
      */
-    public boolean overviewUi() {
-        return hasFlag(FLAG_OVERVIEW_UI);
+    public boolean isRecentsViewVisible() {
+        return hasFlag(FLAG_RECENTS_VIEW_VISIBLE);
     }
 
     private static class ModalState extends RecentsState {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
index 075e539..848a43a 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
@@ -31,6 +31,7 @@
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.util.DisplayController;
 import com.android.quickstep.DeviceConfigWrapper;
+import com.android.quickstep.GestureState;
 import com.android.quickstep.InputConsumer;
 import com.android.quickstep.NavHandle;
 import com.android.quickstep.RecentsAnimationDeviceState;
@@ -61,13 +62,14 @@
     private final NavHandle mNavHandle;
     private final StatsLogManager mStatsLogManager;
     private final TopTaskTracker mTopTaskTracker;
+    private final GestureState mGestureState;
 
     private MotionEvent mCurrentDownEvent;
     private boolean mDeepPressLogged;  // Whether deep press has been logged for the current touch.
 
     public NavHandleLongPressInputConsumer(Context context, InputConsumer delegate,
             InputMonitorCompat inputMonitor, RecentsAnimationDeviceState deviceState,
-            NavHandle navHandle) {
+            NavHandle navHandle, GestureState gestureState) {
         super(delegate, inputMonitor);
         mScreenWidth = DisplayController.INSTANCE.get(context).getInfo().currentSize.x;
         mDeepPressEnabled = DeviceConfigWrapper.get().getEnableLpnhDeepPress();
@@ -82,6 +84,8 @@
         mTouchSlopSquaredOriginal = deviceState.getSquaredTouchSlop();
         mTouchSlopSquared = mTouchSlopSquaredOriginal;
         mOuterTouchSlopSquared = mTouchSlopSquared * (twoStageMultiplier * twoStageMultiplier);
+        mGestureState = gestureState;
+        mGestureState.setIsInExtendedSlopRegion(false);
         if (DEBUG_NAV_HANDLE) {
             Log.d(TAG, "mLongPressTimeout=" + mLongPressTimeout);
             Log.d(TAG, "mOuterLongPressTimeout=" + mOuterLongPressTimeout);
@@ -126,6 +130,7 @@
                 }
                 mCurrentDownEvent = MotionEvent.obtain(ev);
                 mTouchSlopSquared = mTouchSlopSquaredOriginal;
+                mGestureState.setIsInExtendedSlopRegion(false);
                 mDeepPressLogged = false;
                 if (isInNavBarHorizontalArea(ev.getRawX())) {
                     mNavHandleLongPressHandler.onTouchStarted(mNavHandle);
@@ -154,6 +159,7 @@
                                 - (int) (ev.getEventTime() - ev.getDownTime());
                         MAIN_EXECUTOR.getHandler().postDelayed(mTriggerLongPress, delay);
                         mTouchSlopSquared = mOuterTouchSlopSquared;
+                        mGestureState.setIsInExtendedSlopRegion(true);
                         if (DEBUG_NAV_HANDLE) {
                             Log.d(TAG, "Touch in middle region!");
                         }
@@ -219,6 +225,7 @@
         if (DEBUG_NAV_HANDLE) {
             Log.d(TAG, "cancelLongPress");
         }
+        mGestureState.setIsInExtendedSlopRegion(false);
         MAIN_EXECUTOR.getHandler().removeCallbacks(mTriggerLongPress);
         mNavHandleLongPressHandler.onTouchFinished(mNavHandle, reason);
     }
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 9f39476..0d450c6 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -284,8 +284,9 @@
 
                 float horizontalDist = Math.abs(displacementX);
                 float upDist = -displacement;
-                boolean passedSlop = mGestureState.isTrackpadGesture() || squaredHypot(
-                        displacementX, displacementY) >= mSquaredTouchSlop;
+                boolean passedSlop = mGestureState.isTrackpadGesture()
+                        || (squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop
+                            && !mGestureState.isInExtendedSlopRegion());
 
                 if (!mPassedSlopOnThisGesture && passedSlop) {
                     mPassedSlopOnThisGesture = true;
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
index bb8d1d7..c61f71d 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
@@ -48,6 +48,7 @@
     private final BaseContainerInterface<?, T> mContainerInterface;
     private final BaseDragLayer mTarget;
     private final InputMonitorCompat mInputMonitor;
+    private final GestureState mGestureState;
 
     private final int[] mLocationOnScreen = new int[2];
 
@@ -62,6 +63,7 @@
         mInputMonitor = inputMonitor;
         mStartingInActivityBounds = startingInActivityBounds;
         mContainerInterface = gestureState.getContainerInterface();
+        mGestureState = gestureState;
 
         mTarget = container.getDragLayer();
         mTarget.getLocationOnScreen(mLocationOnScreen);
@@ -84,7 +86,10 @@
             ev.setEdgeFlags(flags | Utilities.EDGE_NAV_BAR);
         }
         ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]);
-        boolean handled = mTarget.proxyTouchEvent(ev, mStartingInActivityBounds);
+        boolean handled = false;
+        if (mGestureState == null || !mGestureState.isInExtendedSlopRegion()) {
+            handled = mTarget.proxyTouchEvent(ev, mStartingInActivityBounds);
+        }
         ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
         ev.setEdgeFlags(flags);
 
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
index cd180ba..9a25c32 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
@@ -28,6 +28,8 @@
 import android.content.res.Resources;
 import android.graphics.PointF;
 import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
 import android.view.InputDevice;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
@@ -42,6 +44,7 @@
 import com.android.launcher3.taskbar.bubbles.BubbleControllers;
 import com.android.launcher3.touch.OverScroll;
 import com.android.launcher3.util.DisplayController;
+import com.android.quickstep.GestureState;
 import com.android.quickstep.InputConsumer;
 import com.android.quickstep.OverviewCommandHelper;
 import com.android.systemui.shared.system.InputMonitorCompat;
@@ -51,6 +54,9 @@
  */
 public class TaskbarUnstashInputConsumer extends DelegateInputConsumer {
 
+    private static final int HOVER_TASKBAR_UNSTASH_TIMEOUT = 500;
+    private static final Handler sUnstashHandler = new Handler(Looper.getMainLooper());
+
     private final TaskbarActivityContext mTaskbarActivityContext;
     private final OverviewCommandHelper mOverviewCommandHelper;
     private final float mUnstashArea;
@@ -76,10 +82,11 @@
     private final int mStashedTaskbarBottomEdge;
 
     private final @Nullable TransitionCallback mTransitionCallback;
+    private final GestureState mGestureState;
 
     public TaskbarUnstashInputConsumer(Context context, InputConsumer delegate,
             InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext,
-            OverviewCommandHelper overviewCommandHelper) {
+            OverviewCommandHelper overviewCommandHelper, GestureState gestureState) {
         super(delegate, inputMonitor);
         mTaskbarActivityContext = taskbarActivityContext;
         mOverviewCommandHelper = overviewCommandHelper;
@@ -103,6 +110,7 @@
         mTransitionCallback = mIsTransientTaskbar
                 ? taskbarActivityContext.getTranslationCallbacks()
                 : null;
+        mGestureState = gestureState;
     }
 
     @Override
@@ -111,6 +119,11 @@
     }
 
     @Override
+    public boolean allowInterceptByParent() {
+        return super.allowInterceptByParent() && !mHasPassedTaskbarNavThreshold;
+    }
+
+    @Override
     public void onMotionEvent(MotionEvent ev) {
         if (mState != STATE_ACTIVE) {
             boolean isStashedTaskbarHovered = isMouseEvent(ev)
@@ -173,7 +186,8 @@
                             boolean passedTaskbarNavThreshold = dY < 0
                                     && Math.abs(dY) >= mTaskbarNavThreshold;
 
-                            if (!mHasPassedTaskbarNavThreshold && passedTaskbarNavThreshold) {
+                            if (!mHasPassedTaskbarNavThreshold && passedTaskbarNavThreshold
+                                    && !mGestureState.isInExtendedSlopRegion()) {
                                 mHasPassedTaskbarNavThreshold = true;
                                 if (mIsInBubbleBarArea && mIsVerticalGestureOverBubbleBar) {
                                     mTaskbarActivityContext.onSwipeToOpenBubblebar();
@@ -299,16 +313,25 @@
                 dp.heightPx);
 
         if (mBottomEdgeBounds.contains(x, y)) {
-            // If hovering stashed taskbar and then hover screen bottom edge, unstash it.
-            mTaskbarActivityContext.onSwipeToUnstashTaskbar();
-            mIsStashedTaskbarHovered = false;
+            // start a single unstash timeout if hovering bottom edge under the hinted taskbar.
+            if (!sUnstashHandler.hasMessagesOrCallbacks()) {
+                sUnstashHandler.postDelayed(() -> {
+                    mTaskbarActivityContext.onSwipeToUnstashTaskbar();
+                    mIsStashedTaskbarHovered = false;
+                }, HOVER_TASKBAR_UNSTASH_TIMEOUT);
+            }
         } else if (!isStashedTaskbarHovered(x, y)) {
-            // If exit hovering stashed taskbar, remove hint.
+            // If exit hovering stashed taskbar, remove hint and clear pending unstash calls.
+            sUnstashHandler.removeCallbacksAndMessages(null);
             startStashedTaskbarHover(/* isHovered = */ false);
+        } else {
+            sUnstashHandler.removeCallbacksAndMessages(null);
         }
     }
 
     private void updateUnhoveredTaskbarState(int x, int y) {
+        sUnstashHandler.removeCallbacksAndMessages(null);
+
         DeviceProfile dp = mTaskbarActivityContext.getDeviceProfile();
         mBottomEdgeBounds.set(
                 0,
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index d5cc447..ad13efb 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -382,7 +382,7 @@
                 }
 
                 @Override
-                public void update(RectF rect, float progress, float radius) {
+                public void update(RectF rect, float progress, float radius, int overlayAlpha) {
                     mFakeIconView.setVisibility(View.VISIBLE);
                     mFakeIconView.update(rect, progress,
                             1f - SHAPE_PROGRESS_DURATION /* shapeProgressStart */,
diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
index f8d695c..5ac04da 100644
--- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
+++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
@@ -148,7 +148,7 @@
     @Override
     public void onDisplayInfoChanged(Context context, Info info, int flags) {
         if ((flags & CHANGE_NAVIGATION_MODE) != 0) {
-            mNavMode = info.navigationMode;
+            mNavMode = info.getNavigationMode();
             mStatsLogManager.logger().log(mNavMode.launcherEvent);
         }
     }
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index ed633df..1d4160d 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -16,6 +16,10 @@
 
 package com.android.quickstep.logging;
 
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
 import static androidx.core.util.Preconditions.checkNotNull;
 import static androidx.core.util.Preconditions.checkState;
 
@@ -26,10 +30,17 @@
 import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.SEARCH_RESULT_CONTAINER;
 import static com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers.ContainerCase.DEVICE_SEARCH_RESULT_CONTAINER;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORKSPACE_SNAPSHOT;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_0;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_90;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_180;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_270;
 import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__ALLAPPS;
 import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__BACKGROUND;
 import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__HOME;
 import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__OVERVIEW;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__RECENTS_ORIENTATION_HANDLER__PORTRAIT;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__RECENTS_ORIENTATION_HANDLER__LANDSCAPE;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__RECENTS_ORIENTATION_HANDLER__SEASCAPE;
 
 import android.content.Context;
 import android.text.TextUtils;
@@ -58,11 +69,8 @@
 import com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers;
 import com.android.launcher3.logging.InstanceId;
 import com.android.launcher3.logging.StatsLogManager;
-import com.android.launcher3.model.AllAppsList;
-import com.android.launcher3.model.BaseModelUpdateTask;
-import com.android.launcher3.model.BgDataModel;
-import com.android.launcher3.model.data.CollectionInfo;
 import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.Executors;
 import com.android.launcher3.util.LogConfig;
 import com.android.launcher3.views.ActivityContext;
@@ -230,10 +238,15 @@
         private int mInputType = SysUiStatsLog.LAUNCHER_UICHANGED__INPUT_TYPE__UNKNOWN;
         private Optional<Integer> mFeatures = Optional.empty();
         private Optional<String> mPackageName = Optional.empty();
+        /**
+         * Indicates the current rotation of the display. Uses {@link android.view.Surface values.}
+         */
+        private final int mDisplayRotation;
 
         StatsCompatLogger(Context context, ActivityContext activityContext) {
             mContext = context;
             mActivityContext = Optional.ofNullable(activityContext);
+            mDisplayRotation = DisplayController.INSTANCE.get(mContext).getInfo().rotation;
         }
 
         @Override
@@ -371,17 +384,9 @@
             if (mItemInfo.container < 0 || !LauncherAppState.INSTANCE.executeIfCreated(app -> {
                 // Item is inside a collection, fetch collection info in a BG thread
                 // and then write to StatsLog.
-                app.getModel().enqueueModelUpdateTask(
-                        new BaseModelUpdateTask() {
-                            @Override
-                            public void execute(@NonNull final LauncherAppState app,
-                                    @NonNull final BgDataModel dataModel,
-                                    @NonNull final AllAppsList apps) {
-                                CollectionInfo collectionInfo =
-                                        dataModel.collections.get(mItemInfo.container);
-                                write(event, applyOverwrites(mItemInfo.buildProto(collectionInfo)));
-                            }
-                        });
+                app.getModel().enqueueModelUpdateTask((taskController, dataModel, apps) ->
+                        write(event, applyOverwrites(mItemInfo.buildProto(
+                                dataModel.collections.get(mItemInfo.container)))));
             })) {
                 // Write log on the model thread so that logs do not go out of order
                 // (for eg: drop comes after drag)
@@ -404,6 +409,20 @@
                 case LAUNCHER_ALLAPPS_VERTICAL_SWIPE_END:
                     InteractionJankMonitorWrapper.end(Cuj.CUJ_LAUNCHER_ALL_APPS_SCROLL);
                     break;
+                case LAUNCHER_PRIVATE_SPACE_LOCK_ANIMATION_BEGIN:
+                    InteractionJankMonitorWrapper.begin(view, Cuj.CUJ_LAUNCHER_PRIVATE_SPACE_LOCK);
+                    break;
+                case LAUNCHER_PRIVATE_SPACE_LOCK_ANIMATION_END:
+                    InteractionJankMonitorWrapper.end(Cuj.CUJ_LAUNCHER_PRIVATE_SPACE_LOCK);
+                    break;
+                case LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_BEGIN:
+                    InteractionJankMonitorWrapper.begin(
+                            view,
+                            Cuj.CUJ_LAUNCHER_PRIVATE_SPACE_UNLOCK);
+                    break;
+                case LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_END:
+                    InteractionJankMonitorWrapper.end(Cuj.CUJ_LAUNCHER_PRIVATE_SPACE_UNLOCK);
+                    break;
                 default:
                     break;
             }
@@ -500,7 +519,28 @@
                     getSearchAttributes(atomInfo) /* searchAttributes */,
                     getAttributes(atomInfo) /* attributes */,
                     inputType /* input_type */,
-                    atomInfo.getUserType() /* user_type */);
+                    atomInfo.getUserType() /* user_type */,
+                    getDisplayRotation() /* display_rotation */,
+                    getRecentsOrientationHandler(atomInfo) /* recents_orientation_handler */);
+        }
+
+        private int getDisplayRotation() {
+            return switch (mDisplayRotation) {
+                case ROTATION_90 -> LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_90;
+                case ROTATION_180 -> LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_180;
+                case ROTATION_270 -> LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_270;
+                default -> LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_0;
+            };
+        }
+
+        private int getRecentsOrientationHandler(LauncherAtom.ItemInfo itemInfo) {
+            var orientationHandler =
+                    itemInfo.getContainerInfo().getTaskSwitcherContainer().getOrientationHandler();
+            return switch (orientationHandler) {
+                case PORTRAIT -> LAUNCHER_UICHANGED__RECENTS_ORIENTATION_HANDLER__PORTRAIT;
+                case LANDSCAPE -> LAUNCHER_UICHANGED__RECENTS_ORIENTATION_HANDLER__LANDSCAPE;
+                case SEASCAPE -> LAUNCHER_UICHANGED__RECENTS_ORIENTATION_HANDLER__SEASCAPE;
+            };
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.kt b/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.kt
index 1640104..8f8cc6e 100644
--- a/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.kt
+++ b/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.kt
@@ -42,6 +42,7 @@
 import com.android.launcher3.LauncherAnimUtils
 import com.android.launcher3.R
 import com.android.launcher3.Utilities
+import com.android.launcher3.logger.LauncherAtom.TaskSwitcherContainer
 import com.android.launcher3.touch.PagedOrientationHandler.ChildBounds
 import com.android.launcher3.touch.PagedOrientationHandler.Float2DAction
 import com.android.launcher3.touch.PagedOrientationHandler.Int2DAction
@@ -611,6 +612,9 @@
     override fun getFloatingTaskPrimaryTranslation(floatingTask: View, dp: DeviceProfile): Float =
         floatingTask.translationY
 
+    override fun getHandlerTypeForLogging(): TaskSwitcherContainer.OrientationHandler =
+        TaskSwitcherContainer.OrientationHandler.LANDSCAPE
+
     /**
      * Retrieves split icons position
      *
diff --git a/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java b/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java
index 1be908b..f6284d5 100644
--- a/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java
+++ b/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java
@@ -46,9 +46,12 @@
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 
+import androidx.annotation.NonNull;
+
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.logger.LauncherAtom;
 import com.android.launcher3.touch.DefaultPagedViewHandler;
 import com.android.launcher3.touch.SingleAxisSwipeDetector;
 import com.android.launcher3.util.SplitConfigurationOptions;
@@ -802,4 +805,10 @@
                 ? floatingTask.getTranslationX()
                 : floatingTask.getTranslationY();
     }
+
+    @NonNull
+    @Override
+    public LauncherAtom.TaskSwitcherContainer.OrientationHandler getHandlerTypeForLogging() {
+        return LauncherAtom.TaskSwitcherContainer.OrientationHandler.PORTRAIT;
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.kt b/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.kt
index 6c82890..5bc1be8 100644
--- a/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.kt
+++ b/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.kt
@@ -26,6 +26,7 @@
 import android.widget.FrameLayout
 import android.widget.LinearLayout
 import com.android.launcher3.DeviceProfile
+import com.android.launcher3.logger.LauncherAtom
 import com.android.launcher3.touch.PagedOrientationHandler
 import com.android.launcher3.touch.PagedOrientationHandler.Float2DAction
 import com.android.launcher3.touch.PagedOrientationHandler.Int2DAction
@@ -371,6 +372,8 @@
      */
     fun getFloatingTaskPrimaryTranslation(floatingTask: View, dp: DeviceProfile): Float
 
+    fun getHandlerTypeForLogging(): LauncherAtom.TaskSwitcherContainer.OrientationHandler
+
     companion object {
         @JvmField val PORTRAIT: RecentsPagedOrientationHandler = PortraitPagedViewHandler()
         @JvmField val LANDSCAPE: RecentsPagedOrientationHandler = LandscapePagedViewHandler()
diff --git a/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt b/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt
index 5bebf8c..46e4b0c 100644
--- a/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt
+++ b/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt
@@ -32,6 +32,7 @@
 import com.android.launcher3.Flags
 import com.android.launcher3.R
 import com.android.launcher3.Utilities
+import com.android.launcher3.logger.LauncherAtom
 import com.android.launcher3.touch.SingleAxisSwipeDetector
 import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT
 import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT
@@ -395,4 +396,8 @@
             iconView.layoutParams = layoutParams
         }
     }
+
+    @Override
+    override fun getHandlerTypeForLogging(): LauncherAtom.TaskSwitcherContainer.OrientationHandler =
+        LauncherAtom.TaskSwitcherContainer.OrientationHandler.SEASCAPE
 }
diff --git a/quickstep/src/com/android/quickstep/recents/data/RecentTasksDataSource.kt b/quickstep/src/com/android/quickstep/recents/data/RecentTasksDataSource.kt
new file mode 100644
index 0000000..6719099
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/recents/data/RecentTasksDataSource.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 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.recents.data
+
+import com.android.quickstep.util.GroupTask
+import java.util.function.Consumer
+
+interface RecentTasksDataSource {
+    fun getTasks(callback: Consumer<List<GroupTask>>?): Int
+}
diff --git a/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt b/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt
new file mode 100644
index 0000000..ad8ae20
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2024 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.recents.data
+
+import com.android.quickstep.TaskIconCache
+import com.android.quickstep.task.thumbnail.data.TaskThumbnailDataSource
+import com.android.quickstep.util.GroupTask
+import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.ThumbnailData
+import kotlin.coroutines.resume
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.suspendCancellableCoroutine
+
+@OptIn(ExperimentalCoroutinesApi::class)
+class TasksRepository(
+    private val recentsModel: RecentTasksDataSource,
+    private val taskThumbnailDataSource: TaskThumbnailDataSource,
+    private val taskIconCache: TaskIconCache,
+) {
+    private val groupedTaskData = MutableStateFlow(emptyList<GroupTask>())
+    private val _taskData =
+        groupedTaskData.map { groupTaskList -> groupTaskList.flatMap { it.tasks } }
+    private val visibleTaskIds = MutableStateFlow(emptySet<Int>())
+
+    private val taskData: Flow<List<Task>> =
+        combine(_taskData, getThumbnailQueryResults()) { tasks, results ->
+            tasks.forEach { task ->
+                // Add retrieved thumbnails + remove unnecessary thumbnails
+                task.thumbnail = results[task.key.id]
+            }
+            tasks
+        }
+
+    fun getAllTaskData(forceRefresh: Boolean = false): Flow<List<Task>> {
+        if (forceRefresh) {
+            recentsModel.getTasks { groupedTaskData.value = it }
+        }
+        return taskData
+    }
+
+    fun getTaskDataById(taskId: Int): Flow<Task?> =
+        taskData.map { taskList -> taskList.firstOrNull { it.key.id == taskId } }
+
+    fun setVisibleTasks(visibleTaskIdList: List<Int>) {
+        this.visibleTaskIds.value = visibleTaskIdList.toSet()
+    }
+
+    /** Flow wrapper for [TaskThumbnailDataSource.updateThumbnailInBackground] api */
+    private fun getThumbnailDataRequest(task: Task): ThumbnailDataRequest =
+        flow {
+                emit(task.key.id to task.thumbnail)
+                val thumbnailDataResult: ThumbnailData? =
+                    suspendCancellableCoroutine { continuation ->
+                        val cancellableTask =
+                            taskThumbnailDataSource.updateThumbnailInBackground(task) {
+                                continuation.resume(it)
+                            }
+                        continuation.invokeOnCancellation { cancellableTask?.cancel() }
+                    }
+                emit(task.key.id to thumbnailDataResult)
+            }
+            .distinctUntilChanged()
+
+    /**
+     * This is a Flow that makes a query for thumbnail data to the [taskThumbnailDataSource] for
+     * each visible task. It then collects the responses and returns them in a Map as soon as they
+     * are available.
+     */
+    private fun getThumbnailQueryResults(): Flow<Map<Int, ThumbnailData?>> {
+        val visibleTasks =
+            combine(_taskData, visibleTaskIds) { tasks, visibleIds ->
+                tasks.filter { it.key.id in visibleIds }
+            }
+        val visibleThumbnailDataRequests: Flow<List<ThumbnailDataRequest>> =
+            visibleTasks.map {
+                it.map { visibleTask ->
+                    val taskCopy = Task(visibleTask).apply { thumbnail = visibleTask.thumbnail }
+                    getThumbnailDataRequest(taskCopy)
+                }
+            }
+        return visibleThumbnailDataRequests.flatMapLatest {
+            thumbnailRequestFlows: List<ThumbnailDataRequest> ->
+            if (thumbnailRequestFlows.isEmpty()) {
+                flowOf(emptyMap())
+            } else {
+                combine(thumbnailRequestFlows) { it.toMap() }
+            }
+        }
+    }
+}
+
+typealias ThumbnailDataRequest = Flow<Pair<Int, ThumbnailData?>>
diff --git a/quickstep/src/com/android/quickstep/recents/viewmodel/RecentsViewData.kt b/quickstep/src/com/android/quickstep/recents/viewmodel/RecentsViewData.kt
new file mode 100644
index 0000000..28212cf
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/recents/viewmodel/RecentsViewData.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.recents.viewmodel
+
+import kotlinx.coroutines.flow.MutableStateFlow
+
+// This is far from complete but serves the purpose of enabling refactoring in other areas
+class RecentsViewData {
+    val fullscreenProgress = MutableStateFlow(1f)
+
+    // This is typically a View concern but it is used to invalidate rendering in other Views
+    val scale = MutableStateFlow(1f)
+}
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
index d51069f..8762976 100644
--- a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
@@ -17,22 +17,44 @@
 package com.android.quickstep.task.thumbnail
 
 import android.content.Context
+import android.content.res.Configuration
 import android.graphics.Canvas
+import android.graphics.Outline
 import android.graphics.Paint
 import android.graphics.PorterDuff
 import android.graphics.PorterDuffXfermode
 import android.util.AttributeSet
 import android.view.View
-import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.*
+import android.view.ViewOutlineProvider
+import com.android.launcher3.Utilities
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
+import com.android.quickstep.util.TaskCornerRadius
+import com.android.quickstep.views.RecentsView
+import com.android.quickstep.views.RecentsViewContainer
+import com.android.quickstep.views.TaskView
+import com.android.systemui.shared.system.QuickStepContract
 import kotlinx.coroutines.MainScope
 import kotlinx.coroutines.launch
 
 class TaskThumbnailView : View {
     // TODO(b/335649589): Ideally create and obtain this from DI. This ViewModel should be scoped
     //  to [TaskView], and also shared between [TaskView] and [TaskThumbnailView]
-    val viewModel = TaskThumbnailViewModel()
+    //  This is using a lazy for now because the dependencies cannot be obtained without DI.
+    val viewModel by lazy {
+        TaskThumbnailViewModel(
+            RecentsViewContainer.containerFromContext<RecentsViewContainer>(context)
+                .getOverviewPanel<RecentsView<*, *>>()
+                .mRecentsViewData,
+            (parent as TaskView).taskViewData
+        )
+    }
 
     private var uiState: TaskThumbnailUiState = Uninitialized
+    private var inheritedScale: Float = 1f
+
+    private var cornerRadius: Float = TaskCornerRadius.get(context)
+    private var fullscreenCornerRadius: Float = QuickStepContract.getWindowCornerRadius(context)
 
     constructor(context: Context?) : super(context)
     constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
@@ -51,6 +73,27 @@
                 invalidate()
             }
         }
+        MainScope().launch { viewModel.recentsFullscreenProgress.collect { invalidateOutline() } }
+        MainScope().launch {
+            viewModel.inheritedScale.collect { viewModelInheritedScale ->
+                inheritedScale = viewModelInheritedScale
+                invalidateOutline()
+            }
+        }
+
+        clipToOutline = true
+        outlineProvider =
+            object : ViewOutlineProvider() {
+                override fun getOutline(view: View, outline: Outline) {
+                    outline.setRoundRect(
+                        0,
+                        0,
+                        view.measuredWidth,
+                        view.measuredHeight,
+                        getCurrentCornerRadius()
+                    )
+                }
+            }
     }
 
     override fun onDraw(canvas: Canvas) {
@@ -60,19 +103,25 @@
         }
     }
 
-    private fun drawTransparentUiState(canvas: Canvas) {
-        canvas.drawRoundRect(
-            0f,
-            0f,
-            measuredWidth.toFloat(),
-            measuredHeight.toFloat(),
-            // TODO(b/334826840) add rounded corners
-            0f,
-            0f,
-            CLEAR_PAINT
-        )
+    override fun onConfigurationChanged(newConfig: Configuration?) {
+        super.onConfigurationChanged(newConfig)
+
+        cornerRadius = TaskCornerRadius.get(context)
+        fullscreenCornerRadius = QuickStepContract.getWindowCornerRadius(context)
+        invalidateOutline()
     }
 
+    private fun drawTransparentUiState(canvas: Canvas) {
+        canvas.drawRect(0f, 0f, measuredWidth.toFloat(), measuredHeight.toFloat(), CLEAR_PAINT)
+    }
+
+    private fun getCurrentCornerRadius() =
+        Utilities.mapRange(
+            viewModel.recentsFullscreenProgress.value,
+            cornerRadius,
+            fullscreenCornerRadius
+        ) / inheritedScale
+
     companion object {
         private val CLEAR_PAINT =
             Paint().apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) }
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
index 9925873..71bc865 100644
--- a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
@@ -16,20 +16,32 @@
 
 package com.android.quickstep.task.thumbnail
 
+import com.android.quickstep.recents.viewmodel.RecentsViewData
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
+import com.android.quickstep.task.viewmodel.TaskViewData
 import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
 
-class TaskThumbnailViewModel {
-    private val _uiState: MutableStateFlow<TaskThumbnailUiState> =
-        MutableStateFlow(TaskThumbnailUiState.Uninitialized)
-    val uiState: StateFlow<TaskThumbnailUiState> = _uiState
+class TaskThumbnailViewModel(recentsViewData: RecentsViewData, taskViewData: TaskViewData) {
+    private val task = MutableStateFlow<TaskThumbnail?>(null)
+
+    val recentsFullscreenProgress = recentsViewData.fullscreenProgress
+    val inheritedScale =
+        combine(recentsViewData.scale, taskViewData.scale) { recentsScale, taskScale ->
+            recentsScale * taskScale
+        }
+    val uiState =
+        task.map { taskVal ->
+            when {
+                taskVal == null -> Uninitialized
+                taskVal.isRunning -> LiveTile
+                else -> Uninitialized
+            }
+        }
 
     fun bind(task: TaskThumbnail) {
-        _uiState.value =
-            if (task.isRunning) {
-                TaskThumbnailUiState.LiveTile
-            } else {
-                TaskThumbnailUiState.Uninitialized
-            }
+        this.task.value = task
     }
 }
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/data/TaskThumbnailDataSource.kt b/quickstep/src/com/android/quickstep/task/thumbnail/data/TaskThumbnailDataSource.kt
new file mode 100644
index 0000000..55598f0
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/data/TaskThumbnailDataSource.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 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.task.thumbnail.data
+
+import com.android.launcher3.util.CancellableTask
+import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.ThumbnailData
+import java.util.function.Consumer
+
+interface TaskThumbnailDataSource {
+    fun updateThumbnailInBackground(
+        task: Task,
+        callback: Consumer<ThumbnailData>
+    ): CancellableTask<ThumbnailData>?
+}
diff --git a/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt b/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt
new file mode 100644
index 0000000..a8b5112
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 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.task.viewmodel
+
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class TaskViewData {
+    // This is typically a View concern but it is used to invalidate rendering in other Views
+    val scale = MutableStateFlow(1f)
+}
diff --git a/quickstep/src/com/android/quickstep/util/AppPairsController.java b/quickstep/src/com/android/quickstep/util/AppPairsController.java
index a82031a..e4e2eb2 100644
--- a/quickstep/src/com/android/quickstep/util/AppPairsController.java
+++ b/quickstep/src/com/android/quickstep/util/AppPairsController.java
@@ -22,6 +22,7 @@
 import static com.android.internal.jank.Cuj.CUJ_LAUNCHER_LAUNCH_APP_PAIR_FROM_TASKBAR;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_PAIR_LAUNCH;
 import static com.android.launcher3.model.data.AppInfo.PACKAGE_KEY_COMPARATOR;
+import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_SUPPORTS_MULTI_INSTANCE;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
@@ -32,34 +33,38 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ActivityInfo;
 import android.content.pm.LauncherApps;
-import android.content.pm.PackageManager;
 import android.util.Log;
 import android.util.Pair;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.jank.Cuj;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.R;
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
 import com.android.launcher3.allapps.AllAppsStore;
 import com.android.launcher3.apppairs.AppPairIcon;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.logging.InstanceId;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.AppPairInfo;
 import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.taskbar.TaskbarActivityContext;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
 import com.android.launcher3.views.ActivityContext;
 import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.TaskUtils;
 import com.android.quickstep.TopTaskTracker;
 import com.android.quickstep.views.GroupedTaskView;
 import com.android.quickstep.views.TaskView;
@@ -101,6 +106,55 @@
     }
 
     /**
+     * Returns whether the specified GroupedTaskView can be saved as an app pair.
+     */
+    public boolean canSaveAppPair(TaskView taskView) {
+        if (mContext == null) {
+            // Can ignore as the activity is already destroyed
+            return false;
+        }
+
+        // Disallow saving app pairs if:
+        // - app pairs feature is not enabled
+        // - the task in question is a single task
+        // - at least one app in app pair is unpinnable
+        // - the task is not a GroupedTaskView
+        // - both tasks in the GroupedTaskView are from the same app and the app does not
+        //   support multi-instance
+        boolean hasUnpinnableApp = taskView.getTaskContainers().stream()
+                .anyMatch(att -> att != null && att.getItemInfo() != null
+                        && ((att.getItemInfo().runtimeStatusFlags
+                            & ItemInfoWithIcon.FLAG_NOT_PINNABLE) != 0));
+        if (!FeatureFlags.enableAppPairs()
+                || !taskView.containsMultipleTasks()
+                || hasUnpinnableApp
+                || !(taskView instanceof GroupedTaskView)) {
+            return false;
+        }
+
+        GroupedTaskView gtv = (GroupedTaskView) taskView;
+        List<TaskView.TaskContainer> containers = gtv.getTaskContainers();
+        ComponentKey taskKey1 = TaskUtils.getLaunchComponentKeyForTask(
+                containers.get(0).getTask().key);
+        ComponentKey taskKey2 = TaskUtils.getLaunchComponentKeyForTask(
+                containers.get(1).getTask().key);
+        AppInfo app1 = resolveAppInfoByComponent(taskKey1);
+        AppInfo app2 = resolveAppInfoByComponent(taskKey2);
+
+        if (app1 == null || app2 == null) {
+            // Disallow saving app pairs for apps that don't have a front-door in Launcher
+            return false;
+        }
+
+        if (PackageManagerHelper.isSameAppForMultiInstance(app1, app2)) {
+            if (!app1.supportsMultiInstance() || !app2.supportsMultiInstance()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
      * Creates a new app pair ItemInfo and adds it to the workspace.
      * <br>
      * We create WorkspaceItemInfos to save onto the app pair in the following way:
@@ -116,34 +170,26 @@
      */
     public void saveAppPair(GroupedTaskView gtv) {
         InteractionJankMonitorWrapper.begin(gtv, Cuj.CUJ_LAUNCHER_SAVE_APP_PAIR);
-        TaskView.TaskIdAttributeContainer[] attributes = gtv.getTaskIdAttributeContainers();
-        WorkspaceItemInfo recentsInfo1 = attributes[0].getItemInfo();
-        WorkspaceItemInfo recentsInfo2 = attributes[1].getItemInfo();
-        WorkspaceItemInfo app1 = lookupLaunchableItem(recentsInfo1.getComponentKey());
-        WorkspaceItemInfo app2 = lookupLaunchableItem(recentsInfo2.getComponentKey());
+        List<TaskView.TaskContainer> containers = gtv.getTaskContainers();
+        WorkspaceItemInfo recentsInfo1 = containers.get(0).getItemInfo();
+        WorkspaceItemInfo recentsInfo2 = containers.get(1).getItemInfo();
+        WorkspaceItemInfo app1 = resolveAppPairWorkspaceInfo(recentsInfo1);
+        WorkspaceItemInfo app2 = resolveAppPairWorkspaceInfo(recentsInfo2);
 
-        // If app lookup fails, use the WorkspaceItemInfo that we have, but try to override default
-        // intent with one from PackageManager.
-        if (app1 == null) {
-            Log.w(TAG, "Creating an app pair, but app lookup for " + recentsInfo1.title
-                    + " failed. Falling back to the WorkspaceItemInfo from Recents.");
-            app1 = convertRecentsItemToAppItem(recentsInfo1);
+        if (app1 == null || app2 == null) {
+            // This shouldn't happen if canSaveAppPair() is called above, but log an error and do
+            // not create the app pair if the workspace items can't be resolved
+            Log.w(TAG, "Failed to save app pair due to invalid apps ("
+                    + "app1=" + recentsInfo1.getComponentKey().componentName
+                    + " app2=" + recentsInfo2.getComponentKey().componentName + ")");
+            return;
         }
-        if (app2 == null) {
-            Log.w(TAG, "Creating an app pair, but app lookup for " + recentsInfo2.title
-                    + " failed. Falling back to the WorkspaceItemInfo from Recents.");
-            app2 = convertRecentsItemToAppItem(recentsInfo2);
-        }
-
-        // WorkspaceItemProcessor won't process these new ItemInfos until the next launcher restart,
-        // so update some flags now.
-        updateWorkspaceItemFlags(app1);
-        updateWorkspaceItemFlags(app2);
 
         @PersistentSnapPosition int snapPosition = gtv.getSnapPosition();
         if (!isPersistentSnapPosition(snapPosition)) {
-            // if we received an illegal snap position, log an error and do not create the app pair.
-            Log.wtf(TAG, "tried to save an app pair with illegal snapPosition " + snapPosition);
+            // If we received an illegal snap position, log an error and do not create the app pair
+            Log.wtf(TAG, "Tried to save an app pair with illegal snapPosition "
+                    + snapPosition);
             return;
         }
 
@@ -229,67 +275,38 @@
     }
 
     /**
+     * Returns an AppInfo associated with the app for the given ComponentKey, or null if no such
+     * package exists in the AllAppsStore.
+     */
+    @Nullable
+    private AppInfo resolveAppInfoByComponent(@NonNull ComponentKey key) {
+        AllAppsStore appsStore = ActivityContext.lookupContext(mContext)
+                .getAppsView().getAppsStore();
+
+        // First look up the app info in order of:
+        // - The exact activity for the recent task
+        // - The first(?) loaded activity from the package
+        AppInfo appInfo = appsStore.getApp(key);
+        if (appInfo == null) {
+            appInfo = appsStore.getApp(key, PACKAGE_KEY_COMPARATOR);
+        }
+        return appInfo;
+    }
+
+    /**
      * Creates a new launchable WorkspaceItemInfo of itemType=ITEM_TYPE_APPLICATION by looking the
      * ComponentKey up in the AllAppsStore. If no app is found, attempts a lookup by package
      * instead. If that lookup fails, returns null.
      */
     @Nullable
-    private WorkspaceItemInfo lookupLaunchableItem(@Nullable ComponentKey key) {
-        if (key == null) {
+    private WorkspaceItemInfo resolveAppPairWorkspaceInfo(
+            @NonNull WorkspaceItemInfo recentTaskInfo) {
+        // ComponentKey should never be null (see TaskView#getItemInfo)
+        AppInfo appInfo = resolveAppInfoByComponent(recentTaskInfo.getComponentKey());
+        if (appInfo == null) {
             return null;
         }
-
-        AllAppsStore appsStore = ActivityContext.lookupContext(mContext)
-                .getAppsView().getAppsStore();
-
-        // Lookup by ComponentKey
-        AppInfo appInfo = appsStore.getApp(key);
-        if (appInfo == null) {
-            // Lookup by package
-            appInfo = appsStore.getApp(key, PACKAGE_KEY_COMPARATOR);
-        }
-
-        return appInfo != null ? appInfo.makeWorkspaceItem(mContext) : null;
-    }
-
-    /**
-     * Updates flags for newly created WorkspaceItemInfos.
-     */
-    private void updateWorkspaceItemFlags(WorkspaceItemInfo wii) {
-        PackageManager pm = mContext.getPackageManager();
-        ActivityInfo ai = null;
-        try {
-            ai = pm.getActivityInfo(wii.getTargetComponent(), 0);
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.w(TAG, "PackageManager lookup failed.");
-        }
-
-        if (ai != null) {
-            wii.setNonResizeable(ai.resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE);
-        }
-    }
-
-    /**
-     * Converts a WorkspaceItemInfo of itemType=ITEM_TYPE_TASK (from a Recents task) to a new
-     * WorkspaceItemInfo of itemType=ITEM_TYPE_APPLICATION.
-     */
-    private WorkspaceItemInfo convertRecentsItemToAppItem(WorkspaceItemInfo recentsItem) {
-        if (recentsItem.itemType != LauncherSettings.Favorites.ITEM_TYPE_TASK) {
-            Log.w(TAG, "Expected ItemInfo of type ITEM_TYPE_TASK, but received "
-                    + recentsItem.itemType);
-        }
-
-        WorkspaceItemInfo launchableItem = recentsItem.clone();
-        PackageManager p = mContext.getPackageManager();
-        Intent launchIntent = p.getLaunchIntentForPackage(recentsItem.getTargetPackage());
-        Log.w(TAG, "Initial intent from Recents: " + launchableItem.intent + "\n"
-                + "Intent from PackageManager: " + launchIntent);
-        if (launchIntent != null) {
-            // If lookup from PackageManager fails, just use the existing intent
-            launchableItem.intent = launchIntent;
-        }
-        launchableItem.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
-        return launchableItem;
+        return appInfo.makeWorkspaceItem(mContext);
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/util/AssistStateManager.java b/quickstep/src/com/android/quickstep/util/AssistStateManager.java
index 42db65f..7acb28d 100644
--- a/quickstep/src/com/android/quickstep/util/AssistStateManager.java
+++ b/quickstep/src/com/android/quickstep/util/AssistStateManager.java
@@ -33,8 +33,8 @@
 
     public AssistStateManager() {}
 
-    /** Whether search is available. */
-    public boolean isSearchAvailable() {
+    /** Return {@code true} if the Settings toggle is enabled. */
+    public boolean isSettingsAllEntrypointsEnabled() {
         return false;
     }
 
@@ -43,14 +43,9 @@
         return false;
     }
 
-    /** Whether CsHelper CtS invocation path is available. */
-    public Optional<Boolean> isCsHelperAvailable() {
-        return Optional.empty();
-    }
-
-    /** Whether VIS CtS invocation path is available. */
-    public Optional<Boolean> isVisAvailable() {
-        return Optional.empty();
+    /** Whether ContextualSearchService invocation path is available. */
+    public boolean isContextualSearchServiceAvailable() {
+        return false;
     }
 
     /** Get the Launcher overridden long press nav handle duration to trigger Assistant. */
@@ -90,11 +85,6 @@
         return Optional.empty();
     }
 
-    /** Return {@code true} if the Settings toggle is enabled. */
-    public boolean isSettingsAllEntrypointsEnabled() {
-        return false;
-    }
-
     /** Dump states. */
     public void dump(String prefix, PrintWriter writer) {}
 
diff --git a/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java b/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java
index 328a727..f1e2dd7 100644
--- a/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java
@@ -21,8 +21,11 @@
 import android.view.ViewGroup;
 import android.view.WindowManager;
 
+import androidx.annotation.MainThread;
+
 import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator;
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
+import com.android.systemui.unfold.dagger.UnfoldMain;
 import com.android.systemui.unfold.updates.RotationChangeProvider;
 
 import java.util.HashMap;
@@ -34,7 +37,7 @@
 public abstract class BaseUnfoldMoveFromCenterAnimator implements TransitionProgressListener {
 
     private final UnfoldMoveFromCenterAnimator mMoveFromCenterAnimation;
-    private final RotationChangeProvider mRotationChangeProvider;
+    @UnfoldMain private final RotationChangeProvider mRotationChangeProvider;
 
     private final Map<ViewGroup, Boolean> mOriginalClipToPadding = new HashMap<>();
     private final Map<ViewGroup, Boolean> mOriginalClipChildren = new HashMap<>();
@@ -48,7 +51,7 @@
     private Float mLastTransitionProgress = null;
 
     public BaseUnfoldMoveFromCenterAnimator(WindowManager windowManager,
-            RotationChangeProvider rotationChangeProvider) {
+            @UnfoldMain RotationChangeProvider rotationChangeProvider) {
         mMoveFromCenterAnimation = new UnfoldMoveFromCenterAnimator(windowManager,
                 new LauncherViewsMoveFromCenterTranslationApplier());
         mRotationChangeProvider = rotationChangeProvider;
@@ -143,8 +146,14 @@
     private class UnfoldMoveFromCenterRotationListener implements
             RotationChangeProvider.RotationListener {
 
+        @MainThread
         @Override
         public void onRotationChanged(@Rotation int newRotation) {
+            onRotationChangedInternal(newRotation);
+        }
+
+        @MainThread
+        private void onRotationChangedInternal(@Rotation int newRotation) {
             mMoveFromCenterAnimation.updateDisplayProperties(newRotation);
             updateRegisteredViewsIfNeeded();
         }
diff --git a/quickstep/src/com/android/quickstep/util/BorderAnimator.kt b/quickstep/src/com/android/quickstep/util/BorderAnimator.kt
index 44eb070..85238ed 100644
--- a/quickstep/src/com/android/quickstep/util/BorderAnimator.kt
+++ b/quickstep/src/com/android/quickstep/util/BorderAnimator.kt
@@ -86,7 +86,7 @@
         fun createSimpleBorderAnimator(
             @Px borderRadiusPx: Int,
             @Px borderWidthPx: Int,
-            boundsBuilder: (rect: Rect?) -> Unit,
+            boundsBuilder: (Rect) -> Unit,
             targetView: View,
             @ColorInt borderColor: Int = DEFAULT_BORDER_COLOR,
             appearanceDurationMs: Long = DEFAULT_APPEARANCE_ANIMATION_DURATION_MS,
@@ -250,7 +250,7 @@
     /** BorderAnimationParams that simply draws the border outside the bounds of the target view. */
     private class SimpleParams(
         @Px borderWidthPx: Int,
-        boundsBuilder: (rect: Rect?) -> Unit,
+        boundsBuilder: (Rect) -> Unit,
         targetView: View,
     ) : BorderAnimationParams(borderWidthPx, boundsBuilder, targetView) {
         override val alignmentAdjustmentInset = 0
diff --git a/quickstep/src/com/android/quickstep/util/DesktopTask.java b/quickstep/src/com/android/quickstep/util/DesktopTask.java
index b3f5d82..8d99069 100644
--- a/quickstep/src/com/android/quickstep/util/DesktopTask.java
+++ b/quickstep/src/com/android/quickstep/util/DesktopTask.java
@@ -21,7 +21,7 @@
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task;
 
-import java.util.ArrayList;
+import java.util.List;
 
 /**
  * A {@link Task} container that can contain N number of tasks that are part of the desktop in
@@ -30,9 +30,9 @@
 public class DesktopTask extends GroupTask {
 
     @NonNull
-    public final ArrayList<Task> tasks;
+    public final List<Task> tasks;
 
-    public DesktopTask(@NonNull ArrayList<Task> tasks) {
+    public DesktopTask(@NonNull List<Task> tasks) {
         super(tasks.get(0), null, null, TaskView.Type.DESKTOP);
         this.tasks = tasks;
     }
@@ -53,7 +53,19 @@
     }
 
     @Override
+    @NonNull
+    public List<Task> getTasks() {
+        return tasks;
+    }
+
+    @Override
     public DesktopTask copy() {
         return new DesktopTask(tasks);
     }
+
+    @Override
+    public String toString() {
+        return "type=" + taskViewType + " tasks=" + tasks;
+    }
+
 }
diff --git a/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt b/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt
index 544c64d..d36dc7e 100644
--- a/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt
+++ b/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt
@@ -48,12 +48,14 @@
                 PropReader(
                     object : PropProvider {
                         override fun <T : Any> get(key: String, fallback: T): T {
-                            if (fallback is Int)
+                            if (fallback is Int) {
+                                allKeys.add(key)
                                 return DeviceConfig.getInt(NAMESPACE_LAUNCHER, key, fallback) as T
-                            else if (fallback is Boolean)
+                            } else if (fallback is Boolean) {
+                                allKeys.add(key)
                                 return DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, key, fallback)
                                     as T
-                            else return fallback
+                            } else return fallback
                         }
                     }
                 )
diff --git a/quickstep/src/com/android/quickstep/util/GroupTask.java b/quickstep/src/com/android/quickstep/util/GroupTask.java
index 9c49647..945ffe3 100644
--- a/quickstep/src/com/android/quickstep/util/GroupTask.java
+++ b/quickstep/src/com/android/quickstep/util/GroupTask.java
@@ -23,6 +23,10 @@
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
 /**
  * A {@link Task} container that can contain one or two tasks, depending on if the two tasks
  * are represented as an app-pair in the recents task list.
@@ -62,6 +66,17 @@
     }
 
     /**
+     * Returns a List of all the Tasks in this GroupTask
+     */
+    public List<Task> getTasks() {
+        if (task2 == null) {
+            return Collections.singletonList(task1);
+        } else {
+            return Arrays.asList(task1, task2);
+        }
+    }
+
+    /**
      * Create a copy of this instance
      */
     public GroupTask copy() {
@@ -70,4 +85,10 @@
                 task2 != null ? new Task(task2) : null,
                 mSplitBounds);
     }
+
+    @Override
+    public String toString() {
+        return "type=" + taskViewType + " task1=" + task1 + " task2=" + task2;
+    }
+
 }
diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
index 4474f33..26668c8 100644
--- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
+++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
@@ -39,6 +39,7 @@
 import com.android.quickstep.util.unfold.PreemptiveUnfoldTransitionProgressProvider;
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
+import com.android.systemui.unfold.dagger.UnfoldMain;
 import com.android.systemui.unfold.updates.RotationChangeProvider;
 import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
@@ -76,7 +77,7 @@
             QuickstepLauncher launcher,
             WindowManager windowManager,
             UnfoldTransitionProgressProvider unfoldTransitionProgressProvider,
-            RotationChangeProvider rotationChangeProvider) {
+            @UnfoldMain RotationChangeProvider rotationChangeProvider) {
         mLauncher = launcher;
 
         if (FeatureFlags.PREEMPTIVE_UNFOLD_ANIMATION_START.get()) {
diff --git a/quickstep/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
deleted file mode 100644
index 9418512..0000000
--- a/quickstep/src/com/android/quickstep/util/NavBarPosition.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 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.util;
-
-import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
-
-import android.view.Surface;
-
-import com.android.launcher3.util.DisplayController.Info;
-import com.android.launcher3.util.NavigationMode;
-
-/**
- * Utility class to check nav bar position.
- */
-public class NavBarPosition {
-
-    private final boolean mIsTablet;
-    private final NavigationMode mMode;
-    private final int mDisplayRotation;
-
-    public NavBarPosition(NavigationMode mode, Info info) {
-        mIsTablet = info.isTablet(info.realBounds);
-        mMode = mode;
-        mDisplayRotation = info.rotation;
-    }
-
-    public boolean isRightEdge() {
-        return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90 && !mIsTablet;
-    }
-
-    public boolean isLeftEdge() {
-        return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270 && !mIsTablet;
-    }
-
-    public float getRotation() {
-        return isLeftEdge() ? 90 : (isRightEdge() ? -90 : 0);
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/util/NavBarPosition.kt b/quickstep/src/com/android/quickstep/util/NavBarPosition.kt
new file mode 100644
index 0000000..43cf540
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/NavBarPosition.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 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.util
+
+import android.view.Surface
+import com.android.launcher3.util.DisplayController.Info
+import com.android.launcher3.util.NavigationMode
+import com.android.launcher3.util.NavigationMode.NO_BUTTON
+
+/** Utility class to check nav bar position. */
+data class NavBarPosition(
+    val isTablet: Boolean,
+    val displayRotation: Int,
+    val mode: NavigationMode
+) {
+    constructor(
+        mode: NavigationMode,
+        info: Info
+    ) : this(info.isTablet(info.realBounds), info.rotation, mode)
+
+    val isRightEdge: Boolean
+        get() = mode != NO_BUTTON && displayRotation == Surface.ROTATION_90 && !isTablet
+    val isLeftEdge: Boolean
+        get() = mode != NO_BUTTON && displayRotation == Surface.ROTATION_270 && !isTablet
+
+    val rotation: Float
+        get() = if (isLeftEdge) 90f else if (isRightEdge) -90f else 0f
+}
diff --git a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
index 5505bb3..769ccc0 100644
--- a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
+++ b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
@@ -565,7 +565,11 @@
                 final float bottomThreshold = deviceProfile.heightPx - padding.bottom;
 
                 if (targetRect.bottom > bottomThreshold) {
-                    tracking = TRACKING_BOTTOM;
+                    if (enableScalingRevealHomeAnimation()) {
+                        tracking = TRACKING_CENTER;
+                    } else {
+                        tracking = TRACKING_BOTTOM;
+                    }
                 } else if (targetRect.top < topThreshold) {
                     tracking = TRACKING_TOP;
                 } else {
diff --git a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
index 1bf77f1..4513fa2 100644
--- a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
+++ b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
@@ -17,11 +17,12 @@
 package com.android.quickstep.util
 
 import android.graphics.Matrix
+import android.graphics.Path
 import android.graphics.RectF
 import android.view.View
+import android.view.animation.PathInterpolator
 import androidx.core.graphics.transform
 import com.android.app.animation.Interpolators
-import com.android.app.animation.Interpolators.EMPHASIZED
 import com.android.app.animation.Interpolators.LINEAR
 import com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY
 import com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_WORKSPACE_STATE
@@ -53,6 +54,19 @@
         private const val MIN_ALPHA = 0f
         private const val MAX_SIZE = 1f
         private const val MIN_SIZE = 0.85f
+
+        /**
+         * Custom interpolator for both the home and wallpaper scaling. Necessary because EMPHASIZED
+         * is too aggressive, but EMPHASIZED_DECELERATE is too soft.
+         */
+        private val SCALE_INTERPOLATOR =
+            PathInterpolator(
+                Path().apply {
+                    moveTo(0f, 0f)
+                    cubicTo(0.045f, 0.0356f, 0.0975f, 0.2055f, 0.15f, 0.3952f)
+                    cubicTo(0.235f, 0.6855f, 0.235f, 1f, 1f, 1f)
+                }
+            )
     }
 
     private val animation = PendingAnimation(SCALE_DURATION_MS)
@@ -78,20 +92,20 @@
         val hotseat = launcher.hotseat
 
         // Scale the Workspace and Hotseat around the same pivot.
+        workspace.setPivotToScaleWithSelf(hotseat)
         animation.addFloat(
             workspace,
             WORKSPACE_SCALE_PROPERTY_FACTORY[SCALE_INDEX_WORKSPACE_STATE],
             MIN_SIZE,
             MAX_SIZE,
-            EMPHASIZED,
+            SCALE_INTERPOLATOR,
         )
-        workspace.setPivotToScaleWithSelf(hotseat)
         animation.addFloat(
             hotseat,
             HOTSEAT_SCALE_PROPERTY_FACTORY[SCALE_INDEX_WORKSPACE_STATE],
             MIN_SIZE,
             MAX_SIZE,
-            EMPHASIZED,
+            SCALE_INTERPOLATOR,
         )
 
         // Fade in quickly at the beginning of the animation, so the content doesn't look like it's
@@ -114,11 +128,11 @@
 
         // Match the Wallpaper animation to the rest of the content.
         val depthController = (launcher as? QuickstepLauncher)?.depthController
-        transitionConfig.setInterpolator(StateAnimationConfig.ANIM_DEPTH, EMPHASIZED)
+        transitionConfig.setInterpolator(StateAnimationConfig.ANIM_DEPTH, SCALE_INTERPOLATOR)
         depthController?.setStateWithAnimation(LauncherState.NORMAL, transitionConfig, animation)
 
         // Make sure that the contrast scrim animates correctly if needed.
-        transitionConfig.setInterpolator(StateAnimationConfig.ANIM_SCRIM_FADE, EMPHASIZED)
+        transitionConfig.setInterpolator(StateAnimationConfig.ANIM_SCRIM_FADE, SCALE_INTERPOLATOR)
         launcher.workspace.stateTransitionAnimation.setScrim(
             animation,
             LauncherState.NORMAL,
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
index f430d79..8243ede 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
@@ -23,6 +23,7 @@
 import android.animation.ObjectAnimator
 import android.animation.ValueAnimator
 import android.app.ActivityManager.RunningTaskInfo
+import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
 import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW
 import android.content.Context
 import android.graphics.Bitmap
@@ -50,6 +51,7 @@
 import com.android.launcher3.apppairs.AppPairIcon
 import com.android.launcher3.config.FeatureFlags
 import com.android.launcher3.logging.StatsLogManager.EventEnum
+import com.android.launcher3.model.data.WorkspaceItemInfo
 import com.android.launcher3.statehandlers.DepthController
 import com.android.launcher3.statemanager.StateManager
 import com.android.launcher3.taskbar.TaskbarActivityContext
@@ -67,8 +69,9 @@
 import com.android.quickstep.views.SplitInstructionsView
 import com.android.quickstep.views.TaskThumbnailViewDeprecated
 import com.android.quickstep.views.TaskView
-import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
+import com.android.quickstep.views.TaskView.TaskContainer
 import com.android.quickstep.views.TaskViewIcon
+import com.android.wm.shell.shared.TransitionUtil
 import java.util.Optional
 import java.util.function.Supplier
 
@@ -111,12 +114,12 @@
         } else if (splitSelectStateController.isDismissingFromSplitPair) {
             // Initiating split from overview, but on a split pair
             val taskView = taskViewSupplier.get()
-            for (container: TaskIdAttributeContainer in taskView.taskIdAttributeContainers) {
+            for (container: TaskContainer in taskView.taskContainers) {
                 if (container.task.getKey().getId() == splitSelectStateController.initialTaskId) {
                     val drawable = getDrawable(container.iconView, splitSelectSource)
                     return SplitAnimInitProps(
-                        container.thumbnailView,
-                        container.thumbnailView.thumbnail,
+                        container.thumbnailViewDeprecated,
+                        container.thumbnailViewDeprecated.thumbnail,
                         drawable!!,
                         fadeWithThumbnail = true,
                         isStagedTask = true,
@@ -131,15 +134,17 @@
         } else {
             // Initiating split from overview on fullscreen task TaskView
             val taskView = taskViewSupplier.get()
-            val drawable = getDrawable(taskView.iconView, splitSelectSource)
-            return SplitAnimInitProps(
-                taskView.thumbnail,
-                taskView.thumbnail.thumbnail,
-                drawable!!,
-                fadeWithThumbnail = true,
-                isStagedTask = true,
-                taskView.iconView.asView()
-            )
+            taskView.taskContainers.first().let {
+                val drawable = getDrawable(it.iconView, splitSelectSource)
+                return SplitAnimInitProps(
+                    it.thumbnailViewDeprecated,
+                    it.thumbnailViewDeprecated.thumbnail,
+                    drawable!!,
+                    fadeWithThumbnail = true,
+                    isStagedTask = true,
+                    iconView = it.iconView.asView()
+                )
+            }
         }
     }
 
@@ -170,14 +175,14 @@
      *   (opposite of that representing [taskIdAttributeContainer])
      */
     fun addInitialSplitFromPair(
-        taskIdAttributeContainer: TaskIdAttributeContainer,
+        taskIdAttributeContainer: TaskContainer,
         builder: PendingAnimation,
         deviceProfile: DeviceProfile,
         taskViewWidth: Int,
         taskViewHeight: Int,
         isPrimaryTaskSplitting: Boolean
     ) {
-        val thumbnail = taskIdAttributeContainer.thumbnailView
+        val thumbnail = taskIdAttributeContainer.thumbnailViewDeprecated
         val iconView: View = taskIdAttributeContainer.iconView.asView()
         builder.add(ObjectAnimator.ofFloat(thumbnail, TaskThumbnailViewDeprecated.SPLASH_ALPHA, 1f))
         thumbnail.setShowSplashForSplitSelection(true)
@@ -553,8 +558,19 @@
             check(info != null && t != null) {
                 "trying to launch an app pair icon, but encountered an unexpected null"
             }
-
-            composeIconSplitLaunchAnimator(launchingIconView, info, t, finishCallback)
+            val appPairLaunchingAppIndex = hasChangesForBothAppPairs(launchingIconView, info)
+            if (appPairLaunchingAppIndex == -1) {
+                // Launch split app pair animation
+                composeIconSplitLaunchAnimator(launchingIconView, info, t, finishCallback)
+            } else {
+                composeFullscreenIconSplitLaunchAnimator(
+                    launchingIconView,
+                    info,
+                    t,
+                    finishCallback,
+                    appPairLaunchingAppIndex
+                )
+            }
         } else {
             // Fallback case: simple fade-in animation
             check(info != null && t != null) {
@@ -619,6 +635,43 @@
     }
 
     /**
+     * @return -1 if [transitionInfo] contains both apps of the app pair to be animated, otherwise
+     *   the integer index corresponding to [launchingIconView]'s contents for the single app to be
+     *   animated
+     */
+    fun hasChangesForBothAppPairs(
+        launchingIconView: AppPairIcon,
+        transitionInfo: TransitionInfo
+    ): Int {
+        val intent1 = launchingIconView.info.getFirstApp().intent.component?.packageName
+        val intent2 = launchingIconView.info.getSecondApp().intent.component?.packageName
+        var launchFullscreenAppIndex = -1
+        for (change in transitionInfo.changes) {
+            val taskInfo: RunningTaskInfo = change.taskInfo ?: continue
+            if (
+                TransitionUtil.isOpeningType(change.mode) &&
+                    taskInfo.windowingMode == WINDOWING_MODE_FULLSCREEN
+            ) {
+                val baseIntent = taskInfo.baseIntent.component?.packageName
+                if (baseIntent == intent1) {
+                    if (launchFullscreenAppIndex > -1) {
+                        launchFullscreenAppIndex = -1
+                        break
+                    }
+                    launchFullscreenAppIndex = 0
+                } else if (baseIntent == intent2) {
+                    if (launchFullscreenAppIndex > -1) {
+                        launchFullscreenAppIndex = -1
+                        break
+                    }
+                    launchFullscreenAppIndex = 1
+                }
+            }
+        }
+        return launchFullscreenAppIndex
+    }
+
+    /**
      * When the user taps an app pair icon to launch split, this will play the tasks' launch
      * animation from the position of the icon.
      *
@@ -653,7 +706,12 @@
         // If launching an app pair from Taskbar inside of an app context (no access to Launcher),
         // use the scale-up animation
         if (launchingIconView.context is TaskbarActivityContext) {
-            composeScaleUpLaunchAnimation(transitionInfo, t, finishCallback)
+            composeScaleUpLaunchAnimation(
+                transitionInfo,
+                t,
+                finishCallback,
+                WINDOWING_MODE_MULTI_WINDOW
+            )
             return
         }
 
@@ -663,11 +721,6 @@
 
         // Create an AnimatorSet that will run both shell and launcher transitions together
         val launchAnimation = AnimatorSet()
-        val progressUpdater = ValueAnimator.ofFloat(0f, 1f)
-        val timings = AnimUtils.getDeviceAppPairLaunchTimings(dp.isTablet)
-        progressUpdater.setDuration(timings.getDuration().toLong())
-        progressUpdater.interpolator = Interpolators.LINEAR
-
         var rootCandidate: Change? = null
 
         for (change in transitionInfo.changes) {
@@ -711,6 +764,122 @@
         // Make sure nothing weird happened, like getChange() returning null.
         check(rootCandidate != null) { "Failed to find a root leash" }
 
+        // Create a new floating view in Launcher, positioned above the launching icon
+        val drawableArea = launchingIconView.iconDrawableArea
+        val appIcon1 = launchingIconView.info.getFirstApp().newIcon(launchingIconView.context)
+        val appIcon2 = launchingIconView.info.getSecondApp().newIcon(launchingIconView.context)
+        appIcon1.setBounds(0, 0, dp.iconSizePx, dp.iconSizePx)
+        appIcon2.setBounds(0, 0, dp.iconSizePx, dp.iconSizePx)
+
+        val floatingView =
+            FloatingAppPairView.getFloatingAppPairView(
+                launcher,
+                drawableArea,
+                appIcon1,
+                appIcon2,
+                dividerPos
+            )
+        floatingView.bringToFront()
+
+        launchAnimation.play(
+            getIconLaunchValueAnimator(t, dp, finishCallback, launcher, floatingView, rootCandidate)
+        )
+        launchAnimation.start()
+    }
+
+    /**
+     * Similar to [composeIconSplitLaunchAnimator], but instructs [FloatingAppPairView] to animate a
+     * single fullscreen icon + background instead of for a pair
+     */
+    @VisibleForTesting
+    fun composeFullscreenIconSplitLaunchAnimator(
+        launchingIconView: AppPairIcon,
+        transitionInfo: TransitionInfo,
+        t: Transaction,
+        finishCallback: Runnable,
+        launchFullscreenIndex: Int
+    ) {
+        // If launching an app pair from Taskbar inside of an app context (no access to Launcher),
+        // use the scale-up animation
+        if (launchingIconView.context is TaskbarActivityContext) {
+            composeScaleUpLaunchAnimation(
+                transitionInfo,
+                t,
+                finishCallback,
+                WINDOWING_MODE_FULLSCREEN
+            )
+            return
+        }
+
+        // Else we are in Launcher and can launch with the full icon stretch-and-split animation.
+        val launcher = QuickstepLauncher.getLauncher(launchingIconView.context)
+        val dp = launcher.deviceProfile
+
+        // Create an AnimatorSet that will run both shell and launcher transitions together
+        val launchAnimation = AnimatorSet()
+
+        val appInfo =
+            launchingIconView.info.getContents()[launchFullscreenIndex] as WorkspaceItemInfo
+        val intentToLaunch = appInfo.intent.component?.packageName
+        var rootCandidate: Change? = null
+        for (change in transitionInfo.changes) {
+            val taskInfo: RunningTaskInfo = change.taskInfo ?: continue
+            val baseIntent = taskInfo.baseIntent.component?.packageName
+            if (
+                TransitionUtil.isOpeningType(change.mode) &&
+                    taskInfo.windowingMode == WINDOWING_MODE_FULLSCREEN &&
+                    baseIntent == intentToLaunch
+            ) {
+                rootCandidate = change
+            }
+        }
+
+        // If we could not find a proper root candidate, something went wrong.
+        check(rootCandidate != null) { "Could not find a split root candidate" }
+
+        // Recurse up the tree until parent is null, then we've found our root.
+        var parentToken: WindowContainerToken? = rootCandidate.parent
+        while (parentToken != null) {
+            rootCandidate = transitionInfo.getChange(parentToken) ?: break
+            parentToken = rootCandidate.parent
+        }
+
+        // Make sure nothing weird happened, like getChange() returning null.
+        check(rootCandidate != null) { "Failed to find a root leash" }
+
+        // Create a new floating view in Launcher, positioned above the launching icon
+        val drawableArea = launchingIconView.iconDrawableArea
+        val appIcon = appInfo.newIcon(launchingIconView.context)
+        appIcon.setBounds(0, 0, dp.iconSizePx, dp.iconSizePx)
+
+        val floatingView =
+            FloatingAppPairView.getFloatingAppPairView(
+                launcher,
+                drawableArea,
+                appIcon,
+                null /*appIcon2*/,
+                0 /*dividerPos*/
+            )
+        floatingView.bringToFront()
+        launchAnimation.play(
+            getIconLaunchValueAnimator(t, dp, finishCallback, launcher, floatingView, rootCandidate)
+        )
+        launchAnimation.start()
+    }
+
+    private fun getIconLaunchValueAnimator(
+        t: Transaction,
+        dp: com.android.launcher3.DeviceProfile,
+        finishCallback: Runnable,
+        launcher: QuickstepLauncher,
+        floatingView: FloatingAppPairView,
+        rootCandidate: Change
+    ): ValueAnimator {
+        val progressUpdater = ValueAnimator.ofFloat(0f, 1f)
+        val timings = AnimUtils.getDeviceAppPairLaunchTimings(dp.isTablet)
+        progressUpdater.setDuration(timings.getDuration().toLong())
+        progressUpdater.interpolator = Interpolators.LINEAR
+
         // Shell animation: the apps are revealed toward end of the launch animation
         progressUpdater.addUpdateListener { valueAnimator: ValueAnimator ->
             val progress =
@@ -726,23 +895,6 @@
             t.apply()
         }
 
-        // Create a new floating view in Launcher, positioned above the launching icon
-        val drawableArea = launchingIconView.iconDrawableArea
-        val appIcon1 = launchingIconView.info.getFirstApp().newIcon(launchingIconView.context)
-        val appIcon2 = launchingIconView.info.getSecondApp().newIcon(launchingIconView.context)
-        appIcon1.setBounds(0, 0, dp.iconSizePx, dp.iconSizePx)
-        appIcon2.setBounds(0, 0, dp.iconSizePx, dp.iconSizePx)
-        val floatingView =
-            FloatingAppPairView.getFloatingAppPairView(
-                launcher,
-                drawableArea,
-                appIcon1,
-                appIcon2,
-                dividerPos
-            )
-        floatingView.bringToFront()
-
-        // Launcher animation: animate the floating view, expanding to fill the display surface
         progressUpdater.addUpdateListener(
             object : MultiValueUpdateListener() {
                 var mDx =
@@ -796,8 +948,6 @@
                 }
             }
         )
-
-        // When animation ends, remove the floating view and run finishCallback
         progressUpdater.addListener(
             object : AnimatorListenerAdapter() {
                 override fun onAnimationEnd(animation: Animator) {
@@ -807,19 +957,20 @@
             }
         )
 
-        launchAnimation.play(progressUpdater)
-        launchAnimation.start()
+        return progressUpdater
     }
 
     /**
      * This is a scale-up-and-fade-in animation (34% to 100%) for launching an app in Overview when
-     * there is no visible associated tile to expand from.
+     * there is no visible associated tile to expand from. [windowingMode] helps determine whether
+     * we are looking for a split or a single fullscreen [Change]
      */
     @VisibleForTesting
     fun composeScaleUpLaunchAnimation(
         transitionInfo: TransitionInfo,
         t: Transaction,
-        finishCallback: Runnable
+        finishCallback: Runnable,
+        windowingMode: Int
     ) {
         val launchAnimation = AnimatorSet()
         val progressUpdater = ValueAnimator.ofFloat(0f, 1f)
@@ -833,9 +984,8 @@
 
             // TODO (b/316490565): Replace this logic when SplitBounds is available to
             //  startAnimation() and we can know the precise taskIds of launching tasks.
-            // Find a change that has WINDOWING_MODE_MULTI_WINDOW.
             if (
-                taskInfo.windowingMode == WINDOWING_MODE_MULTI_WINDOW &&
+                taskInfo.windowingMode == windowingMode &&
                     (change.mode == TRANSIT_OPEN || change.mode == TRANSIT_TO_FRONT)
             ) {
                 // Found one!
@@ -967,12 +1117,12 @@
         animator.setDuration(QuickstepTransitionManager.SPLIT_LAUNCH_DURATION.toLong())
         animator.addUpdateListener { valueAnimator: ValueAnimator ->
             val progress =
-                    Interpolators.clampToProgress(
-                            Interpolators.LINEAR,
-                            valueAnimator.animatedFraction,
-                            0.8f,
-                            1f
-                    )
+                Interpolators.clampToProgress(
+                    Interpolators.LINEAR,
+                    valueAnimator.animatedFraction,
+                    0.8f,
+                    1f
+                )
             for (leash in openingTargets) {
                 animTransaction.setAlpha(leash, progress)
             }
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt b/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt
index 06edb14..8258ab8 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt
@@ -38,36 +38,40 @@
 import java.io.PrintWriter
 
 /**
- * Holds/transforms/signs/seals/delivers information for the transient state of the user
- * selecting a first app to start split with and then choosing a second app.
- * This class DOES NOT associate itself with drag-and-drop split screen starts because they come
- * from the bad part of town.
+ * Holds/transforms/signs/seals/delivers information for the transient state of the user selecting a
+ * first app to start split with and then choosing a second app. This class DOES NOT associate
+ * itself with drag-and-drop split screen starts because they come from the bad part of town.
  *
  * After setting the correct fields for initial/second.* variables, this converts them into the
- * correct [PendingIntent] and [ShortcutInfo] objects where applicable and sends the necessary
- * data back via [getSplitLaunchData]. Note: there should be only one "initial" field and one
- * "second" field set, with the rest remaining null. (Exception: [Intent] and [UserHandle] are
- * always passed in together as a set, and are converted to a single [PendingIntent] or
+ * correct [PendingIntent] and [ShortcutInfo] objects where applicable and sends the necessary data
+ * back via [getSplitLaunchData]. Note: there should be only one "initial" field and one "second"
+ * field set, with the rest remaining null. (Exception: [Intent] and [UserHandle] are always passed
+ * in together as a set, and are converted to a single [PendingIntent] or
  * [ShortcutInfo]+[PendingIntent] before launch.)
  *
  * [SplitLaunchType] indicates the type of tasks/apps/intents being launched given the provided
  * state
  */
-class SplitSelectDataHolder(
-        var context: Context?
-) {
+class SplitSelectDataHolder(var context: Context?) {
     val TAG = SplitSelectDataHolder::class.simpleName
 
     /**
-     * Order of the constant indicates the order of which task/app was selected.
-     * Ex. SPLIT_TASK_SHORTCUT means primary split app identified by task, secondary is shortcut
+     * Order of the constant indicates the order of which task/app was selected. Ex.
+     * SPLIT_TASK_SHORTCUT means primary split app identified by task, secondary is shortcut
      * SPLIT_SHORTCUT_TASK means primary split app is determined by shortcut, secondary is task
      */
     companion object {
-        @IntDef(SPLIT_TASK_TASK, SPLIT_TASK_PENDINGINTENT, SPLIT_TASK_SHORTCUT,
-                SPLIT_PENDINGINTENT_TASK, SPLIT_PENDINGINTENT_PENDINGINTENT, SPLIT_SHORTCUT_TASK,
-                SPLIT_SINGLE_TASK_FULLSCREEN, SPLIT_SINGLE_INTENT_FULLSCREEN,
-                SPLIT_SINGLE_SHORTCUT_FULLSCREEN)
+        @IntDef(
+            SPLIT_TASK_TASK,
+            SPLIT_TASK_PENDINGINTENT,
+            SPLIT_TASK_SHORTCUT,
+            SPLIT_PENDINGINTENT_TASK,
+            SPLIT_PENDINGINTENT_PENDINGINTENT,
+            SPLIT_SHORTCUT_TASK,
+            SPLIT_SINGLE_TASK_FULLSCREEN,
+            SPLIT_SINGLE_INTENT_FULLSCREEN,
+            SPLIT_SINGLE_SHORTCUT_FULLSCREEN
+        )
         @Retention(AnnotationRetention.SOURCE)
         annotation class SplitLaunchType
 
@@ -84,8 +88,7 @@
         const val SPLIT_SINGLE_SHORTCUT_FULLSCREEN = 8
     }
 
-    @StagePosition
-    private var initialStagePosition: Int = STAGE_POSITION_UNDEFINED
+    @StagePosition private var initialStagePosition: Int = STAGE_POSITION_UNDEFINED
     private var itemInfo: ItemInfo? = null
     private var secondItemInfo: ItemInfo? = null
     private var splitEvent: EventEnum? = null
@@ -108,12 +111,16 @@
 
     /**
      * @param alreadyRunningTask if set to [android.app.ActivityTaskManager.INVALID_TASK_ID]
-     * then @param intent will be used to launch the initial task
+     *   then @param intent will be used to launch the initial task
      * @param intent will be ignored if @param alreadyRunningTask is set
      */
-    fun setInitialTaskSelect(intent: Intent?, @StagePosition stagePosition: Int,
-                             itemInfo: ItemInfo?, splitEvent: EventEnum?,
-                             alreadyRunningTask: Int) {
+    fun setInitialTaskSelect(
+        intent: Intent?,
+        @StagePosition stagePosition: Int,
+        itemInfo: ItemInfo?,
+        splitEvent: EventEnum?,
+        alreadyRunningTask: Int
+    ) {
         if (alreadyRunningTask != INVALID_TASK_ID) {
             initialTaskId = alreadyRunningTask
         } else {
@@ -127,15 +134,21 @@
      * To be called after first task selected from using a split shortcut from the fullscreen
      * running app.
      */
-    fun setInitialTaskSelect(info: RunningTaskInfo,
-                             @StagePosition stagePosition: Int, itemInfo: ItemInfo?,
-                             splitEvent: EventEnum?) {
+    fun setInitialTaskSelect(
+        info: RunningTaskInfo,
+        @StagePosition stagePosition: Int,
+        itemInfo: ItemInfo?,
+        splitEvent: EventEnum?
+    ) {
         initialTaskId = info.taskId
         setInitialData(stagePosition, splitEvent, itemInfo)
     }
 
-    private fun setInitialData(@StagePosition stagePosition: Int,
-                               event: EventEnum?, item: ItemInfo?) {
+    private fun setInitialData(
+        @StagePosition stagePosition: Int,
+        event: EventEnum?,
+        item: ItemInfo?
+    ) {
         itemInfo = item
         initialStagePosition = stagePosition
         splitEvent = event
@@ -143,6 +156,7 @@
 
     /**
      * To be called as soon as user selects the second task (even if animations aren't complete)
+     *
      * @param taskId The second task that will be launched.
      */
     fun setSecondTask(taskId: Int, itemInfo: ItemInfo) {
@@ -152,6 +166,7 @@
 
     /**
      * To be called as soon as user selects the second app (even if animations aren't complete)
+     *
      * @param intent The second intent that will be launched.
      * @param user The user of that intent.
      */
@@ -162,8 +177,9 @@
     }
 
     /**
-     * To be called as soon as user selects the second app (even if animations aren't complete)
-     * Sets [secondUser] from that of the pendingIntent
+     * To be called as soon as user selects the second app (even if animations aren't complete) Sets
+     * [secondUser] from that of the pendingIntent
+     *
      * @param pendingIntent The second PendingIntent that will be launched.
      */
     fun setSecondTask(pendingIntent: PendingIntent, itemInfo: ItemInfo) {
@@ -173,9 +189,9 @@
     }
 
     /**
-     * Similar to [setSecondTask] except this is to be called for widgets which can pass through
-     * an extra intent from their RemoteResponse.
-     * See [android.widget.RemoteViews.RemoteResponse.getLaunchOptions].first
+     * Similar to [setSecondTask] except this is to be called for widgets which can pass through an
+     * extra intent from their RemoteResponse. See
+     * [android.widget.RemoteViews.RemoteResponse.getLaunchOptions].first
      */
     fun setSecondWidget(pendingIntent: PendingIntent, widgetIntent: Intent?, itemInfo: ItemInfo) {
         setSecondTask(pendingIntent, itemInfo)
@@ -184,8 +200,7 @@
 
     private fun getShortcutInfo(intent: Intent?, user: UserHandle?): ShortcutInfo? {
         val intentPackage = intent?.getPackage() ?: return null
-        val shortcutId = intent.getStringExtra(ShortcutKey.EXTRA_SHORTCUT_ID)
-                ?: return null
+        val shortcutId = intent.getStringExtra(ShortcutKey.EXTRA_SHORTCUT_ID) ?: return null
         try {
             val context: Context =
                 if (user != null) {
@@ -200,9 +215,7 @@
         return null
     }
 
-    /**
-     * Converts intents to pendingIntents, associating the [user] with the intent if provided
-     */
+    /** Converts intents to pendingIntents, associating the [user] with the intent if provided */
     private fun getPendingIntent(intent: Intent?, user: UserHandle?): PendingIntent? {
         if (intent != initialIntent && intent != secondIntent) {
             throw IllegalStateException("Invalid intent to convert to PendingIntent")
@@ -211,12 +224,21 @@
         return if (intent == null) {
             null
         } else if (user != null) {
-            PendingIntent.getActivityAsUser(context, 0, intent,
-                    PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT,
-                    null /* options */, user)
+            PendingIntent.getActivityAsUser(
+                context,
+                0,
+                intent,
+                PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT,
+                null /* options */,
+                user
+            )
         } else {
-            PendingIntent.getActivity(context, 0, intent,
-                    PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT)
+            PendingIntent.getActivity(
+                context,
+                0,
+                intent,
+                PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT
+            )
         }
     }
 
@@ -224,7 +246,7 @@
      * @return [SplitLaunchData] with the necessary fields populated as determined by
      *   [SplitLaunchData.splitLaunchType]. This is to be used for launching splitscreen
      */
-    fun getSplitLaunchData() : SplitLaunchData {
+    fun getSplitLaunchData(): SplitLaunchData {
         // Convert all intents to shortcut infos to see if determine if we launch shortcut or intent
         convertIntentsToFinalTypes()
         val splitLaunchType = getSplitLaunchType()
@@ -241,7 +263,7 @@
      *   [SplitLaunchData.splitLaunchType]. This is to be used for launching an initially selected
      *   split task in fullscreen
      */
-    fun getFullscreenLaunchData() : SplitLaunchData {
+    fun getFullscreenLaunchData(): SplitLaunchData {
         // Convert all intents to shortcut infos to determine if we launch shortcut or intent
         convertIntentsToFinalTypes()
         val splitLaunchType = getFullscreenLaunchType()
@@ -249,21 +271,22 @@
         return generateSplitLaunchData(splitLaunchType)
     }
 
-    private fun generateSplitLaunchData(@SplitLaunchType splitLaunchType: Int) : SplitLaunchData {
+    private fun generateSplitLaunchData(@SplitLaunchType splitLaunchType: Int): SplitLaunchData {
         return SplitLaunchData(
-                splitLaunchType,
-                initialTaskId,
-                secondTaskId,
-                initialPendingIntent,
-                secondPendingIntent,
-                widgetSecondIntent,
-                initialUser?.identifier ?: -1,
-                secondUser?.identifier ?: -1,
-                initialShortcut,
-                secondShortcut,
-                itemInfo,
-                splitEvent,
-                initialStagePosition)
+            splitLaunchType,
+            initialTaskId,
+            secondTaskId,
+            initialPendingIntent,
+            secondPendingIntent,
+            widgetSecondIntent,
+            initialUser?.identifier ?: -1,
+            secondUser?.identifier ?: -1,
+            initialShortcut,
+            secondShortcut,
+            itemInfo,
+            splitEvent,
+            initialStagePosition
+        )
     }
 
     /**
@@ -273,8 +296,7 @@
      * Note that both [initialIntent] and [secondIntent] will be nullified on method return
      *
      * One caveat is that if [secondPendingIntent] is set, we will use that and *not* attempt to
-     * convert [secondIntent].
-     * This also leaves [widgetSecondIntent] untouched.
+     * convert [secondIntent]. This also leaves [widgetSecondIntent] untouched.
      */
     private fun convertIntentsToFinalTypes() {
         initialShortcut = getShortcutInfo(initialIntent, initialUser)
@@ -297,8 +319,8 @@
     }
 
     /**
-     * Only valid data fields at this point should be tasks, shortcuts, or pendingIntents
-     * Intents need to be converted in [convertIntentsToFinalTypes] prior to calling this method
+     * Only valid data fields at this point should be tasks, shortcuts, or pendingIntents Intents
+     * need to be converted in [convertIntentsToFinalTypes] prior to calling this method
      */
     @VisibleForTesting
     @SplitLaunchType
@@ -354,41 +376,40 @@
     }
 
     data class SplitLaunchData(
-            @SplitLaunchType
-            val splitLaunchType: Int,
-            var initialTaskId: Int = INVALID_TASK_ID,
-            var secondTaskId: Int = INVALID_TASK_ID,
-            var initialPendingIntent: PendingIntent? = null,
-            var secondPendingIntent: PendingIntent? = null,
-            var widgetSecondIntent: Intent? = null,
-            var initialUserId: Int = -1,
-            var secondUserId: Int = -1,
-            var initialShortcut: ShortcutInfo? = null,
-            var secondShortcut: ShortcutInfo? = null,
-            var itemInfo: ItemInfo? = null,
-            var splitEvent: EventEnum? = null,
-            val initialStagePosition: Int = STAGE_POSITION_UNDEFINED
+        @SplitLaunchType val splitLaunchType: Int,
+        var initialTaskId: Int = INVALID_TASK_ID,
+        var secondTaskId: Int = INVALID_TASK_ID,
+        var initialPendingIntent: PendingIntent? = null,
+        var secondPendingIntent: PendingIntent? = null,
+        var widgetSecondIntent: Intent? = null,
+        var initialUserId: Int = -1,
+        var secondUserId: Int = -1,
+        var initialShortcut: ShortcutInfo? = null,
+        var secondShortcut: ShortcutInfo? = null,
+        var itemInfo: ItemInfo? = null,
+        var splitEvent: EventEnum? = null,
+        val initialStagePosition: Int = STAGE_POSITION_UNDEFINED
     )
 
     /**
-     * @return `true` if first task has been selected and waiting for the second task to be
-     * chosen
+     * @return `true` if first task has been selected and waiting for the second task to be chosen
      */
     fun isSplitSelectActive(): Boolean {
         return isInitialTaskIntentSet() && !isSecondTaskIntentSet()
     }
 
     /**
-     * @return `true` if the first and second task have been chosen and split is waiting to
-     * be launched
+     * @return `true` if the first and second task have been chosen and split is waiting to be
+     *   launched
      */
     fun isBothSplitAppsConfirmed(): Boolean {
         return isInitialTaskIntentSet() && isSecondTaskIntentSet()
     }
 
     private fun isInitialTaskIntentSet(): Boolean {
-        return initialTaskId != INVALID_TASK_ID || initialIntent != null ||
-                initialPendingIntent != null
+        return initialTaskId != INVALID_TASK_ID ||
+            initialIntent != null ||
+            initialPendingIntent != null
     }
 
     fun getInitialTaskId(): Int {
@@ -416,8 +437,9 @@
     }
 
     private fun isSecondTaskIntentSet(): Boolean {
-        return secondTaskId != INVALID_TASK_ID || secondIntent != null
-                || secondPendingIntent != null
+        return secondTaskId != INVALID_TASK_ID ||
+            secondIntent != null ||
+            secondPendingIntent != null
     }
 
     fun resetState() {
@@ -437,7 +459,7 @@
     }
 
     fun dump(prefix: String, writer: PrintWriter) {
-        writer.println("$prefix ${javaClass.simpleName}")
+        writer.println("$prefix SplitSelectDataHolder")
         writer.println("$prefix\tinitialStagePosition= $initialStagePosition")
         writer.println("$prefix\tinitialTaskId= $initialTaskId")
         writer.println("$prefix\tsecondTaskId= $secondTaskId")
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index c257be6..7e7c794 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -90,7 +90,6 @@
 import com.android.quickstep.OverviewComponentObserver;
 import com.android.quickstep.RecentsAnimationCallbacks;
 import com.android.quickstep.RecentsAnimationController;
-import com.android.quickstep.RecentsAnimationDeviceState;
 import com.android.quickstep.RecentsAnimationTargets;
 import com.android.quickstep.RecentsModel;
 import com.android.quickstep.SplitSelectionListener;
@@ -646,8 +645,13 @@
         }
     }
 
-    public void initSplitFromDesktopController(QuickstepLauncher launcher) {
-        initSplitFromDesktopController(new SplitFromDesktopController(launcher));
+    /**
+     * Init {@code SplitFromDesktopController}
+     */
+    public void initSplitFromDesktopController(QuickstepLauncher launcher,
+            OverviewComponentObserver overviewComponentObserver) {
+        initSplitFromDesktopController(
+                new SplitFromDesktopController(launcher, overviewComponentObserver));
     }
 
     @VisibleForTesting
@@ -956,12 +960,10 @@
         private ISplitSelectListener mSplitSelectListener;
         private Drawable mAppIcon;
 
-        public SplitFromDesktopController(QuickstepLauncher launcher) {
+        public SplitFromDesktopController(QuickstepLauncher launcher,
+                OverviewComponentObserver overviewComponentObserver) {
             mLauncher = launcher;
-            RecentsAnimationDeviceState deviceState = new RecentsAnimationDeviceState(
-                    launcher.getApplicationContext());
-            mOverviewComponentObserver =
-                    new OverviewComponentObserver(launcher.getApplicationContext(), deviceState);
+            mOverviewComponentObserver = overviewComponentObserver;
             mSplitPlaceholderSize = mLauncher.getResources().getDimensionPixelSize(
                     R.dimen.split_placeholder_size);
             mSplitPlaceholderInset = mLauncher.getResources().getDimensionPixelSize(
@@ -981,6 +983,7 @@
         void onDestroy() {
             SystemUiProxy.INSTANCE.get(mLauncher).unregisterSplitSelectListener(
                     mSplitSelectListener);
+            mSplitSelectListener = null;
         }
 
         /**
diff --git a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
index 555bf21..5e42b90 100644
--- a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
@@ -62,12 +62,13 @@
     private final int mSplitPlaceholderInset;
 
     public SplitWithKeyboardShortcutController(QuickstepLauncher launcher,
-            SplitSelectStateController controller) {
+            SplitSelectStateController controller,
+            OverviewComponentObserver overviewComponentObserver,
+            RecentsAnimationDeviceState deviceState) {
         mLauncher = launcher;
         mController = controller;
-        mDeviceState = new RecentsAnimationDeviceState(launcher.getApplicationContext());
-        mOverviewComponentObserver = new OverviewComponentObserver(launcher.getApplicationContext(),
-                mDeviceState);
+        mDeviceState = deviceState;
+        mOverviewComponentObserver = overviewComponentObserver;
 
         mSplitPlaceholderSize = mLauncher.getResources().getDimensionPixelSize(
                 R.dimen.split_placeholder_size);
@@ -135,7 +136,7 @@
             RectF startingTaskRect = new RectF();
             final FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(
                     mLauncher, mLauncher.getDragLayer(),
-                    controller.screenshotTask(runningTaskInfo.taskId).thumbnail,
+                    controller.screenshotTask(runningTaskInfo.taskId).getThumbnail(),
                     null /* icon */, startingTaskRect);
             RecentsModel.INSTANCE.get(mLauncher.getApplicationContext())
                     .getIconCache()
diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
index f823aff..99f10a7 100644
--- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
@@ -46,7 +46,7 @@
  * when swiping up (in gesture navigation mode).
  */
 public class SwipePipToHomeAnimator extends RectFSpringAnim {
-    private static final String TAG = SwipePipToHomeAnimator.class.getSimpleName();
+    private static final String TAG = "SwipePipToHomeAnimator";
 
     private static final float END_PROGRESS = 1.0f;
 
diff --git a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
index 9268511..304b8f4 100644
--- a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
+++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
@@ -26,9 +26,11 @@
 import android.view.WindowMetrics;
 
 import com.android.internal.policy.SystemBarUtils;
+import com.android.launcher3.statehandlers.DesktopVisibilityController;
 import com.android.launcher3.util.WindowBounds;
 import com.android.launcher3.util.window.CachedDisplayInfo;
 import com.android.launcher3.util.window.WindowManagerProxy;
+import com.android.quickstep.LauncherActivityInterface;
 
 import java.util.List;
 import java.util.Set;
@@ -49,6 +51,13 @@
     }
 
     @Override
+    public boolean isInDesktopMode() {
+        DesktopVisibilityController desktopController =
+                LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
+        return desktopController != null && desktopController.areDesktopTasksVisible();
+    }
+
+    @Override
     public int getRotation(Context displayInfoContext) {
         return displayInfoContext.getResources().getConfiguration().windowConfiguration
                 .getRotation();
diff --git a/quickstep/src/com/android/quickstep/util/TaskKeyByLastActiveTimeCache.java b/quickstep/src/com/android/quickstep/util/TaskKeyByLastActiveTimeCache.java
index 21c9e09..69137cc 100644
--- a/quickstep/src/com/android/quickstep/util/TaskKeyByLastActiveTimeCache.java
+++ b/quickstep/src/com/android/quickstep/util/TaskKeyByLastActiveTimeCache.java
@@ -37,7 +37,7 @@
  * @param <V> Type of object stored in the cache
  */
 public class TaskKeyByLastActiveTimeCache<V> implements TaskKeyCache<V> {
-    private static final String TAG = TaskKeyByLastActiveTimeCache.class.getSimpleName();
+    private static final String TAG = "TaskKeyByLastActiveTimeCache";
     private final AtomicInteger mMaxSize;
     private final Map<Integer, Entry<V>> mMap;
     // To sort task id by last active time
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index fcb865f..49f4e5f 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -245,7 +245,7 @@
         if (mSplitBounds == null) {
             mStagePosition = STAGE_POSITION_UNDEFINED;
         } else {
-            mStagePosition = mThumbnailPosition.equals(splitInfo.leftTopBounds)
+            mStagePosition = runningTarget.taskId == splitInfo.leftTopTaskId
                     ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT;
             mPositionHelper.setSplitBounds(convertLauncherSplitBoundsToShell(mSplitBounds),
                     mStagePosition);
@@ -551,7 +551,7 @@
      * TaskView
      */
     public float getCurrentCornerRadius() {
-        float visibleRadius = mCurrentFullscreenParams.mCurrentDrawnCornerRadius;
+        float visibleRadius = mCurrentFullscreenParams.getCurrentDrawnCornerRadius();
         mTempPoint[0] = visibleRadius;
         mTempPoint[1] = 0;
         mInversePositionMatrix.mapVectors(mTempPoint);
diff --git a/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java b/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
index c63a58e..671b2ea 100644
--- a/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
+++ b/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
@@ -99,6 +99,7 @@
                         if (mDisableHorizontalSwipe
                                 && Math.abs(displacementX) > Math.abs(displacementY)) {
                             // Horizontal gesture is not allowed in this region
+                            mOnSwipeUp.onSwipeUpCancelled();
                             endTouchTracking();
                             break;
                         }
@@ -111,6 +112,7 @@
             }
 
             case ACTION_CANCEL:
+                mOnSwipeUp.onSwipeUpCancelled();
                 endTouchTracking();
                 break;
 
diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java
index 4aea1b8..a740e0b 100644
--- a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java
@@ -21,6 +21,7 @@
 
 import com.android.launcher3.Hotseat;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.systemui.unfold.dagger.UnfoldMain;
 import com.android.systemui.unfold.updates.RotationChangeProvider;
 
 /**
@@ -30,8 +31,9 @@
 
     private final QuickstepLauncher mLauncher;
 
-    public UnfoldMoveFromCenterHotseatAnimator(QuickstepLauncher launcher,
-            WindowManager windowManager, RotationChangeProvider rotationChangeProvider) {
+    public UnfoldMoveFromCenterHotseatAnimator(
+            QuickstepLauncher launcher, WindowManager windowManager,
+            @UnfoldMain RotationChangeProvider rotationChangeProvider) {
         super(windowManager, rotationChangeProvider);
         mLauncher = launcher;
     }
diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
index 0ec3ae0..6e330bb 100644
--- a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
@@ -22,6 +22,7 @@
 import com.android.launcher3.ShortcutAndWidgetContainer;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.systemui.unfold.dagger.UnfoldMain;
 import com.android.systemui.unfold.updates.RotationChangeProvider;
 
 /**
@@ -31,8 +32,9 @@
 
     private final QuickstepLauncher mLauncher;
 
-    public UnfoldMoveFromCenterWorkspaceAnimator(QuickstepLauncher launcher,
-            WindowManager windowManager, RotationChangeProvider rotationChangeProvider) {
+    public UnfoldMoveFromCenterWorkspaceAnimator(
+            QuickstepLauncher launcher, WindowManager windowManager,
+            @UnfoldMain RotationChangeProvider rotationChangeProvider) {
         super(windowManager, rotationChangeProvider);
         mLauncher = launcher;
     }
diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
index b8afd9d..c3efc3c 100644
--- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java
+++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
@@ -34,7 +34,6 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Flags;
 import com.android.launcher3.R;
-import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
 import com.android.quickstep.util.BorderAnimator;
 
@@ -136,6 +135,10 @@
      * Enable or disable showing border on focus change
      */
     public void setBorderEnabled(boolean enabled) {
+        if (mBorderEnabled == enabled) {
+            return;
+        }
+
         mBorderEnabled = enabled;
         if (mFocusBorderAnimator != null) {
             mFocusBorderAnimator.setBorderVisibility(/* visible= */
diff --git a/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java b/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
deleted file mode 100644
index 6a9a268..0000000
--- a/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.views;
-
-import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
-import static com.android.app.animation.Interpolators.LINEAR;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.LinearLayout;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.Launcher;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.uioverrides.QuickstepLauncher;
-
-/**
- * Floating view show on launcher home screen that notifies the user that an app will be launched to
- * the desktop.
- */
-public class DesktopAppSelectView extends LinearLayout {
-
-    private static final int SHOW_INITIAL_HEIGHT_DP = 7;
-    private static final int SHOW_CONTAINER_SCALE_DURATION = 333;
-    private static final int SHOW_CONTAINER_ALPHA_DURATION = 83;
-    private static final int SHOW_CONTENT_ALPHA_DELAY = 67;
-    private static final int SHOW_CONTENT_ALPHA_DURATION = 83;
-    private static final int HIDE_DURATION = 83;
-
-    private final RecentsViewContainer mContainer;
-
-    private View mText;
-    private View mCloseButton;
-    @Nullable
-    private Runnable mOnCloseCallback;
-    private AnimatorSet mShowAnimation;
-    private Animator mHideAnimation;
-
-    public DesktopAppSelectView(Context context) {
-        this(context, null);
-    }
-
-    public DesktopAppSelectView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public DesktopAppSelectView(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public DesktopAppSelectView(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        mContainer = RecentsViewContainer.containerFromContext(context);
-    }
-
-    /**
-     * Show the popup on launcher home screen
-     *
-     * @param onCloseCallback optional callback that is called when user clicks the close button
-     * @return the created view
-     */
-    public static DesktopAppSelectView show(Launcher launcher, @Nullable Runnable onCloseCallback) {
-        DesktopAppSelectView view = (DesktopAppSelectView) launcher.getLayoutInflater().inflate(
-                R.layout.floating_desktop_app_select, launcher.getDragLayer(), false);
-        view.setOnCloseClickCallback(onCloseCallback);
-        view.show();
-        return view;
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mText = findViewById(R.id.desktop_app_select_text);
-        mCloseButton = findViewById(R.id.close_button);
-        mCloseButton.setOnClickListener(v -> {
-            if (mHideAnimation == null) {
-                hide();
-                if (mOnCloseCallback != null) {
-                    mOnCloseCallback.run();
-                }
-            }
-        });
-    }
-
-    private void show() {
-        mContainer.getDragLayer().addView(this);
-
-        // Set up initial values
-        getBackground().setAlpha(0);
-        mText.setAlpha(0);
-        mCloseButton.setAlpha(0);
-        int initialHeightPx = Utilities.dpToPx(SHOW_INITIAL_HEIGHT_DP);
-        int finalHeight = getResources().getDimensionPixelSize(
-                R.dimen.desktop_mode_floating_app_select_height);
-        float initialScale = initialHeightPx / (float) finalHeight;
-        setScaleY(initialScale);
-        setPivotY(0);
-
-        // Animate the container
-        ValueAnimator containerBackground = ValueAnimator.ofInt(0, 255);
-        containerBackground.addUpdateListener(
-                animation -> getBackground().setAlpha((Integer) animation.getAnimatedValue()));
-        containerBackground.setDuration(SHOW_CONTAINER_ALPHA_DURATION);
-        containerBackground.setInterpolator(LINEAR);
-
-        ObjectAnimator containerSize = ObjectAnimator.ofFloat(this, SCALE_Y, 1f);
-        containerSize.setDuration(SHOW_CONTAINER_SCALE_DURATION);
-        containerSize.setInterpolator(EMPHASIZED_DECELERATE);
-
-        // Animate the contents
-        ObjectAnimator textAlpha = ObjectAnimator.ofFloat(mText, ALPHA, 1);
-        ObjectAnimator buttonAlpha = ObjectAnimator.ofFloat(mCloseButton, ALPHA, 1);
-        AnimatorSet contentAlpha = new AnimatorSet();
-        contentAlpha.playTogether(textAlpha, buttonAlpha);
-        contentAlpha.setStartDelay(SHOW_CONTENT_ALPHA_DELAY);
-        contentAlpha.setDuration(SHOW_CONTENT_ALPHA_DURATION);
-        contentAlpha.setInterpolator(LINEAR);
-
-        // Start the animation
-        mShowAnimation = new AnimatorSet();
-        mShowAnimation.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                super.onAnimationEnd(animation);
-                mShowAnimation = null;
-            }
-        });
-        mShowAnimation.playTogether(containerBackground, containerSize, contentAlpha);
-        mShowAnimation.start();
-    }
-
-    /**
-     * Hide the floating view
-     */
-    public void hide() {
-        if (mShowAnimation != null) {
-            mShowAnimation.cancel();
-        }
-        mHideAnimation = ObjectAnimator.ofFloat(this, ALPHA, 0);
-        mHideAnimation.setDuration(HIDE_DURATION).setInterpolator(LINEAR);
-        mHideAnimation.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                super.onAnimationEnd(animation);
-                mContainer.getDragLayer().removeView(DesktopAppSelectView.this);
-                mHideAnimation = null;
-            }
-        });
-        mHideAnimation.start();
-    }
-
-    /**
-     * Add a callback that is called when close button is clicked
-     */
-    public void setOnCloseClickCallback(@Nullable Runnable callback) {
-        mOnCloseCallback = callback;
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
deleted file mode 100644
index a0ec525..0000000
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.quickstep.views;
-
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-
-import static com.android.launcher3.LauncherState.BACKGROUND_APP;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
-
-import android.content.Context;
-import android.graphics.Point;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.RoundRectShape;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.desktop.DesktopRecentsTransitionController;
-import com.android.launcher3.util.CancellableTask;
-import com.android.launcher3.util.RunnableList;
-import com.android.quickstep.BaseContainerInterface;
-import com.android.quickstep.RecentsModel;
-import com.android.quickstep.TaskThumbnailCache;
-import com.android.quickstep.util.RecentsOrientedState;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.ThumbnailData;
-import com.android.systemui.shared.system.QuickStepContract;
-
-import kotlin.Unit;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.function.Consumer;
-
-/**
- * TaskView that contains all tasks that are part of the desktop.
- */
-// TODO(b/249371338): TaskView needs to be refactored to have better support for N tasks.
-public class DesktopTaskView extends TaskView {
-
-    private static final String TAG = DesktopTaskView.class.getSimpleName();
-
-    private static final boolean DEBUG = false;
-
-    @NonNull
-    private List<Task> mTasks = new ArrayList<>();
-
-    private final ArrayList<TaskThumbnailViewDeprecated> mSnapshotViews = new ArrayList<>();
-
-    /** Maps {@code taskIds} to corresponding {@link TaskThumbnailViewDeprecated}s */
-    private final SparseArray<TaskThumbnailViewDeprecated> mSnapshotViewMap = new SparseArray<>();
-
-    private final ArrayList<CancellableTask<?>> mPendingThumbnailRequests = new ArrayList<>();
-
-    private final TaskView.FullscreenDrawParams mSnapshotDrawParams;
-
-    private View mBackgroundView;
-
-    private int mChildCountAtInflation;
-
-    private final PointF mTempPointF = new PointF();
-
-    public DesktopTaskView(Context context) {
-        this(context, null);
-    }
-
-    public DesktopTaskView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public DesktopTaskView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-
-        mSnapshotDrawParams = new FullscreenDrawParams(context) {
-            @Override
-            public float computeTaskCornerRadius(Context context) {
-                return QuickStepContract.getWindowCornerRadius(context);
-            }
-
-            @Override
-            public float computeWindowCornerRadius(Context context) {
-                return QuickStepContract.getWindowCornerRadius(context);
-            }
-        };
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-
-        mBackgroundView = findViewById(R.id.background);
-
-        int topMarginPx =
-                mContainer.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
-        FrameLayout.LayoutParams params = (LayoutParams) mBackgroundView.getLayoutParams();
-        params.topMargin = topMarginPx;
-        mBackgroundView.setLayoutParams(params);
-
-        float[] outerRadii = new float[8];
-        Arrays.fill(outerRadii, getTaskCornerRadius());
-        RoundRectShape shape = new RoundRectShape(outerRadii, null, null);
-        ShapeDrawable background = new ShapeDrawable(shape);
-        background.setTint(getResources().getColor(android.R.color.system_neutral2_300,
-                getContext().getTheme()));
-        mBackgroundView.setBackground(background);
-
-        Drawable icon = getResources().getDrawable(R.drawable.ic_desktop, getContext().getTheme());
-        Drawable iconBackground = getResources().getDrawable(R.drawable.bg_circle,
-                getContext().getTheme());
-        setIcon(mIconView, new LayerDrawable(new Drawable[]{iconBackground, icon}));
-
-        mChildCountAtInflation = getChildCount();
-    }
-
-    @Override
-    protected Unit updateBorderBounds(@NonNull Rect bounds) {
-        bounds.set(mBackgroundView.getLeft(), mBackgroundView.getTop(), mBackgroundView.getRight(),
-                mBackgroundView.getBottom());
-        return Unit.INSTANCE;
-    }
-
-    @Override
-    public void bind(Task task, RecentsOrientedState orientedState) {
-        bind(Collections.singletonList(task), orientedState);
-    }
-
-    /**
-     * Updates this desktop task to the gives task list defined in {@code tasks}
-     */
-    public void bind(List<Task> tasks, RecentsOrientedState orientedState) {
-        if (DEBUG) {
-            StringBuilder sb = new StringBuilder();
-            sb.append("bind tasks=").append(tasks.size()).append("\n");
-            for (Task task : tasks) {
-                sb.append(" key=").append(task.key).append("\n");
-            }
-            Log.d(TAG, sb.toString());
-        }
-        cancelPendingLoadTasks();
-
-        mTasks = new ArrayList<>(tasks);
-        mSnapshotViewMap.clear();
-
-        // Ensure there are equal number of snapshot views and tasks.
-        // More tasks than views, add views. More views than tasks, remove views.
-        // TODO(b/251586230): use a ViewPool for creating TaskThumbnailViews
-        if (mSnapshotViews.size() > mTasks.size()) {
-            int diff = mSnapshotViews.size() - mTasks.size();
-            for (int i = 0; i < diff; i++) {
-                TaskThumbnailViewDeprecated snapshotView = mSnapshotViews.remove(0);
-                removeView(snapshotView);
-            }
-        } else if (mSnapshotViews.size() < mTasks.size()) {
-            int diff = mTasks.size() - mSnapshotViews.size();
-            for (int i = 0; i < diff; i++) {
-                TaskThumbnailViewDeprecated snapshotView =
-                        new TaskThumbnailViewDeprecated(getContext());
-                mSnapshotViews.add(snapshotView);
-                // Add snapshots from to position after the initial child views.
-                addView(snapshotView, mChildCountAtInflation,
-                        new LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
-            }
-        }
-
-        for (int i = 0; i < mTasks.size(); i++) {
-            Task task = mTasks.get(i);
-            TaskThumbnailViewDeprecated snapshotView = mSnapshotViews.get(i);
-            snapshotView.bind(task);
-            mSnapshotViewMap.put(task.key.id, snapshotView);
-        }
-
-        updateTaskIdContainer();
-        updateTaskIdAttributeContainer();
-
-        setOrientationState(orientedState);
-    }
-
-    private void updateTaskIdContainer() {
-        // TODO(b/249371338): TaskView expects the array to have at least 2 elements.
-        // At least 2 elements in the array
-        mTaskIdContainer = new int[Math.max(mTasks.size(), 2)];
-        for (int i = 0; i < mTasks.size(); i++) {
-            mTaskIdContainer[i] = mTasks.get(i).key.id;
-        }
-    }
-
-    private void updateTaskIdAttributeContainer() {
-        // TODO(b/249371338): TaskView expects the array to have at least 2 elements.
-        // At least 2 elements in the array
-        mTaskIdAttributeContainer = new TaskIdAttributeContainer[Math.max(mTasks.size(), 2)];
-        for (int i = 0; i < mTasks.size(); i++) {
-            Task task = mTasks.get(i);
-            TaskThumbnailViewDeprecated thumbnailView = mSnapshotViewMap.get(task.key.id);
-            mTaskIdAttributeContainer[i] = createAttributeContainer(task, thumbnailView);
-        }
-    }
-
-    private TaskIdAttributeContainer createAttributeContainer(Task task,
-            TaskThumbnailViewDeprecated thumbnailView) {
-        return new TaskIdAttributeContainer(task, thumbnailView, mIconView,
-                STAGE_POSITION_UNDEFINED);
-    }
-
-    @Nullable
-    @Override
-    public Task getTask() {
-        // TODO(b/249371338): returning first task. This won't work well with multiple tasks.
-        return mTasks.size() > 0 ? mTasks.get(0) : null;
-    }
-
-    @Override
-    public TaskThumbnailViewDeprecated getThumbnail() {
-        // TODO(b/249371338): returning single thumbnail. This won't work well with multiple tasks.
-        Task task = getTask();
-        if (task != null) {
-            return mSnapshotViewMap.get(task.key.id);
-        }
-        // Return the place holder snapshot views. Callers expect this to be non-null
-        return mTaskThumbnailViewDeprecated;
-    }
-
-    @Override
-    public boolean containsTaskId(int taskId) {
-        // Thumbnail map contains taskId -> thumbnail map. Use the keys for contains
-        return mSnapshotViewMap.contains(taskId);
-    }
-
-    @Override
-    public void onTaskListVisibilityChanged(boolean visible, int changes) {
-        cancelPendingLoadTasks();
-        if (visible) {
-            RecentsModel model = RecentsModel.INSTANCE.get(getContext());
-            TaskThumbnailCache thumbnailCache = model.getThumbnailCache();
-
-            if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
-                for (Task task : mTasks) {
-                    CancellableTask<?> thumbLoadRequest =
-                            thumbnailCache.updateThumbnailInBackground(task, thumbnailData -> {
-                                TaskThumbnailViewDeprecated thumbnailView =
-                                        mSnapshotViewMap.get(task.key.id);
-                                if (thumbnailView != null) {
-                                    thumbnailView.setThumbnail(task, thumbnailData);
-                                }
-                            });
-                    if (thumbLoadRequest != null) {
-                        mPendingThumbnailRequests.add(thumbLoadRequest);
-                    }
-                }
-            }
-        } else {
-            if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
-                for (Task task : mTasks) {
-                    TaskThumbnailViewDeprecated thumbnailView = mSnapshotViewMap.get(task.key.id);
-                    if (thumbnailView != null) {
-                        thumbnailView.setThumbnail(null, null);
-                    }
-                    // Reset the task thumbnail ref
-                    task.thumbnail = null;
-                }
-            }
-        }
-    }
-
-    @Override
-    protected void setThumbnailOrientation(RecentsOrientedState orientationState) {
-        // no-op
-    }
-
-    @Override
-    protected void cancelPendingLoadTasks() {
-        for (CancellableTask<?> cancellableTask : mPendingThumbnailRequests) {
-            cancellableTask.cancel();
-        }
-        mPendingThumbnailRequests.clear();
-    }
-
-    @Nullable
-    @Override
-    public RunnableList launchTaskAnimated() {
-        RunnableList endCallback = new RunnableList();
-
-        RecentsView recentsView = getRecentsView();
-        DesktopRecentsTransitionController recentsController =
-                recentsView.getDesktopRecentsController();
-        if (recentsController != null) {
-            recentsController.launchDesktopFromRecents(this, success -> {
-                endCallback.executeAllAndDestroy();
-            });
-        }
-
-        // Callbacks get run from recentsView for case when recents animation already running
-        recentsView.addSideTaskLaunchCallback(endCallback);
-        return endCallback;
-    }
-
-    @Override
-    public void launchTask(@NonNull Consumer<Boolean> callback, boolean isQuickswitch) {
-        launchTasks();
-        callback.accept(true);
-    }
-
-    @Override
-    public boolean isDesktopTask() {
-        return true;
-    }
-
-    @Override
-    void refreshThumbnails(@Nullable HashMap<Integer, ThumbnailData> thumbnailDatas) {
-        // Sets new thumbnails based on the incoming data and refreshes the rest.
-        // Create a copy of the thumbnail map, so we can track thumbnails that need refreshing.
-        SparseArray<TaskThumbnailViewDeprecated> thumbnailsToRefresh = mSnapshotViewMap.clone();
-        if (thumbnailDatas != null) {
-            for (Task task : mTasks) {
-                int key = task.key.id;
-                TaskThumbnailViewDeprecated thumbnailView = thumbnailsToRefresh.get(key);
-                ThumbnailData thumbnailData = thumbnailDatas.get(key);
-                if (thumbnailView != null && thumbnailData != null) {
-                    thumbnailView.setThumbnail(task, thumbnailData);
-                    // Remove this thumbnail from the list that should be refreshed.
-                    thumbnailsToRefresh.remove(key);
-                }
-            }
-        }
-
-        // Refresh the rest that were not updated.
-        for (int i = 0; i < thumbnailsToRefresh.size(); i++) {
-            thumbnailsToRefresh.valueAt(i).refresh();
-        }
-    }
-
-    @Override
-    public TaskThumbnailViewDeprecated[] getThumbnails() {
-        TaskThumbnailViewDeprecated[] thumbnails =
-                new TaskThumbnailViewDeprecated[mSnapshotViewMap.size()];
-        for (int i = 0; i < thumbnails.length; i++) {
-            thumbnails[i] = mSnapshotViewMap.valueAt(i);
-        }
-        return thumbnails;
-    }
-
-    @Override
-    public void onRecycle() {
-        resetPersistentViewTransforms();
-        // Clear any references to the thumbnail (it will be re-read either from the cache or the
-        // system on next bind)
-        for (Task task : mTasks) {
-            TaskThumbnailViewDeprecated thumbnailView = mSnapshotViewMap.get(task.key.id);
-            if (thumbnailView != null) {
-                thumbnailView.setThumbnail(task, null);
-            }
-        }
-        setOverlayEnabled(false);
-        onTaskListVisibilityChanged(false);
-        setVisibility(VISIBLE);
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        int containerWidth = MeasureSpec.getSize(widthMeasureSpec);
-        int containerHeight = MeasureSpec.getSize(heightMeasureSpec);
-
-        setMeasuredDimension(containerWidth, containerHeight);
-
-        int thumbnailTopMarginPx = mContainer.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
-        containerHeight -= thumbnailTopMarginPx;
-
-        int thumbnails = mSnapshotViewMap.size();
-        if (thumbnails == 0) {
-            return;
-        }
-
-        BaseContainerInterface.getTaskDimension(mContext, mContainer.getDeviceProfile(),
-                mTempPointF);
-        int windowWidth = (int) mTempPointF.x;
-        int windowHeight = (int) mTempPointF.y;
-
-        float scaleWidth = containerWidth / (float) windowWidth;
-        float scaleHeight = containerHeight / (float) windowHeight;
-
-        if (DEBUG) {
-            Log.d(TAG,
-                    "onMeasure: container=[" + containerWidth + "," + containerHeight + "] window=["
-                            + windowWidth + "," + windowHeight + "] scale=[" + scaleWidth + ","
-                            + scaleHeight + "]");
-        }
-
-        // Desktop tile is a shrunk down version of launcher and freeform task thumbnails.
-        for (int i = 0; i < mTasks.size(); i++) {
-            Task task = mTasks.get(i);
-            Rect taskSize = task.appBounds;
-            if (taskSize == null) {
-                // Default to quarter of the desktop if we did not get app bounds.
-                taskSize = new Rect(0, 0, windowWidth / 4, windowHeight / 4);
-            }
-
-            int thumbWidth = (int) (taskSize.width() * scaleWidth);
-            int thumbHeight = (int) (taskSize.height() * scaleHeight);
-
-            TaskThumbnailViewDeprecated thumbnailView = mSnapshotViewMap.get(task.key.id);
-            if (thumbnailView != null) {
-                thumbnailView.measure(MeasureSpec.makeMeasureSpec(thumbWidth, MeasureSpec.EXACTLY),
-                        MeasureSpec.makeMeasureSpec(thumbHeight, MeasureSpec.EXACTLY));
-
-                // Position the task to the same position as it would be on the desktop
-                Point positionInParent = task.positionInParent;
-                if (positionInParent == null) {
-                    positionInParent = new Point(0, 0);
-                }
-                int taskX = (int) (positionInParent.x * scaleWidth);
-                int taskY = (int) (positionInParent.y * scaleHeight);
-                // move task down by margin size
-                taskY += thumbnailTopMarginPx;
-                thumbnailView.setX(taskX);
-                thumbnailView.setY(taskY);
-
-                if (DEBUG) {
-                    Log.d(TAG, "onMeasure: task=" + task.key + " thumb=[" + thumbWidth + ","
-                            + thumbHeight + "]" + " pos=[" + taskX + "," + taskY + "]");
-                }
-            }
-        }
-    }
-
-    @Override
-    public void setOverlayEnabled(boolean overlayEnabled) {
-        // TODO(b/330685808) support overlay for Screenshot action
-    }
-
-    @Override
-    public void setFullscreenProgress(float progress) {
-        // TODO(b/249371338): this copies parent implementation and makes it work for N thumbs
-        progress = Utilities.boundToRange(progress, 0, 1);
-        mFullscreenProgress = progress;
-        mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
-        if (mFullscreenProgress > 0) {
-            // Don't show background while we are transitioning to/from fullscreen
-            mBackgroundView.setVisibility(INVISIBLE);
-        } else {
-            mBackgroundView.setVisibility(VISIBLE);
-        }
-        for (int i = 0; i < mSnapshotViewMap.size(); i++) {
-            TaskThumbnailViewDeprecated thumbnailView = mSnapshotViewMap.valueAt(i);
-            thumbnailView.getTaskOverlay().setFullscreenProgress(progress);
-        }
-        // Animate icons and DWB banners in/out, except in QuickSwitch state, when tiles are
-        // oversized and banner would look disproportionately large.
-        if (mContainer.<RecentsView<?, ?>>getOverviewPanel().getStateManager().getState()
-                != BACKGROUND_APP) {
-            setIconsAndBannersTransitionProgress(progress, true);
-        }
-        updateSnapshotRadius();
-    }
-
-    @Override
-    protected void updateSnapshotRadius() {
-        super.updateSnapshotRadius();
-        for (int i = 0; i < mSnapshotViewMap.size(); i++) {
-            if (i == 0) {
-                // All snapshots share the same params. Only update it with the first snapshot.
-                updateFullscreenParams(mSnapshotDrawParams);
-            }
-            mSnapshotViewMap.valueAt(i).setFullscreenParams(mSnapshotDrawParams);
-        }
-    }
-
-    @Override
-    public void setColorTint(float amount, int tintColor) {
-        for (int i = 0; i < mSnapshotViewMap.size(); i++) {
-            mSnapshotViewMap.valueAt(i).setDimAlpha(amount);
-        }
-    }
-
-    @Override
-    protected void applyThumbnailSplashAlpha() {
-        for (int i = 0; i < mSnapshotViewMap.size(); i++) {
-            mSnapshotViewMap.valueAt(i).setSplashAlpha(mTaskThumbnailSplashAlpha);
-        }
-    }
-
-    @Override
-    void setThumbnailVisibility(int visibility, int taskId) {
-        for (int i = 0; i < mSnapshotViewMap.size(); i++) {
-            mSnapshotViewMap.valueAt(i).setVisibility(visibility);
-        }
-    }
-
-    @Override
-    protected boolean confirmSecondSplitSelectApp() {
-        // Desktop tile can't be in split screen
-        return false;
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt b/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
new file mode 100644
index 0000000..936f6a1
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.views
+
+import android.content.Context
+import android.graphics.Point
+import android.graphics.PointF
+import android.graphics.Rect
+import android.graphics.drawable.LayerDrawable
+import android.graphics.drawable.ShapeDrawable
+import android.graphics.drawable.shapes.RoundRectShape
+import android.util.AttributeSet
+import android.util.Log
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.view.updateLayoutParams
+import com.android.launcher3.R
+import com.android.launcher3.util.RunnableList
+import com.android.launcher3.util.SplitConfigurationOptions
+import com.android.launcher3.util.TransformingTouchDelegate
+import com.android.launcher3.util.ViewPool
+import com.android.launcher3.util.rects.set
+import com.android.quickstep.BaseContainerInterface
+import com.android.quickstep.TaskOverlayFactory
+import com.android.quickstep.util.RecentsOrientedState
+import com.android.systemui.shared.recents.model.Task
+
+/** TaskView that contains all tasks that are part of the desktop. */
+class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
+    TaskView(context, attrs) {
+
+    private val snapshotDrawParams =
+        object : FullscreenDrawParams(context) {
+            // DesktopTaskView thumbnail's corner radius is independent of fullscreenProgress.
+            override fun computeTaskCornerRadius(context: Context) =
+                computeWindowCornerRadius(context)
+        }
+    private val taskThumbnailViewPool =
+        ViewPool<TaskThumbnailViewDeprecated>(
+            context,
+            this,
+            R.layout.task_thumbnail,
+            VIEW_POOL_MAX_SIZE,
+            VIEW_POOL_INITIAL_SIZE
+        )
+    private val tempPointF = PointF()
+    private val tempRect = Rect()
+    private lateinit var backgroundView: View
+    private lateinit var iconView: TaskViewIcon
+    private var childCountAtInflation = 0
+
+    override fun onFinishInflate() {
+        super.onFinishInflate()
+        backgroundView =
+            findViewById<View>(R.id.background)!!.apply {
+                updateLayoutParams<LayoutParams> {
+                    topMargin = container.deviceProfile.overviewTaskThumbnailTopMarginPx
+                }
+                background =
+                    ShapeDrawable(RoundRectShape(FloatArray(8) { taskCornerRadius }, null, null))
+                        .apply {
+                            setTint(
+                                resources.getColor(
+                                    android.R.color.system_neutral2_300,
+                                    context.theme
+                                )
+                            )
+                        }
+            }
+        iconView =
+            getOrInflateIconView(R.id.icon).apply {
+                val iconBackground = resources.getDrawable(R.drawable.bg_circle, context.theme)
+                val icon = resources.getDrawable(R.drawable.ic_desktop, context.theme)
+                setIcon(this, LayerDrawable(arrayOf(iconBackground, icon)))
+            }
+        childCountAtInflation = childCount
+    }
+
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+        val containerWidth = MeasureSpec.getSize(widthMeasureSpec)
+        var containerHeight = MeasureSpec.getSize(heightMeasureSpec)
+        setMeasuredDimension(containerWidth, containerHeight)
+
+        if (taskContainers.isEmpty()) {
+            return
+        }
+
+        val thumbnailTopMarginPx = container.deviceProfile.overviewTaskThumbnailTopMarginPx
+        containerHeight -= thumbnailTopMarginPx
+
+        BaseContainerInterface.getTaskDimension(mContext, container.deviceProfile, tempPointF)
+        val windowWidth = tempPointF.x.toInt()
+        val windowHeight = tempPointF.y.toInt()
+        val scaleWidth = containerWidth / windowWidth.toFloat()
+        val scaleHeight = containerHeight / windowHeight.toFloat()
+        if (DEBUG) {
+            Log.d(
+                TAG,
+                "onMeasure: container=[$containerWidth,$containerHeight] " +
+                    "window=[$windowWidth,$windowHeight] scale=[$scaleWidth,$scaleHeight]"
+            )
+        }
+
+        // Desktop tile is a shrunk down version of launcher and freeform task thumbnails.
+        taskContainers.forEach {
+            // Default to quarter of the desktop if we did not get app bounds.
+            val taskSize =
+                it.task.appBounds
+                    ?: tempRect.apply {
+                        left = 0
+                        top = 0
+                        right = windowWidth / 4
+                        bottom = windowHeight / 4
+                    }
+            val thumbWidth = (taskSize.width() * scaleWidth).toInt()
+            val thumbHeight = (taskSize.height() * scaleHeight).toInt()
+            it.thumbnailViewDeprecated.measure(
+                MeasureSpec.makeMeasureSpec(thumbWidth, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(thumbHeight, MeasureSpec.EXACTLY)
+            )
+
+            // Position the task to the same position as it would be on the desktop
+            val positionInParent = it.task.positionInParent ?: ORIGIN
+            val taskX = (positionInParent.x * scaleWidth).toInt()
+            var taskY = (positionInParent.y * scaleHeight).toInt()
+            // move task down by margin size
+            taskY += thumbnailTopMarginPx
+            it.thumbnailViewDeprecated.x = taskX.toFloat()
+            it.thumbnailViewDeprecated.y = taskY.toFloat()
+            if (DEBUG) {
+                Log.d(
+                    TAG,
+                    "onMeasure: task=${it.task.key} thumb=[$thumbWidth,$thumbHeight]" +
+                        " pos=[$taskX,$taskY]"
+                )
+            }
+        }
+    }
+
+    override fun onRecycle() {
+        super.onRecycle()
+        visibility = VISIBLE
+    }
+
+    /** Updates this desktop task to the gives task list defined in `tasks` */
+    fun bind(
+        tasks: List<Task>,
+        orientedState: RecentsOrientedState,
+        taskOverlayFactory: TaskOverlayFactory
+    ) {
+        if (DEBUG) {
+            val sb = StringBuilder()
+            sb.append("bind tasks=").append(tasks.size).append("\n")
+            tasks.forEach { sb.append(" key=${it.key}\n") }
+            Log.d(TAG, sb.toString())
+        }
+        cancelPendingLoadTasks()
+
+        if (!isTaskContainersInitialized()) {
+            taskContainers = arrayListOf()
+        }
+        val taskContainers = taskContainers as ArrayList
+        taskContainers.ensureCapacity(tasks.size)
+        tasks.forEachIndexed { index, task ->
+            val thumbnailViewDeprecated: TaskThumbnailViewDeprecated
+            if (index >= taskContainers.size) {
+                thumbnailViewDeprecated = taskThumbnailViewPool.view
+                // Add thumbnailView from to position after the initial child views.
+                addView(
+                    thumbnailViewDeprecated,
+                    childCountAtInflation,
+                    LayoutParams(
+                        ViewGroup.LayoutParams.WRAP_CONTENT,
+                        ViewGroup.LayoutParams.WRAP_CONTENT
+                    )
+                )
+            } else {
+                thumbnailViewDeprecated = taskContainers[index].thumbnailViewDeprecated
+            }
+            val taskContainer =
+                TaskContainer(
+                        task,
+                        // TODO(b/338360089): Support new TTV for DesktopTaskView
+                        thumbnailView = null,
+                        thumbnailViewDeprecated,
+                        iconView,
+                        TransformingTouchDelegate(iconView.asView()),
+                        SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
+                        digitalWellBeingToast = null,
+                        showWindowsView = null,
+                        taskOverlayFactory
+                    )
+                    .apply { thumbnailViewDeprecated.bind(task, overlay) }
+            if (index >= taskContainers.size) {
+                taskContainers.add(taskContainer)
+            } else {
+                taskContainers[index] = taskContainer
+            }
+        }
+        repeat(taskContainers.size - tasks.size) {
+            with(taskContainers.removeLast()) {
+                removeView(thumbnailViewDeprecated)
+                taskThumbnailViewPool.recycle(thumbnailViewDeprecated)
+            }
+        }
+
+        setOrientationState(orientedState)
+    }
+
+    override fun needsUpdate(dataChange: Int, flag: Int) =
+        if (flag == FLAG_UPDATE_THUMBNAIL) super.needsUpdate(dataChange, flag) else false
+
+    // thumbnailView is laid out differently and is handled in onMeasure
+    override fun updateThumbnailSize() {}
+
+    override fun getThumbnailBounds(bounds: Rect, relativeToDragLayer: Boolean) {
+        if (relativeToDragLayer) {
+            container.dragLayer.getDescendantRectRelativeToSelf(backgroundView, bounds)
+        } else {
+            bounds.set(backgroundView)
+        }
+    }
+
+    override fun launchTaskAnimated(): RunnableList? {
+        val recentsView = recentsView ?: return null
+        val endCallback = RunnableList()
+        val desktopController = recentsView.desktopRecentsController
+        checkNotNull(desktopController) { "recentsController is null" }
+        desktopController.launchDesktopFromRecents(this) { endCallback.executeAllAndDestroy() }
+        Log.d(TAG, "launchTaskAnimated - launchDesktopFromRecents: ${taskIds.contentToString()}")
+
+        // Callbacks get run from recentsView for case when recents animation already running
+        recentsView.addSideTaskLaunchCallback(endCallback)
+        return endCallback
+    }
+
+    override fun launchTask(callback: (launched: Boolean) -> Unit, isQuickSwitch: Boolean) {
+        launchTasks()
+        callback(true)
+    }
+
+    // Desktop tile can't be in split screen
+    override fun confirmSecondSplitSelectApp(): Boolean = false
+
+    // TODO(b/330685808) support overlay for Screenshot action
+    override fun setOverlayEnabled(overlayEnabled: Boolean) {}
+
+    override fun onFullscreenProgressChanged(fullscreenProgress: Float) {
+        // Don't show background while we are transitioning to/from fullscreen
+        backgroundView.visibility = if (fullscreenProgress > 0) INVISIBLE else VISIBLE
+    }
+
+    override fun updateCurrentFullscreenParams() {
+        super.updateCurrentFullscreenParams()
+        updateFullscreenParams(snapshotDrawParams)
+    }
+
+    override fun getThumbnailFullscreenParams() = snapshotDrawParams
+
+    companion object {
+        private const val TAG = "DesktopTaskView"
+        private const val DEBUG = false
+        private const val VIEW_POOL_MAX_SIZE = 10
+        // As DesktopTaskView is inflated in background, use initialSize=0 to avoid initPool.
+        private const val VIEW_POOL_INITIAL_SIZE = 0
+        private val ORIGIN = Point(0, 0)
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
index 82ba30b..a8ebe51 100644
--- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -79,7 +79,7 @@
     static final Intent OPEN_APP_USAGE_SETTINGS_TEMPLATE = new Intent(ACTION_APP_USAGE_SETTINGS);
     static final int MINUTE_MS = 60000;
 
-    private static final String TAG = DigitalWellBeingToast.class.getSimpleName();
+    private static final String TAG = "DigitalWellBeingToast";
 
     private final RecentsViewContainer mContainer;
     private final TaskView mTaskView;
@@ -320,12 +320,12 @@
                 (FrameLayout.LayoutParams) mBanner.getLayoutParams();
         DeviceProfile deviceProfile = mContainer.getDeviceProfile();
         layoutParams.bottomMargin = ((ViewGroup.MarginLayoutParams)
-                mTaskView.getThumbnail().getLayoutParams()).bottomMargin;
+                mTaskView.getFirstThumbnailViewDeprecated().getLayoutParams()).bottomMargin;
         RecentsPagedOrientationHandler orientationHandler = mTaskView.getPagedOrientationHandler();
         Pair<Float, Float> translations = orientationHandler
                 .getDwbLayoutTranslations(mTaskView.getMeasuredWidth(),
                         mTaskView.getMeasuredHeight(), mSplitBounds, deviceProfile,
-                        mTaskView.getThumbnails(), mTask.key.id, mBanner);
+                        mTaskView.getThumbnailViews(), mTask.key.id, mBanner);
         mSplitOffsetTranslationX = translations.first;
         mSplitOffsetTranslationY = translations.second;
         updateTranslationY();
diff --git a/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt b/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt
index 0d49309..e024995 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt
+++ b/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt
@@ -36,17 +36,18 @@
  * animation. Consists of a rectangular background that splits into two, and two app icons that
  * increase in size during the animation.
  */
-class FloatingAppPairBackground(
-    context: Context,
-    private val floatingView: FloatingAppPairView, // the view that we will draw this background on
-    private val appIcon1: Drawable,
-    private val appIcon2: Drawable,
-    dividerPos: Int
+open class FloatingAppPairBackground(
+        context: Context,
+        // the view that we will draw this background on
+        protected val floatingView: FloatingAppPairView,
+        private val appIcon1: Drawable,
+        private val appIcon2: Drawable?,
+        dividerPos: Int
 ) : Drawable() {
     companion object {
         // Design specs -- app icons start small and expand during the animation
-        private val STARTING_ICON_SIZE_PX = Utilities.dpToPx(22f)
-        private val ENDING_ICON_SIZE_PX = Utilities.dpToPx(66f)
+        internal val STARTING_ICON_SIZE_PX = Utilities.dpToPx(22f)
+        internal val ENDING_ICON_SIZE_PX = Utilities.dpToPx(66f)
 
         // Null values to use with drawDoubleRoundRect(), since there doesn't seem to be any other
         // API for drawing rectangles with 4 different corner radii.
@@ -58,13 +59,13 @@
     private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG)
 
     // Animation interpolators
-    private val expandXInterpolator: Interpolator
-    private val expandYInterpolator: Interpolator
+    protected val expandXInterpolator: Interpolator
+    protected val expandYInterpolator: Interpolator
     private val cellSplitInterpolator: Interpolator
-    private val iconFadeInterpolator: Interpolator
+    protected val iconFadeInterpolator: Interpolator
 
     // Device-specific measurements
-    private val deviceCornerRadius: Float
+    protected val deviceCornerRadius: Float
     private val deviceHalfDividerSize: Float
     private val desiredSplitRatio: Float
 
@@ -214,7 +215,7 @@
         canvas.save()
         canvas.translate(changingIcon2Left, changingIconTop)
         canvas.scale(changingIconScaleX, changingIconScaleY)
-        appIcon2.alpha = changingIconAlpha
+        appIcon2!!.alpha = changingIconAlpha
         appIcon2.draw(canvas)
         canvas.restore()
     }
@@ -312,7 +313,7 @@
         canvas.save()
         canvas.translate(changingIconLeft, changingIcon2Top)
         canvas.scale(changingIconScaleX, changingIconScaleY)
-        appIcon2.alpha = changingIconAlpha
+        appIcon2!!.alpha = changingIconAlpha
         appIcon2.draw(canvas)
         canvas.restore()
     }
@@ -325,7 +326,7 @@
      * @param radii An array of 8 radii for the corners: top left x, top left y, top right x, top
      *   right y, bottom right x, and so on.
      */
-    private fun drawCustomRoundedRect(c: Canvas, rect: RectF, radii: FloatArray) {
+    protected fun drawCustomRoundedRect(c: Canvas, rect: RectF, radii: FloatArray) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
             // Canvas.drawDoubleRoundRect is supported from Q onward
             c.drawDoubleRoundRect(rect, radii, EMPTY_RECT, ARRAY_OF_ZEROES, backgroundPaint)
diff --git a/quickstep/src/com/android/quickstep/views/FloatingAppPairView.kt b/quickstep/src/com/android/quickstep/views/FloatingAppPairView.kt
index e90aa13..e8d1cc1 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingAppPairView.kt
+++ b/quickstep/src/com/android/quickstep/views/FloatingAppPairView.kt
@@ -40,8 +40,8 @@
         fun getFloatingAppPairView(
             launcher: StatefulActivity<*>,
             originalView: View,
-            appIcon1: Drawable,
-            appIcon2: Drawable,
+            appIcon1: Drawable?,
+            appIcon2: Drawable?,
             dividerPos: Int
         ): FloatingAppPairView {
             val dragLayer: ViewGroup = launcher.getDragLayer()
@@ -64,8 +64,8 @@
     fun init(
         launcher: StatefulActivity<*>,
         originalView: View,
-        appIcon1: Drawable,
-        appIcon2: Drawable,
+        appIcon1: Drawable?,
+        appIcon2: Drawable?,
         dividerPos: Int
     ) {
         val viewBounds = Rect(0, 0, originalView.width, originalView.height)
@@ -92,7 +92,14 @@
         layoutParams = lp
 
         // Prepare to draw app pair icon background
-        background = FloatingAppPairBackground(context, this, appIcon1, appIcon2, dividerPos)
+        background = if (appIcon1 == null || appIcon2 == null) {
+            val iconToAnimate = appIcon1 ?: appIcon2
+            checkNotNull(iconToAnimate)
+            FloatingFullscreenAppPairBackground(context, this, iconToAnimate,
+                    dividerPos)
+        } else {
+            FloatingAppPairBackground(context, this, appIcon1, appIcon2, dividerPos)
+        }
         background.setBounds(0, 0, lp.width, lp.height)
     }
 
diff --git a/quickstep/src/com/android/quickstep/views/FloatingFullscreenAppPairBackground.kt b/quickstep/src/com/android/quickstep/views/FloatingFullscreenAppPairBackground.kt
new file mode 100644
index 0000000..8cd997f
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/FloatingFullscreenAppPairBackground.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.views
+
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.RectF
+import android.graphics.drawable.Drawable
+
+class FloatingFullscreenAppPairBackground(
+        context: Context,
+        floatingView: FloatingAppPairView,
+        private val iconToLaunch: Drawable,
+        dividerPos: Int) :
+        FloatingAppPairBackground(
+                context,
+                floatingView,
+                iconToLaunch,
+                null /*appIcon2*/,
+                dividerPos
+) {
+
+    /** Animates the background as if launching a fullscreen task. */
+    override fun draw(canvas: Canvas) {
+        val progress = floatingView.progress
+
+        // Since the entire floating app pair surface is scaling up during this animation, we
+        // scale down most of these drawn elements so that they appear the proper size on-screen.
+        val scaleFactorX = floatingView.scaleX
+        val scaleFactorY = floatingView.scaleY
+
+        // Get the bounds where we will draw the background image
+        val width = bounds.width().toFloat()
+        val height = bounds.height().toFloat()
+
+        // Get device-specific measurements
+        val cornerRadiusX = deviceCornerRadius / scaleFactorX
+        val cornerRadiusY = deviceCornerRadius / scaleFactorY
+
+        // Draw background
+        drawCustomRoundedRect(
+                canvas,
+                RectF(0f, 0f, width, height),
+                floatArrayOf(
+                        cornerRadiusX,
+                        cornerRadiusY,
+                        cornerRadiusX,
+                        cornerRadiusY,
+                        cornerRadiusX,
+                        cornerRadiusY,
+                        cornerRadiusX,
+                        cornerRadiusY,
+                )
+        )
+
+        // Calculate changing measurements for icon.
+        val changingIconSizeX =
+                (STARTING_ICON_SIZE_PX +
+                        ((ENDING_ICON_SIZE_PX - STARTING_ICON_SIZE_PX) *
+                                expandXInterpolator.getInterpolation(progress))) / scaleFactorX
+        val changingIconSizeY =
+                (STARTING_ICON_SIZE_PX +
+                        ((ENDING_ICON_SIZE_PX - STARTING_ICON_SIZE_PX) *
+                                expandYInterpolator.getInterpolation(progress))) / scaleFactorY
+
+        val changingIcon1Left = (width / 2f) - (changingIconSizeX / 2f)
+        val changingIconTop = (height / 2f) - (changingIconSizeY / 2f)
+        val changingIconScaleX = changingIconSizeX / iconToLaunch.bounds.width()
+        val changingIconScaleY = changingIconSizeY / iconToLaunch.bounds.height()
+        val changingIconAlpha =
+                (255 - (255 * iconFadeInterpolator.getInterpolation(progress))).toInt()
+
+        // Draw icon
+        canvas.save()
+        canvas.translate(changingIcon1Left, changingIconTop)
+        canvas.scale(changingIconScaleX, changingIconScaleY)
+        iconToLaunch.alpha = changingIconAlpha
+        iconToLaunch.draw(canvas)
+        canvas.restore()
+    }
+}
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
deleted file mode 100644
index a593712..0000000
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ /dev/null
@@ -1,540 +0,0 @@
-package com.android.quickstep.views;
-
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-
-import static com.android.launcher3.Flags.enableOverviewIconMenu;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.quickstep.util.SplitScreenUtils.convertLauncherSplitBoundsToShell;
-
-import android.content.Context;
-import android.graphics.Point;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Pair;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewStub;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.jank.Cuj;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.util.CancellableTask;
-import com.android.launcher3.util.RunnableList;
-import com.android.launcher3.util.SplitConfigurationOptions;
-import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds;
-import com.android.launcher3.util.TransformingTouchDelegate;
-import com.android.quickstep.RecentsModel;
-import com.android.quickstep.TaskIconCache;
-import com.android.quickstep.TaskThumbnailCache;
-import com.android.quickstep.util.RecentsOrientedState;
-import com.android.quickstep.util.SplitSelectStateController;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.ThumbnailData;
-import com.android.systemui.shared.recents.utilities.PreviewPositionHelper;
-import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
-import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
-
-import kotlin.Unit;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.function.Consumer;
-
-/**
- * TaskView that contains and shows thumbnails for not one, BUT TWO(!!) tasks
- *
- * That's right. If you call within the next 5 minutes we'll go ahead and double your order and
- * send you !! TWO !! Tasks along with their TaskThumbnailViews complimentary. On. The. House.
- * And not only that, we'll even clean up your thumbnail request if you don't like it.
- * All the benefits of one TaskView, except DOUBLED!
- *
- * (Icon loading sold separately, fees may apply. Shipping & Handling for Overlays not included).
- */
-public class GroupedTaskView extends TaskView {
-
-    private static final String TAG = TaskView.class.getSimpleName();
-    @Nullable
-    private Task mSecondaryTask;
-    // TODO(b/336612373): Support new TTV for GroupedTaskView
-    private TaskThumbnailViewDeprecated mSnapshotView2;
-    private TaskViewIcon mIconView2;
-    @Nullable
-    private CancellableTask<ThumbnailData> mThumbnailLoadRequest2;
-    @Nullable
-    private CancellableTask mIconLoadRequest2;
-    private final float[] mIcon2CenterCoords = new float[2];
-    private TransformingTouchDelegate mIcon2TouchDelegate;
-    @Nullable
-    private SplitBounds mSplitBoundsConfig;
-    private final DigitalWellBeingToast mDigitalWellBeingToast2;
-
-    public GroupedTaskView(Context context) {
-        this(context, null);
-    }
-
-    public GroupedTaskView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public GroupedTaskView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        mDigitalWellBeingToast2 = new DigitalWellBeingToast(mContainer, this);
-    }
-
-    @Override
-    protected Unit updateBorderBounds(@NonNull Rect bounds) {
-        if (mSplitBoundsConfig == null) {
-            super.updateBorderBounds(bounds);
-            return Unit.INSTANCE;
-        }
-        bounds.set(
-                Math.min(mTaskThumbnailViewDeprecated.getLeft() + Math.round(
-                                mTaskThumbnailViewDeprecated.getTranslationX()),
-                        mSnapshotView2.getLeft() + Math.round(mSnapshotView2.getTranslationX())),
-                Math.min(mTaskThumbnailViewDeprecated.getTop() + Math.round(
-                                mTaskThumbnailViewDeprecated.getTranslationY()),
-                        mSnapshotView2.getTop() + Math.round(mSnapshotView2.getTranslationY())),
-                Math.max(mTaskThumbnailViewDeprecated.getRight() + Math.round(
-                                mTaskThumbnailViewDeprecated.getTranslationX()),
-                        mSnapshotView2.getRight() + Math.round(mSnapshotView2.getTranslationX())),
-                Math.max(mTaskThumbnailViewDeprecated.getBottom() + Math.round(
-                                mTaskThumbnailViewDeprecated.getTranslationY()),
-                        mSnapshotView2.getBottom() + Math.round(mSnapshotView2.getTranslationY())));
-        return Unit.INSTANCE;
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mSnapshotView2 = findViewById(R.id.bottomright_snapshot);
-        ViewStub iconViewStub2 = findViewById(R.id.bottomRight_icon);
-        if (enableOverviewIconMenu()) {
-            iconViewStub2.setLayoutResource(R.layout.icon_app_chip_view);
-        } else {
-            iconViewStub2.setLayoutResource(R.layout.icon_view);
-        }
-        mIconView2 = (TaskViewIcon) iconViewStub2.inflate();
-        mIcon2TouchDelegate = new TransformingTouchDelegate(mIconView2.asView());
-    }
-
-    public void bind(Task primary, Task secondary, RecentsOrientedState orientedState,
-            @Nullable SplitBounds splitBoundsConfig) {
-        super.bind(primary, orientedState);
-        mSecondaryTask = secondary;
-        mTaskIdContainer[1] = secondary.key.id;
-        mTaskIdAttributeContainer[1] = new TaskIdAttributeContainer(secondary, mSnapshotView2,
-                mIconView2, STAGE_POSITION_BOTTOM_OR_RIGHT);
-        mTaskIdAttributeContainer[0].setStagePosition(
-                SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT);
-        mSnapshotView2.bind(secondary);
-        mSplitBoundsConfig = splitBoundsConfig;
-        if (mSplitBoundsConfig == null) {
-            return;
-        }
-        mTaskThumbnailViewDeprecated.getPreviewPositionHelper().setSplitBounds(
-                convertLauncherSplitBoundsToShell(splitBoundsConfig),
-                PreviewPositionHelper.STAGE_POSITION_TOP_OR_LEFT);
-        mSnapshotView2.getPreviewPositionHelper().setSplitBounds(
-                convertLauncherSplitBoundsToShell(splitBoundsConfig),
-                PreviewPositionHelper.STAGE_POSITION_BOTTOM_OR_RIGHT);
-    }
-
-    /**
-     * Sets up an on-click listener and the visibility for show_windows icon on top of each task.
-     */
-    @Override
-    public void setUpShowAllInstancesListener() {
-        // sets up the listener for the left/top task
-        super.setUpShowAllInstancesListener();
-
-        // right/bottom task's base package name
-        String taskPackageName = mTaskIdAttributeContainer[1].getTask().key.getPackageName();
-
-        // icon of the right/bottom task
-        View showWindowsView = findViewById(R.id.show_windows_right);
-        updateFilterCallback(showWindowsView, getFilterUpdateCallback(taskPackageName));
-    }
-
-    @Override
-    public void onTaskListVisibilityChanged(boolean visible, int changes) {
-        super.onTaskListVisibilityChanged(visible, changes);
-        if (visible) {
-            RecentsModel model = RecentsModel.INSTANCE.get(getContext());
-            TaskThumbnailCache thumbnailCache = model.getThumbnailCache();
-            TaskIconCache iconCache = model.getIconCache();
-
-            if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
-                mThumbnailLoadRequest2 = thumbnailCache.updateThumbnailInBackground(mSecondaryTask,
-                        thumbnailData -> mSnapshotView2.setThumbnail(
-                                mSecondaryTask, thumbnailData
-                        ));
-            }
-
-            if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
-                mIconLoadRequest2 = iconCache.updateIconInBackground(mSecondaryTask,
-                        (task) -> {
-                            setIcon(mIconView2, task.icon);
-                            if (enableOverviewIconMenu()) {
-                                setText(mIconView2, task.title);
-                            }
-                            mDigitalWellBeingToast2.initialize(mSecondaryTask);
-                            mDigitalWellBeingToast2.setSplitConfiguration(mSplitBoundsConfig);
-                            mDigitalWellBeingToast.setSplitConfiguration(mSplitBoundsConfig);
-                        });
-            }
-        } else {
-            if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
-                mSnapshotView2.setThumbnail(null, null);
-                // Reset the task thumbnail reference as well (it will be fetched from the cache or
-                // reloaded next time we need it)
-                mSecondaryTask.thumbnail = null;
-            }
-            if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
-                setIcon(mIconView2, null);
-                if (enableOverviewIconMenu()) {
-                    setText(mIconView2, null);
-                }
-            }
-        }
-    }
-
-    public void updateSplitBoundsConfig(SplitBounds splitBounds) {
-        mSplitBoundsConfig = splitBounds;
-        invalidate();
-    }
-
-    @Nullable
-    public SplitBounds getSplitBoundsConfig() {
-        return mSplitBoundsConfig;
-    }
-
-    /**
-     * Returns the {@link PersistentSnapPosition} of this pair of tasks.
-     */
-    public @PersistentSnapPosition int getSnapPosition() {
-        if (mSplitBoundsConfig == null) {
-            throw new IllegalStateException("mSplitBoundsConfig is null");
-        }
-
-        return mSplitBoundsConfig.snapPosition;
-    }
-
-    @Override
-    public boolean offerTouchToChildren(MotionEvent event) {
-        computeAndSetIconTouchDelegate(mIconView2, mIcon2CenterCoords, mIcon2TouchDelegate);
-        if (mIcon2TouchDelegate.onTouchEvent(event)) {
-            return true;
-        }
-
-        return super.offerTouchToChildren(event);
-    }
-
-    @Override
-    protected void cancelPendingLoadTasks() {
-        super.cancelPendingLoadTasks();
-        if (mThumbnailLoadRequest2 != null) {
-            mThumbnailLoadRequest2.cancel();
-            mThumbnailLoadRequest2 = null;
-        }
-        if (mIconLoadRequest2 != null) {
-            mIconLoadRequest2.cancel();
-            mIconLoadRequest2 = null;
-        }
-    }
-
-    @Nullable
-    @Override
-    public RunnableList launchTaskAnimated() {
-        if (mTask == null || mSecondaryTask == null) {
-            return null;
-        }
-
-        RunnableList endCallback = new RunnableList();
-        RecentsView recentsView = getRecentsView();
-        // Callbacks run from remote animation when recents animation not currently running
-        InteractionJankMonitorWrapper.begin(this, Cuj.CUJ_SPLIT_SCREEN_ENTER,
-                "Enter form GroupedTaskView");
-        launchTaskInternal(success -> {
-            endCallback.executeAllAndDestroy();
-            InteractionJankMonitorWrapper.end(Cuj.CUJ_SPLIT_SCREEN_ENTER);
-        }, false /* freezeTaskList */, true /*launchingExistingTaskview*/);
-
-        // Callbacks get run from recentsView for case when recents animation already running
-        recentsView.addSideTaskLaunchCallback(endCallback);
-        return endCallback;
-    }
-
-    @Override
-    public void launchTask(@NonNull Consumer<Boolean> callback, boolean isQuickswitch) {
-        launchTaskInternal(callback, isQuickswitch, false /*launchingExistingTaskview*/);
-    }
-
-    /**
-     * @param launchingExistingTaskView {@link SplitSelectStateController#launchExistingSplitPair}
-     * uses existence of GroupedTaskView as control flow of how to animate in the incoming task. If
-     * we're launching from overview (from overview thumbnails) then pass in {@code true},
-     * otherwise pass in {@code false} for case like quickswitching from home to task
-     */
-    private void launchTaskInternal(@NonNull Consumer<Boolean> callback, boolean isQuickswitch,
-            boolean launchingExistingTaskView) {
-        getRecentsView().getSplitSelectController().launchExistingSplitPair(
-                launchingExistingTaskView ? this : null, mTask.key.id,
-                mSecondaryTask.key.id, SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT,
-                callback, isQuickswitch, getSnapPosition());
-        Log.d(TAG, "launchTaskInternal - launchExistingSplitPair: " + Arrays.toString(
-                getTaskIds()));
-    }
-
-    @Override
-    void refreshThumbnails(@Nullable HashMap<Integer, ThumbnailData> thumbnailDatas) {
-        super.refreshThumbnails(thumbnailDatas);
-        if (mSecondaryTask != null && thumbnailDatas != null) {
-            final ThumbnailData thumbnailData = thumbnailDatas.get(mSecondaryTask.key.id);
-            if (thumbnailData != null) {
-                mSnapshotView2.setThumbnail(mSecondaryTask, thumbnailData);
-                return;
-            }
-        }
-
-        mSnapshotView2.refresh();
-    }
-
-    @Override
-    public boolean containsTaskId(int taskId) {
-        return (mTask != null && mTask.key.id == taskId)
-                || (mSecondaryTask != null && mSecondaryTask.key.id == taskId);
-    }
-
-    @Override
-    public TaskThumbnailViewDeprecated[] getThumbnails() {
-        return new TaskThumbnailViewDeprecated[]{mTaskThumbnailViewDeprecated, mSnapshotView2};
-    }
-
-    @Override
-    protected int getLastSelectedChildTaskIndex() {
-        SplitSelectStateController splitSelectController =
-                getRecentsView().getSplitSelectController();
-        if (splitSelectController.isDismissingFromSplitPair()) {
-            // return the container index of the task that wasn't initially selected to split with
-            // because that is the only remaining app that can be selected. The coordinate checks
-            // below aren't reliable since both of those views may be gone/transformed
-            int initSplitTaskId = getThisTaskCurrentlyInSplitSelection();
-            if (initSplitTaskId != INVALID_TASK_ID) {
-                return initSplitTaskId == mTask.key.id ? 1 : 0;
-            }
-        }
-
-        // Check which of the two apps was selected
-        if (isCoordInView(mIconView2.asView(), mLastTouchDownPosition)
-                || isCoordInView(mSnapshotView2, mLastTouchDownPosition)) {
-            return 1;
-        }
-        return super.getLastSelectedChildTaskIndex();
-    }
-
-    private boolean isCoordInView(View v, PointF position) {
-        float[] localPos = new float[]{position.x, position.y};
-        Utilities.mapCoordInSelfToDescendant(v, this, localPos);
-        return Utilities.pointInView(v, localPos[0], localPos[1], 0f /* slop */);
-    }
-
-    @Override
-    public void onRecycle() {
-        super.onRecycle();
-        mSnapshotView2.setThumbnail(mSecondaryTask, null);
-        mSplitBoundsConfig = null;
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-        setMeasuredDimension(widthSize, heightSize);
-        if (mSplitBoundsConfig == null || mTaskThumbnailViewDeprecated == null
-                || mSnapshotView2 == null) {
-            return;
-        }
-        int initSplitTaskId = getThisTaskCurrentlyInSplitSelection();
-        if (initSplitTaskId == INVALID_TASK_ID) {
-            getPagedOrientationHandler().measureGroupedTaskViewThumbnailBounds(
-                    mTaskThumbnailViewDeprecated,
-                    mSnapshotView2, widthSize, heightSize, mSplitBoundsConfig,
-                    mContainer.getDeviceProfile(), getLayoutDirection() == LAYOUT_DIRECTION_RTL);
-            // Should we be having a separate translation step apart from the measuring above?
-            // The following only applies to large screen for now, but for future reference
-            // we'd want to abstract this out in PagedViewHandlers to get the primary/secondary
-            // translation directions
-            mTaskThumbnailViewDeprecated.applySplitSelectTranslateX(
-                    mTaskThumbnailViewDeprecated.getTranslationX());
-            mTaskThumbnailViewDeprecated.applySplitSelectTranslateY(
-                    mTaskThumbnailViewDeprecated.getTranslationY());
-            mSnapshotView2.applySplitSelectTranslateX(mSnapshotView2.getTranslationX());
-            mSnapshotView2.applySplitSelectTranslateY(mSnapshotView2.getTranslationY());
-        } else {
-            // Currently being split with this taskView, let the non-split selected thumbnail
-            // take up full thumbnail area
-            TaskIdAttributeContainer container =
-                    mTaskIdAttributeContainer[initSplitTaskId == mTask.key.id ? 1 : 0];
-            container.getThumbnailView().measure(widthMeasureSpec,
-                    View.MeasureSpec.makeMeasureSpec(
-                            heightSize -
-                                    mContainer.getDeviceProfile().overviewTaskThumbnailTopMarginPx,
-                            MeasureSpec.EXACTLY));
-        }
-        if (!enableOverviewIconMenu()) {
-            updateIconPlacement();
-        }
-    }
-
-    @Override
-    public void setOverlayEnabled(boolean overlayEnabled) {
-        if (FeatureFlags.enableAppPairs()) {
-            super.setOverlayEnabled(overlayEnabled);
-        } else {
-            // Intentional no-op to prevent setting smart actions overlay on thumbnails
-        }
-    }
-
-    @Override
-    public void setOrientationState(RecentsOrientedState orientationState) {
-        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
-        if (enableOverviewIconMenu() && mSplitBoundsConfig != null) {
-            ViewGroup.LayoutParams layoutParams = getLayoutParams();
-            Pair<Point, Point> groupedTaskViewSizes =
-                    orientationState.getOrientationHandler().getGroupedTaskViewSizes(
-                            deviceProfile,
-                            mSplitBoundsConfig,
-                            layoutParams.width,
-                            layoutParams.height
-                    );
-            int iconViewMarginStart = getResources().getDimensionPixelSize(
-                    R.dimen.task_thumbnail_icon_menu_expanded_top_start_margin);
-            int iconViewBackgroundMarginStart = getResources().getDimensionPixelSize(
-                    R.dimen.task_thumbnail_icon_menu_background_margin_top_start);
-            int iconMargins = (iconViewMarginStart + iconViewBackgroundMarginStart) * 2;
-            ((IconAppChipView) mIconView).setMaxWidth(groupedTaskViewSizes.first.x - iconMargins);
-            ((IconAppChipView) mIconView2).setMaxWidth(groupedTaskViewSizes.second.x - iconMargins);
-        }
-        // setMaxWidth() needs to be called before mIconView.setIconOrientation which is called in
-        // the super below.
-        super.setOrientationState(orientationState);
-
-        boolean isGridTask = deviceProfile.isTablet && !isFocusedTask();
-        mIconView2.setIconOrientation(orientationState, isGridTask);
-        updateIconPlacement();
-        updateSecondaryDwbPlacement();
-    }
-
-    private void updateIconPlacement() {
-        if (mSplitBoundsConfig == null) {
-            return;
-        }
-
-        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
-        int taskIconHeight = deviceProfile.overviewTaskIconSizePx;
-        boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
-
-        if (enableOverviewIconMenu()) {
-            ViewGroup.LayoutParams layoutParams = getLayoutParams();
-            Pair<Point, Point> groupedTaskViewSizes =
-                    getPagedOrientationHandler()
-                            .getGroupedTaskViewSizes(
-                                    deviceProfile,
-                                    mSplitBoundsConfig,
-                                    layoutParams.width,
-                                    layoutParams.height
-                            );
-
-            getPagedOrientationHandler().setSplitIconParams(mIconView.asView(), mIconView2.asView(),
-                    taskIconHeight, groupedTaskViewSizes.first.x, groupedTaskViewSizes.first.y,
-                    getLayoutParams().height, getLayoutParams().width, isRtl, deviceProfile,
-                    mSplitBoundsConfig);
-        } else {
-            getPagedOrientationHandler().setSplitIconParams(mIconView.asView(), mIconView2.asView(),
-                    taskIconHeight, mTaskThumbnailViewDeprecated.getMeasuredWidth(),
-                    mTaskThumbnailViewDeprecated.getMeasuredHeight(), getMeasuredHeight(),
-                    getMeasuredWidth(),
-                    isRtl, deviceProfile, mSplitBoundsConfig);
-        }
-    }
-
-    private void updateSecondaryDwbPlacement() {
-        if (mSecondaryTask == null) {
-            return;
-        }
-        mDigitalWellBeingToast2.initialize(mSecondaryTask);
-    }
-
-    @Override
-    protected void updateSnapshotRadius() {
-        super.updateSnapshotRadius();
-        mSnapshotView2.setFullscreenParams(mCurrentFullscreenParams);
-    }
-
-    @Override
-    protected void setIconsAndBannersTransitionProgress(float progress, boolean invert) {
-        super.setIconsAndBannersTransitionProgress(progress, invert);
-        // Value set by super call
-        float scale = mIconView.getAlpha();
-        mIconView2.setContentAlpha(scale);
-        mDigitalWellBeingToast2.updateBannerOffset(1f - scale);
-    }
-
-    @Override
-    public void setColorTint(float amount, int tintColor) {
-        super.setColorTint(amount, tintColor);
-        mIconView2.setIconColorTint(tintColor, amount);
-        mSnapshotView2.setDimAlpha(amount);
-        mDigitalWellBeingToast2.setBannerColorTint(tintColor, amount);
-    }
-
-    @Override
-    protected void applyThumbnailSplashAlpha() {
-        super.applyThumbnailSplashAlpha();
-        mSnapshotView2.setSplashAlpha(mTaskThumbnailSplashAlpha);
-    }
-
-    @Override
-    protected void refreshTaskThumbnailSplash() {
-        super.refreshTaskThumbnailSplash();
-        mSnapshotView2.refreshSplashView();
-    }
-
-    @Override
-    protected void resetViewTransforms() {
-        super.resetViewTransforms();
-        mSnapshotView2.resetViewTransforms();
-    }
-
-    /**
-     * Sets visibility for thumbnails and associated elements (DWB banners).
-     * IconView is unaffected.
-     *
-     * When setting INVISIBLE, sets the visibility for the last selected child task.
-     * When setting VISIBLE (as a reset), sets the visibility for both tasks.
-     */
-    @Override
-    void setThumbnailVisibility(int visibility, int taskId) {
-        if (visibility == VISIBLE) {
-            mTaskThumbnailViewDeprecated.setVisibility(visibility);
-            mDigitalWellBeingToast.setBannerVisibility(visibility);
-            mSnapshotView2.setVisibility(visibility);
-            mDigitalWellBeingToast2.setBannerVisibility(visibility);
-        } else if (taskId == getTaskIds()[0]) {
-            mTaskThumbnailViewDeprecated.setVisibility(visibility);
-            mDigitalWellBeingToast.setBannerVisibility(visibility);
-        } else {
-            mSnapshotView2.setVisibility(visibility);
-            mDigitalWellBeingToast2.setBannerVisibility(visibility);
-        }
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
new file mode 100644
index 0000000..efbfa09
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.views
+
+import android.app.ActivityTaskManager.INVALID_TASK_ID
+import android.content.Context
+import android.graphics.PointF
+import android.util.AttributeSet
+import android.util.Log
+import android.view.View
+import com.android.internal.jank.Cuj
+import com.android.launcher3.Flags.enableOverviewIconMenu
+import com.android.launcher3.R
+import com.android.launcher3.Utilities
+import com.android.launcher3.config.FeatureFlags
+import com.android.launcher3.util.RunnableList
+import com.android.launcher3.util.SplitConfigurationOptions
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
+import com.android.quickstep.TaskOverlayFactory
+import com.android.quickstep.util.RecentsOrientedState
+import com.android.quickstep.util.SplitScreenUtils.Companion.convertLauncherSplitBoundsToShell
+import com.android.quickstep.util.SplitSelectStateController
+import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
+import com.android.systemui.shared.system.InteractionJankMonitorWrapper
+import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition
+
+/**
+ * TaskView that contains and shows thumbnails for not one, BUT TWO(!!) tasks
+ *
+ * That's right. If you call within the next 5 minutes we'll go ahead and double your order and send
+ * you !! TWO !! Tasks along with their TaskThumbnailViews complimentary. On. The. House. And not
+ * only that, we'll even clean up your thumbnail request if you don't like it. All the benefits of
+ * one TaskView, except DOUBLED!
+ *
+ * (Icon loading sold separately, fees may apply. Shipping & Handling for Overlays not included).
+ */
+class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
+    TaskView(context, attrs) {
+    // TODO(b/336612373): Support new TTV for GroupedTaskView
+    var splitBoundsConfig: SplitConfigurationOptions.SplitBounds? = null
+        private set
+
+    @get:PersistentSnapPosition
+    val snapPosition: Int
+        /** Returns the [PersistentSnapPosition] of this pair of tasks. */
+        get() = splitBoundsConfig?.snapPosition ?: STAGE_POSITION_UNDEFINED
+
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
+        val heightSize = MeasureSpec.getSize(heightMeasureSpec)
+        setMeasuredDimension(widthSize, heightSize)
+        val splitBoundsConfig = splitBoundsConfig ?: return
+        val initSplitTaskId = getThisTaskCurrentlyInSplitSelection()
+        if (initSplitTaskId == INVALID_TASK_ID) {
+            pagedOrientationHandler.measureGroupedTaskViewThumbnailBounds(
+                taskContainers[0].thumbnailViewDeprecated,
+                taskContainers[1].thumbnailViewDeprecated,
+                widthSize,
+                heightSize,
+                splitBoundsConfig,
+                container.deviceProfile,
+                layoutDirection == LAYOUT_DIRECTION_RTL
+            )
+            // Should we be having a separate translation step apart from the measuring above?
+            // The following only applies to large screen for now, but for future reference
+            // we'd want to abstract this out in PagedViewHandlers to get the primary/secondary
+            // translation directions
+            taskContainers[0]
+                .thumbnailViewDeprecated
+                .applySplitSelectTranslateX(taskContainers[0].thumbnailViewDeprecated.translationX)
+            taskContainers[0]
+                .thumbnailViewDeprecated
+                .applySplitSelectTranslateY(taskContainers[0].thumbnailViewDeprecated.translationY)
+            taskContainers[1]
+                .thumbnailViewDeprecated
+                .applySplitSelectTranslateX(taskContainers[1].thumbnailViewDeprecated.translationX)
+            taskContainers[1]
+                .thumbnailViewDeprecated
+                .applySplitSelectTranslateY(taskContainers[1].thumbnailViewDeprecated.translationY)
+        } else {
+            // Currently being split with this taskView, let the non-split selected thumbnail
+            // take up full thumbnail area
+            taskContainers
+                .firstOrNull { it.task.key.id != initSplitTaskId }
+                ?.thumbnailViewDeprecated
+                ?.measure(
+                    widthMeasureSpec,
+                    MeasureSpec.makeMeasureSpec(
+                        heightSize - container.deviceProfile.overviewTaskThumbnailTopMarginPx,
+                        MeasureSpec.EXACTLY
+                    )
+                )
+        }
+        if (!enableOverviewIconMenu()) {
+            updateIconPlacement()
+        }
+    }
+
+    override fun onRecycle() {
+        super.onRecycle()
+        splitBoundsConfig = null
+    }
+
+    fun bind(
+        primaryTask: Task,
+        secondaryTask: Task,
+        orientedState: RecentsOrientedState,
+        taskOverlayFactory: TaskOverlayFactory,
+        splitBoundsConfig: SplitConfigurationOptions.SplitBounds?,
+    ) {
+        cancelPendingLoadTasks()
+        taskContainers =
+            listOf(
+                createTaskContainer(
+                    primaryTask,
+                    R.id.snapshot,
+                    R.id.icon,
+                    R.id.show_windows,
+                    STAGE_POSITION_TOP_OR_LEFT,
+                    taskOverlayFactory
+                ),
+                createTaskContainer(
+                    secondaryTask,
+                    R.id.bottomright_snapshot,
+                    R.id.bottomRight_icon,
+                    R.id.show_windows_right,
+                    STAGE_POSITION_BOTTOM_OR_RIGHT,
+                    taskOverlayFactory
+                )
+            )
+        this.splitBoundsConfig =
+            splitBoundsConfig?.also {
+                taskContainers[0]
+                    .thumbnailViewDeprecated
+                    .previewPositionHelper
+                    .setSplitBounds(
+                        convertLauncherSplitBoundsToShell(it),
+                        PreviewPositionHelper.STAGE_POSITION_TOP_OR_LEFT
+                    )
+                taskContainers[1]
+                    .thumbnailViewDeprecated
+                    .previewPositionHelper
+                    .setSplitBounds(
+                        convertLauncherSplitBoundsToShell(it),
+                        PreviewPositionHelper.STAGE_POSITION_BOTTOM_OR_RIGHT
+                    )
+            }
+        setOrientationState(orientedState)
+    }
+
+    override fun setOrientationState(orientationState: RecentsOrientedState) {
+        if (enableOverviewIconMenu()) {
+            splitBoundsConfig?.let {
+                val groupedTaskViewSizes =
+                    orientationState.orientationHandler.getGroupedTaskViewSizes(
+                        container.deviceProfile,
+                        it,
+                        layoutParams.width,
+                        layoutParams.height
+                    )
+                val iconViewMarginStart =
+                    resources.getDimensionPixelSize(
+                        R.dimen.task_thumbnail_icon_menu_expanded_top_start_margin
+                    )
+                val iconViewBackgroundMarginStart =
+                    resources.getDimensionPixelSize(
+                        R.dimen.task_thumbnail_icon_menu_background_margin_top_start
+                    )
+                val iconMargins = (iconViewMarginStart + iconViewBackgroundMarginStart) * 2
+                // setMaxWidth() needs to be called before mIconView.setIconOrientation which is
+                // called in the super below.
+                (taskContainers[0].iconView as IconAppChipView).setMaxWidth(
+                    groupedTaskViewSizes.first.x - iconMargins
+                )
+                (taskContainers[1].iconView as IconAppChipView).setMaxWidth(
+                    groupedTaskViewSizes.second.x - iconMargins
+                )
+            }
+        }
+        super.setOrientationState(orientationState)
+        updateIconPlacement()
+    }
+
+    private fun updateIconPlacement() {
+        val splitBoundsConfig = splitBoundsConfig ?: return
+        val taskIconHeight = container.deviceProfile.overviewTaskIconSizePx
+        val isRtl = layoutDirection == LAYOUT_DIRECTION_RTL
+        if (enableOverviewIconMenu()) {
+            val groupedTaskViewSizes =
+                pagedOrientationHandler.getGroupedTaskViewSizes(
+                    container.deviceProfile,
+                    splitBoundsConfig,
+                    layoutParams.width,
+                    layoutParams.height
+                )
+            pagedOrientationHandler.setSplitIconParams(
+                taskContainers[0].iconView.asView(),
+                taskContainers[1].iconView.asView(),
+                taskIconHeight,
+                groupedTaskViewSizes.first.x,
+                groupedTaskViewSizes.first.y,
+                layoutParams.height,
+                layoutParams.width,
+                isRtl,
+                container.deviceProfile,
+                splitBoundsConfig
+            )
+        } else {
+            pagedOrientationHandler.setSplitIconParams(
+                taskContainers[0].iconView.asView(),
+                taskContainers[1].iconView.asView(),
+                taskIconHeight,
+                taskContainers[0].thumbnailViewDeprecated.measuredWidth,
+                taskContainers[0].thumbnailViewDeprecated.measuredHeight,
+                measuredHeight,
+                measuredWidth,
+                isRtl,
+                container.deviceProfile,
+                splitBoundsConfig
+            )
+        }
+    }
+
+    fun updateSplitBoundsConfig(splitBounds: SplitConfigurationOptions.SplitBounds?) {
+        splitBoundsConfig = splitBounds
+        invalidate()
+    }
+
+    override fun launchTaskAnimated(): RunnableList? {
+        if (taskContainers.isEmpty()) {
+            Log.d(TAG, "launchTaskAnimated - task is not bound")
+            return null
+        }
+        val recentsView = recentsView ?: return null
+        val endCallback = RunnableList()
+        // Callbacks run from remote animation when recents animation not currently running
+        InteractionJankMonitorWrapper.begin(
+            this,
+            Cuj.CUJ_SPLIT_SCREEN_ENTER,
+            "Enter form GroupedTaskView"
+        )
+        launchTaskInternal(isQuickSwitch = false, launchingExistingTaskView = true) {
+            endCallback.executeAllAndDestroy()
+            InteractionJankMonitorWrapper.end(Cuj.CUJ_SPLIT_SCREEN_ENTER)
+        }
+
+        // Callbacks get run from recentsView for case when recents animation already running
+        recentsView.addSideTaskLaunchCallback(endCallback)
+        return endCallback
+    }
+
+    override fun launchTask(callback: (launched: Boolean) -> Unit, isQuickSwitch: Boolean) {
+        launchTaskInternal(isQuickSwitch, false, callback /*launchingExistingTaskview*/)
+    }
+
+    /**
+     * @param launchingExistingTaskView [SplitSelectStateController.launchExistingSplitPair] uses
+     *   existence of GroupedTaskView as control flow of how to animate in the incoming task. If
+     *   we're launching from overview (from overview thumbnails) then pass in `true`, otherwise
+     *   pass in `false` for case like quickswitching from home to task
+     */
+    private fun launchTaskInternal(
+        isQuickSwitch: Boolean,
+        launchingExistingTaskView: Boolean,
+        callback: (launched: Boolean) -> Unit
+    ) {
+        recentsView?.let {
+            it.splitSelectController.launchExistingSplitPair(
+                if (launchingExistingTaskView) this else null,
+                taskContainers[0].task.key.id,
+                taskContainers[1].task.key.id,
+                STAGE_POSITION_TOP_OR_LEFT,
+                callback,
+                isQuickSwitch,
+                snapPosition
+            )
+            Log.d(TAG, "launchTaskInternal - launchExistingSplitPair: ${taskIds.contentToString()}")
+        }
+    }
+
+    /**
+     * Returns taskId that split selection was initiated with, [INVALID_TASK_ID] if no tasks in this
+     * TaskView are part of split selection
+     */
+    private fun getThisTaskCurrentlyInSplitSelection(): Int {
+        val initialTaskId = recentsView?.splitSelectController?.initialTaskId
+        return if (initialTaskId != null && containsTaskId(initialTaskId)) initialTaskId
+        else INVALID_TASK_ID
+    }
+
+    override fun getLastSelectedChildTaskIndex(): Int {
+        if (recentsView?.splitSelectController?.isDismissingFromSplitPair == true) {
+            // return the container index of the task that wasn't initially selected to split
+            // with because that is the only remaining app that can be selected. The coordinate
+            // checks below aren't reliable since both of those views may be gone/transformed
+            val initSplitTaskId = getThisTaskCurrentlyInSplitSelection()
+            if (initSplitTaskId != INVALID_TASK_ID) {
+                return if (initSplitTaskId == taskContainers[0].task.key.id) 1 else 0
+            }
+        }
+
+        // Check which of the two apps was selected
+        if (
+            taskContainers[1].iconView.asView().containsPoint(lastTouchDownPosition) ||
+                taskContainers[1].thumbnailViewDeprecated.containsPoint(lastTouchDownPosition)
+        ) {
+            return 1
+        }
+        return super.getLastSelectedChildTaskIndex()
+    }
+
+    private fun View.containsPoint(position: PointF): Boolean {
+        val localPos = floatArrayOf(position.x, position.y)
+        Utilities.mapCoordInSelfToDescendant(this, this@GroupedTaskView, localPos)
+        return Utilities.pointInView(this, localPos[0], localPos[1], 0f /* slop */)
+    }
+
+    override fun setOverlayEnabled(overlayEnabled: Boolean) {
+        if (FeatureFlags.enableAppPairs()) {
+            super.setOverlayEnabled(overlayEnabled)
+        } else {
+            // Intentional no-op to prevent setting smart actions overlay on thumbnails
+        }
+    }
+
+    companion object {
+        private const val TAG = "GroupedTaskView"
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/views/IconView.java b/quickstep/src/com/android/quickstep/views/IconView.java
index 1312ec3..bb4a7ec 100644
--- a/quickstep/src/com/android/quickstep/views/IconView.java
+++ b/quickstep/src/com/android/quickstep/views/IconView.java
@@ -28,6 +28,7 @@
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.util.MultiValueAlpha;
 import com.android.launcher3.views.ActivityContext;
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
 import com.android.quickstep.util.RecentsOrientedState;
@@ -37,21 +38,33 @@
  * when the drawable changes.
  */
 public class IconView extends View implements TaskViewIcon {
+    private static final int NUM_ALPHA_CHANNELS = 2;
+    private static final int INDEX_CONTENT_ALPHA = 0;
+    private static final int INDEX_MODAL_ALPHA = 1;
+
+    private final MultiValueAlpha mMultiValueAlpha;
 
     @Nullable
     private Drawable mDrawable;
     private int mDrawableWidth, mDrawableHeight;
 
     public IconView(Context context) {
-        super(context);
+        this(context, null);
     }
 
     public IconView(Context context, AttributeSet attrs) {
-        super(context, attrs);
+        this(context, attrs, 0);
     }
 
     public IconView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public IconView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        mMultiValueAlpha = new MultiValueAlpha(this, NUM_ALPHA_CHANNELS);
+        mMultiValueAlpha.setUpdateVisibility(/* updateVisibility= */ true);
     }
 
     /**
@@ -143,22 +156,12 @@
 
     @Override
     public void setContentAlpha(float alpha) {
-        setAlpha(alpha);
+        mMultiValueAlpha.get(INDEX_CONTENT_ALPHA).setValue(alpha);
     }
 
     @Override
     public void setModalAlpha(float alpha) {
-        setAlpha(alpha);
-    }
-
-    @Override
-    public void setAlpha(float alpha) {
-        super.setAlpha(alpha);
-        if (alpha > 0) {
-            setVisibility(VISIBLE);
-        } else {
-            setVisibility(INVISIBLE);
-        }
+        mMultiValueAlpha.get(INDEX_MODAL_ALPHA).setValue(alpha);
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 8d1907f..5284b44 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -56,6 +56,8 @@
 import com.android.quickstep.util.SplitSelectStateController;
 import com.android.systemui.shared.recents.model.Task;
 
+import kotlin.Unit;
+
 /**
  * {@link RecentsView} used in Launcher activity
  */
@@ -107,7 +109,7 @@
     }
 
     @Override
-    protected void onTaskLaunchAnimationEnd(boolean success) {
+    protected Unit onTaskLaunchAnimationEnd(boolean success) {
         if (success) {
             getStateManager().moveToRestState();
         } else {
@@ -115,6 +117,7 @@
             mContainer.getAllAppsController().setState(state);
         }
         super.onTaskLaunchAnimationEnd(success);
+        return Unit.INSTANCE;
     }
 
     @Override
@@ -143,7 +146,7 @@
 
     @Override
     public void onStateTransitionStart(LauncherState toState) {
-        setOverviewStateEnabled(toState.overviewUi);
+        setOverviewStateEnabled(toState.isRecentsViewVisible);
 
         setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile()));
         setOverviewFullscreenEnabled(toState.getOverviewFullscreenProgress() == 1);
@@ -154,7 +157,7 @@
         }
 
         // Set border after select mode changes to avoid showing border during state transition
-        if (!toState.overviewUi || toState == OVERVIEW_MODAL_TASK) {
+        if (!toState.isRecentsViewVisible || toState == OVERVIEW_MODAL_TASK) {
             setTaskBorderEnabled(false);
         }
 
@@ -178,7 +181,7 @@
             setOverviewSelectEnabled(false);
         }
 
-        if (finalState.overviewUi && finalState != OVERVIEW_MODAL_TASK) {
+        if (finalState.isRecentsViewVisible && finalState != OVERVIEW_MODAL_TASK) {
             setTaskBorderEnabled(true);
         }
 
@@ -203,7 +206,7 @@
     public boolean onTouchEvent(MotionEvent ev) {
         boolean result = super.onTouchEvent(ev);
         // Do not let touch escape to siblings below this view.
-        return result || getStateManager().getState().overviewUi;
+        return result || getStateManager().getState().isRecentsViewVisible;
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 5188d4a..83a2ceb 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -33,9 +33,8 @@
 import com.android.launcher3.Flags;
 import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.launcher3.util.NavigationMode;
 import com.android.quickstep.TaskOverlayFactory.OverlayUICallbacks;
@@ -43,13 +42,13 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
 
 /**
  * View for showing action buttons in Overview
  */
 public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayout
         implements OnClickListener, Insettable {
-
     private final Rect mInsets = new Rect();
 
     @IntDef(flag = true, value = {
@@ -89,30 +88,30 @@
     private static final int INDEX_HIDDEN_FLAGS_ALPHA = 3;
     private static final int INDEX_SHARE_TARGET_ALPHA = 4;
     private static final int INDEX_SCROLL_ALPHA = 5;
-    private static final int NUM_ALPHAS = 6;
-
-    public @interface ScreenshotButtonHiddenFlags { }
-    public static final int FLAG_MULTIPLE_TASKS_HIDE_SCREENSHOT = 1 << 0;
+    private static final int INDEX_GROUPED_ALPHA = 6;
+    private static final int INDEX_3P_LAUNCHER = 7;
+    private static final int NUM_ALPHAS = 8;
 
     public @interface SplitButtonHiddenFlags { }
     public static final int FLAG_SMALL_SCREEN_HIDE_SPLIT = 1 << 0;
-    public static final int FLAG_MULTIPLE_TASKS_HIDE_SPLIT = 1 << 1;
 
-    public @interface SplitButtonDisabledFlags { }
-    public static final int FLAG_SINGLE_TASK_DISABLE_SPLIT = 1 << 0;
+    /**
+     * Holds an AnimatedFloat for each alpha property, used to set or animate alpha values in
+     * {@link #mMultiValueAlphas}.
+     */
+    private final AnimatedFloat[] mAlphaProperties = new AnimatedFloat[NUM_ALPHAS];
 
-    public @interface AppPairButtonHiddenFlags { }
-    public static final int FLAG_SINGLE_TASK_HIDE_APP_PAIR = 1 << 0;
-    public static final int FLAG_SMALL_SCREEN_HIDE_APP_PAIR = 1 << 1;
-    public static final int FLAG_3P_LAUNCHER_HIDE_APP_PAIR = 1 << 2;
+    /** Holds MultiValueAlpha values for all actions bars */
+    private final MultiValueAlpha[] mMultiValueAlphas = new MultiValueAlpha[2];
+    /** Index used for single-task actions in the mMultiValueAlphas array */
+    private static final int ACTIONS_ALPHAS = 0;
+    /** Index used for grouped-task actions in the mMultiValueAlphas array */
+    private static final int GROUP_ACTIONS_ALPHAS = 1;
 
-    private MultiValueAlpha mMultiValueAlpha;
-
+    /** Container for the action buttons below a focused, non-split Overview tile. */
     protected LinearLayout mActionButtons;
-    // The screenshot button is implemented as a Button in launcher3 and NexusLauncher, but is an
-    // ImageButton in go launcher (does not share a common class with Button). Take care when
-    // casting this.
-    private View mScreenshotButton;
+    /** Container for the action buttons below a focused, split Overview tile. */
+    protected LinearLayout mGroupActionButtons;
     private Button mSplitButton;
     private Button mSaveAppPairButton;
 
@@ -122,21 +121,17 @@
     @ActionsDisabledFlags
     protected int mDisabledFlags;
 
-    @ScreenshotButtonHiddenFlags
-    private int mScreenshotButtonHiddenFlags;
-
     @SplitButtonHiddenFlags
     private int mSplitButtonHiddenFlags;
 
-    @AppPairButtonHiddenFlags
-    private int mAppPairButtonHiddenFlags;
-
     @Nullable
     protected T mCallbacks;
 
     @Nullable
     protected DeviceProfile mDp;
     private final Rect mTaskSize = new Rect();
+    private boolean mIsGroupedTask = false;
+    private boolean mCanSaveAppPair = false;
 
     public OverviewActionsView(Context context) {
         this(context, null);
@@ -153,12 +148,31 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
+        // Initialize 2 view containers: one for single tasks, one for grouped tasks.
+        // These will take up the same space on the screen and alternate visibility as needed.
         mActionButtons = findViewById(R.id.action_buttons);
-        mMultiValueAlpha = new MultiValueAlpha(mActionButtons, NUM_ALPHAS);
-        mMultiValueAlpha.setUpdateVisibility(true);
+        mGroupActionButtons = findViewById(R.id.group_action_buttons);
+        // Initialize a list to hold alphas for mActionButtons and mGroupActionButtons.
+        mMultiValueAlphas[ACTIONS_ALPHAS] = new MultiValueAlpha(mActionButtons, NUM_ALPHAS);
+        mMultiValueAlphas[GROUP_ACTIONS_ALPHAS] =
+                new MultiValueAlpha(mGroupActionButtons, NUM_ALPHAS);
+        Arrays.stream(mMultiValueAlphas).forEach(a -> a.setUpdateVisibility(true));
+        // To control alpha simultaneously on mActionButtons and mGroupActionButtons, we set up an
+        // AnimatedFloat for each alpha property.
+        for (int i = 0; i < NUM_ALPHAS; i++) {
+            final int index = i;
+            mAlphaProperties[index] = new AnimatedFloat(() -> {
+                for (MultiValueAlpha multiValueAlpha : mMultiValueAlphas) {
+                    multiValueAlpha.get(index).setValue(mAlphaProperties[index].value);
+                }
+            }, 1f /* initialValue */);
+        }
 
-        mScreenshotButton = findViewById(R.id.action_screenshot);
-        mScreenshotButton.setOnClickListener(this);
+        // The screenshot button is implemented as a Button in launcher3 and NexusLauncher, but is
+        // an ImageButton in go launcher (does not share a common class with Button). Take care when
+        // casting this.
+        View screenshotButton = findViewById(R.id.action_screenshot);
+        screenshotButton.setOnClickListener(this);
         mSplitButton = findViewById(R.id.action_split);
         mSplitButton.setOnClickListener(this);
         mSaveAppPairButton = findViewById(R.id.action_save_app_pair);
@@ -209,7 +223,7 @@
             mHiddenFlags &= ~visibilityFlags;
         }
         boolean isHidden = mHiddenFlags != 0;
-        mMultiValueAlpha.get(INDEX_HIDDEN_FLAGS_ALPHA).setValue(isHidden ? 0 : 1);
+        mAlphaProperties[INDEX_HIDDEN_FLAGS_ALPHA].updateValue(isHidden ? 0 : 1);
     }
 
     /**
@@ -234,14 +248,13 @@
      * Updates a batch of flags to hide and show actions buttons when a grouped task (split screen)
      * is focused.
      * @param isGroupedTask True if the focused task is a grouped task.
+     * @param canSaveAppPair True if the focused task is a grouped task and can be saved as an app
+     *                      pair.
      */
-    public void updateForGroupedTask(boolean isGroupedTask) {
-        // Update flags to see if split button should be hidden.
-        updateSplitButtonHiddenFlags(FLAG_MULTIPLE_TASKS_HIDE_SPLIT, isGroupedTask);
-        // Update flags to see if screenshot button should be hidden.
-        updateScreenshotButtonHiddenFlags(FLAG_MULTIPLE_TASKS_HIDE_SCREENSHOT, isGroupedTask);
-        // Update flags to see if save app pair button should be hidden.
-        updateAppPairButtonHiddenFlags(FLAG_SINGLE_TASK_HIDE_APP_PAIR, !isGroupedTask);
+    public void updateForGroupedTask(boolean isGroupedTask, boolean canSaveAppPair) {
+        mIsGroupedTask = isGroupedTask;
+        mCanSaveAppPair = canSaveAppPair;
+        updateActionButtonsVisibility();
     }
 
     /**
@@ -251,36 +264,30 @@
         assert mDp != null;
         // Update flags to see if split button should be hidden.
         updateSplitButtonHiddenFlags(FLAG_SMALL_SCREEN_HIDE_SPLIT, !mDp.isTablet);
-        // Update flags to see if save app pair button should be hidden.
-        updateAppPairButtonHiddenFlags(FLAG_SMALL_SCREEN_HIDE_APP_PAIR, !mDp.isTablet);
+        updateActionButtonsVisibility();
+    }
+
+    private void updateActionButtonsVisibility() {
+        assert mDp != null;
+        boolean showSingleTaskActions = !mIsGroupedTask;
+        boolean showGroupActions = mIsGroupedTask && mDp.isTablet && mCanSaveAppPair;
+        getActionsAlphas().get(INDEX_GROUPED_ALPHA).setValue(showSingleTaskActions ? 1 : 0);
+        getGroupActionsAlphas().get(INDEX_GROUPED_ALPHA).setValue(showGroupActions ? 1 : 0);
     }
 
     /**
      * Updates flags to hide and show actions buttons for 1p/3p launchers.
      */
     public void updateFor3pLauncher(boolean is3pLauncher) {
-        updateAppPairButtonHiddenFlags(FLAG_3P_LAUNCHER_HIDE_APP_PAIR, is3pLauncher);
+        getGroupActionsAlphas().get(INDEX_3P_LAUNCHER).setValue(is3pLauncher ? 0 : 1);
     }
 
-    /**
-     * Updates the proper flags to indicate whether the "Screenshot" button should be hidden.
-     *
-     * @param flag   The flag to update.
-     * @param enable Whether to enable the hidden flag: True will cause view to be hidden.
-     */
-    private void updateScreenshotButtonHiddenFlags(@ScreenshotButtonHiddenFlags int flag,
-            boolean enable) {
-        if (mScreenshotButton == null) return;
-        if (enable) {
-            mScreenshotButtonHiddenFlags |= flag;
-        } else {
-            mScreenshotButtonHiddenFlags &= ~flag;
-        }
-        int desiredVisibility = mScreenshotButtonHiddenFlags == 0 ? VISIBLE : GONE;
-        if (mScreenshotButton.getVisibility() != desiredVisibility) {
-            mScreenshotButton.setVisibility(desiredVisibility);
-            mActionButtons.requestLayout();
-        }
+    private MultiValueAlpha getActionsAlphas() {
+        return mMultiValueAlphas[ACTIONS_ALPHAS];
+    }
+
+    private MultiValueAlpha getGroupActionsAlphas() {
+        return mMultiValueAlphas[GROUP_ACTIONS_ALPHAS];
     }
 
     /**
@@ -304,56 +311,32 @@
         }
     }
 
-    /**
-     * Updates the proper flags to indicate whether the "Save app pair" button should be disabled.
-     *
-     * @param flag   The flag to update.
-     * @param enable Whether to enable the hidden flag: True will cause view to be hidden.
-     */
-    private void updateAppPairButtonHiddenFlags(
-            @AppPairButtonHiddenFlags int flag, boolean enable) {
-        if (!FeatureFlags.enableAppPairs()) {
-            return;
-        }
-
-        if (mSaveAppPairButton == null) return;
-        if (enable) {
-            mAppPairButtonHiddenFlags |= flag;
-        } else {
-            mAppPairButtonHiddenFlags &= ~flag;
-        }
-        int desiredVisibility = mAppPairButtonHiddenFlags == 0 ? VISIBLE : GONE;
-        if (mSaveAppPairButton.getVisibility() != desiredVisibility) {
-            mSaveAppPairButton.setVisibility(desiredVisibility);
-            mActionButtons.requestLayout();
-        }
+    public AnimatedFloat getContentAlpha() {
+        return mAlphaProperties[INDEX_CONTENT_ALPHA];
     }
 
-    public MultiProperty getContentAlpha() {
-        return mMultiValueAlpha.get(INDEX_CONTENT_ALPHA);
+    public AnimatedFloat getVisibilityAlpha() {
+        return mAlphaProperties[INDEX_VISIBILITY_ALPHA];
     }
 
-    public MultiProperty getVisibilityAlpha() {
-        return mMultiValueAlpha.get(INDEX_VISIBILITY_ALPHA);
+    public AnimatedFloat getFullscreenAlpha() {
+        return mAlphaProperties[INDEX_FULLSCREEN_ALPHA];
     }
 
-    public MultiProperty getFullscreenAlpha() {
-        return mMultiValueAlpha.get(INDEX_FULLSCREEN_ALPHA);
+    public AnimatedFloat getShareTargetAlpha() {
+        return mAlphaProperties[INDEX_SHARE_TARGET_ALPHA];
     }
 
-    public MultiProperty getShareTargetAlpha() {
-        return mMultiValueAlpha.get(INDEX_SHARE_TARGET_ALPHA);
-    }
-
-    public MultiProperty getIndexScrollAlpha() {
-        return mMultiValueAlpha.get(INDEX_SCROLL_ALPHA);
+    public AnimatedFloat getIndexScrollAlpha() {
+        return mAlphaProperties[INDEX_SCROLL_ALPHA];
     }
 
     /**
      * Returns the visibility of the overview actions buttons.
      */
-    public @Visibility int getActionsButtonVisibility() {
-        return mActionButtons.getVisibility();
+    public boolean areActionsButtonsVisible() {
+        return mActionButtons.getVisibility() == View.VISIBLE
+                || mGroupActionButtons.getVisibility() == View.VISIBLE;
     }
 
     /**
@@ -366,10 +349,17 @@
 
     /** Updates vertical margins for different navigation mode or configuration changes. */
     public void updateVerticalMargin(NavigationMode mode) {
+        updateActionBarPosition(mActionButtons);
+        updateActionBarPosition(mGroupActionButtons);
+    }
+
+    /** Positions actions buttons according to device settings and insets. */
+    private void updateActionBarPosition(LinearLayout actionBar) {
         if (mDp == null) {
             return;
         }
-        LayoutParams actionParams = (LayoutParams) mActionButtons.getLayoutParams();
+
+        LayoutParams actionParams = (LayoutParams) actionBar.getLayoutParams();
         actionParams.setMargins(
                 actionParams.leftMargin, mDp.overviewActionsTopMarginPx,
                 actionParams.rightMargin, getBottomMargin());
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 5daafcf..5eee64d 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -35,6 +35,7 @@
 import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
 import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
 import static com.android.launcher3.Flags.enableGridOnlyOverview;
+import static com.android.launcher3.Flags.enableRefactorTaskThumbnail;
 import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.LauncherState.BACKGROUND_APP;
@@ -44,6 +45,7 @@
 import static com.android.launcher3.Utilities.squaredHypot;
 import static com.android.launcher3.Utilities.squaredTouchSlop;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ACTIONS_SPLIT;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ORIENTATION_CHANGED;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
@@ -144,6 +146,7 @@
 import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.desktop.DesktopRecentsTransitionController;
+import com.android.launcher3.logger.LauncherAtom;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.statehandlers.DepthController;
@@ -167,7 +170,6 @@
 import com.android.launcher3.util.VibratorWrapper;
 import com.android.launcher3.util.ViewPool;
 import com.android.quickstep.BaseContainerInterface;
-import com.android.quickstep.DesktopModeStatus;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.OverviewCommandHelper;
 import com.android.quickstep.RecentsAnimationController;
@@ -186,6 +188,7 @@
 import com.android.quickstep.TopTaskTracker;
 import com.android.quickstep.ViewUtils;
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
+import com.android.quickstep.recents.viewmodel.RecentsViewData;
 import com.android.quickstep.util.ActiveGestureErrorDetector;
 import com.android.quickstep.util.ActiveGestureLog;
 import com.android.quickstep.util.AnimUtils;
@@ -204,7 +207,7 @@
 import com.android.quickstep.util.TaskVisualsChangeListener;
 import com.android.quickstep.util.TransformParams;
 import com.android.quickstep.util.VibrationConstants;
-import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
+import com.android.quickstep.views.TaskView.TaskContainer;
 import com.android.systemui.plugins.ResourceProvider;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -214,6 +217,9 @@
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.TaskStackChangeListeners;
 import com.android.wm.shell.common.pip.IPipAnimationListener;
+import com.android.wm.shell.shared.DesktopModeStatus;
+
+import kotlin.Unit;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -376,6 +382,9 @@
                 public void setValue(RecentsView view, float scale) {
                     view.setScaleX(scale);
                     view.setScaleY(scale);
+                    if (enableRefactorTaskThumbnail()) {
+                        view.mRecentsViewData.getScale().setValue(scale);
+                    }
                     view.mLastComputedTaskStartPushOutDistance = null;
                     view.mLastComputedTaskEndPushOutDistance = null;
                     view.runActionOnRemoteHandles(new Consumer<RemoteTargetHandle>() {
@@ -446,6 +455,8 @@
 
     private static final float FOREGROUND_SCRIM_TINT = 0.32f;
 
+    public final RecentsViewData mRecentsViewData = new RecentsViewData();
+
     protected final RecentsOrientedState mOrientationState;
     protected final BaseContainerInterface<STATE_TYPE, CONTAINER_TYPE> mSizeStrategy;
     @Nullable
@@ -591,7 +602,7 @@
             if (taskView == null) {
                 return;
             }
-            Task.TaskKey taskKey = taskView.getTask().key;
+            Task.TaskKey taskKey = taskView.getFirstTask().key;
             UI_HELPER_EXECUTOR.execute(new CancellableTask<>(
                     () -> PackageManagerWrapper.getInstance()
                             .getActivityInfo(taskKey.getComponent(), taskKey.userId) == null,
@@ -626,7 +637,6 @@
      */
     protected int mRunningTaskViewId = -1;
     private int mTaskViewIdCount;
-    private final int[] INVALID_TASK_IDS = new int[]{-1, -1};
     protected boolean mRunningTaskTileHidden;
     @Nullable
     private Task[] mTmpRunningTasks;
@@ -771,6 +781,8 @@
     // keeps track of the state of the filter for tasks in recents view
     private final RecentsFilterState mFilterState = new RecentsFilterState();
 
+    private int mOffsetMidpointIndexOverride = INVALID_PAGE;
+
     public RecentsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
             BaseContainerInterface sizeStrategy) {
         super(context, attrs, defStyleAttr);
@@ -990,12 +1002,12 @@
         if (mHandleTaskStackChanges) {
             TaskView taskView = getTaskViewByTaskId(taskId);
             if (taskView != null) {
-                for (TaskIdAttributeContainer container :
-                        taskView.getTaskIdAttributeContainers()) {
+                for (TaskContainer container : taskView.getTaskContainers()) {
                     if (container == null || taskId != container.getTask().key.id) {
                         continue;
                     }
-                    container.getThumbnailView().setThumbnail(container.getTask(), thumbnailData);
+                    container.getThumbnailViewDeprecated().setThumbnail(container.getTask(),
+                            thumbnailData);
                 }
             }
         }
@@ -1006,11 +1018,11 @@
     public void onTaskIconChanged(String pkg, UserHandle user) {
         for (int i = 0; i < getTaskViewCount(); i++) {
             TaskView tv = requireTaskViewAt(i);
-            Task task = tv.getTask();
-            if (task != null && task.key != null && pkg.equals(task.key.getPackageName())
-                    && task.key.userId == user.getIdentifier()) {
+            Task task = tv.getFirstTask();
+            if (pkg.equals(task.key.getPackageName()) && task.key.userId == user.getIdentifier()) {
                 task.icon = null;
-                if (tv.getIconView().getDrawable() != null) {
+                if (tv.getTaskContainers().stream().anyMatch(
+                        container -> container.getIconView().getDrawable() != null)) {
                     tv.onTaskListVisibilityChanged(true /* visible */);
                 }
             }
@@ -1041,13 +1053,13 @@
                 continue;
             }
             // taskView could be a GroupedTaskView, so select the relevant task by ID
-            TaskIdAttributeContainer taskAttributes = taskView.getTaskAttributesById(id);
+            TaskContainer taskAttributes = taskView.getTaskContainerById(id);
             if (taskAttributes == null) {
                 continue;
             }
             Task task = taskAttributes.getTask();
             TaskThumbnailViewDeprecated taskThumbnailViewDeprecated =
-                    taskAttributes.getThumbnailView();
+                    taskAttributes.getThumbnailViewDeprecated();
             taskThumbnailViewDeprecated.setThumbnail(task, thumbnail, refreshNow);
             // thumbnailData can contain 1-2 ids, but they should correspond to the same
             // TaskView, so overwriting is ok
@@ -1129,6 +1141,7 @@
         if (FeatureFlags.enableSplitContextually()) {
             mSplitSelectStateController.unregisterSplitListener(mSplitSelectionListener);
         }
+        reset();
     }
 
     @Override
@@ -1413,7 +1426,7 @@
      */
     @Nullable
     public TaskView getTaskViewByTaskIds(int[] taskIds) {
-        if (!hasAnyValidTaskIds(taskIds)) {
+        if (!hasAllValidTaskIds(taskIds)) {
             return null;
         }
 
@@ -1432,9 +1445,11 @@
         return null;
     }
 
-    /** Returns false if {@code taskIds} is null or contains invalid values, true otherwise */
-    private boolean hasAnyValidTaskIds(int[] taskIds) {
-        return taskIds != null && !Arrays.equals(taskIds, INVALID_TASK_IDS);
+    /** Returns false if {@code taskIds} is null or contains any invalid values, true otherwise */
+    private boolean hasAllValidTaskIds(int[] taskIds) {
+        return taskIds != null
+                && taskIds.length > 0
+                && Arrays.stream(taskIds).noneMatch(taskId -> taskId == INVALID_TASK_ID);
     }
 
     public void setOverviewStateEnabled(boolean enabled) {
@@ -1701,12 +1716,18 @@
         return super.isPageScrollsInitialized() && mLoadPlanEverApplied;
     }
 
-    protected void applyLoadPlan(ArrayList<GroupTask> taskGroups) {
+    protected void applyLoadPlan(List<GroupTask> taskGroups) {
         if (mPendingAnimation != null) {
             mPendingAnimation.addEndListener(success -> applyLoadPlan(taskGroups));
             return;
         }
 
+        if (taskGroups == null) {
+            Log.d(TAG, "applyLoadPlan - taskGroups is null");
+        } else {
+            Log.d(TAG, "applyLoadPlan - taskGroups: " + taskGroups.stream().map(
+                    GroupTask::toString).toList());
+        }
         mLoadPlanEverApplied = true;
         if (taskGroups == null || taskGroups.isEmpty()) {
             removeTasksViewsAndClearAllButton();
@@ -1720,10 +1741,12 @@
             return;
         }
 
-        int[] currentTaskId = INVALID_TASK_IDS;
+        int[] currentTaskIds;
         TaskView currentTaskView = getTaskViewAt(mCurrentPage);
-        if (currentTaskView != null && currentTaskView.getTask() != null) {
-            currentTaskId = currentTaskView.getTaskIds();
+        if (currentTaskView != null) {
+            currentTaskIds = currentTaskView.getTaskIds();
+        } else {
+            currentTaskIds = new int[0];
         }
 
         // Unload existing visible task data
@@ -1735,8 +1758,8 @@
 
         // Save running task ID if it exists before rebinding all taskViews, otherwise the task from
         // the runningTaskView currently bound could get assigned to another TaskView
-        int[] runningTaskId = getTaskIdsForTaskViewId(mRunningTaskViewId);
-        int[] focusedTaskId = getTaskIdsForTaskViewId(mFocusedTaskViewId);
+        int[] runningTaskIds = getTaskIdsForTaskViewId(mRunningTaskViewId);
+        int[] focusedTaskIds = getTaskIdsForTaskViewId(mFocusedTaskViewId);
 
         // Reset the focused task to avoiding initializing TaskViews layout as focused task during
         // binding. The focused task view will be updated after all the TaskViews are bound.
@@ -1750,12 +1773,12 @@
 
         // If we are entering Overview as a result of initiating a split from somewhere else
         // (e.g. split from Home), we need to make sure the staged app is not drawn as a thumbnail.
-        int stagedTaskIdToBeRemovedFromGrid;
+        int stagedTaskIdToBeRemoved;
         if (isSplitSelectionActive()) {
-            stagedTaskIdToBeRemovedFromGrid = mSplitSelectStateController.getInitialTaskId();
+            stagedTaskIdToBeRemoved = mSplitSelectStateController.getInitialTaskId();
             updateCurrentTaskActionsVisibility();
         } else {
-            stagedTaskIdToBeRemovedFromGrid = INVALID_TASK_ID;
+            stagedTaskIdToBeRemoved = INVALID_TASK_ID;
         }
         // update the map of instance counts
         mFilterState.updateInstanceCountMap(taskGroups);
@@ -1767,46 +1790,36 @@
         // taskGroups backwards populates the thumbnail grid from least recent to most recent.
         for (int i = taskGroups.size() - 1; i >= 0; i--) {
             GroupTask groupTask = taskGroups.get(i);
-            boolean isRemovalNeeded = stagedTaskIdToBeRemovedFromGrid != INVALID_TASK_ID
-                    && groupTask.containsTask(stagedTaskIdToBeRemovedFromGrid);
+            boolean isRemovalNeeded = stagedTaskIdToBeRemoved != INVALID_TASK_ID
+                    && groupTask.containsTask(stagedTaskIdToBeRemoved);
 
-            TaskView taskView;
-            if (isRemovalNeeded && groupTask.hasMultipleTasks()) {
-                // If we need to remove half of a pair of tasks, force a TaskView with Type.SINGLE
-                // to be a temporary container for the remaining task.
-                taskView = getTaskViewFromPool(TaskView.Type.SINGLE);
-            } else {
-                taskView = getTaskViewFromPool(groupTask.taskViewType);
+            if (isRemovalNeeded && !groupTask.hasMultipleTasks()) {
+                // If the task we need to remove is not part of a pair, avoiding creating the
+                // TaskView.
+                continue;
             }
 
-            addView(taskView);
-
-            if (isRemovalNeeded && groupTask.hasMultipleTasks()) {
-                if (groupTask.task1.key.id == stagedTaskIdToBeRemovedFromGrid) {
-                    taskView.bind(groupTask.task2, mOrientationState);
-                } else {
-                    taskView.bind(groupTask.task1, mOrientationState);
-                }
-            } else if (isRemovalNeeded) {
-                // If the task we need to remove is not part of a pair, bind it to the TaskView
-                // first (to prevent problems), then remove the whole thing.
-                taskView.bind(groupTask.task1, mOrientationState);
-                removeView(taskView);
-            } else if (taskView instanceof GroupedTaskView) {
+            // If we need to remove half of a pair of tasks, force a TaskView with Type.SINGLE
+            // to be a temporary container for the remaining task.
+            TaskView taskView = getTaskViewFromPool(
+                    isRemovalNeeded ? TaskView.Type.SINGLE : groupTask.taskViewType);
+            if (taskView instanceof GroupedTaskView) {
                 boolean firstTaskIsLeftTopTask =
                         groupTask.mSplitBounds.leftTopTaskId == groupTask.task1.key.id;
                 Task leftTopTask = firstTaskIsLeftTopTask ? groupTask.task1 : groupTask.task2;
                 Task rightBottomTask = firstTaskIsLeftTopTask ? groupTask.task2 : groupTask.task1;
-
                 ((GroupedTaskView) taskView).bind(leftTopTask, rightBottomTask, mOrientationState,
-                        groupTask.mSplitBounds);
+                        mTaskOverlayFactory, groupTask.mSplitBounds);
             } else if (taskView instanceof DesktopTaskView) {
                 ((DesktopTaskView) taskView).bind(((DesktopTask) groupTask).tasks,
-                        mOrientationState);
+                        mOrientationState, mTaskOverlayFactory);
                 mDesktopTaskView = (DesktopTaskView) taskView;
             } else {
-                taskView.bind(groupTask.task1, mOrientationState);
+                Task task = groupTask.task1.key.id == stagedTaskIdToBeRemoved ? groupTask.task2
+                        : groupTask.task1;
+                taskView.bind(task, mOrientationState, mTaskOverlayFactory);
             }
+            addView(taskView);
 
             // enables instance filtering if the feature flag for it is on
             if (FeatureFlags.ENABLE_MULTI_INSTANCE.get()) {
@@ -1819,7 +1832,7 @@
         }
 
         // Keep same previous focused task
-        TaskView newFocusedTaskView = getTaskViewByTaskIds(focusedTaskId);
+        TaskView newFocusedTaskView = getTaskViewByTaskIds(focusedTaskIds);
         // If the list changed, maybe the focused task doesn't exist anymore
         if (newFocusedTaskView == null && getTaskViewCount() > 0) {
             newFocusedTaskView = getTaskViewAt(0);
@@ -1830,10 +1843,10 @@
         updateChildTaskOrientations();
 
         TaskView newRunningTaskView = null;
-        if (hasAnyValidTaskIds(runningTaskId)) {
+        if (hasAllValidTaskIds(runningTaskIds)) {
             // Update mRunningTaskViewId to be the new TaskView that was assigned by binding
             // the full list of tasks to taskViews
-            newRunningTaskView = getTaskViewByTaskIds(runningTaskId);
+            newRunningTaskView = getTaskViewByTaskIds(runningTaskIds);
             if (newRunningTaskView != null) {
                 setRunningTaskViewId(newRunningTaskView.getTaskViewId());
             } else {
@@ -1853,8 +1866,8 @@
         if (mNextPage != INVALID_PAGE) {
             // Restore mCurrentPage but don't call setCurrentPage() as that clobbers the scroll.
             mCurrentPage = previousCurrentPage;
-            if (hasAnyValidTaskIds(currentTaskId)) {
-                currentTaskView = getTaskViewByTaskIds(currentTaskId);
+            if (hasAllValidTaskIds(currentTaskIds)) {
+                currentTaskView = getTaskViewByTaskIds(currentTaskIds);
                 if (currentTaskView != null) {
                     targetPage = indexOfChild(currentTaskView);
                 }
@@ -1863,7 +1876,7 @@
             targetPage = previousFocusedPage;
         } else {
             // Set the current page to the running task, but not if settling on new task.
-            if (hasAnyValidTaskIds(runningTaskId)) {
+            if (hasAllValidTaskIds(runningTaskIds)) {
                 targetPage = indexOfChild(newRunningTaskView);
             } else if (getTaskViewCount() > 0) {
                 targetPage = indexOfChild(requireTaskViewAt(0));
@@ -1963,7 +1976,8 @@
     public void resetTaskVisuals() {
         for (int i = getTaskViewCount() - 1; i >= 0; i--) {
             TaskView taskView = requireTaskViewAt(i);
-            if (mIgnoreResetTaskId != taskView.getTaskIds()[0]) {
+            if (Arrays.stream(taskView.getTaskIds()).noneMatch(
+                    taskId -> taskId == mIgnoreResetTaskId)) {
                 taskView.resetViewTransforms();
                 taskView.setIconScaleAndDim(mTaskIconScaledDown ? 0 : 1);
                 taskView.setStableAlpha(mContentAlpha);
@@ -2000,6 +2014,9 @@
 
     public void setFullscreenProgress(float fullscreenProgress) {
         mFullscreenProgress = fullscreenProgress;
+        if (enableRefactorTaskThumbnail()) {
+            mRecentsViewData.getFullscreenProgress().setValue(mFullscreenProgress);
+        }
         int taskCount = getTaskViewCount();
         for (int i = 0; i < taskCount; i++) {
             requireTaskViewAt(i).setFullscreenProgress(mFullscreenProgress);
@@ -2007,7 +2024,7 @@
         mClearAllButton.setFullscreenProgress(fullscreenProgress);
 
         // Fade out the actions view quickly (0.1 range)
-        mActionsView.getFullscreenAlpha().setValue(
+        mActionsView.getFullscreenAlpha().updateValue(
                 mapToRange(fullscreenProgress, 0, 0.1f, 1f, 0f, LINEAR));
     }
 
@@ -2063,12 +2080,17 @@
                 : View.LAYOUT_DIRECTION_RTL);
         mClearAllButton.setRotation(getPagedOrientationHandler().getDegreesRotated());
 
-        if (forceRecreateDragLayerControllers
-                || !getPagedOrientationHandler().equals(oldOrientationHandler)) {
+        boolean isOrientationHandlerChanged =
+                !getPagedOrientationHandler().equals(oldOrientationHandler);
+        if (forceRecreateDragLayerControllers || isOrientationHandlerChanged) {
             // Changed orientations, update controllers so they intercept accordingly.
             mContainer.getDragLayer().recreateControllers();
             onOrientationChanged();
             resetTaskVisuals();
+            // Log fake orientation changed.
+            if (isOrientationHandlerChanged) {
+                logOrientationChanged();
+            }
         }
 
         boolean isInLandscape = mOrientationState.getTouchRotation() != ROTATION_0
@@ -2153,7 +2175,8 @@
         }
         for (int i = 0; i < taskCount; i++) {
             TaskView taskView = requireTaskViewAt(i);
-            taskView.updateTaskSize();
+            taskView.updateTaskSize(mLastComputedTaskSize, mLastComputedGridTaskSize,
+                    mLastComputedCarouselTaskSize);
             taskView.setNonGridTranslationX(accumulatedTranslationX);
             taskView.setNonGridPivotTranslationX(translateXToMiddle);
             // Compensate space caused by TaskView scaling.
@@ -2258,8 +2281,8 @@
     }
 
     private void animateActionsViewAlpha(float alphaValue, long duration) {
-        mActionsViewAlphaAnimator = ObjectAnimator.ofFloat(
-                mActionsView.getVisibilityAlpha(), MULTI_PROPERTY_VALUE, alphaValue);
+        mActionsViewAlphaAnimator = ObjectAnimator.ofFloat(mActionsView.getVisibilityAlpha(),
+                AnimatedFloat.VALUE, alphaValue);
         mActionsViewAlphaAnimatorFinalValue = alphaValue;
         mActionsViewAlphaAnimator.setDuration(duration);
         // Set autocancel to prevent race-conditiony setting of alpha from other animations
@@ -2278,7 +2301,7 @@
         mClearAllButton.onRecentsViewScroll(scroll, mOverviewGridEnabled);
 
         // Clear all button alpha was set by the previous line.
-        mActionsView.getIndexScrollAlpha().setValue(1 - mClearAllButton.getScrollAlpha());
+        mActionsView.getIndexScrollAlpha().updateValue(1 - mClearAllButton.getScrollAlpha());
     }
 
     @Override
@@ -2342,8 +2365,8 @@
         // Update the task data for the in/visible children
         for (int i = 0; i < getTaskViewCount(); i++) {
             TaskView taskView = requireTaskViewAt(i);
-            TaskIdAttributeContainer[] containers = taskView.getTaskIdAttributeContainers();
-            if (containers[0] == null && containers[1] == null) {
+            List<TaskContainer> containers = taskView.getTaskContainers();
+            if (containers.isEmpty()) {
                 continue;
             }
             int index = indexOfChild(taskView);
@@ -2355,8 +2378,8 @@
             }
             if (visible) {
                 // Default update all non-null tasks, then remove running ones
-                List<Task> tasksToUpdate = Arrays.stream(containers).filter(Objects::nonNull)
-                        .map(TaskIdAttributeContainer::getTask)
+                List<Task> tasksToUpdate = containers.stream()
+                        .map(TaskContainer::getTask)
                         .collect(Collectors.toCollection(ArrayList::new));
                 if (mTmpRunningTasks != null) {
                     for (Task t : mTmpRunningTasks) {
@@ -2381,7 +2404,7 @@
                     mHasVisibleTaskData.put(task.key.id, visible);
                 }
             } else {
-                for (TaskIdAttributeContainer container : containers) {
+                for (TaskContainer container : containers) {
                     if (container == null) {
                         continue;
                     }
@@ -2498,7 +2521,7 @@
         // For now 2 distinct task IDs is max for split screen
         TaskView runningTaskView = getTaskViewFromTaskViewId(taskViewId);
         if (runningTaskView == null) {
-            return INVALID_TASK_IDS;
+            return new int[0];
         }
 
         return runningTaskView.getTaskIds();
@@ -2587,7 +2610,7 @@
      */
     public void onGestureAnimationStart(
             Task[] runningTasks, RotationTouchHelper rotationTouchHelper) {
-        Log.d(TAG, "onGestureAnimationStart");
+        Log.d(TAG, "onGestureAnimationStart - runningTasks: " + Arrays.toString(runningTasks));
         mActiveGestureRunningTasks = runningTasks;
         // This needs to be called before the other states are set since it can create the task view
         if (mOrientationState.setGestureActive(true)) {
@@ -2736,22 +2759,19 @@
      * Returns true if we should add a stub taskView for the running task id
      */
     protected boolean shouldAddStubTaskView(Task[] runningTasks) {
-        TaskView taskView = getTaskViewByTaskId(runningTasks[0].key.id);
-        if (taskView == null) {
-            // No TaskView found, add a stub task.
-            return true;
-        }
-
-        if (runningTasks.length > 1) {
-            // Ensure all taskIds matches the TaskView, otherwise add a stub task.
-            return Arrays.stream(runningTasks).anyMatch(
-                    runningTask -> !taskView.containsTaskId(runningTask.key.id));
+        int[] runningTaskIds = Arrays.stream(runningTasks).mapToInt(task -> task.key.id).toArray();
+        TaskView matchingTaskView = null;
+        if (hasDesktopTask(runningTasks) && runningTaskIds.length == 1) {
+            // TODO(b/249371338): Unsure if it's expected, desktop runningTasks only have a single
+            // taskId, therefore we match any DesktopTaskView that contains the runningTaskId.
+            TaskView taskview = getTaskViewByTaskId(runningTaskIds[0]);
+            if (taskview instanceof DesktopTaskView) {
+                matchingTaskView = taskview;
+            }
         } else {
-            // Ensure the TaskView only contains a single taskId, or is a DesktopTask,
-            // otherwise add a stub task.
-            // TODO(b/249371338): Figure out why DesktopTask only have a single runningTask.
-            return taskView.containsMultipleTasks() && !taskView.isDesktopTask();
+            matchingTaskView = getTaskViewByTaskIds(runningTaskIds);
         }
+        return matchingTaskView == null;
     }
 
     /**
@@ -2761,6 +2781,7 @@
      * is called.  Also scrolls the view to this task.
      */
     private void showCurrentTask(Task[] runningTasks) {
+        Log.d(TAG, "showCurrentTask - runningTasks: " + Arrays.toString(runningTasks));
         if (runningTasks.length == 0) {
             return;
         }
@@ -2774,26 +2795,24 @@
             if (needDesktopTask) {
                 taskView = getTaskViewFromPool(TaskView.Type.DESKTOP);
                 mTmpRunningTasks = Arrays.copyOf(runningTasks, runningTasks.length);
-                addView(taskView, 0);
                 ((DesktopTaskView) taskView).bind(Arrays.asList(mTmpRunningTasks),
-                        mOrientationState);
+                        mOrientationState, mTaskOverlayFactory);
             } else if (needGroupTaskView) {
                 taskView = getTaskViewFromPool(TaskView.Type.GROUPED);
                 mTmpRunningTasks = new Task[]{runningTasks[0], runningTasks[1]};
-                addView(taskView, 0);
                 // When we create a placeholder task view mSplitBoundsConfig will be null, but with
                 // the actual app running we won't need to show the thumbnail until all the tasks
                 // load later anyways
                 ((GroupedTaskView)taskView).bind(mTmpRunningTasks[0], mTmpRunningTasks[1],
-                        mOrientationState, mSplitBoundsConfig);
+                        mOrientationState, mTaskOverlayFactory, mSplitBoundsConfig);
             } else {
                 taskView = getTaskViewFromPool(TaskView.Type.SINGLE);
-                addView(taskView, 0);
                 // The temporary running task is only used for the duration between the start of the
                 // gesture and the task list is loaded and applied
                 mTmpRunningTasks = new Task[]{runningTasks[0]};
-                taskView.bind(mTmpRunningTasks[0], mOrientationState);
+                taskView.bind(mTmpRunningTasks[0], mOrientationState, mTaskOverlayFactory);
             }
+            addView(taskView, 0);
             runningTaskViewId = taskView.getTaskViewId();
             if (wasEmpty) {
                 addView(mClearAllButton);
@@ -2891,7 +2910,7 @@
         mRunningTaskShowScreenshot = showScreenshot;
         TaskView runningTaskView = getRunningTaskView();
         if (runningTaskView != null) {
-            runningTaskView.setShowScreenshot(mRunningTaskShowScreenshot);
+            runningTaskView.setShouldShowScreenshot(mRunningTaskShowScreenshot);
         }
     }
 
@@ -3735,7 +3754,7 @@
                 if (taskView == nextFocusedTaskView) {
                     // Enlarge the task to be focused next, and translate into focus position.
                     float scale = mTaskWidth / (float) mLastComputedGridTaskSize.width();
-                    anim.setFloat(taskView, TaskView.SNAPSHOT_SCALE, scale,
+                    anim.setFloat(taskView, TaskView.DISMISS_SCALE, scale,
                             clampToProgress(LINEAR, animationStartProgress,
                                     dismissTranslationInterpolationEnd));
                     anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(),
@@ -3806,19 +3825,17 @@
 
                 if (success) {
                     if (shouldRemoveTask) {
-                        if (dismissedTaskView.getTask() != null) {
-                            if (dismissedTaskView.isRunningTask()) {
-                                finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
-                                        () -> removeTaskInternal(dismissedTaskViewId));
-                            } else {
-                                removeTaskInternal(dismissedTaskViewId);
-                            }
-                            announceForAccessibility(
-                                    getResources().getString(R.string.task_view_closed));
-                            mContainer.getStatsLogManager().logger()
-                                    .withItemInfo(dismissedTaskView.getItemInfo())
-                                    .log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
+                        if (dismissedTaskView.isRunningTask()) {
+                            finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
+                                    () -> removeTaskInternal(dismissedTaskViewId));
+                        } else {
+                            removeTaskInternal(dismissedTaskViewId);
                         }
+                        announceForAccessibility(
+                                getResources().getString(R.string.task_view_closed));
+                        mContainer.getStatsLogManager().logger()
+                                .withItemInfo(dismissedTaskView.getFirstItemInfo())
+                                .log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
                     }
 
                     int pageToSnapTo = mCurrentPage;
@@ -3867,7 +3884,8 @@
                                         taskViewIdArray.removeValue(
                                                 finalNextFocusedTaskView.getTaskViewId());
                                     }
-                                    if (snappedIndex < taskViewIdArray.size()) {
+                                    if (snappedIndex >= 0
+                                            && snappedIndex < taskViewIdArray.size()) {
                                         taskViewIdToSnapTo = taskViewIdArray.get(snappedIndex);
                                     } else if (snappedIndex == taskViewIdArray.size()) {
                                         // If the snapped task is the last item from the
@@ -4001,7 +4019,9 @@
      * * Device is large screen
      */
     private void updateCurrentTaskActionsVisibility() {
-        boolean isCurrentSplit = getCurrentPageTaskView() instanceof GroupedTaskView;
+        TaskView taskView = getCurrentPageTaskView();
+        boolean isCurrentSplit = taskView instanceof GroupedTaskView;
+        GroupedTaskView groupedTaskView = isCurrentSplit ? (GroupedTaskView) taskView : null;
         // Update flags to see if entire actions bar should be hidden.
         if (!FeatureFlags.enableAppPairs()) {
             mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SCREEN, isCurrentSplit);
@@ -4009,9 +4029,11 @@
         mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SELECT_ACTIVE, isSplitSelectionActive());
         // Update flags to see if actions bar should show buttons for a single task or a pair of
         // tasks.
-        mActionsView.updateForGroupedTask(isCurrentSplit);
+        boolean canSaveAppPair = isCurrentSplit && supportsAppPairs() &&
+                getSplitSelectController().getAppPairsController().canSaveAppPair(groupedTaskView);
+        mActionsView.updateForGroupedTask(isCurrentSplit, canSaveAppPair);
 
-        boolean isCurrentDesktop = getCurrentPageTaskView() instanceof DesktopTaskView;
+        boolean isCurrentDesktop = taskView instanceof DesktopTaskView;
         mActionsView.updateHiddenFlags(HIDDEN_DESKTOP, isCurrentDesktop);
     }
 
@@ -4273,13 +4295,10 @@
         alpha = Utilities.boundToRange(alpha, 0, 1);
         mContentAlpha = alpha;
 
-        int runningTaskId = getTaskIdsForRunningTaskView()[0];
+        TaskView runningTaskView = getRunningTaskView();
         for (int i = getTaskViewCount() - 1; i >= 0; i--) {
             TaskView child = requireTaskViewAt(i);
-            int[] childTaskIds = child.getTaskIds();
-            if (runningTaskId != INVALID_TASK_ID
-                    && mRunningTaskTileHidden
-                    && (childTaskIds[0] == runningTaskId || childTaskIds[1] == runningTaskId)) {
+            if (runningTaskView != null && mRunningTaskTileHidden && child == runningTaskView) {
                 continue;
             }
             child.setStableAlpha(alpha);
@@ -4288,7 +4307,7 @@
         int alphaInt = Math.round(alpha * 255);
         mEmptyMessagePaint.setAlpha(alphaInt);
         mEmptyIcon.setAlpha(alphaInt);
-        mActionsView.getContentAlpha().setValue(mContentAlpha);
+        mActionsView.getContentAlpha().updateValue(mContentAlpha);
 
         if (alpha > 0) {
             setVisibility(VISIBLE);
@@ -4334,7 +4353,10 @@
     public void updateRecentsRotation() {
         final int rotation = TraceHelper.allowIpcs(
                 "RecentsView.updateRecentsRotation", () -> mContainer.getDisplay().getRotation());
-        mOrientationState.setRecentsRotation(rotation);
+        // Log real orientation change.
+        if (mOrientationState.setRecentsRotation(rotation)) {
+            logOrientationChanged();
+        }
     }
 
     public void setLayoutRotation(int touchRotation, int displayRotation) {
@@ -4460,15 +4482,26 @@
         setPivotY(mTempPointF.y);
     }
 
+    /**
+     * Sets whether we should force-override the page offset mid-point to the current task, rather
+     * than the running task, when updating page offsets.
+     */
+    public void setOffsetMidpointIndexOverride(int offsetMidpointIndexOverride) {
+        mOffsetMidpointIndexOverride = offsetMidpointIndexOverride;
+        updatePageOffsets();
+    }
+
     private void updatePageOffsets() {
         float offset = mAdjacentPageHorizontalOffset;
         float modalOffset = ACCELERATE_0_75.getInterpolation(mTaskModalness);
         int count = getChildCount();
         boolean showAsGrid = showAsGrid();
 
-        TaskView runningTask = mRunningTaskViewId == -1 || !mRunningTaskTileHidden
+        TaskView runningTask = mRunningTaskViewId == INVALID_PAGE || !mRunningTaskTileHidden
                 ? null : getRunningTaskView();
-        int midpoint = runningTask == null ? -1 : indexOfChild(runningTask);
+        int midpoint = mOffsetMidpointIndexOverride == INVALID_PAGE
+                ? (runningTask == null ? INVALID_PAGE : indexOfChild(runningTask))
+                : mOffsetMidpointIndexOverride;
         int modalMidpoint = getCurrentPage();
         boolean isModalGridWithoutFocusedTask =
                 showAsGrid && enableGridOnlyOverview() && mTaskModalness > 0;
@@ -4712,7 +4745,8 @@
      */
     public void resetModalVisuals() {
         if (mSelectedTask != null) {
-            mSelectedTask.getThumbnail().getTaskOverlay().resetModalVisuals();
+            mSelectedTask.taskContainers.forEach(
+                    taskContainer -> taskContainer.getOverlay().resetModalVisuals());
         }
     }
 
@@ -4730,8 +4764,8 @@
     public void initiateSplitSelect(TaskView taskView, @StagePosition int stagePosition,
             StatsLogManager.EventEnum splitEvent) {
         mSplitHiddenTaskView = taskView;
-        mSplitSelectStateController.setInitialTaskSelect(null /*intent*/,
-                stagePosition, taskView.getItemInfo(), splitEvent, taskView.mTask.key.id);
+        mSplitSelectStateController.setInitialTaskSelect(null /*intent*/, stagePosition,
+                taskView.getFirstItemInfo(), splitEvent, taskView.getFirstTask().key.id);
         mSplitSelectStateController.setAnimateCurrentTaskDismissal(
                 true /*animateCurrentTaskDismissal*/);
         mSplitHiddenTaskViewIndex = indexOfChild(taskView);
@@ -4753,7 +4787,7 @@
 
         // Prevent dismissing whole task if we're only initiating from one of 2 tasks in split pair
         mSplitSelectStateController.setDismissingFromSplitPair(mSplitHiddenTaskView != null
-                && mSplitHiddenTaskView.containsMultipleTasks());
+                && mSplitHiddenTaskView instanceof GroupedTaskView);
         mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
                 splitSelectSource.position.stagePosition, splitSelectSource.itemInfo,
                 splitSelectSource.splitEvent, splitSelectSource.alreadyRunningTaskId);
@@ -4774,19 +4808,19 @@
                 mSplitSelectStateController.isAnimateCurrentTaskDismissal();
         boolean isInitiatingTaskViewSplitPair =
                 mSplitSelectStateController.isDismissingFromSplitPair();
-        if (isInitiatingSplitFromTaskView && isInitiatingTaskViewSplitPair) {
+        if (isInitiatingSplitFromTaskView && isInitiatingTaskViewSplitPair
+                && mSplitHiddenTaskView instanceof GroupedTaskView) {
             // Splitting from Overview for split pair task
             createInitialSplitSelectAnimation(builder);
 
             // Animate pair thumbnail into full thumbnail
-            boolean primaryTaskSelected =
-                    mSplitHiddenTaskView.getTaskIdAttributeContainers()[0].getTask().key.id ==
-                            mSplitSelectStateController.getInitialTaskId();
-            TaskIdAttributeContainer taskIdAttributeContainer = mSplitHiddenTaskView
-                    .getTaskIdAttributeContainers()[primaryTaskSelected ? 1 : 0];
-            TaskThumbnailViewDeprecated thumbnail = taskIdAttributeContainer.getThumbnailView();
+            boolean primaryTaskSelected = mSplitHiddenTaskView.getTaskIds()[0]
+                    == mSplitSelectStateController.getInitialTaskId();
+            TaskContainer taskContainer = mSplitHiddenTaskView
+                    .getTaskContainers().get(primaryTaskSelected ? 1 : 0);
+            TaskThumbnailViewDeprecated thumbnail = taskContainer.getThumbnailViewDeprecated();
             mSplitSelectStateController.getSplitAnimationController()
-                    .addInitialSplitFromPair(taskIdAttributeContainer, builder,
+                    .addInitialSplitFromPair(taskContainer, builder,
                             mContainer.getDeviceProfile(),
                             mSplitHiddenTaskView.getWidth(), mSplitHiddenTaskView.getHeight(),
                             primaryTaskSelected);
@@ -5184,7 +5218,7 @@
         updateGridProperties();
         updateScrollSynchronously();
 
-        int targetSysUiFlags = tv.getThumbnail().getSysUiStatusNavFlags();
+        int targetSysUiFlags = tv.getFirstThumbnailViewDeprecated().getSysUiStatusNavFlags();
         final boolean[] passedOverviewThreshold = new boolean[] {false};
         ValueAnimator progressAnim = ValueAnimator.ofFloat(0, 1);
         progressAnim.addUpdateListener(animator -> {
@@ -5232,7 +5266,8 @@
         mPendingAnimation.addOnFrameCallback(this::redrawLiveTile);
         mPendingAnimation.addEndListener(isSuccess -> {
             if (isSuccess) {
-                if (tv.getTaskIds()[1] != -1 && mRemoteTargetHandles != null) {
+                if (tv instanceof GroupedTaskView && hasAllValidTaskIds(tv.getTaskIds())
+                        && mRemoteTargetHandles != null) {
                     // TODO(b/194414938): make this part of the animations instead.
                     TaskViewUtils.createSplitAuxiliarySurfacesAnimator(
                             mRemoteTargetHandles[0].getTransformParams().getTargetSet().nonApps,
@@ -5247,11 +5282,8 @@
                 } else {
                     tv.launchTask(this::onTaskLaunchAnimationEnd);
                 }
-                Task task = tv.getTask();
-                if (task != null) {
-                    mContainer.getStatsLogManager().logger().withItemInfo(tv.getItemInfo())
-                            .log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN);
-                }
+                mContainer.getStatsLogManager().logger().withItemInfo(tv.getFirstItemInfo())
+                        .log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN);
             } else {
                 onTaskLaunchAnimationEnd(false);
             }
@@ -5260,10 +5292,11 @@
         return mPendingAnimation;
     }
 
-    protected void onTaskLaunchAnimationEnd(boolean success) {
+    protected Unit onTaskLaunchAnimationEnd(boolean success) {
         if (success) {
             resetTaskVisuals();
         }
+        return Unit.INSTANCE;
     }
 
     @Override
@@ -5457,8 +5490,9 @@
      * Called when a running recents animation has finished or canceled.
      */
     public void onRecentsAnimationComplete() {
-        Log.d(TAG, "onRecentsAnimationComplete - mRecentsAnimationController: "
-                + mRecentsAnimationController);
+        Log.d(TAG, "onRecentsAnimationComplete "
+                + "- mRecentsAnimationController: " + mRecentsAnimationController
+                + ", mSideTaskLaunchCallback: " + mSideTaskLaunchCallback);
         // At this point, the recents animation is not running and if the animation was canceled
         // by a display rotation then reset this state to show the screenshot
         setRunningTaskViewShowScreenshot(true);
@@ -5878,16 +5912,15 @@
             return;
         }
 
-        taskView.setShowScreenshot(true);
-        for (TaskIdAttributeContainer container :
-                taskView.getTaskIdAttributeContainers()) {
+        taskView.setShouldShowScreenshot(true);
+        for (TaskContainer container : taskView.getTaskContainers()) {
             if (container == null) {
                 continue;
             }
 
             ThumbnailData td =
                     mRecentsAnimationController.screenshotTask(container.getTask().key.id);
-            TaskThumbnailViewDeprecated thumbnailView = container.getThumbnailView();
+            TaskThumbnailViewDeprecated thumbnailView = container.getThumbnailViewDeprecated();
             if (td != null) {
                 thumbnailView.setThumbnail(container.getTask(), td);
             } else {
@@ -5908,7 +5941,7 @@
             Runnable onFinishRunnable) {
         final TaskView taskView = getRunningTaskView();
         if (taskView != null) {
-            taskView.setShowScreenshot(true);
+            taskView.setShouldShowScreenshot(true);
             taskView.refreshThumbnails(thumbnailDatas);
             ViewUtils.postFrameDrawn(taskView, onFinishRunnable);
         } else {
@@ -6012,7 +6045,8 @@
     }
 
     public void cleanupRemoteTargets() {
-        Log.d(TAG, "cleanupRemoteTargets");
+        Log.d(TAG, "cleanupRemoteTargets - mRemoteTargetHandles: " + Arrays.toString(
+                mRemoteTargetHandles));
         mRemoteTargetHandles = null;
     }
 
@@ -6249,7 +6283,7 @@
     /**
      * Moves the provided task into desktop mode, and invoke {@code successCallback} if succeeded.
      */
-    public void moveTaskToDesktop(TaskIdAttributeContainer taskContainer,
+    public void moveTaskToDesktop(TaskContainer taskContainer,
             Runnable successCallback) {
         if (!DesktopModeStatus.canEnterDesktopMode(mContext)) {
             return;
@@ -6258,7 +6292,7 @@
                 () -> moveTaskToDesktopInternal(taskContainer, successCallback)));
     }
 
-    private void moveTaskToDesktopInternal(TaskIdAttributeContainer taskContainer,
+    private void moveTaskToDesktopInternal(TaskContainer taskContainer,
             Runnable successCallback) {
         if (mDesktopRecentsTransitionController == null) {
             return;
@@ -6267,6 +6301,24 @@
         successCallback.run();
     }
 
+    // Logs when the orientation of Overview changes. We log both real and fake orientation changes.
+    private void logOrientationChanged() {
+        // Only log when Overview is showing.
+        if (mOverviewStateEnabled) {
+            mContainer.getStatsLogManager()
+                    .logger()
+                    .withContainerInfo(
+                            LauncherAtom.ContainerInfo.newBuilder()
+                                    .setTaskSwitcherContainer(
+                                            LauncherAtom.TaskSwitcherContainer.newBuilder()
+                                                    .setOrientationHandler(
+                                                            getPagedOrientationHandler()
+                                                                    .getHandlerTypeForLogging()))
+                                    .build())
+                    .log(LAUNCHER_OVERVIEW_ORIENTATION_CHANGED);
+        }
+    }
+
     public interface TaskLaunchListener {
         void onTaskLaunched();
     }
diff --git a/src/com/android/quickstep/views/RecentsViewContainer.java b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
similarity index 80%
rename from src/com/android/quickstep/views/RecentsViewContainer.java
rename to quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
index 0c3f4f1..060c71e 100644
--- a/src/com/android/quickstep/views/RecentsViewContainer.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
@@ -27,6 +27,7 @@
 import android.view.Window;
 
 import com.android.launcher3.BaseActivity;
+import com.android.launcher3.logger.LauncherAtom;
 import com.android.launcher3.util.SystemUiController;
 import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.views.ScrimView;
@@ -165,4 +166,36 @@
      * Begins transition from overview back to homescreen
      */
     void returnToHomescreen();
+
+    /**
+     * True if the overview panel is visible.
+     * @return Boolean
+     */
+    boolean isRecentsViewVisible();
+
+    /**
+     * Overwrites any logged item in Launcher that doesn't have a container with the
+     * {@link com.android.launcher3.touch.PagedOrientationHandler} in use for Overview.
+     *
+     * @param itemInfoBuilder {@link LauncherAtom.ItemInfo.Builder}
+     */
+    default void applyOverwritesToLogItem(LauncherAtom.ItemInfo.Builder itemInfoBuilder) {
+        if (!itemInfoBuilder.getContainerInfo().hasTaskSwitcherContainer()) {
+            return;
+        }
+
+        if (!isRecentsViewVisible()) {
+            return;
+        }
+
+        RecentsView<?, ?> recentsView = getOverviewPanel();
+        var orientationForLogging =
+                recentsView.getPagedOrientationHandler().getHandlerTypeForLogging();
+        itemInfoBuilder.setContainerInfo(
+                LauncherAtom.ContainerInfo.newBuilder()
+                        .setTaskSwitcherContainer(
+                                LauncherAtom.TaskSwitcherContainer.newBuilder()
+                                        .setOrientationHandler(orientationForLogging))
+                        .build());
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index 443f83c..59ffc39 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -18,8 +18,6 @@
 
 import static com.android.app.animation.Interpolators.EMPHASIZED;
 import static com.android.launcher3.Flags.enableOverviewIconMenu;
-import static com.android.launcher3.testing.shared.TestProtocol.TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE;
-import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
 import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.quickstep.views.TaskThumbnailViewDeprecated.DIM_ALPHA;
@@ -56,7 +54,7 @@
 import com.android.quickstep.TaskUtils;
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
 import com.android.quickstep.util.TaskCornerRadius;
-import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
+import com.android.quickstep.views.TaskView.TaskContainer;
 
 /**
  * Contains options for a recent task when long-pressing its icon.
@@ -76,7 +74,7 @@
     private ValueAnimator mRevealAnimator;
     @Nullable private Runnable mOnClosingStartCallback;
     private TaskView mTaskView;
-    private TaskIdAttributeContainer mTaskContainer;
+    private TaskContainer mTaskContainer;
     private LinearLayout mOptionLayout;
     private float mMenuTranslationYBeforeOpen;
     private float mMenuTranslationXBeforeOpen;
@@ -163,7 +161,10 @@
         }
     }
 
-    public static boolean showForTask(TaskIdAttributeContainer taskContainer,
+    /**
+     * Show a task menu for the given taskContainer.
+     */
+    public static boolean showForTask(TaskContainer taskContainer,
             @Nullable Runnable onClosingStartCallback) {
         RecentsViewContainer container = RecentsViewContainer.containerFromContext(
                 taskContainer.getTaskView().getContext());
@@ -173,11 +174,14 @@
         return taskMenuView.populateAndShowForTask(taskContainer);
     }
 
-    public static boolean showForTask(TaskIdAttributeContainer taskContainer) {
+    /**
+     * Show a task menu for the given taskContainer.
+     */
+    public static boolean showForTask(TaskContainer taskContainer) {
         return showForTask(taskContainer, null);
     }
 
-    private boolean populateAndShowForTask(TaskIdAttributeContainer taskContainer) {
+    private boolean populateAndShowForTask(TaskContainer taskContainer) {
         if (isAttachedToWindow()) {
             return false;
         }
@@ -198,7 +202,7 @@
         return true;
     }
 
-    private void addMenuOptions(TaskIdAttributeContainer taskContainer) {
+    private void addMenuOptions(TaskContainer taskContainer) {
         if (enableOverviewIconMenu()) {
             removeView(mTaskName);
         } else {
@@ -226,7 +230,7 @@
         mOptionLayout.addView(menuOptionView);
     }
 
-    private void orientAroundTaskView(TaskIdAttributeContainer taskContainer) {
+    private void orientAroundTaskView(TaskContainer taskContainer) {
         RecentsView recentsView = mContainer.getOverviewPanel();
         RecentsPagedOrientationHandler orientationHandler =
                 recentsView.getPagedOrientationHandler();
@@ -237,12 +241,13 @@
         mContainer.getDragLayer().getDescendantRectRelativeToSelf(
                 enableOverviewIconMenu()
                         ? getIconView().findViewById(R.id.icon_view_menu_anchor)
-                        : taskContainer.getThumbnailView(),
+                        : taskContainer.getThumbnailViewDeprecated(),
                 sTempRect);
         Rect insets = mContainer.getDragLayer().getInsets();
         BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) getLayoutParams();
-        params.width = orientationHandler.getTaskMenuWidth(taskContainer.getThumbnailView(),
-                deviceProfile, taskContainer.getStagePosition());
+        params.width = orientationHandler.getTaskMenuWidth(
+                taskContainer.getThumbnailViewDeprecated(), deviceProfile,
+                taskContainer.getStagePosition());
         // Gravity set to Left instead of Start as sTempRect.left measures Left distance not Start
         params.gravity = Gravity.LEFT;
         setLayoutParams(params);
@@ -275,10 +280,10 @@
             // Margin that insets the menuView inside the taskView
             float taskInsetMargin = getResources().getDimension(R.dimen.task_card_margin);
             setTranslationX(orientationHandler.getTaskMenuX(thumbnailAlignedX,
-                    mTaskContainer.getThumbnailView(), deviceProfile, taskInsetMargin,
+                    mTaskContainer.getThumbnailViewDeprecated(), deviceProfile, taskInsetMargin,
                     getIconView()));
             setTranslationY(orientationHandler.getTaskMenuY(
-                    thumbnailAlignedY, mTaskContainer.getThumbnailView(),
+                    thumbnailAlignedY, mTaskContainer.getThumbnailViewDeprecated(),
                     mTaskContainer.getStagePosition(), this, taskInsetMargin,
                     getIconView()));
         }
@@ -301,7 +306,6 @@
 
     private void animateOpenOrClosed(boolean closing) {
         if (mOpenCloseAnimator != null && mOpenCloseAnimator.isRunning()) {
-            testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE, "getting canceled");
             mOpenCloseAnimator.cancel();
         }
         mOpenCloseAnimator = new AnimatorSet();
@@ -358,24 +362,18 @@
                     iconAppChip.getMenuTranslationX(),
                     MULTI_PROPERTY_VALUE, closing ? 0 : -additionalTranslationX);
             menuTranslationXAnim.setInterpolator(EMPHASIZED);
-            testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE,
-                    "TaskMenuView.java.animateOpenOrClosed: running translation animations");
 
             mOpenCloseAnimator.playTogether(translationYAnim, translationXAnim,
                     menuTranslationXAnim, menuTranslationYAnim);
         }
-        testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE,
-                "TaskMenuView.java.animateOpenOrClosed: running animation 2");
         mOpenCloseAnimator.playTogether(mRevealAnimator,
                 ObjectAnimator.ofFloat(
-                        mTaskContainer.getThumbnailView(), DIM_ALPHA,
+                        mTaskContainer.getThumbnailViewDeprecated(), DIM_ALPHA,
                         closing ? 0 : TaskView.MAX_PAGE_SCRIM_ALPHA),
                 ObjectAnimator.ofFloat(this, ALPHA, closing ? 0 : 1));
         mOpenCloseAnimator.addListener(new AnimationSuccessListener() {
             @Override
             public void onAnimationStart(Animator animation) {
-                testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE,
-                        "TaskMenuView.java.animateOpenOrClosed: onAnimationStart");
                 setVisibility(VISIBLE);
                 if (closing && mOnClosingStartCallback != null) {
                     mOnClosingStartCallback.run();
@@ -383,16 +381,7 @@
             }
 
             @Override
-            public void onAnimationCancel(Animator animation) {
-                super.onAnimationCancel(animation);
-                testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE,
-                        "TaskMenuView.java.animateOpenOrClosed: onAnimationCancel");
-            }
-
-            @Override
             public void onAnimationSuccess(Animator animator) {
-                testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE,
-                        "TaskMenuView.java.animateOpenOrClosed: onAnimationSuccess");
                 if (closing) {
                     closeComplete();
                 }
@@ -403,7 +392,6 @@
     }
 
     private void closeComplete() {
-        testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE, "TaskMenuView.java.closeComplete");
         mIsOpen = false;
         mContainer.getDragLayer().removeView(this);
         mRevealAnimator = null;
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
index a138db0..659cc0c 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
@@ -37,16 +37,13 @@
 import com.android.launcher3.popup.SystemShortcut
 import com.android.launcher3.util.Themes
 import com.android.quickstep.TaskOverlayFactory
-import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
+import com.android.quickstep.views.TaskView.TaskContainer
 
 class TaskMenuViewWithArrow<T> : ArrowPopup<T> where T : RecentsViewContainer, T : Context {
     companion object {
         const val TAG = "TaskMenuViewWithArrow"
 
-        fun <T> showForTask(
-            taskContainer: TaskIdAttributeContainer,
-            alignedOptionIndex: Int = 0
-        ): Boolean where T : RecentsViewContainer, T : Context {
+        fun showForTask(taskContainer: TaskContainer, alignedOptionIndex: Int = 0): Boolean {
             val container: RecentsViewContainer =
                 RecentsViewContainer.containerFromContext(taskContainer.taskView.context)
             val taskMenuViewWithArrow =
@@ -54,7 +51,7 @@
                     R.layout.task_menu_with_arrow,
                     container.dragLayer,
                     false
-                ) as TaskMenuViewWithArrow<T>
+                ) as TaskMenuViewWithArrow<*>
 
             return taskMenuViewWithArrow.populateAndShowForTask(taskContainer, alignedOptionIndex)
         }
@@ -87,7 +84,7 @@
 
     private lateinit var taskView: TaskView
     private lateinit var optionLayout: LinearLayout
-    private lateinit var taskContainer: TaskIdAttributeContainer
+    private lateinit var taskContainer: TaskContainer
 
     private var optionMeasuredHeight = 0
     private val arrowHorizontalPadding: Int
@@ -141,7 +138,7 @@
     }
 
     private fun populateAndShowForTask(
-        taskContainer: TaskIdAttributeContainer,
+        taskContainer: TaskContainer,
         alignedOptionIndex: Int
     ): Boolean {
         if (isAttachedToWindow) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
index 9802beb..447002f 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
@@ -53,6 +53,7 @@
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.SystemUiController;
 import com.android.launcher3.util.SystemUiController.SystemUiControllerFlags;
+import com.android.launcher3.util.ViewPool;
 import com.android.quickstep.TaskOverlayFactory.TaskOverlay;
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
 import com.android.quickstep.views.TaskView.FullscreenDrawParams;
@@ -66,7 +67,7 @@
  * @deprecated This class will be replaced by the new [TaskThumbnailView].
  */
 @Deprecated
-public class TaskThumbnailViewDeprecated extends View {
+public class TaskThumbnailViewDeprecated extends View implements ViewPool.Reusable {
     private static final MainThreadInitializedObject<FullscreenDrawParams> TEMP_PARAMS =
             new MainThreadInitializedObject<>(FullscreenDrawParams::new);
 
@@ -127,8 +128,7 @@
             };
 
     private final RecentsViewContainer mContainer;
-    @Nullable
-    private TaskOverlay mOverlay;
+    private TaskOverlay<?> mOverlay;
     private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     private final Paint mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     private final Paint mSplashBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -187,8 +187,9 @@
     /**
      * Updates the thumbnail to draw the provided task
      */
-    public void bind(Task task) {
-        getTaskOverlay().reset();
+    public void bind(Task task, TaskOverlay<?> overlay) {
+        mOverlay = overlay;
+        mOverlay.reset();
         mTask = task;
         int color = task == null ? Color.BLACK : task.colorBackground | 0xFF000000;
         mPaint.setColor(color);
@@ -198,6 +199,17 @@
     }
 
     /**
+     * Sets TaskOverlay without binding a task.
+     *
+     * @deprecated Should only be used when using new
+     * {@link com.android.quickstep.task.thumbnail.TaskThumbnailView}.
+     */
+    @Deprecated
+    public void setTaskOverlay(TaskOverlay<?> overlay) {
+        mOverlay = overlay;
+    }
+
+    /**
      * Updates the thumbnail.
      *
      * @param refreshNow whether the {@code thumbnailData} will be used to redraw immediately.
@@ -211,8 +223,8 @@
             boolean refreshNow) {
         mTask = task;
         boolean thumbnailWasNull = mThumbnailData == null;
-        mThumbnailData =
-                (thumbnailData != null && thumbnailData.thumbnail != null) ? thumbnailData : null;
+        mThumbnailData = (thumbnailData != null && thumbnailData.getThumbnail() != null)
+                ? thumbnailData : null;
         if (mTask != null) {
             updateSplashView(mTask.icon);
         }
@@ -237,8 +249,8 @@
      * @param shouldRefreshOverlay whether to re-initialize overlay
      */
     private void refresh(boolean shouldRefreshOverlay) {
-        if (mThumbnailData != null && mThumbnailData.thumbnail != null) {
-            Bitmap bm = mThumbnailData.thumbnail;
+        if (mThumbnailData != null && mThumbnailData.getThumbnail() != null) {
+            Bitmap bm = mThumbnailData.getThumbnail();
             bm.prepareToDraw();
             mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
             mPaint.setShader(mBitmapShader);
@@ -250,7 +262,7 @@
             mBitmapShader = null;
             mThumbnailData = null;
             mPaint.setShader(null);
-            getTaskOverlay().reset();
+            mOverlay.reset();
         }
         updateThumbnailPaintFilter();
     }
@@ -278,13 +290,6 @@
         invalidate();
     }
 
-    public TaskOverlay getTaskOverlay() {
-        if (mOverlay == null) {
-            mOverlay = getTaskView().getRecentsView().getTaskOverlayFactory().createOverlay(this);
-        }
-        return mOverlay;
-    }
-
     public float getDimAlpha() {
         return mDimAlpha;
     }
@@ -302,8 +307,10 @@
         }
 
         RectF bitmapRect = new RectF(
-                0, 0,
-                mThumbnailData.thumbnail.getWidth(), mThumbnailData.thumbnail.getHeight());
+                0,
+                0,
+                mThumbnailData.getThumbnail().getWidth(),
+                mThumbnailData.getThumbnail().getHeight());
         RectF viewRect = new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight());
 
         // The position helper matrix tells us how to transform the bitmap to fit the view, the
@@ -347,7 +354,7 @@
         canvas.save();
         // Draw the insets if we're being drawn fullscreen (we do this for quick switch).
         drawOnCanvas(canvas, 0, 0, getMeasuredWidth(), getMeasuredHeight(),
-                mFullscreenParams.mCurrentDrawnCornerRadius);
+                mFullscreenParams.getCurrentDrawnCornerRadius());
         canvas.restore();
     }
 
@@ -357,13 +364,13 @@
 
     public void setFullscreenParams(TaskView.FullscreenDrawParams fullscreenParams) {
         mFullscreenParams = fullscreenParams;
-        getTaskOverlay().setFullscreenParams(fullscreenParams);
         invalidate();
     }
 
     public void drawOnCanvas(Canvas canvas, float x, float y, float width, float height,
             float cornerRadius) {
-        if (mTask != null && getTaskView().isRunningTask() && !getTaskView().showScreenshot()) {
+        if (mTask != null && getTaskView().isRunningTask()
+                && !getTaskView().getShouldShowScreenshot()) {
             canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mClearPaint);
             canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius,
                     mDimmingPaintAfterClearing);
@@ -501,13 +508,13 @@
     }
 
     private boolean isThumbnailAspectRatioDifferentFromThumbnailData() {
-        if (mThumbnailData == null || mThumbnailData.thumbnail == null) {
+        if (mThumbnailData == null || mThumbnailData.getThumbnail() == null) {
             return false;
         }
 
         float thumbnailViewAspect = getWidth() / (float) getHeight();
-        float thumbnailDataAspect =
-                mThumbnailData.thumbnail.getWidth() / (float) mThumbnailData.thumbnail.getHeight();
+        float thumbnailDataAspect = mThumbnailData.getThumbnail().getWidth()
+                / (float) mThumbnailData.getThumbnail().getHeight();
 
         return isRelativePercentDifferenceGreaterThan(thumbnailViewAspect,
                 thumbnailDataAspect, MAX_PCT_BEFORE_ASPECT_RATIOS_CONSIDERED_DIFFERENT);
@@ -533,10 +540,10 @@
      */
     private void refreshOverlay() {
         if (mOverlayEnabled) {
-            getTaskOverlay().initOverlay(mTask, mThumbnailData, mPreviewPositionHelper.getMatrix(),
+            mOverlay.initOverlay(mTask, mThumbnailData, mPreviewPositionHelper.getMatrix(),
                     mPreviewPositionHelper.isOrientationChanged());
         } else {
-            getTaskOverlay().reset();
+            mOverlay.reset();
         }
     }
 
@@ -558,10 +565,9 @@
         DeviceProfile dp = mContainer.getDeviceProfile();
         mPreviewPositionHelper.setOrientationChanged(false);
         if (mBitmapShader != null && mThumbnailData != null) {
-            mPreviewRect.set(0, 0, mThumbnailData.thumbnail.getWidth(),
-                    mThumbnailData.thumbnail.getHeight());
-            int currentRotation = getTaskView().getRecentsView().getPagedViewOrientedState()
-                    .getRecentsActivityRotation();
+            mPreviewRect.set(0, 0, mThumbnailData.getThumbnail().getWidth(),
+                    mThumbnailData.getThumbnail().getHeight());
+            int currentRotation = getTaskView().getOrientedState().getRecentsActivityRotation();
             boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
             mPreviewPositionHelper.updateThumbnailMatrix(mPreviewRect, mThumbnailData,
                     getMeasuredWidth(), getMeasuredHeight(), dp.isTablet, currentRotation, isRtl);
@@ -593,7 +599,7 @@
         if (mThumbnailData == null) {
             return null;
         }
-        return mThumbnailData.thumbnail;
+        return mThumbnailData.getThumbnail();
     }
 
     /**
@@ -606,4 +612,9 @@
         }
         return mThumbnailData.isRealSnapshot && !mTask.isLocked;
     }
+
+    @Override
+    public void onRecycle() {
+        // Do nothing
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
deleted file mode 100644
index 8fd99de..0000000
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ /dev/null
@@ -1,2023 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.quickstep.views;
-
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.widget.Toast.LENGTH_SHORT;
-
-import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.app.animation.Interpolators.LINEAR;
-import static com.android.launcher3.Flags.enableCursorHoverStates;
-import static com.android.launcher3.Flags.enableGridOnlyOverview;
-import static com.android.launcher3.Flags.enableOverviewIconMenu;
-import static com.android.launcher3.Flags.enableRefactorTaskThumbnail;
-import static com.android.launcher3.LauncherState.BACKGROUND_APP;
-import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
-import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_NOT_PINNABLE;
-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.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
-import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
-import static com.android.quickstep.TaskOverlayFactory.getEnabledShortcuts;
-import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.EXPECTING_TASK_APPEARED;
-import static com.android.quickstep.util.BorderAnimator.DEFAULT_BORDER_COLOR;
-
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.annotation.IdRes;
-import android.app.ActivityOptions;
-import android.app.ActivityTaskManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.util.FloatProperty;
-import android.util.Log;
-import android.view.Display;
-import android.view.MotionEvent;
-import android.view.RemoteAnimationTarget;
-import android.view.TouchDelegate;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewStub;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.FrameLayout;
-import android.widget.Toast;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.app.animation.Interpolators;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Flags;
-import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.pm.UserCache;
-import com.android.launcher3.popup.SystemShortcut;
-import com.android.launcher3.testing.TestLogging;
-import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.launcher3.util.ActivityOptionsWrapper;
-import com.android.launcher3.util.CancellableTask;
-import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.RunnableList;
-import com.android.launcher3.util.SafeCloseable;
-import com.android.launcher3.util.SplitConfigurationOptions;
-import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
-import com.android.launcher3.util.TraceHelper;
-import com.android.launcher3.util.TransformingTouchDelegate;
-import com.android.launcher3.util.ViewPool.Reusable;
-import com.android.quickstep.RecentsModel;
-import com.android.quickstep.RemoteAnimationTargets;
-import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
-import com.android.quickstep.TaskAnimationManager;
-import com.android.quickstep.TaskIconCache;
-import com.android.quickstep.TaskThumbnailCache;
-import com.android.quickstep.TaskUtils;
-import com.android.quickstep.TaskViewUtils;
-import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
-import com.android.quickstep.task.thumbnail.TaskThumbnail;
-import com.android.quickstep.task.thumbnail.TaskThumbnailView;
-import com.android.quickstep.util.ActiveGestureLog;
-import com.android.quickstep.util.BorderAnimator;
-import com.android.quickstep.util.RecentsOrientedState;
-import com.android.quickstep.util.SplitSelectStateController;
-import com.android.quickstep.util.TaskCornerRadius;
-import com.android.quickstep.util.TaskRemovedDuringLaunchListener;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.ThumbnailData;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.QuickStepContract;
-
-import kotlin.Unit;
-
-import java.lang.annotation.Retention;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
-
-
-/**
- * A task in the Recents view.
- */
-public class TaskView extends FrameLayout implements Reusable {
-
-    private static final String TAG = TaskView.class.getSimpleName();
-    public static final int FLAG_UPDATE_ICON = 1;
-    public static final int FLAG_UPDATE_THUMBNAIL = FLAG_UPDATE_ICON << 1;
-    public static final int FLAG_UPDATE_CORNER_RADIUS = FLAG_UPDATE_THUMBNAIL << 1;
-
-    public static final int FLAG_UPDATE_ALL = FLAG_UPDATE_ICON | FLAG_UPDATE_THUMBNAIL
-            | FLAG_UPDATE_CORNER_RADIUS;
-
-    /**
-     * Used in conjunction with {@link #onTaskListVisibilityChanged(boolean, int)}, providing more
-     * granularity on which components of this task require an update
-     */
-    @Retention(SOURCE)
-    @IntDef({FLAG_UPDATE_ALL, FLAG_UPDATE_ICON, FLAG_UPDATE_THUMBNAIL, FLAG_UPDATE_CORNER_RADIUS})
-    public @interface TaskDataChanges {}
-
-    /**
-     * Type of task view
-     */
-    @Retention(SOURCE)
-    @IntDef({Type.SINGLE, Type.GROUPED, Type.DESKTOP})
-    public @interface Type {
-        int SINGLE = 1;
-        int GROUPED = 2;
-        int DESKTOP = 3;
-    }
-
-    /** The maximum amount that a task view can be scrimmed, dimmed or tinted. */
-    public static final float MAX_PAGE_SCRIM_ALPHA = 0.4f;
-
-    private static final float EDGE_SCALE_DOWN_FACTOR_CAROUSEL = 0.03f;
-    private static final float EDGE_SCALE_DOWN_FACTOR_GRID = 0.00f;
-
-    public static final long SCALE_ICON_DURATION = 120;
-    private static final long DIM_ANIM_DURATION = 700;
-
-    /**
-     * This technically can be a vanilla {@link TouchDelegate} class, however that class requires
-     * setting the touch bounds at construction, so we'd repeatedly be created many instances
-     * unnecessarily as scrolling occurs, whereas {@link TransformingTouchDelegate} allows touch
-     * delegated bounds only to be updated.
-     */
-    private TransformingTouchDelegate mIconTouchDelegate;
-
-    private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
-            Collections.singletonList(new Rect());
-
-    public static final FloatProperty<TaskView> FOCUS_TRANSITION =
-            new FloatProperty<>("focusTransition") {
-                @Override
-                public void setValue(TaskView taskView, float v) {
-                    taskView.setIconsAndBannersTransitionProgress(v, false /* invert */);
-                }
-
-                @Override
-                public Float get(TaskView taskView) {
-                    return taskView.mFocusTransitionProgress;
-                }
-            };
-
-    private static final FloatProperty<TaskView> SPLIT_SELECT_TRANSLATION_X =
-            new FloatProperty<>("splitSelectTranslationX") {
-                @Override
-                public void setValue(TaskView taskView, float v) {
-                    taskView.setSplitSelectTranslationX(v);
-                }
-
-                @Override
-                public Float get(TaskView taskView) {
-                    return taskView.mSplitSelectTranslationX;
-                }
-            };
-
-    private static final FloatProperty<TaskView> SPLIT_SELECT_TRANSLATION_Y =
-            new FloatProperty<>("splitSelectTranslationY") {
-                @Override
-                public void setValue(TaskView taskView, float v) {
-                    taskView.setSplitSelectTranslationY(v);
-                }
-
-                @Override
-                public Float get(TaskView taskView) {
-                    return taskView.mSplitSelectTranslationY;
-                }
-            };
-
-    private static final FloatProperty<TaskView> DISMISS_TRANSLATION_X =
-            new FloatProperty<>("dismissTranslationX") {
-                @Override
-                public void setValue(TaskView taskView, float v) {
-                    taskView.setDismissTranslationX(v);
-                }
-
-                @Override
-                public Float get(TaskView taskView) {
-                    return taskView.mDismissTranslationX;
-                }
-            };
-
-    private static final FloatProperty<TaskView> DISMISS_TRANSLATION_Y =
-            new FloatProperty<>("dismissTranslationY") {
-                @Override
-                public void setValue(TaskView taskView, float v) {
-                    taskView.setDismissTranslationY(v);
-                }
-
-                @Override
-                public Float get(TaskView taskView) {
-                    return taskView.mDismissTranslationY;
-                }
-            };
-
-    private static final FloatProperty<TaskView> TASK_OFFSET_TRANSLATION_X =
-            new FloatProperty<>("taskOffsetTranslationX") {
-                @Override
-                public void setValue(TaskView taskView, float v) {
-                    taskView.setTaskOffsetTranslationX(v);
-                }
-
-                @Override
-                public Float get(TaskView taskView) {
-                    return taskView.mTaskOffsetTranslationX;
-                }
-            };
-
-    private static final FloatProperty<TaskView> TASK_OFFSET_TRANSLATION_Y =
-            new FloatProperty<>("taskOffsetTranslationY") {
-                @Override
-                public void setValue(TaskView taskView, float v) {
-                    taskView.setTaskOffsetTranslationY(v);
-                }
-
-                @Override
-                public Float get(TaskView taskView) {
-                    return taskView.mTaskOffsetTranslationY;
-                }
-            };
-
-    private static final FloatProperty<TaskView> TASK_RESISTANCE_TRANSLATION_X =
-            new FloatProperty<>("taskResistanceTranslationX") {
-                @Override
-                public void setValue(TaskView taskView, float v) {
-                    taskView.setTaskResistanceTranslationX(v);
-                }
-
-                @Override
-                public Float get(TaskView taskView) {
-                    return taskView.mTaskResistanceTranslationX;
-                }
-            };
-
-    private static final FloatProperty<TaskView> TASK_RESISTANCE_TRANSLATION_Y =
-            new FloatProperty<>("taskResistanceTranslationY") {
-                @Override
-                public void setValue(TaskView taskView, float v) {
-                    taskView.setTaskResistanceTranslationY(v);
-                }
-
-                @Override
-                public Float get(TaskView taskView) {
-                    return taskView.mTaskResistanceTranslationY;
-                }
-            };
-
-    public static final FloatProperty<TaskView> GRID_END_TRANSLATION_X =
-            new FloatProperty<>("gridEndTranslationX") {
-                @Override
-                public void setValue(TaskView taskView, float v) {
-                    taskView.setGridEndTranslationX(v);
-                }
-
-                @Override
-                public Float get(TaskView taskView) {
-                    return taskView.mGridEndTranslationX;
-                }
-            };
-
-    public static final FloatProperty<TaskView> SNAPSHOT_SCALE =
-            new FloatProperty<>("snapshotScale") {
-                @Override
-                public void setValue(TaskView taskView, float v) {
-                    taskView.setSnapshotScale(v);
-                }
-
-                @Override
-                public Float get(TaskView taskView) {
-                    return taskView.mTaskThumbnailViewDeprecated.getScaleX();
-                }
-            };
-
-    @Nullable
-    protected Task mTask;
-    @Nullable // can be null when enableRefactorTaskThumbnail() == true
-    protected TaskThumbnailViewDeprecated mTaskThumbnailViewDeprecated;
-    protected TaskThumbnailView mTaskThumbnailView;
-    protected TaskViewIcon mIconView;
-    protected final DigitalWellBeingToast mDigitalWellBeingToast;
-    protected float mFullscreenProgress;
-    private float mGridProgress;
-    protected float mTaskThumbnailSplashAlpha;
-    private float mNonGridScale = 1;
-    private float mDismissScale = 1;
-    protected final FullscreenDrawParams mCurrentFullscreenParams;
-    protected final RecentsViewContainer mContainer;
-
-    // Various causes of changing primary translation, which we aggregate to setTranslationX/Y().
-    private float mDismissTranslationX;
-    private float mDismissTranslationY;
-    private float mTaskOffsetTranslationX;
-    private float mTaskOffsetTranslationY;
-    private float mTaskResistanceTranslationX;
-    private float mTaskResistanceTranslationY;
-    // The following translation variables should only be used in the same orientation as Launcher.
-    private float mBoxTranslationY;
-    // The following grid translations scales with mGridProgress.
-    private float mGridTranslationX;
-    private float mGridTranslationY;
-    // The following grid translation is used to animate closing the gap between grid and clear all.
-    private float mGridEndTranslationX;
-    // Applied as a complement to gridTranslation, for adjusting the carousel overview and quick
-    // switch.
-    private float mNonGridTranslationX;
-    private float mNonGridPivotTranslationX;
-    // Used when in SplitScreenSelectState
-    private float mSplitSelectTranslationY;
-    private float mSplitSelectTranslationX;
-
-    @Nullable
-    private ObjectAnimator mIconAndDimAnimator;
-    private float mIconScaleAnimStartProgress = 0;
-    private float mFocusTransitionProgress = 1;
-    private float mModalness = 0;
-    private float mStableAlpha = 1;
-
-    private int mTaskViewId = -1;
-    /**
-     * Index 0 will contain taskID of left/top task, index 1 will contain taskId of bottom/right
-     */
-    protected int[] mTaskIdContainer = new int[]{-1, -1};
-    protected TaskIdAttributeContainer[] mTaskIdAttributeContainer =
-            new TaskIdAttributeContainer[2];
-
-    private boolean mShowScreenshot;
-    private boolean mBorderEnabled;
-
-    // The current background requests to load the task thumbnail and icon
-    @Nullable
-    private CancellableTask mThumbnailLoadRequest;
-    @Nullable
-    private CancellableTask mIconLoadRequest;
-
-    private boolean mEndQuickswitchCuj;
-
-    private final float[] mIconCenterCoords = new float[2];
-
-    protected final PointF mLastTouchDownPosition = new PointF();
-
-    private boolean mIsClickableAsLiveTile = true;
-
-    @Nullable private final BorderAnimator mFocusBorderAnimator;
-
-    @Nullable private final BorderAnimator mHoverBorderAnimator;
-
-    public TaskView(Context context) {
-        this(context, null);
-    }
-
-    public TaskView(Context context, @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public TaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public TaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        this(context, attrs, defStyleAttr, defStyleRes, null, null);
-    }
-
-    @VisibleForTesting
-    public TaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
-            int defStyleRes, BorderAnimator focusBorderAnimator,
-            BorderAnimator hoverBorderAnimator) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        mContainer = RecentsViewContainer.containerFromContext(context);
-        setOnClickListener(this::onClick);
-
-        mCurrentFullscreenParams = new FullscreenDrawParams(context);
-        mDigitalWellBeingToast = new DigitalWellBeingToast(mContainer, this);
-
-        boolean keyboardFocusHighlightEnabled = FeatureFlags.ENABLE_KEYBOARD_QUICK_SWITCH.get()
-                || Flags.enableFocusOutline();
-        boolean cursorHoverStatesEnabled = enableCursorHoverStates();
-
-        setWillNotDraw(!keyboardFocusHighlightEnabled && !cursorHoverStatesEnabled);
-
-        TypedArray styledAttrs = context.obtainStyledAttributes(
-                attrs, R.styleable.TaskView, defStyleAttr, defStyleRes);
-
-        if (focusBorderAnimator != null) {
-            mFocusBorderAnimator = focusBorderAnimator;
-        } else {
-            mFocusBorderAnimator = keyboardFocusHighlightEnabled
-                    ? BorderAnimator.createSimpleBorderAnimator(
-                    /* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius,
-                    /* borderWidthPx= */ context.getResources().getDimensionPixelSize(
-                            R.dimen.keyboard_quick_switch_border_width),
-                    /* boundsBuilder= */ this::updateBorderBounds,
-                    /* targetView= */ this,
-                    /* borderColor= */ styledAttrs.getColor(
-                            R.styleable.TaskView_focusBorderColor, DEFAULT_BORDER_COLOR))
-                    : null;
-        }
-
-        if (hoverBorderAnimator != null) {
-            mHoverBorderAnimator = hoverBorderAnimator;
-        } else {
-            mHoverBorderAnimator = cursorHoverStatesEnabled
-                    ? BorderAnimator.createSimpleBorderAnimator(
-                    /* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius,
-                    /* borderWidthPx= */ context.getResources().getDimensionPixelSize(
-                            R.dimen.task_hover_border_width),
-                    /* boundsBuilder= */ this::updateBorderBounds,
-                    /* targetView= */ this,
-                    /* borderColor= */ styledAttrs.getColor(
-                            R.styleable.TaskView_hoverBorderColor, DEFAULT_BORDER_COLOR))
-                    : null;
-        }
-        styledAttrs.recycle();
-    }
-
-    protected Unit updateBorderBounds(@NonNull Rect bounds) {
-        View snapshotView = getSnapshotView();
-        bounds.set(snapshotView.getLeft() + Math.round(snapshotView.getTranslationX()),
-                snapshotView.getTop() + Math.round(snapshotView.getTranslationY()),
-                snapshotView.getRight() + Math.round(snapshotView.getTranslationX()),
-                snapshotView.getBottom() + Math.round(snapshotView.getTranslationY()));
-        return Unit.INSTANCE;
-    }
-
-    public void setTaskViewId(int id) {
-        this.mTaskViewId = id;
-    }
-
-    public int getTaskViewId() {
-        return mTaskViewId;
-    }
-
-    /**
-     * Updates [TaskThumbnailView] to reflect the latest [Task] state (i.e., task isRunning).
-     */
-    public void notifyIsRunningTaskUpdated() {
-        // TODO(b/335649589): TaskView's VM will already have access to TaskThumbnailView's VM
-        //  so there will be no need to access TaskThumbnailView's VM through the TaskThumbnailView
-        if (mTask != null) {
-            bindTaskThumbnailView();
-        }
-    }
-
-    /**
-     * Builds proto for logging
-     */
-    public WorkspaceItemInfo getItemInfo() {
-        return getItemInfo(mTask);
-    }
-
-    /**
-     * Builds proto for logging
-     */
-    @VisibleForTesting
-    public WorkspaceItemInfo getItemInfo(@Nullable Task task) {
-        WorkspaceItemInfo stubInfo = new WorkspaceItemInfo();
-        stubInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK;
-        stubInfo.container = LauncherSettings.Favorites.CONTAINER_TASKSWITCHER;
-        if (task == null) {
-            return stubInfo;
-        }
-
-        ComponentKey componentKey = TaskUtils.getLaunchComponentKeyForTask(task.key);
-        stubInfo.user = componentKey.user;
-        stubInfo.intent = new Intent().setComponent(componentKey.componentName);
-        stubInfo.title = task.title;
-        if (getRecentsView() != null) {
-            stubInfo.screenId = getRecentsView().indexOfChild(this);
-        }
-        if (Flags.privateSpaceRestrictAccessibilityDrag()) {
-            if (UserCache.getInstance(getContext()).getUserInfo(componentKey.user).isPrivate()) {
-                stubInfo.runtimeStatusFlags |= FLAG_NOT_PINNABLE;
-            }
-        }
-        return stubInfo;
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mTaskThumbnailViewDeprecated = findViewById(R.id.snapshot);
-        if (enableRefactorTaskThumbnail()) {
-            mTaskThumbnailView = new TaskThumbnailView(mContext);
-            mTaskThumbnailView.setLayoutParams(mTaskThumbnailViewDeprecated.getLayoutParams());
-            int indexOfSnapshotView = indexOfChild(mTaskThumbnailViewDeprecated);
-            addView(mTaskThumbnailView, indexOfSnapshotView);
-            mTaskThumbnailViewDeprecated.setVisibility(View.GONE);
-        }
-        ViewStub iconViewStub = findViewById(R.id.icon);
-        if (enableOverviewIconMenu()) {
-            iconViewStub.setLayoutResource(R.layout.icon_app_chip_view);
-        } else {
-            iconViewStub.setLayoutResource(R.layout.icon_view);
-        }
-        mIconView = (TaskViewIcon) iconViewStub.inflate();
-        mIconTouchDelegate = new TransformingTouchDelegate(mIconView.asView());
-    }
-
-    @Override
-    @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
-    public void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
-        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
-        if (mFocusBorderAnimator != null && mBorderEnabled) {
-            mFocusBorderAnimator.setBorderVisibility(gainFocus, /* animated= */ true);
-        }
-    }
-
-    @Override
-    public boolean onHoverEvent(MotionEvent event) {
-        if (mHoverBorderAnimator != null && mBorderEnabled) {
-            switch (event.getAction()) {
-                case MotionEvent.ACTION_HOVER_ENTER:
-                    mHoverBorderAnimator.setBorderVisibility(/* visible= */ true, /* animated= */
-                            true);
-                    break;
-                case MotionEvent.ACTION_HOVER_EXIT:
-                    mHoverBorderAnimator.setBorderVisibility(/* visible= */ false, /* animated= */
-                            true);
-                    break;
-                default:
-                    break;
-            }
-        }
-        return super.onHoverEvent(event);
-    }
-
-    /**
-     * Enable or disable showing border on hover and focus change
-     */
-    public void setBorderEnabled(boolean enabled) {
-        mBorderEnabled = enabled;
-        // Set the animation correctly in case it misses the hover/focus event during state
-        // transition
-        if (mHoverBorderAnimator != null) {
-            mHoverBorderAnimator.setBorderVisibility(/* visible= */
-                    enabled && isHovered(), /* animated= */ true);
-        }
-
-        if (mFocusBorderAnimator != null) {
-            mFocusBorderAnimator.setBorderVisibility(/* visible= */
-                    enabled && isFocused(), /* animated= */true);
-        }
-    }
-
-    @Override
-    public boolean onInterceptHoverEvent(MotionEvent event) {
-        if (enableCursorHoverStates()) {
-            // avoid triggering hover event on child elements which would cause HOVER_EXIT for this
-            // task view
-            return true;
-        } else {
-            return super.onInterceptHoverEvent(event);
-        }
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        // Draw border first so any child views outside of the thumbnail bounds are drawn above it.
-        if (mFocusBorderAnimator != null) {
-            mFocusBorderAnimator.drawBorder(canvas);
-        }
-        if (mHoverBorderAnimator != null) {
-            mHoverBorderAnimator.drawBorder(canvas);
-        }
-        super.draw(canvas);
-    }
-
-    /**
-     * Whether the taskview should take the touch event from parent. Events passed to children
-     * that might require special handling.
-     */
-    public boolean offerTouchToChildren(MotionEvent event) {
-        if (event.getAction() == MotionEvent.ACTION_DOWN) {
-            computeAndSetIconTouchDelegate(mIconView, mIconCenterCoords, mIconTouchDelegate);
-        }
-        return mIconTouchDelegate != null && mIconTouchDelegate.onTouchEvent(event);
-    }
-
-    protected void computeAndSetIconTouchDelegate(TaskViewIcon view, float[] tempCenterCoords,
-            TransformingTouchDelegate transformingTouchDelegate) {
-        if (view == null) {
-            return;
-        }
-        float viewHalfWidth = view.getWidth() / 2f;
-        float viewHalfHeight = view.getHeight() / 2f;
-        tempCenterCoords[0] = viewHalfWidth;
-        tempCenterCoords[1] = viewHalfHeight;
-        getDescendantCoordRelativeToAncestor(view.asView(), mContainer.getDragLayer(),
-                tempCenterCoords, false);
-        transformingTouchDelegate.setBounds(
-                (int) (tempCenterCoords[0] - viewHalfWidth),
-                (int) (tempCenterCoords[1] - viewHalfHeight),
-                (int) (tempCenterCoords[0] + viewHalfWidth),
-                (int) (tempCenterCoords[1] + viewHalfHeight));
-    }
-
-    /**
-     * The modalness of this view is how it should be displayed when it is shown on its own in the
-     * modal state of overview.
-     *
-     * @param modalness [0, 1] 0 being in context with other tasks, 1 being shown on its own.
-     */
-    public void setModalness(float modalness) {
-        if (mModalness == modalness) {
-            return;
-        }
-        mModalness = modalness;
-        mIconView.setModalAlpha(1 - modalness);
-        mDigitalWellBeingToast.updateBannerOffset(modalness);
-    }
-
-    public DigitalWellBeingToast getDigitalWellBeingToast() {
-        return mDigitalWellBeingToast;
-    }
-
-    /**
-     * Updates this task view to the given {@param task}.
-     */
-    public void bind(Task task, RecentsOrientedState orientedState) {
-        cancelPendingLoadTasks();
-        mTask = task;
-        mTaskIdContainer[0] = mTask.key.id;
-        mTaskIdAttributeContainer[0] = new TaskIdAttributeContainer(task,
-                mTaskThumbnailViewDeprecated, mIconView,
-                STAGE_POSITION_UNDEFINED);
-        if (enableRefactorTaskThumbnail()) {
-            bindTaskThumbnailView();
-        } else {
-            mTaskThumbnailViewDeprecated.bind(task);
-        }
-        setOrientationState(orientedState);
-    }
-
-    private void bindTaskThumbnailView() {
-        // TODO(b/335649589): TaskView's VM will already have access to TaskThumbnailView's VM
-        //  so there will be no need to access TaskThumbnailView's VM through the TaskThumbnailView
-        mTaskThumbnailView.getViewModel().bind(new TaskThumbnail(mTask, isRunningTask()));
-    }
-
-    /**
-     * Sets up an on-click listener and the visibility for show_windows icon on top of the task.
-     */
-    public void setUpShowAllInstancesListener() {
-        String taskPackageName = mTaskIdAttributeContainer[0].mTask.key.getPackageName();
-
-        // icon of the top/left task
-        View showWindowsView = findViewById(R.id.show_windows);
-        updateFilterCallback(showWindowsView, getFilterUpdateCallback(taskPackageName));
-    }
-
-    /**
-     * Returns a callback that updates the state of the filter and the recents overview
-     *
-     * @param taskPackageName package name of the task to filter by
-     */
-    @Nullable
-    protected View.OnClickListener getFilterUpdateCallback(String taskPackageName) {
-        View.OnClickListener cb = (view) -> {
-            // update and apply a new filter
-            getRecentsView().setAndApplyFilter(taskPackageName);
-        };
-
-        if (!getRecentsView().getFilterState().shouldShowFilterUI(taskPackageName)) {
-            cb = null;
-        }
-        return cb;
-    }
-
-    /**
-     * Sets the correct visibility and callback on the provided filterView based on whether
-     * the callback is null or not
-     */
-    protected void updateFilterCallback(@NonNull View filterView,
-            @Nullable View.OnClickListener callback) {
-        // Filtering changes alpha instead of the visibility since visibility
-        // can be altered separately through RecentsView#resetFromSplitSelectionState()
-        if (callback == null) {
-            filterView.setAlpha(0);
-        } else {
-            filterView.setAlpha(1);
-        }
-
-        filterView.setOnClickListener(callback);
-    }
-
-    public TaskIdAttributeContainer[] getTaskIdAttributeContainers() {
-        return mTaskIdAttributeContainer;
-    }
-
-    @Nullable
-    public Task getTask() {
-        return mTask;
-    }
-
-    /**
-     * Check if given {@code taskId} is tracked in this view
-     */
-    public boolean containsTaskId(int taskId) {
-        return mTask != null && mTask.key.id == taskId;
-    }
-
-    /**
-     * @return integer array of two elements to be size consistent with max number of tasks possible
-     *         index 0 will contain the taskId, index 1 will be -1 indicating a null taskID value
-     */
-    public int[] getTaskIds() {
-        return Arrays.copyOf(mTaskIdContainer, mTaskIdContainer.length);
-    }
-
-    public boolean containsMultipleTasks() {
-        return mTaskIdContainer[1] != -1;
-    }
-
-    /**
-     * Returns the TaskIdAttributeContainer corresponding to a given taskId, or null if the TaskView
-     * does not contain a Task with that ID.
-     */
-    @Nullable
-    public TaskIdAttributeContainer getTaskAttributesById(int taskId) {
-        for (TaskIdAttributeContainer attributes : mTaskIdAttributeContainer) {
-            if (attributes.getTask().key.id == taskId) {
-                return attributes;
-            }
-        }
-
-        return null;
-    }
-
-    public TaskThumbnailViewDeprecated getThumbnail() {
-        return mTaskThumbnailViewDeprecated;
-    }
-
-    void refreshThumbnails(@Nullable HashMap<Integer, ThumbnailData> thumbnailDatas) {
-        if (enableRefactorTaskThumbnail()) {
-            // TODO(b/334825222) add thumbnail logic
-            return;
-        }
-        if (mTask != null && thumbnailDatas != null) {
-            final ThumbnailData thumbnailData = thumbnailDatas.get(mTask.key.id);
-            if (thumbnailData != null) {
-                mTaskThumbnailViewDeprecated.setThumbnail(mTask, thumbnailData);
-                return;
-            }
-        }
-
-        mTaskThumbnailViewDeprecated.refresh();
-    }
-
-    /** TODO(b/197033698) Remove all usages of above method and migrate to this one */
-    public TaskThumbnailViewDeprecated[] getThumbnails() {
-        return new TaskThumbnailViewDeprecated[]{mTaskThumbnailViewDeprecated};
-    }
-
-    public TaskViewIcon getIconView() {
-        return mIconView;
-    }
-
-    @Override
-    public boolean dispatchTouchEvent(MotionEvent ev) {
-        RecentsView recentsView = getRecentsView();
-        if (recentsView == null || getTask() == null) {
-            return false;
-        }
-        SplitSelectStateController splitSelectStateController =
-                recentsView.getSplitSelectController();
-        // Disable taps for split selection animation unless we have multiple tasks
-        boolean disableTapsForSplitSelect =
-                splitSelectStateController.isSplitSelectActive()
-                        && splitSelectStateController.getInitialTaskId() == getTask().key.id
-                        && !containsMultipleTasks();
-        if (disableTapsForSplitSelect) {
-            return false;
-        }
-
-        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            mLastTouchDownPosition.set(ev.getX(), ev.getY());
-        }
-        return super.dispatchTouchEvent(ev);
-    }
-
-    /**
-     * @return taskId that split selection was initiated with,
-     *         {@link ActivityTaskManager#INVALID_TASK_ID} if no tasks in this TaskView are part of
-     *         split selection
-     */
-    protected int getThisTaskCurrentlyInSplitSelection() {
-        SplitSelectStateController splitSelectController =
-                getRecentsView().getSplitSelectController();
-        int initSplitTaskId = INVALID_TASK_ID;
-        for (TaskIdAttributeContainer container : getTaskIdAttributeContainers()) {
-            int taskId = container.getTask().key.id;
-            if (taskId == splitSelectController.getInitialTaskId()) {
-                initSplitTaskId = taskId;
-                break;
-            }
-        }
-        return initSplitTaskId;
-    }
-
-    private void onClick(View view) {
-        if (getTask() == null) {
-            Log.d("b/310064698", "onClick - task is null");
-            return;
-        }
-        if (confirmSecondSplitSelectApp()) {
-            Log.d("b/310064698", mTask + " - onClick - split select is active");
-            return;
-        }
-        RunnableList callbackList = launchTasks();
-        Log.d("b/310064698", mTask + " - onClick - callbackList: " + callbackList);
-        if (callbackList != null) {
-            callbackList.add(() -> Log.d("b/310064698", mTask + " - onClick - launchCompleted"));
-        }
-        mContainer.getStatsLogManager().logger().withItemInfo(getItemInfo())
-                .log(LAUNCHER_TASK_LAUNCH_TAP);
-    }
-
-    /**
-     * @return {@code true} if user is already in split select mode and this tap was to choose the
-     *         second app. {@code false} otherwise
-     */
-    protected boolean confirmSecondSplitSelectApp() {
-        int index = getLastSelectedChildTaskIndex();
-        TaskIdAttributeContainer container = mTaskIdAttributeContainer[index];
-        if (container != null) {
-            return getRecentsView().confirmSplitSelect(this, container.getTask(),
-                    container.getIconView().getDrawable(), container.getThumbnailView(),
-                    container.getThumbnailView().getThumbnail(), /* intent */ null,
-                    /* user */ null, container.getItemInfo());
-        }
-        return false;
-    }
-
-    /**
-     * Returns the task index of the last selected child task (0 or 1).
-     * If we contain multiple tasks and this TaskView is used as part of split selection, the
-     * selected child task index will be that of the remaining task.
-     */
-    protected int getLastSelectedChildTaskIndex() {
-        return 0;
-    }
-
-    /**
-     * Starts the task associated with this view and animates the startup.
-     * @return CompletionStage to indicate the animation completion or null if the launch failed.
-     */
-    @Nullable
-    public RunnableList launchTaskAnimated() {
-        if (mTask != null) {
-            TestLogging.recordEvent(
-                    TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask);
-            ActivityOptionsWrapper opts =  mContainer.getActivityLaunchOptions(this, null);
-            opts.options.setLaunchDisplayId(
-                    getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
-            if (ActivityManagerWrapper.getInstance()
-                    .startActivityFromRecents(mTask.key, opts.options)) {
-                Log.d(TAG, "launchTaskAnimated - startActivityFromRecents: " + Arrays.toString(
-                        getTaskIds()));
-                ActiveGestureLog.INSTANCE.trackEvent(EXPECTING_TASK_APPEARED);
-                RecentsView recentsView = getRecentsView();
-                if (recentsView.getRunningTaskViewId() != -1) {
-                    recentsView.onTaskLaunchedInLiveTileMode();
-
-                    // Return a fresh callback in the live tile case, so that it's not accidentally
-                    // triggered by QuickstepTransitionManager.AppLaunchAnimationRunner.
-                    RunnableList callbackList = new RunnableList();
-                    recentsView.addSideTaskLaunchCallback(callbackList);
-                    return callbackList;
-                }
-                if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
-                    // If the recents transition is running (ie. in live tile mode), then the start
-                    // of a new task will merge into the existing transition and it currently will
-                    // not be run independently, so we need to rely on the onTaskAppeared() call
-                    // for the new task to trigger the side launch callback to flush this runnable
-                    // list (which is usually flushed when the app launch animation finishes)
-                    recentsView.addSideTaskLaunchCallback(opts.onEndCallback);
-                }
-                return opts.onEndCallback;
-            } else {
-                notifyTaskLaunchFailed(TAG);
-                return null;
-            }
-        } else {
-            Log.d(TAG, "launchTaskAnimated - mTask is null");
-            return null;
-        }
-    }
-
-    /**
-     * Starts the task associated with this view without any animation
-     */
-    public void launchTask(@NonNull Consumer<Boolean> callback) {
-        launchTask(callback, false /* isQuickswitch */);
-    }
-
-    /**
-     * Starts the task associated with this view without any animation
-     */
-    public void launchTask(@NonNull Consumer<Boolean> callback, boolean isQuickswitch) {
-        if (mTask != null) {
-            TestLogging.recordEvent(
-                    TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask);
-
-            TaskRemovedDuringLaunchListener failureListener = new TaskRemovedDuringLaunchListener(
-                    getContext().getApplicationContext());
-            if (isQuickswitch) {
-                // We only listen for failures to launch in quickswitch because the during this
-                // gesture launcher is in the background state, vs other launches which are in
-                // the actual overview state
-                failureListener.register(mContainer, mTask.key.id, () -> {
-                    notifyTaskLaunchFailed(TAG);
-                    RecentsView rv = getRecentsView();
-                    if (rv != null) {
-                        // Disable animations for now, as it is an edge case and the app usually
-                        // covers launcher and also any state transition animation also gets
-                        // clobbered by QuickstepTransitionManager.createWallpaperOpenAnimations
-                        // when launcher shows again
-                        rv.startHome(false /* animated */);
-                        if (rv.mSizeStrategy.getTaskbarController() != null) {
-                            // LauncherTaskbarUIController depends on the launcher state when
-                            // checking whether to handle resume, but that can come in before
-                            // startHome() changes the state, so force-refresh here to ensure the
-                            // taskbar is updated
-                            rv.mSizeStrategy.getTaskbarController().refreshResumedState();
-                        }
-                    }
-                });
-            }
-            // Indicate success once the system has indicated that the transition has started
-            ActivityOptions opts = ActivityOptions.makeCustomTaskAnimation(getContext(), 0, 0,
-                    MAIN_EXECUTOR.getHandler(),
-                    elapsedRealTime -> callback.accept(true),
-                    elapsedRealTime -> failureListener.onTransitionFinished());
-            opts.setLaunchDisplayId(
-                    getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
-            if (isQuickswitch) {
-                opts.setFreezeRecentTasksReordering();
-            }
-            // TODO(b/334826842) add splash functionality to new TTV
-            if (!enableRefactorTaskThumbnail()) {
-                opts.setDisableStartingWindow(mTaskThumbnailViewDeprecated.shouldShowSplashView());
-            }
-            Task.TaskKey key = mTask.key;
-            UI_HELPER_EXECUTOR.execute(() -> {
-                if (!ActivityManagerWrapper.getInstance().startActivityFromRecents(key, opts)) {
-                    // If the call to start activity failed, then post the result immediately,
-                    // otherwise, wait for the animation start callback from the activity options
-                    // above
-                    MAIN_EXECUTOR.post(() -> {
-                        notifyTaskLaunchFailed(TAG);
-                        callback.accept(false);
-                    });
-                }
-            });
-        } else {
-            callback.accept(false);
-        }
-    }
-
-    /**
-     * Launch of the current task (both live and inactive tasks) with an animation.
-     */
-    @Nullable
-    public RunnableList launchTasks() {
-        RecentsView recentsView = getRecentsView();
-        RemoteTargetHandle[] remoteTargetHandles = recentsView.mRemoteTargetHandles;
-        if (isRunningTask() && remoteTargetHandles != null) {
-            if (!mIsClickableAsLiveTile) {
-                Log.e(TAG, "TaskView is not clickable as a live tile; returning to home.");
-                return null;
-            }
-
-            mIsClickableAsLiveTile = false;
-            RemoteAnimationTargets targets;
-            if (remoteTargetHandles.length == 1) {
-                targets = remoteTargetHandles[0].getTransformParams().getTargetSet();
-            } else {
-                RemoteAnimationTarget[] apps = Arrays.stream(remoteTargetHandles)
-                        .flatMap(handle -> Stream.of(
-                                handle.getTransformParams().getTargetSet().apps))
-                        .toArray(RemoteAnimationTarget[]::new);
-                RemoteAnimationTarget[] wallpapers = Arrays.stream(remoteTargetHandles)
-                        .flatMap(handle -> Stream.of(
-                                handle.getTransformParams().getTargetSet().wallpapers))
-                        .toArray(RemoteAnimationTarget[]::new);
-                targets = new RemoteAnimationTargets(apps, wallpapers,
-                        remoteTargetHandles[0].getTransformParams().getTargetSet().nonApps,
-                        remoteTargetHandles[0].getTransformParams().getTargetSet().targetMode);
-            }
-            if (targets == null) {
-                // If the recents animation is cancelled somehow between the parent if block and
-                // here, try to launch the task as a non live tile task.
-                RunnableList runnableList = launchTaskAnimated();
-                if (runnableList == null) {
-                    Log.e(TAG, "Recents animation cancelled and cannot launch task as non-live tile"
-                            + "; returning to home");
-                }
-                mIsClickableAsLiveTile = true;
-                return runnableList;
-            }
-
-            RunnableList runnableList = new RunnableList();
-            AnimatorSet anim = new AnimatorSet();
-            TaskViewUtils.composeRecentsLaunchAnimator(
-                    anim, this, targets.apps,
-                    targets.wallpapers, targets.nonApps, true /* launcherClosing */,
-                    recentsView.getStateManager(), recentsView,
-                    recentsView.getDepthController());
-            anim.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animator) {
-                    if (mTask != null && mTask.key.displayId != getRootViewDisplayId()) {
-                        launchTaskAnimated();
-                    }
-                    mIsClickableAsLiveTile = true;
-                    runEndCallback();
-                }
-
-                @Override
-                public void onAnimationCancel(Animator animation) {
-                    runEndCallback();
-                }
-
-                private void runEndCallback() {
-                    runnableList.executeAllAndDestroy();
-                }
-            });
-            anim.start();
-            Log.d(TAG, "launchTasks - composeRecentsLaunchAnimator: " + Arrays.toString(
-                    getTaskIds()));
-            recentsView.onTaskLaunchedInLiveTileMode();
-            return runnableList;
-        } else {
-            return launchTaskAnimated();
-        }
-    }
-
-    /**
-     * See {@link TaskDataChanges}
-     * @param visible If this task view will be visible to the user in overview or hidden
-     */
-    public void onTaskListVisibilityChanged(boolean visible) {
-        onTaskListVisibilityChanged(visible, FLAG_UPDATE_ALL);
-    }
-
-    /**
-     * See {@link TaskDataChanges}
-     * @param visible If this task view will be visible to the user in overview or hidden
-     */
-    public void onTaskListVisibilityChanged(boolean visible, @TaskDataChanges int changes) {
-        if (mTask == null) {
-            return;
-        }
-        cancelPendingLoadTasks();
-        if (visible) {
-            // These calls are no-ops if the data is already loaded, try and load the high
-            // resolution thumbnail if the state permits
-            RecentsModel model = RecentsModel.INSTANCE.get(getContext());
-            TaskThumbnailCache thumbnailCache = model.getThumbnailCache();
-            TaskIconCache iconCache = model.getIconCache();
-
-            if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
-                mThumbnailLoadRequest = thumbnailCache.updateThumbnailInBackground(
-                        mTask, thumbnail -> {
-                            if (!enableRefactorTaskThumbnail()) {
-                                // TODO(b/334825222) add thumbnail state
-                                mTaskThumbnailViewDeprecated.setThumbnail(mTask, thumbnail);
-                            }
-                        });
-            }
-            if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
-                mIconLoadRequest = iconCache.updateIconInBackground(mTask,
-                        (task) -> {
-                            setIcon(mIconView, task.icon);
-                            if (enableOverviewIconMenu()) {
-                                setText(mIconView, task.title);
-                            }
-                            mDigitalWellBeingToast.initialize(task);
-                        });
-            }
-            if (needsUpdate(changes, FLAG_UPDATE_CORNER_RADIUS)) {
-                mCurrentFullscreenParams.updateCornerRadius(getContext());
-            }
-        } else {
-            if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
-                if (!enableRefactorTaskThumbnail()) {
-                    // TODO(b/334825222) add thumbnail state
-                    mTaskThumbnailViewDeprecated.setThumbnail(null, null);
-                }
-                // Reset the task thumbnail reference as well (it will be fetched from the cache or
-                // reloaded next time we need it)
-                mTask.thumbnail = null;
-            }
-            if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
-                setIcon(mIconView, null);
-                if (enableOverviewIconMenu()) {
-                    setText(mIconView, null);
-                }
-            }
-        }
-    }
-
-    protected boolean needsUpdate(@TaskDataChanges int dataChange, @TaskDataChanges int flag) {
-        return (dataChange & flag) == flag;
-    }
-
-    protected void cancelPendingLoadTasks() {
-        if (mThumbnailLoadRequest != null) {
-            mThumbnailLoadRequest.cancel();
-            mThumbnailLoadRequest = null;
-        }
-        if (mIconLoadRequest != null) {
-            mIconLoadRequest.cancel();
-            mIconLoadRequest = null;
-        }
-    }
-
-    private boolean showTaskMenu(TaskViewIcon iconView) {
-        if (!getRecentsView().canLaunchFullscreenTask()) {
-            // Don't show menu when selecting second split screen app
-            return true;
-        }
-
-        if (!mContainer.getDeviceProfile().isTablet
-                && !getRecentsView().isClearAllHidden()) {
-            getRecentsView().snapToPage(getRecentsView().indexOfChild(this));
-            return false;
-        } else {
-            mContainer.getStatsLogManager().logger().withItemInfo(getItemInfo())
-                    .log(LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS);
-            return showTaskMenuWithContainer(iconView);
-        }
-    }
-
-    protected boolean showTaskMenuWithContainer(TaskViewIcon iconView) {
-        TaskIdAttributeContainer menuContainer =
-                mTaskIdAttributeContainer[iconView == mIconView ? 0 : 1];
-        DeviceProfile dp = mContainer.getDeviceProfile();
-        if (enableOverviewIconMenu() && iconView instanceof IconAppChipView) {
-            ((IconAppChipView) iconView).revealAnim(/* isRevealing= */ true);
-            return TaskMenuView.showForTask(menuContainer,
-                    () -> ((IconAppChipView) iconView).revealAnim(/* isRevealing= */ false));
-        } else if (dp.isTablet) {
-            int alignedOptionIndex = 0;
-            if (getRecentsView().isOnGridBottomRow(menuContainer.getTaskView()) && dp.isLandscape) {
-                if (Flags.enableGridOnlyOverview()) {
-                    // With no focused task, there is less available space below the tasks, so align
-                    // the arrow to the third option in the menu.
-                    alignedOptionIndex = 2;
-                } else  {
-                    // Bottom row of landscape grid aligns arrow to second option to avoid clipping
-                    alignedOptionIndex = 1;
-                }
-            }
-            return TaskMenuViewWithArrow.Companion.showForTask(menuContainer,
-                    alignedOptionIndex);
-        } else {
-            return TaskMenuView.showForTask(menuContainer);
-        }
-    }
-
-    protected void setIcon(TaskViewIcon iconView, @Nullable Drawable icon) {
-        if (icon != null) {
-            iconView.setDrawable(icon);
-            iconView.setOnClickListener(v -> {
-                if (confirmSecondSplitSelectApp()) {
-                    return;
-                }
-                showTaskMenu(iconView);
-            });
-            iconView.setOnLongClickListener(v -> {
-                requestDisallowInterceptTouchEvent(true);
-                return showTaskMenu(iconView);
-            });
-        } else {
-            iconView.setDrawable(null);
-            iconView.setOnClickListener(null);
-            iconView.setOnLongClickListener(null);
-        }
-    }
-
-    protected void setText(TaskViewIcon iconView, CharSequence text) {
-        iconView.setText(text);
-    }
-
-    public void setOrientationState(RecentsOrientedState orientationState) {
-        mIconView.setIconOrientation(orientationState, isGridTask());
-        setThumbnailOrientation(orientationState);
-    }
-
-    protected void setThumbnailOrientation(RecentsOrientedState orientationState) {
-        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
-        int thumbnailTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
-
-        // TODO(b/271468547), we should default to setting trasnlations only on the snapshot instead
-        //  of a hybrid of both margins and translations
-        LayoutParams snapshotParams = (LayoutParams) getSnapshotView().getLayoutParams();
-        snapshotParams.topMargin = thumbnailTopMargin;
-        getSnapshotView().setLayoutParams(snapshotParams);
-
-        // TODO(b/335606129) Investigate the usage of [TaskOverlay] in the new TaskThumbnailView.
-        //  and if it's still necessary we should support that in the new TTV class.
-        if (!enableRefactorTaskThumbnail()) {
-            mTaskThumbnailViewDeprecated.getTaskOverlay().updateOrientationState(orientationState);
-        }
-        mDigitalWellBeingToast.initialize(mTask);
-    }
-
-    /**
-     * Returns whether the task is part of overview grid and not being focused.
-     */
-    public boolean isGridTask() {
-        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
-        return deviceProfile.isTablet && !isFocusedTask();
-    }
-
-    /** Whether this task view represents the desktop */
-    public boolean isDesktopTask() {
-        return false;
-    }
-
-    /**
-     * Called to animate a smooth transition when going directly from an app into Overview (and
-     * vice versa). Icons fade in, and DWB banners slide in with a "shift up" animation.
-     */
-    protected void setIconsAndBannersTransitionProgress(float progress, boolean invert) {
-        if (invert) {
-            progress = 1 - progress;
-        }
-        mFocusTransitionProgress = progress;
-        float iconScalePercentage = (float) SCALE_ICON_DURATION / DIM_ANIM_DURATION;
-        float lowerClamp = invert ? 1f - iconScalePercentage : 0;
-        float upperClamp = invert ? 1 : iconScalePercentage;
-        float scale = Interpolators.clampToProgress(FAST_OUT_SLOW_IN, lowerClamp, upperClamp)
-                .getInterpolation(progress);
-        mIconView.setContentAlpha(scale);
-        mDigitalWellBeingToast.updateBannerOffset(1f - scale);
-    }
-
-    public void setIconScaleAnimStartProgress(float startProgress) {
-        mIconScaleAnimStartProgress = startProgress;
-    }
-
-    public void animateIconScaleAndDimIntoView() {
-        if (mIconAndDimAnimator != null) {
-            mIconAndDimAnimator.cancel();
-        }
-        mIconAndDimAnimator = ObjectAnimator.ofFloat(this, FOCUS_TRANSITION, 1);
-        mIconAndDimAnimator.setCurrentFraction(mIconScaleAnimStartProgress);
-        mIconAndDimAnimator.setDuration(DIM_ANIM_DURATION).setInterpolator(LINEAR);
-        mIconAndDimAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mIconAndDimAnimator = null;
-            }
-        });
-        mIconAndDimAnimator.start();
-    }
-
-    protected void setIconScaleAndDim(float iconScale) {
-        setIconScaleAndDim(iconScale, false);
-    }
-
-    private void setIconScaleAndDim(float iconScale, boolean invert) {
-        if (mIconAndDimAnimator != null) {
-            mIconAndDimAnimator.cancel();
-        }
-        setIconsAndBannersTransitionProgress(iconScale, invert);
-    }
-
-    protected void resetPersistentViewTransforms() {
-        mNonGridTranslationX = mGridTranslationX =
-                mGridTranslationY = mBoxTranslationY = mNonGridPivotTranslationX = 0f;
-        resetViewTransforms();
-    }
-
-    protected void resetViewTransforms() {
-        // fullscreenTranslation and accumulatedTranslation should not be reset, as
-        // resetViewTransforms is called during Quickswitch scrolling.
-        mDismissTranslationX = mTaskOffsetTranslationX =
-                mTaskResistanceTranslationX = mSplitSelectTranslationX = mGridEndTranslationX = 0f;
-        mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY = 0f;
-        if (getRecentsView() == null || !getRecentsView().isSplitSelectionActive()) {
-            mSplitSelectTranslationY = 0f;
-        }
-
-        setSnapshotScale(1f);
-        applyTranslationX();
-        applyTranslationY();
-        setTranslationZ(0);
-        setAlpha(mStableAlpha);
-        setIconScaleAndDim(1);
-        setColorTint(0, 0);
-        if (!enableRefactorTaskThumbnail()) {
-            // TODO(b/335399428) add split select functionality to new TTV
-            mTaskThumbnailViewDeprecated.resetViewTransforms();
-        }
-    }
-
-    public void setStableAlpha(float parentAlpha) {
-        mStableAlpha = parentAlpha;
-        setAlpha(mStableAlpha);
-    }
-
-    @Override
-    public void onRecycle() {
-        resetPersistentViewTransforms();
-        // Clear any references to the thumbnail (it will be re-read either from the cache or the
-        // system on next bind)
-        // TODO(b/334825222): Implement thumbnail/snapshot for the new [TaskThumbnailView].
-        if (enableRefactorTaskThumbnail()) {
-            notifyIsRunningTaskUpdated();
-        } else {
-            mTaskThumbnailViewDeprecated.setThumbnail(mTask, null);
-        }
-        setOverlayEnabled(false);
-        onTaskListVisibilityChanged(false);
-        mBorderEnabled = false;
-    }
-
-    public float getTaskCornerRadius() {
-        return mCurrentFullscreenParams.mCornerRadius;
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
-        int thumbnailTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
-        if (deviceProfile.isTablet) {
-            setPivotX(getLayoutDirection() == LAYOUT_DIRECTION_RTL ? 0 : right - left);
-            setPivotY(thumbnailTopMargin);
-        } else {
-            setPivotX((right - left) * 0.5f);
-            setPivotY(thumbnailTopMargin + (getHeight() - thumbnailTopMargin) * 0.5f);
-        }
-        SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(0, 0, getWidth(), getHeight());
-        setSystemGestureExclusionRects(SYSTEM_GESTURE_EXCLUSION_RECT);
-    }
-
-    /**
-     * How much to scale down pages near the edge of the screen.
-     */
-    public static float getEdgeScaleDownFactor(DeviceProfile deviceProfile) {
-        return deviceProfile.isTablet ? EDGE_SCALE_DOWN_FACTOR_GRID
-                : EDGE_SCALE_DOWN_FACTOR_CAROUSEL;
-    }
-
-    private void setNonGridScale(float nonGridScale) {
-        mNonGridScale = nonGridScale;
-        applyScale();
-    }
-
-    public float getNonGridScale() {
-        return mNonGridScale;
-    }
-
-    private void setSnapshotScale(float dismissScale) {
-        mDismissScale = dismissScale;
-        applyScale();
-    }
-
-    /**
-     * Moves TaskView between carousel and 2 row grid.
-     *
-     * @param gridProgress 0 = carousel; 1 = 2 row grid.
-     */
-    public void setGridProgress(float gridProgress) {
-        mGridProgress = gridProgress;
-        applyTranslationX();
-        applyTranslationY();
-        applyScale();
-    }
-
-    private void applyScale() {
-        float scale = 1;
-        scale *= getPersistentScale();
-        scale *= mDismissScale;
-        setScaleX(scale);
-        setScaleY(scale);
-        updateSnapshotRadius();
-    }
-
-    /**
-     * Returns multiplication of scale that is persistent (e.g. fullscreen and grid), and does not
-     * change according to a temporary state.
-     */
-    public float getPersistentScale() {
-        float scale = 1;
-        scale *= Utilities.mapRange(mGridProgress, mNonGridScale, 1f);
-        return scale;
-    }
-
-    /**
-     * Updates alpha of task thumbnail splash on swipe up/down.
-     */
-    public void setTaskThumbnailSplashAlpha(float taskThumbnailSplashAlpha) {
-        mTaskThumbnailSplashAlpha = taskThumbnailSplashAlpha;
-        applyThumbnailSplashAlpha();
-    }
-
-    protected void applyThumbnailSplashAlpha() {
-        if (!enableRefactorTaskThumbnail()) {
-            // TODO(b/334826842) add splash functionality to new TTV
-            mTaskThumbnailViewDeprecated.setSplashAlpha(mTaskThumbnailSplashAlpha);
-        }
-    }
-
-    protected void refreshTaskThumbnailSplash() {
-        if (!enableRefactorTaskThumbnail()) {
-            // TODO(b/334826842) add splash functionality to new TTV
-            mTaskThumbnailViewDeprecated.refreshSplashView();
-        }
-    }
-
-    private void setSplitSelectTranslationX(float x) {
-        mSplitSelectTranslationX = x;
-        applyTranslationX();
-    }
-
-    private void setSplitSelectTranslationY(float y) {
-        mSplitSelectTranslationY = y;
-        applyTranslationY();
-    }
-
-    private void setDismissTranslationX(float x) {
-        mDismissTranslationX = x;
-        applyTranslationX();
-    }
-
-    private void setDismissTranslationY(float y) {
-        mDismissTranslationY = y;
-        applyTranslationY();
-    }
-
-    private void setTaskOffsetTranslationX(float x) {
-        mTaskOffsetTranslationX = x;
-        applyTranslationX();
-    }
-
-    private void setTaskOffsetTranslationY(float y) {
-        mTaskOffsetTranslationY = y;
-        applyTranslationY();
-    }
-
-    private void setTaskResistanceTranslationX(float x) {
-        mTaskResistanceTranslationX = x;
-        applyTranslationX();
-    }
-
-    private void setTaskResistanceTranslationY(float y) {
-        mTaskResistanceTranslationY = y;
-        applyTranslationY();
-    }
-
-    public float getNonGridTranslationX() {
-        return mNonGridTranslationX;
-    }
-
-    /**
-     * Updates X coordinate of non-grid translation.
-     */
-    public void setNonGridTranslationX(float nonGridTranslationX) {
-        mNonGridTranslationX = nonGridTranslationX;
-        applyTranslationX();
-    }
-
-    public void setGridTranslationX(float gridTranslationX) {
-        mGridTranslationX = gridTranslationX;
-        applyTranslationX();
-    }
-
-    public float getGridTranslationX() {
-        return mGridTranslationX;
-    }
-
-    public void setGridTranslationY(float gridTranslationY) {
-        mGridTranslationY = gridTranslationY;
-        applyTranslationY();
-    }
-
-    public float getGridTranslationY() {
-        return mGridTranslationY;
-    }
-
-    private void setGridEndTranslationX(float gridEndTranslationX) {
-        mGridEndTranslationX = gridEndTranslationX;
-        applyTranslationX();
-    }
-
-    /**
-     * Set translation X for non-grid pivot
-     */
-    public void setNonGridPivotTranslationX(float nonGridPivotTranslationX) {
-        mNonGridPivotTranslationX = nonGridPivotTranslationX;
-        applyTranslationX();
-    }
-
-    public float getScrollAdjustment(boolean gridEnabled) {
-        float scrollAdjustment = 0;
-        if (gridEnabled) {
-            scrollAdjustment += mGridTranslationX;
-        } else {
-            scrollAdjustment += getNonGridTranslationX();
-        }
-        return scrollAdjustment;
-    }
-
-    public float getOffsetAdjustment(boolean gridEnabled) {
-        return getScrollAdjustment(gridEnabled);
-    }
-
-    public float getSizeAdjustment(boolean fullscreenEnabled) {
-        float sizeAdjustment = 1;
-        if (fullscreenEnabled) {
-            sizeAdjustment *= mNonGridScale;
-        }
-        return sizeAdjustment;
-    }
-
-    private void setBoxTranslationY(float boxTranslationY) {
-        mBoxTranslationY = boxTranslationY;
-        applyTranslationY();
-    }
-
-    private void applyTranslationX() {
-        setTranslationX(mDismissTranslationX + mTaskOffsetTranslationX + mTaskResistanceTranslationX
-                + mSplitSelectTranslationX + mGridEndTranslationX + getPersistentTranslationX());
-    }
-
-    private void applyTranslationY() {
-        setTranslationY(mDismissTranslationY + mTaskOffsetTranslationY + mTaskResistanceTranslationY
-                + mSplitSelectTranslationY + getPersistentTranslationY());
-    }
-
-    /**
-     * Returns addition of translationX that is persistent (e.g. fullscreen and grid), and does not
-     * change according to a temporary state (e.g. task offset).
-     */
-    public float getPersistentTranslationX() {
-        return getNonGridTrans(mNonGridTranslationX) + getGridTrans(mGridTranslationX)
-                + getNonGridTrans(mNonGridPivotTranslationX);
-    }
-
-    /**
-     * Returns addition of translationY that is persistent (e.g. fullscreen and grid), and does not
-     * change according to a temporary state (e.g. task offset).
-     */
-    public float getPersistentTranslationY() {
-        return mBoxTranslationY + getGridTrans(mGridTranslationY);
-    }
-
-    public FloatProperty<TaskView> getPrimarySplitTranslationProperty() {
-        return getPagedOrientationHandler().getPrimaryValue(
-                SPLIT_SELECT_TRANSLATION_X, SPLIT_SELECT_TRANSLATION_Y);
-    }
-
-    public FloatProperty<TaskView> getSecondarySplitTranslationProperty() {
-        return getPagedOrientationHandler().getSecondaryValue(
-                SPLIT_SELECT_TRANSLATION_X, SPLIT_SELECT_TRANSLATION_Y);
-    }
-
-    public FloatProperty<TaskView> getPrimaryDismissTranslationProperty() {
-        return getPagedOrientationHandler().getPrimaryValue(
-                DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y);
-    }
-
-    public FloatProperty<TaskView> getSecondaryDismissTranslationProperty() {
-        return getPagedOrientationHandler().getSecondaryValue(
-                DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y);
-    }
-
-    public FloatProperty<TaskView> getPrimaryTaskOffsetTranslationProperty() {
-        return getPagedOrientationHandler().getPrimaryValue(
-                TASK_OFFSET_TRANSLATION_X, TASK_OFFSET_TRANSLATION_Y);
-    }
-
-    public FloatProperty<TaskView> getSecondaryTaskOffsetTranslationProperty() {
-        return getPagedOrientationHandler().getSecondaryValue(
-                TASK_OFFSET_TRANSLATION_X, TASK_OFFSET_TRANSLATION_Y);
-    }
-
-    public FloatProperty<TaskView> getTaskResistanceTranslationProperty() {
-        return getPagedOrientationHandler().getSecondaryValue(
-                TASK_RESISTANCE_TRANSLATION_X, TASK_RESISTANCE_TRANSLATION_Y);
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        // TODO: Clip-out the icon region from the thumbnail, since they are overlapping.
-        return false;
-    }
-
-    public boolean isEndQuickswitchCuj() {
-        return mEndQuickswitchCuj;
-    }
-
-    public void setEndQuickswitchCuj(boolean endQuickswitchCuj) {
-        mEndQuickswitchCuj = endQuickswitchCuj;
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfo(info);
-
-        info.addAction(
-                new AccessibilityNodeInfo.AccessibilityAction(R.string.accessibility_close,
-                        getContext().getText(R.string.accessibility_close)));
-
-        final Context context = getContext();
-        for (TaskIdAttributeContainer taskContainer : mTaskIdAttributeContainer) {
-            if (taskContainer == null) {
-                continue;
-            }
-            for (SystemShortcut s : TraceHelper.allowIpcs(
-                    "TV.a11yInfo", () -> getEnabledShortcuts(this, taskContainer))) {
-                info.addAction(s.createAccessibilityAction(context));
-            }
-        }
-
-        if (mDigitalWellBeingToast.hasLimit()) {
-            info.addAction(
-                    new AccessibilityNodeInfo.AccessibilityAction(
-                            R.string.accessibility_app_usage_settings,
-                            getContext().getText(R.string.accessibility_app_usage_settings)));
-        }
-
-        final RecentsView recentsView = getRecentsView();
-        final AccessibilityNodeInfo.CollectionItemInfo itemInfo =
-                AccessibilityNodeInfo.CollectionItemInfo.obtain(
-                        0, 1, recentsView.getTaskViewCount() - recentsView.indexOfChild(this) - 1,
-                        1, false);
-        info.setCollectionItemInfo(itemInfo);
-    }
-
-    @Override
-    public boolean performAccessibilityAction(int action, Bundle arguments) {
-        if (action == R.string.accessibility_close) {
-            getRecentsView().dismissTask(this, true /*animateTaskView*/,
-                    true /*removeTask*/);
-            return true;
-        }
-
-        if (action == R.string.accessibility_app_usage_settings) {
-            mDigitalWellBeingToast.openAppUsageSettings(this);
-            return true;
-        }
-
-        for (TaskIdAttributeContainer taskContainer : mTaskIdAttributeContainer) {
-            if (taskContainer == null) {
-                continue;
-            }
-            for (SystemShortcut s : getEnabledShortcuts(this,
-                    taskContainer)) {
-                if (s.hasHandlerForAction(action)) {
-                    s.onClick(this);
-                    return true;
-                }
-            }
-        }
-
-        return super.performAccessibilityAction(action, arguments);
-    }
-
-    @Nullable
-    public RecentsView getRecentsView() {
-        return (RecentsView) getParent();
-    }
-
-    RecentsPagedOrientationHandler getPagedOrientationHandler() {
-        return getRecentsView().mOrientationState.getOrientationHandler();
-    }
-
-    private void notifyTaskLaunchFailed(String tag) {
-        String msg = "Failed to launch task";
-        if (mTask != null) {
-            msg += " (task=" + mTask.key.baseIntent + " userId=" + mTask.key.userId + ")";
-        }
-        Log.w(tag, msg);
-        Toast.makeText(getContext(), R.string.activity_not_available, LENGTH_SHORT).show();
-    }
-
-    /**
-     * Hides the icon and shows insets when this TaskView is about to be shown fullscreen.
-     *
-     * @param progress: 0 = show icon and no insets; 1 = don't show icon and show full insets.
-     */
-    public void setFullscreenProgress(float progress) {
-        progress = Utilities.boundToRange(progress, 0, 1);
-        mFullscreenProgress = progress;
-        mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
-        if (!enableRefactorTaskThumbnail()) {
-            // TODO(b/334826840) Add corner rounding to new TTV
-            mTaskThumbnailViewDeprecated.getTaskOverlay().setFullscreenProgress(progress);
-        }
-
-        RecentsView recentsView = mContainer.getOverviewPanel();
-        // Animate icons and DWB banners in/out, except in QuickSwitch state, when tiles are
-        // oversized and banner would look disproportionately large.
-        if (recentsView.getStateManager().getState() != BACKGROUND_APP) {
-            setIconsAndBannersTransitionProgress(progress, true);
-        }
-
-        updateSnapshotRadius();
-    }
-
-    protected void updateSnapshotRadius() {
-        updateCurrentFullscreenParams();
-        if (!enableRefactorTaskThumbnail()) {
-            // TODO(b/334826840) Add corner rounding to new TTV
-            mTaskThumbnailViewDeprecated.setFullscreenParams(mCurrentFullscreenParams);
-        }
-    }
-
-    void updateCurrentFullscreenParams() {
-        updateFullscreenParams(mCurrentFullscreenParams);
-    }
-
-    protected void updateFullscreenParams(TaskView.FullscreenDrawParams fullscreenParams) {
-        if (getRecentsView() == null) {
-            return;
-        }
-        fullscreenParams.setProgress(mFullscreenProgress, getRecentsView().getScaleX(),
-                getScaleX());
-    }
-
-    /**
-     * Updates TaskView scaling and translation required to support variable width if enabled, while
-     * ensuring TaskView fits into screen in fullscreen.
-     */
-    void updateTaskSize() {
-        ViewGroup.LayoutParams params = getLayoutParams();
-        float nonGridScale;
-        float boxTranslationY;
-        int expectedWidth;
-        int expectedHeight;
-        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
-        final int thumbnailPadding = deviceProfile.overviewTaskThumbnailTopMarginPx;
-        final Rect lastComputedTaskSize = getRecentsView().getLastComputedTaskSize();
-        final int taskWidth = lastComputedTaskSize.width();
-        final int taskHeight = lastComputedTaskSize.height();
-        if (deviceProfile.isTablet) {
-            int boxWidth;
-            int boxHeight;
-            boolean isFocusedTask = isFocusedTask();
-            if (isFocusedTask) {
-                // Task will be focused and should use focused task size. Use focusTaskRatio
-                // that is associated with the original orientation of the focused task.
-                boxWidth = taskWidth;
-                boxHeight = taskHeight;
-            } else {
-                // Otherwise task is in grid, and should use lastComputedGridTaskSize.
-                Rect lastComputedGridTaskSize = getRecentsView().getLastComputedGridTaskSize();
-                boxWidth = lastComputedGridTaskSize.width();
-                boxHeight = lastComputedGridTaskSize.height();
-            }
-
-            // Bound width/height to the box size.
-            expectedWidth = boxWidth;
-            expectedHeight = boxHeight + thumbnailPadding;
-
-            // Scale to to fit task Rect.
-            if (enableGridOnlyOverview()) {
-                final Rect lastComputedCarouselTaskSize =
-                        getRecentsView().getLastComputedCarouselTaskSize();
-                nonGridScale = lastComputedCarouselTaskSize.width() / (float) taskWidth;
-            } else {
-                nonGridScale = taskWidth / (float) boxWidth;
-            }
-
-            // Align to top of task Rect.
-            boxTranslationY = (expectedHeight - thumbnailPadding - taskHeight) / 2.0f;
-        } else {
-            nonGridScale = 1f;
-            boxTranslationY = 0f;
-            expectedWidth = enableOverviewIconMenu() ? taskWidth : LayoutParams.MATCH_PARENT;
-            expectedHeight = enableOverviewIconMenu()
-                    ? taskHeight + thumbnailPadding
-                    : LayoutParams.MATCH_PARENT;
-        }
-
-        setNonGridScale(nonGridScale);
-        setBoxTranslationY(boxTranslationY);
-        if (params.width != expectedWidth || params.height != expectedHeight) {
-            params.width = expectedWidth;
-            params.height = expectedHeight;
-            setLayoutParams(params);
-        }
-    }
-
-    private float getGridTrans(float endTranslation) {
-        return Utilities.mapRange(mGridProgress, 0, endTranslation);
-    }
-
-    private float getNonGridTrans(float endTranslation) {
-        return endTranslation - getGridTrans(endTranslation);
-    }
-
-    public boolean isRunningTask() {
-        if (getRecentsView() == null) {
-            return false;
-        }
-        return this == getRecentsView().getRunningTaskView();
-    }
-
-    public boolean isFocusedTask() {
-        if (getRecentsView() == null) {
-            return false;
-        }
-        return this == getRecentsView().getFocusedTaskView();
-    }
-
-    public void setShowScreenshot(boolean showScreenshot) {
-        mShowScreenshot = showScreenshot;
-    }
-
-    public boolean showScreenshot() {
-        if (!isRunningTask()) {
-            return true;
-        }
-        return mShowScreenshot;
-    }
-
-    public void setOverlayEnabled(boolean overlayEnabled) {
-        // TODO(b/335606129) Investigate the usage of [TaskOverlay] in the new TaskThumbnailView.
-        //  and if it's still necessary we should support that in the new TTV class.
-        if (!enableRefactorTaskThumbnail()) {
-            mTaskThumbnailViewDeprecated.setOverlayEnabled(overlayEnabled);
-        }
-    }
-
-    public void initiateSplitSelect(SplitPositionOption splitPositionOption) {
-        getRecentsView().initiateSplitSelect(this, splitPositionOption.stagePosition,
-                getLogEventForPosition(splitPositionOption.stagePosition));
-    }
-
-    /**
-     * Set a color tint on the snapshot and supporting views.
-     */
-    public void setColorTint(float amount, int tintColor) {
-        if (!enableRefactorTaskThumbnail()) {
-            // TODO(b/334832108) Add scrim to new TTV
-            mTaskThumbnailViewDeprecated.setDimAlpha(amount);
-        }
-        mIconView.setIconColorTint(tintColor, amount);
-        mDigitalWellBeingToast.setBannerColorTint(tintColor, amount);
-    }
-
-
-    private int getRootViewDisplayId() {
-        Display  display = getRootView().getDisplay();
-        return display != null ? display.getDisplayId() : DEFAULT_DISPLAY;
-    }
-
-    /**
-     *  Sets visibility for the thumbnail and associated elements (DWB banners and action chips).
-     *  IconView is unaffected.
-     *
-     * @param taskId is only used when setting visibility to a non-{@link View#VISIBLE} value
-     */
-    void setThumbnailVisibility(int visibility, int taskId) {
-        for (int i = 0; i < getChildCount(); i++) {
-            View child = getChildAt(i);
-            if (child != mIconView) {
-                child.setVisibility(visibility);
-            }
-        }
-    }
-
-    private View getSnapshotView() {
-        return enableRefactorTaskThumbnail() ? mTaskThumbnailView : mTaskThumbnailViewDeprecated;
-    }
-
-    /**
-     * We update and subsequently draw these in {@link #setFullscreenProgress(float)}.
-     */
-    public static class FullscreenDrawParams implements SafeCloseable {
-
-        private float mCornerRadius;
-        private float mWindowCornerRadius;
-
-        public float mCurrentDrawnCornerRadius;
-
-        public FullscreenDrawParams(Context context) {
-            updateCornerRadius(context);
-        }
-
-        /** Recomputes the start and end corner radius for the given Context. */
-        public void updateCornerRadius(Context context) {
-            mCornerRadius = computeTaskCornerRadius(context);
-            mWindowCornerRadius = computeWindowCornerRadius(context);
-        }
-
-        @VisibleForTesting
-        public float computeTaskCornerRadius(Context context) {
-            return TaskCornerRadius.get(context);
-        }
-
-        @VisibleForTesting
-        public float computeWindowCornerRadius(Context context) {
-            return QuickStepContract.getWindowCornerRadius(context);
-        }
-
-        /**
-         * Sets the progress in range [0, 1]
-         */
-        public void setProgress(float fullscreenProgress, float parentScale, float taskViewScale) {
-            mCurrentDrawnCornerRadius =
-                    Utilities.mapRange(fullscreenProgress, mCornerRadius, mWindowCornerRadius)
-                            / parentScale / taskViewScale;
-        }
-
-        @Override
-        public void close() { }
-    }
-
-    public class TaskIdAttributeContainer {
-        private final TaskThumbnailViewDeprecated mThumbnailView;
-        private final Task mTask;
-        private final TaskViewIcon mIconView;
-        /** Defaults to STAGE_POSITION_UNDEFINED if in not a split screen task view */
-        private @SplitConfigurationOptions.StagePosition int mStagePosition;
-        @IdRes
-        private final int mA11yNodeId;
-
-        public TaskIdAttributeContainer(Task task, TaskThumbnailViewDeprecated thumbnailView,
-                TaskViewIcon iconView, int stagePosition) {
-            this.mTask = task;
-            this.mThumbnailView = thumbnailView;
-            this.mIconView = iconView;
-            this.mStagePosition = stagePosition;
-            this.mA11yNodeId = (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) ?
-                    R.id.split_bottomRight_appInfo : R.id.split_topLeft_appInfo;
-        }
-
-        public TaskThumbnailViewDeprecated getThumbnailView() {
-            return mThumbnailView;
-        }
-
-        public Task getTask() {
-            return mTask;
-        }
-
-        public WorkspaceItemInfo getItemInfo() {
-            return TaskView.this.getItemInfo(mTask);
-        }
-
-        public TaskView getTaskView() {
-            return TaskView.this;
-        }
-
-        public TaskViewIcon getIconView() {
-            return mIconView;
-        }
-
-        public int getStagePosition() {
-            return mStagePosition;
-        }
-
-        void setStagePosition(@SplitConfigurationOptions.StagePosition int stagePosition) {
-            this.mStagePosition = stagePosition;
-        }
-
-        public int getA11yNodeId() {
-            return mA11yNodeId;
-        }
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt
new file mode 100644
index 0000000..05b9d40
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/TaskView.kt
@@ -0,0 +1,1704 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.views
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
+import android.annotation.IdRes
+import android.app.ActivityOptions
+import android.content.Context
+import android.content.Intent
+import android.graphics.Canvas
+import android.graphics.PointF
+import android.graphics.Rect
+import android.graphics.drawable.Drawable
+import android.os.Bundle
+import android.util.AttributeSet
+import android.util.FloatProperty
+import android.util.Log
+import android.view.Display
+import android.view.MotionEvent
+import android.view.View
+import android.view.View.OnClickListener
+import android.view.ViewGroup
+import android.view.ViewStub
+import android.view.accessibility.AccessibilityNodeInfo
+import android.widget.FrameLayout
+import android.widget.Toast
+import androidx.annotation.IntDef
+import androidx.annotation.VisibleForTesting
+import androidx.core.view.updateLayoutParams
+import com.android.app.animation.Interpolators
+import com.android.launcher3.Flags.enableCursorHoverStates
+import com.android.launcher3.Flags.enableFocusOutline
+import com.android.launcher3.Flags.enableGridOnlyOverview
+import com.android.launcher3.Flags.enableOverviewIconMenu
+import com.android.launcher3.Flags.enableRefactorTaskThumbnail
+import com.android.launcher3.Flags.privateSpaceRestrictAccessibilityDrag
+import com.android.launcher3.LauncherSettings
+import com.android.launcher3.LauncherState
+import com.android.launcher3.R
+import com.android.launcher3.Utilities
+import com.android.launcher3.config.FeatureFlags.ENABLE_KEYBOARD_QUICK_SWITCH
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.ItemInfoWithIcon
+import com.android.launcher3.model.data.WorkspaceItemInfo
+import com.android.launcher3.pm.UserCache
+import com.android.launcher3.testing.TestLogging
+import com.android.launcher3.testing.shared.TestProtocol
+import com.android.launcher3.util.CancellableTask
+import com.android.launcher3.util.Executors
+import com.android.launcher3.util.RunnableList
+import com.android.launcher3.util.SafeCloseable
+import com.android.launcher3.util.SplitConfigurationOptions
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
+import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption
+import com.android.launcher3.util.SplitConfigurationOptions.StagePosition
+import com.android.launcher3.util.TraceHelper
+import com.android.launcher3.util.TransformingTouchDelegate
+import com.android.launcher3.util.ViewPool
+import com.android.launcher3.util.rects.set
+import com.android.quickstep.RecentsModel
+import com.android.quickstep.RemoteAnimationTargets
+import com.android.quickstep.TaskAnimationManager
+import com.android.quickstep.TaskOverlayFactory
+import com.android.quickstep.TaskOverlayFactory.TaskOverlay
+import com.android.quickstep.TaskUtils
+import com.android.quickstep.TaskViewUtils
+import com.android.quickstep.orientation.RecentsPagedOrientationHandler
+import com.android.quickstep.task.thumbnail.TaskThumbnail
+import com.android.quickstep.task.thumbnail.TaskThumbnailView
+import com.android.quickstep.task.viewmodel.TaskViewData
+import com.android.quickstep.util.ActiveGestureErrorDetector
+import com.android.quickstep.util.ActiveGestureLog
+import com.android.quickstep.util.BorderAnimator
+import com.android.quickstep.util.BorderAnimator.Companion.createSimpleBorderAnimator
+import com.android.quickstep.util.RecentsOrientedState
+import com.android.quickstep.util.TaskCornerRadius
+import com.android.quickstep.util.TaskRemovedDuringLaunchListener
+import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.ThumbnailData
+import com.android.systemui.shared.system.ActivityManagerWrapper
+import com.android.systemui.shared.system.QuickStepContract
+
+/** A task in the Recents view. */
+open class TaskView
+@JvmOverloads
+constructor(
+    context: Context,
+    attrs: AttributeSet? = null,
+    defStyleAttr: Int = 0,
+    defStyleRes: Int = 0,
+    focusBorderAnimator: BorderAnimator? = null,
+    hoverBorderAnimator: BorderAnimator? = null
+) : FrameLayout(context, attrs), ViewPool.Reusable {
+    /**
+     * Used in conjunction with [onTaskListVisibilityChanged], providing more granularity on which
+     * components of this task require an update
+     */
+    @Retention(AnnotationRetention.SOURCE)
+    @IntDef(FLAG_UPDATE_ALL, FLAG_UPDATE_ICON, FLAG_UPDATE_THUMBNAIL, FLAG_UPDATE_CORNER_RADIUS)
+    annotation class TaskDataChanges
+
+    /** Type of task view */
+    @Retention(AnnotationRetention.SOURCE)
+    @IntDef(Type.SINGLE, Type.GROUPED, Type.DESKTOP)
+    annotation class Type {
+        companion object {
+            const val SINGLE = 1
+            const val GROUPED = 2
+            const val DESKTOP = 3
+        }
+    }
+
+    val taskViewData = TaskViewData()
+    val taskIds: IntArray
+        /** Returns a copy of integer array containing taskIds of all tasks in the TaskView. */
+        get() = taskContainers.map { it.task.key.id }.toIntArray()
+    val thumbnailViews: Array<TaskThumbnailViewDeprecated>
+        get() = taskContainers.map { it.thumbnailViewDeprecated }.toTypedArray()
+    val isGridTask: Boolean
+        /** Returns whether the task is part of overview grid and not being focused. */
+        get() = container.deviceProfile.isTablet && !isFocusedTask
+    val isRunningTask: Boolean
+        get() = this === recentsView?.runningTaskView
+    val isFocusedTask: Boolean
+        get() = this === recentsView?.focusedTaskView
+    val taskCornerRadius: Float
+        get() = currentFullscreenParams.cornerRadius
+    val recentsView: RecentsView<*, *>?
+        get() = parent as? RecentsView<*, *>
+    val pagedOrientationHandler: RecentsPagedOrientationHandler
+        get() = orientedState.orientationHandler
+
+    @get:Deprecated("Use [taskContainers] instead.")
+    val firstTask: Task
+        /** Returns the first task bound to this TaskView. */
+        get() = taskContainers[0].task
+    @get:Deprecated("Use [taskContainers] instead.")
+    val firstThumbnailViewDeprecated: TaskThumbnailViewDeprecated
+        /** Returns the first thumbnailView of the TaskView. */
+        get() = taskContainers[0].thumbnailViewDeprecated
+    @get:Deprecated("Use [taskContainers] instead.")
+    val firstItemInfo: ItemInfo
+        get() = taskContainers[0].itemInfo
+
+    private val currentFullscreenParams = FullscreenDrawParams(context)
+    protected val container: RecentsViewContainer =
+        RecentsViewContainer.containerFromContext(context)
+    protected val lastTouchDownPosition = PointF()
+
+    // Derived view properties
+    protected val persistentScale: Float
+        /**
+         * Returns multiplication of scale that is persistent (e.g. fullscreen and grid), and does
+         * not change according to a temporary state.
+         */
+        get() = Utilities.mapRange(gridProgress, nonGridScale, 1f)
+    protected val persistentTranslationX: Float
+        /**
+         * Returns addition of translationX that is persistent (e.g. fullscreen and grid), and does
+         * not change according to a temporary state (e.g. task offset).
+         */
+        get() =
+            (getNonGridTrans(nonGridTranslationX) +
+                getGridTrans(this.gridTranslationX) +
+                getNonGridTrans(nonGridPivotTranslationX))
+    protected val persistentTranslationY: Float
+        /**
+         * Returns addition of translationY that is persistent (e.g. fullscreen and grid), and does
+         * not change according to a temporary state (e.g. task offset).
+         */
+        get() = boxTranslationY + getGridTrans(gridTranslationY)
+    protected val primarySplitTranslationProperty: FloatProperty<TaskView>
+        get() =
+            pagedOrientationHandler.getPrimaryValue(
+                SPLIT_SELECT_TRANSLATION_X,
+                SPLIT_SELECT_TRANSLATION_Y
+            )
+    protected val secondarySplitTranslationProperty: FloatProperty<TaskView>
+        get() =
+            pagedOrientationHandler.getSecondaryValue(
+                SPLIT_SELECT_TRANSLATION_X,
+                SPLIT_SELECT_TRANSLATION_Y
+            )
+    protected val primaryDismissTranslationProperty: FloatProperty<TaskView>
+        get() =
+            pagedOrientationHandler.getPrimaryValue(DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y)
+    protected val secondaryDismissTranslationProperty: FloatProperty<TaskView>
+        get() =
+            pagedOrientationHandler.getSecondaryValue(DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y)
+    protected val primaryTaskOffsetTranslationProperty: FloatProperty<TaskView>
+        get() =
+            pagedOrientationHandler.getPrimaryValue(
+                TASK_OFFSET_TRANSLATION_X,
+                TASK_OFFSET_TRANSLATION_Y
+            )
+    protected val secondaryTaskOffsetTranslationProperty: FloatProperty<TaskView>
+        get() =
+            pagedOrientationHandler.getSecondaryValue(
+                TASK_OFFSET_TRANSLATION_X,
+                TASK_OFFSET_TRANSLATION_Y
+            )
+    protected val taskResistanceTranslationProperty: FloatProperty<TaskView>
+        get() =
+            pagedOrientationHandler.getSecondaryValue(
+                TASK_RESISTANCE_TRANSLATION_X,
+                TASK_RESISTANCE_TRANSLATION_Y
+            )
+
+    private val tempCoordinates = FloatArray(2)
+    private val focusBorderAnimator: BorderAnimator?
+    private val hoverBorderAnimator: BorderAnimator?
+    private val rootViewDisplayId: Int
+        get() = rootView.display?.displayId ?: Display.DEFAULT_DISPLAY
+
+    /** Returns a list of all TaskContainers in the TaskView. */
+    lateinit var taskContainers: List<TaskContainer>
+        protected set
+    lateinit var orientedState: RecentsOrientedState
+
+    var taskViewId = -1
+    var isEndQuickSwitchCuj = false
+
+    // Various animation progress variables.
+    // progress: 0 = show icon and no insets; 1 = don't show icon and show full insets.
+    protected var fullscreenProgress = 0f
+        set(value) {
+            field = Utilities.boundToRange(value, 0f, 1f)
+            onFullscreenProgressChanged(field)
+        }
+    // gridProgress 0 = carousel; 1 = 2 row grid.
+    protected var gridProgress = 0f
+        set(value) {
+            field = value
+            onGridProgressChanged()
+        }
+    /**
+     * The modalness of this view is how it should be displayed when it is shown on its own in the
+     * modal state of overview. 0 being in context with other tasks, 1 being shown on its own.
+     */
+    protected var modalness = 0f
+        set(value) {
+            if (field == value) {
+                return
+            }
+            field = value
+            onModalnessUpdated(field)
+        }
+    protected var taskThumbnailSplashAlpha = 0f
+        set(value) {
+            field = value
+            applyThumbnailSplashAlpha()
+        }
+    protected var nonGridScale = 1f
+        set(value) {
+            field = value
+            applyScale()
+        }
+    private var dismissScale = 1f
+        set(value) {
+            field = value
+            applyScale()
+        }
+    private var dismissTranslationX = 0f
+        set(value) {
+            field = value
+            applyTranslationX()
+        }
+    private var dismissTranslationY = 0f
+        set(value) {
+            field = value
+            applyTranslationY()
+        }
+    private var taskOffsetTranslationX = 0f
+        set(value) {
+            field = value
+            applyTranslationX()
+        }
+    private var taskOffsetTranslationY = 0f
+        set(value) {
+            field = value
+            applyTranslationY()
+        }
+    private var taskResistanceTranslationX = 0f
+        set(value) {
+            field = value
+            applyTranslationX()
+        }
+    private var taskResistanceTranslationY = 0f
+        set(value) {
+            field = value
+            applyTranslationY()
+        }
+    // The following translation variables should only be used in the same orientation as Launcher.
+    private var boxTranslationY = 0f
+        set(value) {
+            field = value
+            applyTranslationY()
+        }
+    // The following grid translations scales with mGridProgress.
+    protected var gridTranslationX = 0f
+        set(value) {
+            field = value
+            applyTranslationX()
+        }
+    var gridTranslationY = 0f
+        protected set(value) {
+            field = value
+            applyTranslationY()
+        }
+    // The following grid translation is used to animate closing the gap between grid and clear all.
+    private var gridEndTranslationX = 0f
+        set(value) {
+            field = value
+            applyTranslationX()
+        }
+    // Applied as a complement to gridTranslation, for adjusting the carousel overview and quick
+    // switch.
+    protected var nonGridTranslationX = 0f
+        set(value) {
+            field = value
+            applyTranslationX()
+        }
+    protected var nonGridPivotTranslationX = 0f
+        set(value) {
+            field = value
+            applyTranslationX()
+        }
+    // Used when in SplitScreenSelectState
+    private var splitSelectTranslationY = 0f
+        set(value) {
+            field = value
+            applyTranslationY()
+        }
+    private var splitSelectTranslationX = 0f
+        set(value) {
+            field = value
+            applyTranslationX()
+        }
+    protected var stableAlpha = 1f
+        set(value) {
+            field = value
+            alpha = stableAlpha
+        }
+    protected var shouldShowScreenshot = false
+        get() = !isRunningTask || field
+    /** Enable or disable showing border on hover and focus change */
+    @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+    var borderEnabled = false
+        set(value) {
+            if (field == value) {
+                return
+            }
+            field = value
+            // Set the animation correctly in case it misses the hover/focus event during state
+            // transition
+            hoverBorderAnimator?.setBorderVisibility(visible = field && isHovered, animated = true)
+            focusBorderAnimator?.setBorderVisibility(visible = field && isFocused, animated = true)
+        }
+    protected var iconScaleAnimStartProgress = 0f
+    private var focusTransitionProgress = 1f
+
+    private var iconAndDimAnimator: ObjectAnimator? = null
+    // The current background requests to load the task thumbnail and icon
+    private val pendingThumbnailLoadRequests = mutableListOf<CancellableTask<*>>()
+    private val pendingIconLoadRequests = mutableListOf<CancellableTask<*>>()
+    private var isClickableAsLiveTile = true
+
+    init {
+        setOnClickListener { _ -> onClick() }
+        val keyboardFocusHighlightEnabled =
+            (ENABLE_KEYBOARD_QUICK_SWITCH.get() || enableFocusOutline())
+        val cursorHoverStatesEnabled = enableCursorHoverStates()
+        setWillNotDraw(!keyboardFocusHighlightEnabled && !cursorHoverStatesEnabled)
+        context.obtainStyledAttributes(attrs, R.styleable.TaskView, defStyleAttr, defStyleRes).use {
+            this.focusBorderAnimator =
+                focusBorderAnimator
+                    ?: if (keyboardFocusHighlightEnabled)
+                        createSimpleBorderAnimator(
+                            currentFullscreenParams.cornerRadius.toInt(),
+                            context.resources.getDimensionPixelSize(
+                                R.dimen.keyboard_quick_switch_border_width
+                            ),
+                            { bounds: Rect -> getThumbnailBounds(bounds) },
+                            this,
+                            it.getColor(
+                                R.styleable.TaskView_focusBorderColor,
+                                BorderAnimator.DEFAULT_BORDER_COLOR
+                            )
+                        )
+                    else null
+            this.hoverBorderAnimator =
+                hoverBorderAnimator
+                    ?: if (cursorHoverStatesEnabled)
+                        createSimpleBorderAnimator(
+                            currentFullscreenParams.cornerRadius.toInt(),
+                            context.resources.getDimensionPixelSize(
+                                R.dimen.task_hover_border_width
+                            ),
+                            { bounds: Rect -> getThumbnailBounds(bounds) },
+                            this,
+                            it.getColor(
+                                R.styleable.TaskView_hoverBorderColor,
+                                BorderAnimator.DEFAULT_BORDER_COLOR
+                            )
+                        )
+                    else null
+        }
+    }
+
+    @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+    public override fun onFocusChanged(
+        gainFocus: Boolean,
+        direction: Int,
+        previouslyFocusedRect: Rect?
+    ) {
+        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect)
+        if (borderEnabled) {
+            focusBorderAnimator?.setBorderVisibility(gainFocus, /* animated= */ true)
+        }
+    }
+
+    override fun onHoverEvent(event: MotionEvent): Boolean {
+        if (borderEnabled) {
+            when (event.action) {
+                MotionEvent.ACTION_HOVER_ENTER ->
+                    hoverBorderAnimator?.setBorderVisibility(visible = true, animated = true)
+                MotionEvent.ACTION_HOVER_EXIT ->
+                    hoverBorderAnimator?.setBorderVisibility(visible = false, animated = true)
+                else -> {}
+            }
+        }
+        return super.onHoverEvent(event)
+    }
+
+    // avoid triggering hover event on child elements which would cause HOVER_EXIT for this
+    // task view
+    override fun onInterceptHoverEvent(event: MotionEvent) =
+        if (enableCursorHoverStates()) true else super.onInterceptHoverEvent(event)
+
+    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
+        val recentsView = recentsView ?: return false
+        val splitSelectStateController = recentsView.splitSelectController
+        // Disable taps for split selection animation unless we have a task not being selected
+        if (
+            splitSelectStateController.isSplitSelectActive &&
+                taskContainers.none { it.task.key.id != splitSelectStateController.initialTaskId }
+        ) {
+            return false
+        }
+        if (ev.action == MotionEvent.ACTION_DOWN) {
+            with(lastTouchDownPosition) {
+                x = ev.x
+                y = ev.y
+            }
+        }
+        return super.dispatchTouchEvent(ev)
+    }
+
+    override fun draw(canvas: Canvas) {
+        // Draw border first so any child views outside of the thumbnail bounds are drawn above it.
+        focusBorderAnimator?.drawBorder(canvas)
+        hoverBorderAnimator?.drawBorder(canvas)
+        super.draw(canvas)
+    }
+
+    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
+        super.onLayout(changed, left, top, right, bottom)
+        val thumbnailTopMargin = container.deviceProfile.overviewTaskThumbnailTopMarginPx
+        if (container.deviceProfile.isTablet) {
+            pivotX = (if (layoutDirection == LAYOUT_DIRECTION_RTL) 0 else right - left).toFloat()
+            pivotY = thumbnailTopMargin.toFloat()
+        } else {
+            pivotX = (right - left) * 0.5f
+            pivotY = thumbnailTopMargin + (height - thumbnailTopMargin) * 0.5f
+        }
+        systemGestureExclusionRects =
+            SYSTEM_GESTURE_EXCLUSION_RECT.onEach {
+                it.right = width
+                it.bottom = height
+            }
+    }
+
+    override fun onRecycle() {
+        resetPersistentViewTransforms()
+        // Clear any references to the thumbnail (it will be re-read either from the cache or the
+        // system on next bind)
+        // TODO(b/334825222): Implement thumbnail/snapshot for the new [TaskThumbnailView].
+        if (enableRefactorTaskThumbnail()) {
+            notifyIsRunningTaskUpdated()
+        } else {
+            taskContainers.forEach { it.thumbnailViewDeprecated.setThumbnail(it.task, null) }
+        }
+        setOverlayEnabled(false)
+        onTaskListVisibilityChanged(false)
+        borderEnabled = false
+    }
+
+    // TODO: Clip-out the icon region from the thumbnail, since they are overlapping.
+    override fun hasOverlappingRendering() = false
+
+    override fun onInitializeAccessibilityNodeInfo(info: AccessibilityNodeInfo) {
+        super.onInitializeAccessibilityNodeInfo(info)
+        with(info) {
+            addAction(
+                AccessibilityNodeInfo.AccessibilityAction(
+                    R.string.accessibility_close,
+                    context.getText(R.string.accessibility_close)
+                )
+            )
+            taskContainers.forEach {
+                TraceHelper.allowIpcs("TV.a11yInfo") {
+                    TaskOverlayFactory.getEnabledShortcuts(this@TaskView, it).forEach { shortcut ->
+                        addAction(shortcut.createAccessibilityAction(context))
+                    }
+                }
+            }
+            // TODO(b/341672022): handle multiple digitalWellBeingToast accessibility actions
+            if (taskContainers[0].digitalWellBeingToast?.hasLimit() == true) {
+                addAction(
+                    AccessibilityNodeInfo.AccessibilityAction(
+                        R.string.accessibility_app_usage_settings,
+                        context.getText(R.string.accessibility_app_usage_settings)
+                    )
+                )
+            }
+            recentsView?.let {
+                collectionItemInfo =
+                    AccessibilityNodeInfo.CollectionItemInfo.obtain(
+                        0,
+                        1,
+                        it.taskViewCount - it.indexOfChild(this@TaskView) - 1,
+                        1,
+                        false
+                    )
+            }
+        }
+    }
+
+    override fun performAccessibilityAction(action: Int, arguments: Bundle?): Boolean {
+        if (action == R.string.accessibility_close) {
+            recentsView?.dismissTask(this, true /*animateTaskView*/, true /*removeTask*/)
+            return true
+        }
+        if (action == R.string.accessibility_app_usage_settings) {
+            // TODO(b/341672022): handle multiple digitalWellBeingToast accessibility actions
+            taskContainers[0].digitalWellBeingToast?.openAppUsageSettings(this)
+            return true
+        }
+        taskContainers.forEach {
+            TaskOverlayFactory.getEnabledShortcuts(this, it).forEach { shortcut ->
+                if (shortcut.hasHandlerForAction(action)) {
+                    shortcut.onClick(this)
+                    return true
+                }
+            }
+        }
+        return super.performAccessibilityAction(action, arguments)
+    }
+
+    /** Updates this task view to the given {@param task}. */
+    open fun bind(
+        task: Task,
+        orientedState: RecentsOrientedState,
+        taskOverlayFactory: TaskOverlayFactory
+    ) {
+        cancelPendingLoadTasks()
+        taskContainers =
+            listOf(
+                createTaskContainer(
+                    task,
+                    R.id.snapshot,
+                    R.id.icon,
+                    R.id.show_windows,
+                    STAGE_POSITION_UNDEFINED,
+                    taskOverlayFactory
+                )
+            )
+        setOrientationState(orientedState)
+    }
+
+    protected fun createTaskContainer(
+        task: Task,
+        @IdRes thumbnailViewId: Int,
+        @IdRes iconViewId: Int,
+        @IdRes showWindowViewId: Int,
+        @StagePosition stagePosition: Int,
+        taskOverlayFactory: TaskOverlayFactory
+    ): TaskContainer {
+        val thumbnailViewDeprecated: TaskThumbnailViewDeprecated = findViewById(thumbnailViewId)!!
+        val thumbnailView: TaskThumbnailView?
+        if (enableRefactorTaskThumbnail()) {
+            val indexOfSnapshotView = indexOfChild(thumbnailViewDeprecated)
+            thumbnailView =
+                TaskThumbnailView(context).apply {
+                    layoutParams = thumbnailViewDeprecated.layoutParams
+                    addView(this, indexOfSnapshotView)
+                }
+            thumbnailViewDeprecated.visibility = GONE
+        } else {
+            thumbnailView = null
+        }
+        val iconView = getOrInflateIconView(iconViewId)
+        return TaskContainer(
+                task,
+                thumbnailView,
+                thumbnailViewDeprecated,
+                iconView,
+                TransformingTouchDelegate(iconView.asView()),
+                stagePosition,
+                DigitalWellBeingToast(container, this),
+                findViewById(showWindowViewId)!!,
+                taskOverlayFactory
+            )
+            .apply {
+                if (enableRefactorTaskThumbnail()) {
+                    thumbnailViewDeprecated.setTaskOverlay(overlay)
+                    bindThumbnailView()
+                } else {
+                    thumbnailViewDeprecated.bind(task, overlay)
+                }
+            }
+    }
+
+    protected fun getOrInflateIconView(@IdRes iconViewId: Int): TaskViewIcon {
+        val iconView = findViewById<View>(iconViewId)!!
+        return iconView as? TaskViewIcon
+            ?: (iconView as ViewStub)
+                .apply {
+                    layoutResource =
+                        if (enableOverviewIconMenu()) R.layout.icon_app_chip_view
+                        else R.layout.icon_view
+                }
+                .inflate() as TaskViewIcon
+    }
+
+    protected fun isTaskContainersInitialized() = this::taskContainers.isInitialized
+
+    fun containsMultipleTasks() = taskContainers.size > 1
+
+    /**
+     * Returns the TaskContainer corresponding to a given taskId, or null if the TaskView does not
+     * contain a Task with that ID.
+     */
+    fun getTaskContainerById(taskId: Int) = taskContainers.firstOrNull { it.task.key.id == taskId }
+
+    /** Check if given `taskId` is tracked in this view */
+    fun containsTaskId(taskId: Int) = getTaskContainerById(taskId) != null
+
+    open fun setOrientationState(orientationState: RecentsOrientedState) {
+        this.orientedState = orientationState
+        taskContainers.forEach { it.iconView.setIconOrientation(orientationState, isGridTask) }
+        setThumbnailOrientation(orientationState)
+    }
+
+    protected open fun setThumbnailOrientation(orientationState: RecentsOrientedState) {
+        taskContainers.forEach {
+            it.overlay.updateOrientationState(orientationState)
+            it.digitalWellBeingToast?.initialize(it.task)
+        }
+    }
+
+    /**
+     * Updates TaskView scaling and translation required to support variable width if enabled, while
+     * ensuring TaskView fits into screen in fullscreen.
+     */
+    fun updateTaskSize(
+        lastComputedTaskSize: Rect,
+        lastComputedGridTaskSize: Rect,
+        lastComputedCarouselTaskSize: Rect
+    ) {
+        val thumbnailPadding = container.deviceProfile.overviewTaskThumbnailTopMarginPx
+        val taskWidth = lastComputedTaskSize.width()
+        val taskHeight = lastComputedTaskSize.height()
+        val nonGridScale: Float
+        val boxTranslationY: Float
+        val expectedWidth: Int
+        val expectedHeight: Int
+        if (container.deviceProfile.isTablet) {
+            val boxWidth: Int
+            val boxHeight: Int
+            if (isFocusedTask) {
+                // Task will be focused and should use focused task size. Use focusTaskRatio
+                // that is associated with the original orientation of the focused task.
+                boxWidth = taskWidth
+                boxHeight = taskHeight
+            } else {
+                // Otherwise task is in grid, and should use lastComputedGridTaskSize.
+                boxWidth = lastComputedGridTaskSize.width()
+                boxHeight = lastComputedGridTaskSize.height()
+            }
+
+            // Bound width/height to the box size.
+            expectedWidth = boxWidth
+            expectedHeight = boxHeight + thumbnailPadding
+
+            // Scale to to fit task Rect.
+            nonGridScale =
+                if (enableGridOnlyOverview()) {
+                    lastComputedCarouselTaskSize.width() / taskWidth.toFloat()
+                } else {
+                    taskWidth / boxWidth.toFloat()
+                }
+
+            // Align to top of task Rect.
+            boxTranslationY = (expectedHeight - thumbnailPadding - taskHeight) / 2.0f
+        } else {
+            nonGridScale = 1f
+            boxTranslationY = 0f
+            expectedWidth = if (enableOverviewIconMenu()) taskWidth else LayoutParams.MATCH_PARENT
+            expectedHeight =
+                if (enableOverviewIconMenu()) taskHeight + thumbnailPadding
+                else LayoutParams.MATCH_PARENT
+        }
+        this.nonGridScale = nonGridScale
+        this.boxTranslationY = boxTranslationY
+        updateLayoutParams<ViewGroup.LayoutParams> {
+            width = expectedWidth
+            height = expectedHeight
+        }
+        updateThumbnailSize()
+    }
+
+    protected open fun updateThumbnailSize() {
+        // TODO(b/271468547), we should default to setting translations only on the snapshot instead
+        //  of a hybrid of both margins and translations
+        taskContainers[0].snapshotView.updateLayoutParams<LayoutParams> {
+            topMargin = container.deviceProfile.overviewTaskThumbnailTopMarginPx
+        }
+    }
+
+    /** Returns the thumbnail's bounds, optionally relative to the screen. */
+    @JvmOverloads
+    open fun getThumbnailBounds(bounds: Rect, relativeToDragLayer: Boolean = false) {
+        bounds.setEmpty()
+        taskContainers.forEach {
+            val thumbnailBounds = Rect()
+            if (relativeToDragLayer) {
+                container.dragLayer.getDescendantRectRelativeToSelf(it.snapshotView, bounds)
+            } else {
+                thumbnailBounds.set(it.snapshotView)
+            }
+            bounds.union(thumbnailBounds)
+        }
+    }
+
+    /**
+     * See [TaskDataChanges]
+     *
+     * @param visible If this task view will be visible to the user in overview or hidden
+     */
+    fun onTaskListVisibilityChanged(visible: Boolean) {
+        onTaskListVisibilityChanged(visible, FLAG_UPDATE_ALL)
+    }
+
+    /**
+     * See [TaskDataChanges]
+     *
+     * @param visible If this task view will be visible to the user in overview or hidden
+     */
+    open fun onTaskListVisibilityChanged(visible: Boolean, @TaskDataChanges changes: Int) {
+        cancelPendingLoadTasks()
+        val recentsModel = RecentsModel.INSTANCE.get(context)
+        // These calls are no-ops if the data is already loaded, try and load the high
+        // resolution thumbnail if the state permits
+        if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
+            if (!enableRefactorTaskThumbnail()) {
+                // TODO(b/334825222) add thumbnail state
+                taskContainers.forEach {
+                    if (visible) {
+                        recentsModel.thumbnailCache
+                            .updateThumbnailInBackground(it.task) { thumbnailData ->
+                                it.thumbnailViewDeprecated.setThumbnail(it.task, thumbnailData)
+                            }
+                            ?.also { request -> pendingThumbnailLoadRequests.add(request) }
+                    } else {
+                        it.thumbnailViewDeprecated.setThumbnail(null, null)
+                        // Reset the task thumbnail reference as well (it will be fetched from the
+                        // cache or reloaded next time we need it)
+                        it.task.thumbnail = null
+                    }
+                }
+            }
+        }
+        if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
+            taskContainers.forEach {
+                if (visible) {
+                    recentsModel.iconCache
+                        .updateIconInBackground(it.task) { thumbnailData ->
+                            setIcon(it.iconView, thumbnailData.icon)
+                            if (enableOverviewIconMenu()) {
+                                setText(it.iconView, thumbnailData.title)
+                            }
+                            it.digitalWellBeingToast?.initialize(thumbnailData)
+                        }
+                        ?.also { request -> pendingIconLoadRequests.add(request) }
+                } else {
+                    setIcon(it.iconView, null)
+                    if (enableOverviewIconMenu()) {
+                        setText(it.iconView, null)
+                    }
+                }
+            }
+        }
+        if (needsUpdate(changes, FLAG_UPDATE_CORNER_RADIUS)) {
+            currentFullscreenParams.updateCornerRadius(context)
+        }
+    }
+
+    protected open fun needsUpdate(@TaskDataChanges dataChange: Int, @TaskDataChanges flag: Int) =
+        (dataChange and flag) == flag
+
+    protected open fun cancelPendingLoadTasks() {
+        pendingThumbnailLoadRequests.forEach { it.cancel() }
+        pendingThumbnailLoadRequests.clear()
+        pendingIconLoadRequests.forEach { it.cancel() }
+        pendingIconLoadRequests.clear()
+    }
+
+    protected fun setIcon(iconView: TaskViewIcon, icon: Drawable?) {
+        with(iconView) {
+            if (icon != null) {
+                setDrawable(icon)
+                setOnClickListener {
+                    if (!confirmSecondSplitSelectApp()) {
+                        showTaskMenu(this)
+                    }
+                }
+                setOnLongClickListener {
+                    requestDisallowInterceptTouchEvent(true)
+                    showTaskMenu(this)
+                }
+            } else {
+                setDrawable(null)
+                setOnClickListener(null)
+                setOnLongClickListener(null)
+            }
+        }
+    }
+
+    protected fun setText(iconView: TaskViewIcon, text: CharSequence?) {
+        iconView.setText(text)
+    }
+
+    open fun refreshThumbnails(thumbnailDatas: HashMap<Int, ThumbnailData?>?) {
+        if (enableRefactorTaskThumbnail()) {
+            // TODO(b/334825222) add thumbnail logic
+            return
+        }
+
+        taskContainers.forEach {
+            val thumbnailData = thumbnailDatas?.get(it.task.key.id)
+            if (thumbnailData != null) {
+                it.thumbnailViewDeprecated.setThumbnail(it.task, thumbnailData)
+            } else {
+                it.thumbnailViewDeprecated.refresh()
+            }
+        }
+    }
+
+    private fun onClick() {
+        if (confirmSecondSplitSelectApp()) {
+            Log.d("b/310064698", "${taskIds.contentToString()} - onClick - split select is active")
+            return
+        }
+        val callbackList =
+            launchTasks()?.apply {
+                add {
+                    Log.d("b/310064698", "${taskIds.contentToString()} - onClick - launchCompleted")
+                }
+            }
+        Log.d("b/310064698", "${taskIds.contentToString()} - onClick - callbackList: $callbackList")
+        container.statsLogManager
+            .logger()
+            .withItemInfo(firstItemInfo)
+            .log(LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP)
+    }
+
+    /**
+     * Starts the task associated with this view and animates the startup.
+     *
+     * @return CompletionStage to indicate the animation completion or null if the launch failed.
+     */
+    open fun launchTaskAnimated(): RunnableList? {
+        TestLogging.recordEvent(
+            TestProtocol.SEQUENCE_MAIN,
+            "startActivityFromRecentsAsync",
+            taskIds.contentToString()
+        )
+        val opts =
+            container.getActivityLaunchOptions(this, null).apply {
+                options.launchDisplayId = display?.displayId ?: Display.DEFAULT_DISPLAY
+            }
+        if (
+            ActivityManagerWrapper.getInstance()
+                .startActivityFromRecents(taskContainers[0].task.key, opts.options)
+        ) {
+            Log.d(
+                TAG,
+                "launchTaskAnimated - startActivityFromRecents: ${taskIds.contentToString()}"
+            )
+            ActiveGestureLog.INSTANCE.trackEvent(
+                ActiveGestureErrorDetector.GestureEvent.EXPECTING_TASK_APPEARED
+            )
+            val recentsView = recentsView ?: return null
+            if (recentsView.runningTaskViewId != -1) {
+                recentsView.onTaskLaunchedInLiveTileMode()
+
+                // Return a fresh callback in the live tile case, so that it's not accidentally
+                // triggered by QuickstepTransitionManager.AppLaunchAnimationRunner.
+                return RunnableList().also { recentsView.addSideTaskLaunchCallback(it) }
+            }
+            if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
+                // If the recents transition is running (ie. in live tile mode), then the start
+                // of a new task will merge into the existing transition and it currently will
+                // not be run independently, so we need to rely on the onTaskAppeared() call
+                // for the new task to trigger the side launch callback to flush this runnable
+                // list (which is usually flushed when the app launch animation finishes)
+                recentsView.addSideTaskLaunchCallback(opts.onEndCallback)
+            }
+            return opts.onEndCallback
+        } else {
+            notifyTaskLaunchFailed()
+            return null
+        }
+    }
+
+    /** Starts the task associated with this view without any animation */
+    fun launchTask(callback: (launched: Boolean) -> Unit) {
+        launchTask(callback, isQuickSwitch = false)
+    }
+
+    /** Starts the task associated with this view without any animation */
+    open fun launchTask(callback: (launched: Boolean) -> Unit, isQuickSwitch: Boolean) {
+        TestLogging.recordEvent(
+            TestProtocol.SEQUENCE_MAIN,
+            "startActivityFromRecentsAsync",
+            taskIds.contentToString()
+        )
+        val firstContainer = taskContainers[0]
+        val failureListener = TaskRemovedDuringLaunchListener(context.applicationContext)
+        if (isQuickSwitch) {
+            // We only listen for failures to launch in quickswitch because the during this
+            // gesture launcher is in the background state, vs other launches which are in
+            // the actual overview state
+            failureListener.register(container, firstContainer.task.key.id) {
+                notifyTaskLaunchFailed()
+                recentsView?.let {
+                    // Disable animations for now, as it is an edge case and the app usually
+                    // covers launcher and also any state transition animation also gets
+                    // clobbered by QuickstepTransitionManager.createWallpaperOpenAnimations
+                    // when launcher shows again
+                    it.startHome(false /* animated */)
+                    // LauncherTaskbarUIController depends on the launcher state when
+                    // checking whether to handle resume, but that can come in before
+                    // startHome() changes the state, so force-refresh here to ensure the
+                    // taskbar is updated
+                    it.mSizeStrategy.taskbarController?.refreshResumedState()
+                }
+            }
+        }
+        // Indicate success once the system has indicated that the transition has started
+        val opts =
+            ActivityOptions.makeCustomTaskAnimation(
+                    context,
+                    0,
+                    0,
+                    Executors.MAIN_EXECUTOR.handler,
+                    { callback(true) }
+                ) {
+                    failureListener.onTransitionFinished()
+                }
+                .apply {
+                    launchDisplayId = display?.displayId ?: Display.DEFAULT_DISPLAY
+                    if (isQuickSwitch) {
+                        setFreezeRecentTasksReordering()
+                    }
+                    // TODO(b/334826842) add splash functionality to new TTV
+                    if (!enableRefactorTaskThumbnail()) {
+                        disableStartingWindow =
+                            firstContainer.thumbnailViewDeprecated.shouldShowSplashView()
+                    }
+                }
+        Executors.UI_HELPER_EXECUTOR.execute {
+            if (
+                !ActivityManagerWrapper.getInstance()
+                    .startActivityFromRecents(firstContainer.task.key, opts)
+            ) {
+                // If the call to start activity failed, then post the result immediately,
+                // otherwise, wait for the animation start callback from the activity options
+                // above
+                Executors.MAIN_EXECUTOR.post {
+                    notifyTaskLaunchFailed()
+                    callback(false)
+                }
+            }
+            Log.d(TAG, "launchTask - startActivityFromRecents: ${taskIds.contentToString()}")
+        }
+    }
+
+    /** Launch of the current task (both live and inactive tasks) with an animation. */
+    fun launchTasks(): RunnableList? {
+        val recentsView = recentsView ?: return null
+        val remoteTargetHandles = recentsView.mRemoteTargetHandles
+        if (!isRunningTask || remoteTargetHandles == null) {
+            return launchTaskAnimated()
+        }
+        if (!isClickableAsLiveTile) {
+            Log.e(TAG, "TaskView is not clickable as a live tile; returning to home.")
+            return null
+        }
+        isClickableAsLiveTile = false
+        val targets =
+            if (remoteTargetHandles.size == 1) {
+                remoteTargetHandles[0].transformParams.targetSet
+            } else {
+                val apps =
+                    remoteTargetHandles.flatMap { it.transformParams.targetSet.apps.asIterable() }
+                val wallpapers =
+                    remoteTargetHandles.flatMap {
+                        it.transformParams.targetSet.wallpapers.asIterable()
+                    }
+                RemoteAnimationTargets(
+                    apps.toTypedArray(),
+                    wallpapers.toTypedArray(),
+                    remoteTargetHandles[0].transformParams.targetSet.nonApps,
+                    remoteTargetHandles[0].transformParams.targetSet.targetMode
+                )
+            }
+        if (targets == null) {
+            // If the recents animation is cancelled somehow between the parent if block and
+            // here, try to launch the task as a non live tile task.
+            val runnableList = launchTaskAnimated()
+            if (runnableList == null) {
+                Log.e(
+                    TAG,
+                    "Recents animation cancelled and cannot launch task as non-live tile" +
+                        "; returning to home"
+                )
+            }
+            isClickableAsLiveTile = true
+            return runnableList
+        }
+        val runnableList = RunnableList()
+        with(AnimatorSet()) {
+            TaskViewUtils.composeRecentsLaunchAnimator(
+                this,
+                this@TaskView,
+                targets.apps,
+                targets.wallpapers,
+                targets.nonApps,
+                true /* launcherClosing */,
+                recentsView.stateManager,
+                recentsView,
+                recentsView.depthController
+            )
+            addListener(
+                object : AnimatorListenerAdapter() {
+                    override fun onAnimationEnd(animator: Animator) {
+                        if (taskContainers.any { it.task.key.displayId != rootViewDisplayId }) {
+                            launchTaskAnimated()
+                        }
+                        isClickableAsLiveTile = true
+                        runEndCallback()
+                    }
+
+                    override fun onAnimationCancel(animation: Animator) {
+                        runEndCallback()
+                    }
+
+                    private fun runEndCallback() {
+                        runnableList.executeAllAndDestroy()
+                    }
+                }
+            )
+            start()
+        }
+        Log.d(TAG, "launchTasks - composeRecentsLaunchAnimator: ${taskIds.contentToString()}")
+        recentsView.onTaskLaunchedInLiveTileMode()
+        return runnableList
+    }
+
+    private fun notifyTaskLaunchFailed() {
+        val sb = StringBuilder("Failed to launch task \n")
+        taskContainers.forEach {
+            sb.append("(task=${it.task.key.baseIntent} userId=${it.task.key.userId})\n")
+        }
+        Log.w(TAG, sb.toString())
+        Toast.makeText(context, R.string.activity_not_available, Toast.LENGTH_SHORT).show()
+    }
+
+    fun initiateSplitSelect(splitPositionOption: SplitPositionOption) {
+        recentsView?.initiateSplitSelect(
+            this,
+            splitPositionOption.stagePosition,
+            SplitConfigurationOptions.getLogEventForPosition(splitPositionOption.stagePosition)
+        )
+    }
+
+    /**
+     * Returns `true` if user is already in split select mode and this tap was to choose the second
+     * app. `false` otherwise
+     */
+    protected open fun confirmSecondSplitSelectApp(): Boolean {
+        val index = getLastSelectedChildTaskIndex()
+        if (index >= taskContainers.size) {
+            return false
+        }
+        val container = taskContainers[index]
+        val recentsView = recentsView ?: return false
+        return recentsView.confirmSplitSelect(
+            this,
+            container.task,
+            container.iconView.drawable,
+            container.thumbnailViewDeprecated,
+            container.thumbnailViewDeprecated.thumbnail, /* intent */
+            null, /* user */
+            null,
+            container.itemInfo
+        )
+    }
+
+    /**
+     * Returns the task index of the last selected child task (0 or 1). If we contain multiple tasks
+     * and this TaskView is used as part of split selection, the selected child task index will be
+     * that of the remaining task.
+     */
+    protected open fun getLastSelectedChildTaskIndex() = 0
+
+    private fun showTaskMenu(iconView: TaskViewIcon): Boolean {
+        val recentsView = recentsView ?: return false
+        if (!recentsView.canLaunchFullscreenTask()) {
+            // Don't show menu when selecting second split screen app
+            return true
+        }
+        if (!container.deviceProfile.isTablet && !recentsView.isClearAllHidden) {
+            recentsView.snapToPage(recentsView.indexOfChild(this))
+            return false
+        }
+        val menuContainer = taskContainers.firstOrNull { it.iconView === iconView } ?: return false
+        container.statsLogManager
+            .logger()
+            .withItemInfo(menuContainer.itemInfo)
+            .log(LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS)
+        return showTaskMenuWithContainer(menuContainer)
+    }
+
+    private fun showTaskMenuWithContainer(menuContainer: TaskContainer): Boolean {
+        val recentsView = recentsView ?: return false
+        return if (enableOverviewIconMenu() && menuContainer.iconView is IconAppChipView) {
+            menuContainer.iconView.revealAnim(/* isRevealing= */ true)
+            TaskMenuView.showForTask(menuContainer) {
+                menuContainer.iconView.revealAnim(/* isRevealing= */ false)
+            }
+        } else if (container.deviceProfile.isTablet) {
+            val alignedOptionIndex =
+                if (
+                    recentsView.isOnGridBottomRow(menuContainer.taskView) &&
+                        container.deviceProfile.isLandscape
+                ) {
+                    if (enableGridOnlyOverview()) {
+                        // With no focused task, there is less available space below the tasks, so
+                        // align the arrow to the third option in the menu.
+                        2
+                    } else {
+                        // Bottom row of landscape grid aligns arrow to second option to avoid
+                        // clipping
+                        1
+                    }
+                } else {
+                    0
+                }
+            TaskMenuViewWithArrow.showForTask(menuContainer, alignedOptionIndex)
+        } else {
+            TaskMenuView.showForTask(menuContainer)
+        }
+    }
+
+    /**
+     * Whether the taskview should take the touch event from parent. Events passed to children that
+     * might require special handling.
+     */
+    open fun offerTouchToChildren(event: MotionEvent): Boolean {
+        taskContainers.forEach {
+            if (event.action == MotionEvent.ACTION_DOWN) {
+                computeAndSetIconTouchDelegate(it.iconView, tempCoordinates, it.iconTouchDelegate)
+                if (it.iconTouchDelegate.onTouchEvent(event)) {
+                    return true
+                }
+            }
+        }
+        return false
+    }
+
+    private fun computeAndSetIconTouchDelegate(
+        view: TaskViewIcon,
+        tempCenterCoordinates: FloatArray,
+        transformingTouchDelegate: TransformingTouchDelegate
+    ) {
+        val viewHalfWidth = view.width / 2f
+        val viewHalfHeight = view.height / 2f
+        Utilities.getDescendantCoordRelativeToAncestor(
+            view.asView(),
+            container.dragLayer,
+            tempCenterCoordinates.apply {
+                this[0] = viewHalfWidth
+                this[1] = viewHalfHeight
+            },
+            false
+        )
+        transformingTouchDelegate.setBounds(
+            (tempCenterCoordinates[0] - viewHalfWidth).toInt(),
+            (tempCenterCoordinates[1] - viewHalfHeight).toInt(),
+            (tempCenterCoordinates[0] + viewHalfWidth).toInt(),
+            (tempCenterCoordinates[1] + viewHalfHeight).toInt()
+        )
+    }
+
+    /** Sets up an on-click listener and the visibility for show_windows icon on top of the task. */
+    open fun setUpShowAllInstancesListener() {
+        taskContainers.forEach {
+            it.showWindowsView?.let { showWindowsView ->
+                updateFilterCallback(
+                    showWindowsView,
+                    getFilterUpdateCallback(it.task.key.packageName)
+                )
+            }
+        }
+    }
+
+    /**
+     * Returns a callback that updates the state of the filter and the recents overview
+     *
+     * @param taskPackageName package name of the task to filter by
+     */
+    private fun getFilterUpdateCallback(taskPackageName: String?) =
+        if (recentsView?.filterState?.shouldShowFilterUI(taskPackageName) == true)
+            OnClickListener { recentsView?.setAndApplyFilter(taskPackageName) }
+        else null
+
+    /**
+     * Sets the correct visibility and callback on the provided filterView based on whether the
+     * callback is null or not
+     */
+    private fun updateFilterCallback(filterView: View, callback: OnClickListener?) {
+        // Filtering changes alpha instead of the visibility since visibility
+        // can be altered separately through RecentsView#resetFromSplitSelectionState()
+        with(filterView) {
+            alpha = if (callback == null) 0f else 1f
+            setOnClickListener(callback)
+        }
+    }
+
+    protected open fun setIconsAndBannersFullscreenProgress(progress: Float) {
+        // Animate icons and DWB banners in/out, except in QuickSwitch state, when tiles are
+        // oversized and banner would look disproportionately large.
+        if (recentsView?.stateManager?.state == LauncherState.BACKGROUND_APP) {
+            return
+        }
+        setIconsAndBannersTransitionProgress(progress, invert = true)
+    }
+
+    /**
+     * Called to animate a smooth transition when going directly from an app into Overview (and vice
+     * versa). Icons fade in, and DWB banners slide in with a "shift up" animation.
+     */
+    protected open fun setIconsAndBannersTransitionProgress(progress: Float, invert: Boolean) {
+        focusTransitionProgress = if (invert) 1 - progress else progress
+        getIconContentScale(invert).let { iconContentScale ->
+            taskContainers.forEach {
+                it.iconView.setContentAlpha(iconContentScale)
+                it.digitalWellBeingToast?.updateBannerOffset(1f - iconContentScale)
+            }
+        }
+    }
+
+    private fun getIconContentScale(invert: Boolean): Float {
+        val iconScalePercentage = SCALE_ICON_DURATION.toFloat() / DIM_ANIM_DURATION
+        val lowerClamp = if (invert) 1f - iconScalePercentage else 0f
+        val upperClamp = if (invert) 1f else iconScalePercentage
+        return Interpolators.clampToProgress(Interpolators.FAST_OUT_SLOW_IN, lowerClamp, upperClamp)
+            .getInterpolation(focusTransitionProgress)
+    }
+
+    fun animateIconScaleAndDimIntoView() {
+        iconAndDimAnimator?.cancel()
+        iconAndDimAnimator =
+            ObjectAnimator.ofFloat(this, FOCUS_TRANSITION, 1f).apply {
+                setCurrentFraction(iconScaleAnimStartProgress)
+                setDuration(DIM_ANIM_DURATION).interpolator = Interpolators.LINEAR
+                addListener(
+                    object : AnimatorListenerAdapter() {
+                        override fun onAnimationEnd(animation: Animator) {
+                            iconAndDimAnimator = null
+                        }
+                    }
+                )
+                start()
+            }
+    }
+
+    fun setIconScaleAndDim(iconScale: Float) {
+        iconAndDimAnimator?.cancel()
+        setIconsAndBannersTransitionProgress(iconScale, invert = false)
+    }
+
+    /** Set a color tint on the snapshot and supporting views. */
+    open fun setColorTint(amount: Float, tintColor: Int) {
+        taskContainers.forEach {
+            if (!enableRefactorTaskThumbnail()) {
+                // TODO(b/334832108) Add scrim to new TTV
+                it.thumbnailViewDeprecated.dimAlpha = amount
+            }
+            it.iconView.setIconColorTint(tintColor, amount)
+            it.digitalWellBeingToast?.setBannerColorTint(tintColor, amount)
+        }
+    }
+
+    /**
+     * Sets visibility for the thumbnail and associated elements (DWB banners and action chips).
+     * IconView is unaffected.
+     *
+     * @param taskId is only used when setting visibility to a non-[View.VISIBLE] value
+     */
+    open fun setThumbnailVisibility(visibility: Int, taskId: Int) {
+        taskContainers.forEach {
+            if (visibility == VISIBLE || it.task.key.id == taskId) {
+                it.snapshotView.visibility = visibility
+                it.digitalWellBeingToast?.setBannerVisibility(visibility)
+                it.showWindowsView?.visibility = visibility
+                it.overlay.setVisibility(visibility)
+            }
+        }
+    }
+
+    open fun setOverlayEnabled(overlayEnabled: Boolean) {
+        // TODO(b/335606129) Investigate the usage of [TaskOverlay] in the new TaskThumbnailView.
+        //  and if it's still necessary we should support that in the new TTV class.
+        if (!enableRefactorTaskThumbnail()) {
+            taskContainers.forEach { it.thumbnailViewDeprecated.setOverlayEnabled(overlayEnabled) }
+        }
+    }
+
+    protected open fun refreshTaskThumbnailSplash() {
+        if (!enableRefactorTaskThumbnail()) {
+            // TODO(b/334826842) add splash functionality to new TTV
+            taskContainers.forEach { it.thumbnailViewDeprecated.refreshSplashView() }
+        }
+    }
+
+    protected fun getScrollAdjustment(gridEnabled: Boolean) =
+        if (gridEnabled) gridTranslationX else nonGridTranslationX
+
+    protected fun getOffsetAdjustment(gridEnabled: Boolean) = getScrollAdjustment(gridEnabled)
+
+    fun getSizeAdjustment(fullscreenEnabled: Boolean) = if (fullscreenEnabled) nonGridScale else 1f
+
+    private fun applyScale() {
+        val scale = persistentScale * dismissScale
+        scaleX = scale
+        scaleY = scale
+        if (enableRefactorTaskThumbnail()) {
+            taskViewData.scale.value = scale
+        }
+        updateSnapshotRadius()
+    }
+
+    protected open fun applyThumbnailSplashAlpha() {
+        if (!enableRefactorTaskThumbnail()) {
+            // TODO(b/334826842) add splash functionality to new TTV
+            taskContainers.forEach {
+                it.thumbnailViewDeprecated.setSplashAlpha(taskThumbnailSplashAlpha)
+            }
+        }
+    }
+
+    private fun applyTranslationX() {
+        translationX =
+            dismissTranslationX +
+                taskOffsetTranslationX +
+                taskResistanceTranslationX +
+                splitSelectTranslationX +
+                gridEndTranslationX +
+                persistentTranslationX
+    }
+
+    private fun applyTranslationY() {
+        translationY =
+            dismissTranslationY +
+                taskOffsetTranslationY +
+                taskResistanceTranslationY +
+                splitSelectTranslationY +
+                persistentTranslationY
+    }
+
+    private fun onGridProgressChanged() {
+        applyTranslationX()
+        applyTranslationY()
+        applyScale()
+    }
+
+    protected open fun onFullscreenProgressChanged(fullscreenProgress: Float) {
+        taskContainers.forEach {
+            it.iconView.setVisibility(if (fullscreenProgress < 1) VISIBLE else INVISIBLE)
+            it.overlay.setFullscreenProgress(fullscreenProgress)
+        }
+        setIconsAndBannersFullscreenProgress(fullscreenProgress)
+        updateSnapshotRadius()
+    }
+
+    protected open fun updateSnapshotRadius() {
+        updateCurrentFullscreenParams()
+        taskContainers.forEach {
+            it.thumbnailViewDeprecated.setFullscreenParams(getThumbnailFullscreenParams())
+            it.overlay.setFullscreenParams(getThumbnailFullscreenParams())
+        }
+    }
+
+    protected open fun updateCurrentFullscreenParams() {
+        updateFullscreenParams(currentFullscreenParams)
+    }
+
+    protected fun updateFullscreenParams(fullscreenParams: FullscreenDrawParams) {
+        recentsView?.let { fullscreenParams.setProgress(fullscreenProgress, it.scaleX, scaleX) }
+    }
+
+    protected open fun getThumbnailFullscreenParams(): FullscreenDrawParams =
+        currentFullscreenParams
+
+    private fun onModalnessUpdated(modalness: Float) {
+        taskContainers.forEach {
+            it.iconView.setModalAlpha(1 - modalness)
+            it.digitalWellBeingToast?.updateBannerOffset(modalness)
+        }
+    }
+
+    /** Updates [TaskThumbnailView] to reflect the latest [Task] state (i.e., task isRunning). */
+    fun notifyIsRunningTaskUpdated() {
+        // TODO(b/335649589): TaskView's VM will already have access to TaskThumbnailView's VM
+        //  so there will be no need to access TaskThumbnailView's VM through the TaskThumbnailView
+        taskContainers.forEach { it.bindThumbnailView() }
+    }
+
+    fun resetPersistentViewTransforms() {
+        nonGridTranslationX = 0f
+        gridTranslationX = 0f
+        gridTranslationY = 0f
+        boxTranslationY = 0f
+        nonGridPivotTranslationX = 0f
+        resetViewTransforms()
+    }
+
+    open fun resetViewTransforms() {
+        // fullscreenTranslation and accumulatedTranslation should not be reset, as
+        // resetViewTransforms is called during QuickSwitch scrolling.
+        dismissTranslationX = 0f
+        taskOffsetTranslationX = 0f
+        taskResistanceTranslationX = 0f
+        splitSelectTranslationX = 0f
+        gridEndTranslationX = 0f
+        dismissTranslationY = 0f
+        taskOffsetTranslationY = 0f
+        taskResistanceTranslationY = 0f
+        if (recentsView?.isSplitSelectionActive != true) {
+            splitSelectTranslationY = 0f
+        }
+        dismissScale = 1f
+        translationZ = 0f
+        alpha = stableAlpha
+        setIconScaleAndDim(1f)
+        setColorTint(0f, 0)
+        if (!enableRefactorTaskThumbnail()) {
+            // TODO(b/335399428) add split select functionality to new TTV
+            taskContainers.forEach { it.thumbnailViewDeprecated.resetViewTransforms() }
+        }
+    }
+
+    private fun getGridTrans(endTranslation: Float) =
+        Utilities.mapRange(gridProgress, 0f, endTranslation)
+
+    private fun getNonGridTrans(endTranslation: Float) =
+        endTranslation - getGridTrans(endTranslation)
+
+    /** We update and subsequently draw these in [fullscreenProgress]. */
+    open class FullscreenDrawParams(context: Context) : SafeCloseable {
+        var cornerRadius = 0f
+        private var windowCornerRadius = 0f
+        var currentDrawnCornerRadius = 0f
+
+        init {
+            updateCornerRadius(context)
+        }
+
+        /** Recomputes the start and end corner radius for the given Context. */
+        fun updateCornerRadius(context: Context) {
+            cornerRadius = computeTaskCornerRadius(context)
+            windowCornerRadius = computeWindowCornerRadius(context)
+        }
+
+        @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+        open fun computeTaskCornerRadius(context: Context): Float {
+            return TaskCornerRadius.get(context)
+        }
+
+        @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+        open fun computeWindowCornerRadius(context: Context): Float {
+            return QuickStepContract.getWindowCornerRadius(context)
+        }
+
+        /** Sets the progress in range [0, 1] */
+        fun setProgress(fullscreenProgress: Float, parentScale: Float, taskViewScale: Float) {
+            currentDrawnCornerRadius =
+                Utilities.mapRange(fullscreenProgress, cornerRadius, windowCornerRadius) /
+                    parentScale /
+                    taskViewScale
+        }
+
+        override fun close() {}
+    }
+
+    /** Holder for all Task dependent information. */
+    inner class TaskContainer(
+        val task: Task,
+        val thumbnailView: TaskThumbnailView?,
+        val thumbnailViewDeprecated: TaskThumbnailViewDeprecated,
+        val iconView: TaskViewIcon,
+        /**
+         * This technically can be a vanilla [android.view.TouchDelegate] class, however that class
+         * requires setting the touch bounds at construction, so we'd repeatedly be created many
+         * instances unnecessarily as scrolling occurs, whereas [TransformingTouchDelegate] allows
+         * touch delegated bounds only to be updated.
+         */
+        val iconTouchDelegate: TransformingTouchDelegate,
+        /** Defaults to STAGE_POSITION_UNDEFINED if in not a split screen task view */
+        @StagePosition val stagePosition: Int,
+        val digitalWellBeingToast: DigitalWellBeingToast?,
+        val showWindowsView: View?,
+        taskOverlayFactory: TaskOverlayFactory
+    ) {
+        val overlay: TaskOverlay<*> = taskOverlayFactory.createOverlay(this)
+
+        @IdRes
+        val a11yNodeId: Int =
+            if (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) R.id.split_bottomRight_appInfo
+            else R.id.split_topLeft_appInfo
+
+        val snapshotView: View
+            get() = thumbnailView ?: thumbnailViewDeprecated
+
+        /** Builds proto for logging */
+        val itemInfo: WorkspaceItemInfo
+            get() =
+                WorkspaceItemInfo().apply {
+                    itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK
+                    container = LauncherSettings.Favorites.CONTAINER_TASKSWITCHER
+                    val componentKey = TaskUtils.getLaunchComponentKeyForTask(task.key)
+                    user = componentKey.user
+                    intent = Intent().setComponent(componentKey.componentName)
+                    title = task.title
+                    recentsView?.let { screenId = it.indexOfChild(this@TaskView) }
+                    if (privateSpaceRestrictAccessibilityDrag()) {
+                        if (
+                            UserCache.getInstance(context).getUserInfo(componentKey.user).isPrivate
+                        ) {
+                            runtimeStatusFlags =
+                                runtimeStatusFlags or ItemInfoWithIcon.FLAG_NOT_PINNABLE
+                        }
+                    }
+                }
+
+        val taskView: TaskView
+            get() = this@TaskView
+
+        // TODO(b/335649589): TaskView's VM will already have access to TaskThumbnailView's VM
+        //  so there will be no need to access TaskThumbnailView's VM through the TaskThumbnailView
+        fun bindThumbnailView() {
+            thumbnailView?.viewModel?.bind(TaskThumbnail(task, isRunningTask))
+        }
+    }
+
+    companion object {
+        private const val TAG = "TaskView"
+        const val FLAG_UPDATE_ICON = 1
+        const val FLAG_UPDATE_THUMBNAIL = FLAG_UPDATE_ICON shl 1
+        const val FLAG_UPDATE_CORNER_RADIUS = FLAG_UPDATE_THUMBNAIL shl 1
+        const val FLAG_UPDATE_ALL =
+            (FLAG_UPDATE_ICON or FLAG_UPDATE_THUMBNAIL or FLAG_UPDATE_CORNER_RADIUS)
+
+        /** The maximum amount that a task view can be scrimmed, dimmed or tinted. */
+        const val MAX_PAGE_SCRIM_ALPHA = 0.4f
+        const val SCALE_ICON_DURATION: Long = 120
+        private const val DIM_ANIM_DURATION: Long = 700
+        private val SYSTEM_GESTURE_EXCLUSION_RECT = listOf(Rect())
+
+        @JvmField
+        val FOCUS_TRANSITION: FloatProperty<TaskView> =
+            object : FloatProperty<TaskView>("focusTransition") {
+                override fun setValue(taskView: TaskView, v: Float) {
+                    taskView.setIconsAndBannersTransitionProgress(v, false /* invert */)
+                }
+
+                override fun get(taskView: TaskView) = taskView.focusTransitionProgress
+            }
+        private val SPLIT_SELECT_TRANSLATION_X: FloatProperty<TaskView> =
+            object : FloatProperty<TaskView>("splitSelectTranslationX") {
+                override fun setValue(taskView: TaskView, v: Float) {
+                    taskView.splitSelectTranslationX = v
+                }
+
+                override fun get(taskView: TaskView) = taskView.splitSelectTranslationX
+            }
+        private val SPLIT_SELECT_TRANSLATION_Y: FloatProperty<TaskView> =
+            object : FloatProperty<TaskView>("splitSelectTranslationY") {
+                override fun setValue(taskView: TaskView, v: Float) {
+                    taskView.splitSelectTranslationY = v
+                }
+
+                override fun get(taskView: TaskView) = taskView.splitSelectTranslationY
+            }
+        private val DISMISS_TRANSLATION_X: FloatProperty<TaskView> =
+            object : FloatProperty<TaskView>("dismissTranslationX") {
+                override fun setValue(taskView: TaskView, v: Float) {
+                    taskView.dismissTranslationX = v
+                }
+
+                override fun get(taskView: TaskView) = taskView.dismissTranslationX
+            }
+        private val DISMISS_TRANSLATION_Y: FloatProperty<TaskView> =
+            object : FloatProperty<TaskView>("dismissTranslationY") {
+                override fun setValue(taskView: TaskView, v: Float) {
+                    taskView.dismissTranslationY = v
+                }
+
+                override fun get(taskView: TaskView) = taskView.dismissTranslationY
+            }
+        private val TASK_OFFSET_TRANSLATION_X: FloatProperty<TaskView> =
+            object : FloatProperty<TaskView>("taskOffsetTranslationX") {
+                override fun setValue(taskView: TaskView, v: Float) {
+                    taskView.taskOffsetTranslationX = v
+                }
+
+                override fun get(taskView: TaskView) = taskView.taskOffsetTranslationX
+            }
+        private val TASK_OFFSET_TRANSLATION_Y: FloatProperty<TaskView> =
+            object : FloatProperty<TaskView>("taskOffsetTranslationY") {
+                override fun setValue(taskView: TaskView, v: Float) {
+                    taskView.taskOffsetTranslationY = v
+                }
+
+                override fun get(taskView: TaskView) = taskView.taskOffsetTranslationY
+            }
+        private val TASK_RESISTANCE_TRANSLATION_X: FloatProperty<TaskView> =
+            object : FloatProperty<TaskView>("taskResistanceTranslationX") {
+                override fun setValue(taskView: TaskView, v: Float) {
+                    taskView.taskResistanceTranslationX = v
+                }
+
+                override fun get(taskView: TaskView) = taskView.taskResistanceTranslationX
+            }
+        private val TASK_RESISTANCE_TRANSLATION_Y: FloatProperty<TaskView> =
+            object : FloatProperty<TaskView>("taskResistanceTranslationY") {
+                override fun setValue(taskView: TaskView, v: Float) {
+                    taskView.taskResistanceTranslationY = v
+                }
+
+                override fun get(taskView: TaskView) = taskView.taskResistanceTranslationY
+            }
+        @JvmField
+        val GRID_END_TRANSLATION_X: FloatProperty<TaskView> =
+            object : FloatProperty<TaskView>("gridEndTranslationX") {
+                override fun setValue(taskView: TaskView, v: Float) {
+                    taskView.gridEndTranslationX = v
+                }
+
+                override fun get(taskView: TaskView) = taskView.gridEndTranslationX
+            }
+        @JvmField
+        val DISMISS_SCALE: FloatProperty<TaskView> =
+            object : FloatProperty<TaskView>("dismissScale") {
+                override fun setValue(taskView: TaskView, v: Float) {
+                    taskView.dismissScale = v
+                }
+
+                override fun get(taskView: TaskView) = taskView.dismissScale
+            }
+    }
+}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/bubbles/OWNERS b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/OWNERS
similarity index 100%
rename from quickstep/tests/src/com/android/launcher3/taskbar/bubbles/OWNERS
rename to quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/OWNERS
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
index 3d8484d..49e54fb 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
@@ -22,7 +22,6 @@
 import android.graphics.drawable.ColorDrawable
 import android.view.LayoutInflater
 import android.view.View
-import android.view.View.INVISIBLE
 import android.view.View.VISIBLE
 import android.widget.FrameLayout
 import androidx.core.graphics.drawable.toBitmap
@@ -44,7 +43,10 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.atLeastOnce
 import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
 import org.mockito.kotlin.whenever
 
 @SmallTest
@@ -52,41 +54,23 @@
 class BubbleBarViewAnimatorTest {
 
     private val context = ApplicationProvider.getApplicationContext<Context>()
-    private val animatorScheduler = TestBubbleBarViewAnimatorScheduler()
+    private lateinit var animatorScheduler: TestBubbleBarViewAnimatorScheduler
+    private lateinit var overflowView: BubbleView
+    private lateinit var bubbleView: BubbleView
+    private lateinit var bubble: BubbleBarBubble
+    private lateinit var bubbleBarView: BubbleBarView
+    private lateinit var bubbleStashController: BubbleStashController
 
     @Before
     fun setUp() {
+        animatorScheduler = TestBubbleBarViewAnimatorScheduler()
         PhysicsAnimatorTestUtils.prepareForTest()
     }
 
     @Test
     fun animateBubbleInForStashed() {
-        lateinit var overflowView: BubbleView
-        lateinit var bubbleView: BubbleView
-        lateinit var bubble: BubbleBarBubble
-        val bubbleBarView = BubbleBarView(context)
-        InstrumentationRegistry.getInstrumentation().runOnMainSync {
-            bubbleBarView.layoutParams = FrameLayout.LayoutParams(0, 0)
-            val inflater = LayoutInflater.from(context)
-
-            val bitmap = ColorDrawable(Color.WHITE).toBitmap(width = 20, height = 20)
-            overflowView =
-                inflater.inflate(R.layout.bubblebar_item_view, bubbleBarView, false) as BubbleView
-            overflowView.setOverflow(BubbleBarOverflow(overflowView), bitmap)
-            bubbleBarView.addView(overflowView)
-
-            val bubbleInfo = BubbleInfo("key", 0, null, null, 0, context.packageName, null, false)
-            bubbleView =
-                inflater.inflate(R.layout.bubblebar_item_view, bubbleBarView, false) as BubbleView
-            bubble =
-                BubbleBarBubble(bubbleInfo, bubbleView, bitmap, bitmap, Color.WHITE, Path(), "")
-            bubbleView.setBubble(bubble)
-            bubbleBarView.addView(bubbleView)
-        }
-        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
-
-        val bubbleStashController = mock<BubbleStashController>()
-        whenever(bubbleStashController.isStashed).thenReturn(true)
+        setUpBubbleBar()
+        setUpBubbleStashController()
 
         val handle = View(context)
         val handleAnimator = PhysicsAnimator.getInstance(handle)
@@ -100,42 +84,304 @@
         }
 
         // let the animation start and wait for it to complete
-        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {}
         PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
 
         assertThat(handle.alpha).isEqualTo(0)
-        assertThat(handle.translationY).isEqualTo(-70)
-        assertThat(overflowView.visibility).isEqualTo(INVISIBLE)
+        assertThat(handle.translationY)
+            .isEqualTo(DIFF_BETWEEN_HANDLE_AND_BAR_CENTERS + BAR_TRANSLATION_Y_FOR_TASKBAR)
         assertThat(bubbleBarView.visibility).isEqualTo(VISIBLE)
-        assertThat(bubbleView.visibility).isEqualTo(VISIBLE)
-        assertThat(bubbleView.alpha).isEqualTo(1)
-        assertThat(bubbleView.translationY).isEqualTo(-20)
-        assertThat(bubbleView.scaleY).isEqualTo(1)
+        assertThat(bubbleBarView.scaleX).isEqualTo(1)
+        assertThat(bubbleBarView.scaleY).isEqualTo(1)
+        assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_TASKBAR)
+        assertThat(bubbleBarView.isAnimatingNewBubble).isTrue()
 
         // execute the hide bubble animation
         assertThat(animatorScheduler.delayedBlock).isNotNull()
         InstrumentationRegistry.getInstrumentation().runOnMainSync(animatorScheduler.delayedBlock!!)
 
         // let the animation start and wait for it to complete
-        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {}
         PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
 
-        assertThat(bubbleView.alpha).isEqualTo(1)
-        assertThat(bubbleView.visibility).isEqualTo(VISIBLE)
-        assertThat(bubbleView.translationY).isEqualTo(0)
-        assertThat(bubbleBarView.alpha).isEqualTo(0)
-        assertThat(overflowView.alpha).isEqualTo(1)
-        assertThat(overflowView.visibility).isEqualTo(VISIBLE)
         assertThat(handle.alpha).isEqualTo(1)
         assertThat(handle.translationY).isEqualTo(0)
+        assertThat(bubbleBarView.alpha).isEqualTo(0)
+        assertThat(bubbleBarView.isAnimatingNewBubble).isFalse()
+        verify(bubbleStashController).stashBubbleBarImmediate()
     }
 
     @Test
     fun animateBubbleInForStashed_tapAnimatingBubble() {
-        lateinit var overflowView: BubbleView
-        lateinit var bubbleView: BubbleView
-        lateinit var bubble: BubbleBarBubble
-        val bubbleBarView = BubbleBarView(context)
+        setUpBubbleBar()
+        setUpBubbleStashController()
+
+        val handle = View(context)
+        val handleAnimator = PhysicsAnimator.getInstance(handle)
+        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+
+        val animator =
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            animator.animateBubbleInForStashed(bubble)
+        }
+
+        // let the animation start and wait for it to complete
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {}
+        PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+
+        assertThat(handle.alpha).isEqualTo(0)
+        assertThat(handle.translationY)
+            .isEqualTo(DIFF_BETWEEN_HANDLE_AND_BAR_CENTERS + BAR_TRANSLATION_Y_FOR_TASKBAR)
+        assertThat(bubbleBarView.visibility).isEqualTo(VISIBLE)
+        assertThat(bubbleBarView.scaleX).isEqualTo(1)
+        assertThat(bubbleBarView.scaleY).isEqualTo(1)
+        assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_TASKBAR)
+        assertThat(bubbleBarView.isAnimatingNewBubble).isTrue()
+
+        verify(bubbleStashController, atLeastOnce()).updateTaskbarTouchRegion()
+
+        // verify the hide bubble animation is pending
+        assertThat(animatorScheduler.delayedBlock).isNotNull()
+
+        animator.onBubbleBarTouchedWhileAnimating()
+
+        assertThat(animatorScheduler.delayedBlock).isNull()
+        assertThat(bubbleBarView.alpha).isEqualTo(1)
+        assertThat(bubbleBarView.visibility).isEqualTo(VISIBLE)
+        assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_TASKBAR)
+        assertThat(bubbleBarView.isAnimatingNewBubble).isFalse()
+    }
+
+    @Test
+    fun animateBubbleInForStashed_touchTaskbarArea_whileShowing() {
+        setUpBubbleBar()
+        setUpBubbleStashController()
+
+        val handle = View(context)
+        val handleAnimator = PhysicsAnimator.getInstance(handle)
+        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+
+        val animator =
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            animator.animateBubbleInForStashed(bubble)
+        }
+
+        // wait for the animation to start
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {}
+        PhysicsAnimatorTestUtils.blockUntilFirstAnimationFrameWhereTrue(handleAnimator) { true }
+
+        handleAnimator.assertIsRunning()
+        assertThat(bubbleBarView.isAnimatingNewBubble).isTrue()
+        // verify the hide bubble animation is pending
+        assertThat(animatorScheduler.delayedBlock).isNotNull()
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            animator.onStashStateChangingWhileAnimating()
+        }
+
+        // verify that the hide animation was canceled
+        assertThat(animatorScheduler.delayedBlock).isNull()
+        assertThat(bubbleBarView.isAnimatingNewBubble).isFalse()
+        verify(bubbleStashController).onNewBubbleAnimationInterrupted(any(), any())
+
+        // PhysicsAnimatorTestUtils posts the cancellation to the main thread so we need to wait
+        // again
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+        handleAnimator.assertIsNotRunning()
+    }
+
+    @Test
+    fun animateBubbleInForStashed_touchTaskbarArea_whileHiding() {
+        setUpBubbleBar()
+        setUpBubbleStashController()
+
+        val handle = View(context)
+        val handleAnimator = PhysicsAnimator.getInstance(handle)
+        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+
+        val animator =
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            animator.animateBubbleInForStashed(bubble)
+        }
+
+        // let the animation start and wait for it to complete
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {}
+        PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+
+        // execute the hide bubble animation
+        assertThat(animatorScheduler.delayedBlock).isNotNull()
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(animatorScheduler.delayedBlock!!)
+
+        // wait for the hide animation to start
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {}
+        handleAnimator.assertIsRunning()
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            animator.onStashStateChangingWhileAnimating()
+        }
+
+        assertThat(bubbleBarView.isAnimatingNewBubble).isFalse()
+        verify(bubbleStashController).onNewBubbleAnimationInterrupted(any(), any())
+
+        // PhysicsAnimatorTestUtils posts the cancellation to the main thread so we need to wait
+        // again
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+        handleAnimator.assertIsNotRunning()
+    }
+
+    @Test
+    fun animateBubbleInForStashed_showAnimationCanceled() {
+        setUpBubbleBar()
+        setUpBubbleStashController()
+
+        val handle = View(context)
+        val handleAnimator = PhysicsAnimator.getInstance(handle)
+        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+
+        val animator =
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            animator.animateBubbleInForStashed(bubble)
+        }
+
+        // wait for the animation to start
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {}
+        PhysicsAnimatorTestUtils.blockUntilFirstAnimationFrameWhereTrue(handleAnimator) { true }
+
+        handleAnimator.assertIsRunning()
+        assertThat(bubbleBarView.isAnimatingNewBubble).isTrue()
+        assertThat(animatorScheduler.delayedBlock).isNotNull()
+
+        handleAnimator.cancel()
+        handleAnimator.assertIsNotRunning()
+        assertThat(bubbleBarView.isAnimatingNewBubble).isFalse()
+        assertThat(animatorScheduler.delayedBlock).isNull()
+    }
+
+    @Test
+    fun animateToInitialState_inApp() {
+        setUpBubbleBar()
+        setUpBubbleStashController()
+        whenever(bubbleStashController.bubbleBarTranslationY)
+            .thenReturn(BAR_TRANSLATION_Y_FOR_TASKBAR)
+
+        val handle = View(context)
+        val handleAnimator = PhysicsAnimator.getInstance(handle)
+        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+
+        val barAnimator = PhysicsAnimator.getInstance(bubbleBarView)
+
+        val animator =
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            animator.animateToInitialState(bubble, isInApp = true, isExpanding = false)
+        }
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {}
+        PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+
+        barAnimator.assertIsNotRunning()
+        assertThat(bubbleBarView.isAnimatingNewBubble).isTrue()
+        assertThat(bubbleBarView.alpha).isEqualTo(1)
+        assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_TASKBAR)
+
+        assertThat(animatorScheduler.delayedBlock).isNotNull()
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(animatorScheduler.delayedBlock!!)
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {}
+        PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+        assertThat(bubbleBarView.isAnimatingNewBubble).isFalse()
+        assertThat(bubbleBarView.alpha).isEqualTo(0)
+        assertThat(handle.translationY).isEqualTo(0)
+        assertThat(handle.alpha).isEqualTo(1)
+
+        verify(bubbleStashController).stashBubbleBarImmediate()
+    }
+
+    @Test
+    fun animateToInitialState_inApp_autoExpanding() {
+        setUpBubbleBar()
+        setUpBubbleStashController()
+        whenever(bubbleStashController.bubbleBarTranslationY)
+            .thenReturn(BAR_TRANSLATION_Y_FOR_TASKBAR)
+
+        val handle = View(context)
+        val handleAnimator = PhysicsAnimator.getInstance(handle)
+        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+
+        val barAnimator = PhysicsAnimator.getInstance(bubbleBarView)
+
+        val animator =
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            animator.animateToInitialState(bubble, isInApp = true, isExpanding = true)
+        }
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {}
+        PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+
+        barAnimator.assertIsNotRunning()
+        assertThat(bubbleBarView.isAnimatingNewBubble).isTrue()
+        assertThat(bubbleBarView.alpha).isEqualTo(1)
+        assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_TASKBAR)
+
+        assertThat(animatorScheduler.delayedBlock).isNotNull()
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(animatorScheduler.delayedBlock!!)
+
+        assertThat(bubbleBarView.isAnimatingNewBubble).isFalse()
+        assertThat(bubbleBarView.alpha).isEqualTo(1)
+        assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_TASKBAR)
+
+        verify(bubbleStashController).showBubbleBarImmediate()
+    }
+
+    @Test
+    fun animateToInitialState_inHome() {
+        setUpBubbleBar()
+        setUpBubbleStashController()
+        whenever(bubbleStashController.bubbleBarTranslationY)
+            .thenReturn(BAR_TRANSLATION_Y_FOR_HOTSEAT)
+
+        val barAnimator = PhysicsAnimator.getInstance(bubbleBarView)
+
+        val animator =
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            animator.animateToInitialState(bubble, isInApp = false, isExpanding = false)
+        }
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {}
+        PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+
+        barAnimator.assertIsNotRunning()
+        assertThat(bubbleBarView.isAnimatingNewBubble).isTrue()
+        assertThat(bubbleBarView.alpha).isEqualTo(1)
+        assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_HOTSEAT)
+
+        assertThat(animatorScheduler.delayedBlock).isNotNull()
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(animatorScheduler.delayedBlock!!)
+
+        assertThat(bubbleBarView.isAnimatingNewBubble).isFalse()
+        assertThat(bubbleBarView.alpha).isEqualTo(1)
+        assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_HOTSEAT)
+
+        verify(bubbleStashController).showBubbleBarImmediate()
+    }
+
+    private fun setUpBubbleBar() {
+        bubbleBarView = BubbleBarView(context)
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
             bubbleBarView.layoutParams = FrameLayout.LayoutParams(0, 0)
             val inflater = LayoutInflater.from(context)
@@ -155,46 +401,29 @@
             bubbleBarView.addView(bubbleView)
         }
         InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+    }
 
-        val bubbleStashController = mock<BubbleStashController>()
+    private fun setUpBubbleStashController() {
+        bubbleStashController = mock<BubbleStashController>()
         whenever(bubbleStashController.isStashed).thenReturn(true)
+        whenever(bubbleStashController.diffBetweenHandleAndBarCenters)
+            .thenReturn(DIFF_BETWEEN_HANDLE_AND_BAR_CENTERS)
+        whenever(bubbleStashController.stashedHandleTranslationForNewBubbleAnimation)
+            .thenReturn(HANDLE_TRANSLATION)
+        whenever(bubbleStashController.bubbleBarTranslationYForTaskbar)
+            .thenReturn(BAR_TRANSLATION_Y_FOR_TASKBAR)
+    }
 
-        val handle = View(context)
-        val handleAnimator = PhysicsAnimator.getInstance(handle)
-        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
-
-        val animator =
-            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
-
+    private fun <T> PhysicsAnimator<T>.assertIsRunning() {
         InstrumentationRegistry.getInstrumentation().runOnMainSync {
-            animator.animateBubbleInForStashed(bubble)
+            assertThat(isRunning()).isTrue()
         }
+    }
 
-        // let the animation start and wait for it to complete
-        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
-        PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
-
-        assertThat(handle.alpha).isEqualTo(0)
-        assertThat(handle.translationY).isEqualTo(-70)
-        assertThat(overflowView.visibility).isEqualTo(INVISIBLE)
-        assertThat(bubbleBarView.visibility).isEqualTo(VISIBLE)
-        assertThat(bubbleView.visibility).isEqualTo(VISIBLE)
-        assertThat(bubbleView.alpha).isEqualTo(1)
-        assertThat(bubbleView.translationY).isEqualTo(-20)
-        assertThat(bubbleView.scaleY).isEqualTo(1)
-
-        // verify the hide bubble animation is pending
-        assertThat(animatorScheduler.delayedBlock).isNotNull()
-
-        animator.onBubbleClickedWhileAnimating()
-
-        assertThat(animatorScheduler.delayedBlock).isNull()
-        assertThat(overflowView.visibility).isEqualTo(VISIBLE)
-        assertThat(overflowView.alpha).isEqualTo(1)
-        assertThat(bubbleView.alpha).isEqualTo(1)
-        assertThat(bubbleView.visibility).isEqualTo(VISIBLE)
-        assertThat(bubbleBarView.background).isNotNull()
-        assertThat(bubbleBarView.isAnimatingNewBubble).isFalse()
+    private fun <T> PhysicsAnimator<T>.assertIsNotRunning() {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            assertThat(isRunning()).isFalse()
+        }
     }
 
     private class TestBubbleBarViewAnimatorScheduler : BubbleBarViewAnimator.Scheduler {
@@ -217,3 +446,8 @@
         }
     }
 }
+
+private const val DIFF_BETWEEN_HANDLE_AND_BAR_CENTERS = -20f
+private const val HANDLE_TRANSLATION = -30f
+private const val BAR_TRANSLATION_Y_FOR_TASKBAR = -50f
+private const val BAR_TRANSLATION_Y_FOR_HOTSEAT = -40f
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
index c327166..c8f7946 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
@@ -17,8 +17,6 @@
 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_END_CONTEXTUAL_BUTTONS
 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_END_NAV_BUTTONS
 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_START_CONTEXTUAL_BUTTONS
-import com.android.systemui.shared.rotation.RotationButton
-import java.lang.IllegalStateException
 import org.junit.Assume.assumeTrue
 import org.junit.Before
 import org.junit.Test
@@ -39,10 +37,9 @@
     private val mockRecentsButton: ImageView = mock()
     private val mockHomeButton: ImageView = mock()
     private val mockImeSwitcher: ImageView = mock()
-    private val mockRotationButton: RotationButton = mock()
     private val mockA11yButton: ImageView = mock()
     private val mockSpace: Space = mock()
-    private val mockConfiguration: Configuration = mock();
+    private val mockConfiguration: Configuration = mock()
 
     private var surfaceRotation = Surface.ROTATION_0
 
@@ -210,7 +207,6 @@
             phoneMode = phoneMode,
             surfaceRotation = surfaceRotation,
             imeSwitcher = mockImeSwitcher,
-            rotationButton = mockRotationButton,
             a11yButton = mockA11yButton,
             space = mockSpace,
         )
diff --git a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
similarity index 88%
rename from quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
index db06b6b..5d62a4c 100644
--- a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
@@ -53,7 +53,7 @@
         )
 
         val expectedRadius = TaskCornerRadius.get(context)
-        assertThat(params.mCurrentDrawnCornerRadius).isEqualTo(expectedRadius)
+        assertThat(params.currentDrawnCornerRadius).isEqualTo(expectedRadius)
     }
 
     @Test
@@ -67,7 +67,7 @@
         )
 
         val expectedRadius = QuickStepContract.getWindowCornerRadius(context)
-        assertThat(params.mCurrentDrawnCornerRadius).isEqualTo(expectedRadius)
+        assertThat(params.currentDrawnCornerRadius).isEqualTo(expectedRadius)
     }
 
     @Test
@@ -81,7 +81,7 @@
         )
 
         val expectedRadius = TaskCornerRadius.get(context)
-        assertThat(params.mCurrentDrawnCornerRadius).isEqualTo(expectedRadius)
+        assertThat(params.currentDrawnCornerRadius).isEqualTo(expectedRadius)
     }
 
     @Test
@@ -95,7 +95,7 @@
         )
 
         val expectedRadius = QuickStepContract.getWindowCornerRadius(context)
-        assertThat(params.mCurrentDrawnCornerRadius).isEqualTo(expectedRadius)
+        assertThat(params.currentDrawnCornerRadius).isEqualTo(expectedRadius)
     }
 
     @Test
@@ -117,7 +117,7 @@
             /* parentScale= */ 1.0f,
             /* taskViewScale= */ 1.0f
         )
-        assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display1TaskRadius)
+        assertThat(spyParams.currentDrawnCornerRadius).isEqualTo(display1TaskRadius)
 
         spyParams.updateCornerRadius(display2Context)
         spyParams.setProgress(
@@ -125,7 +125,7 @@
             /* parentScale= */ 1.0f,
             /* taskViewScale= */ 1.0f
         )
-        assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display2TaskRadius)
+        assertThat(spyParams.currentDrawnCornerRadius).isEqualTo(display2TaskRadius)
     }
 
     @Test
@@ -147,7 +147,7 @@
             /* parentScale= */ 1.0f,
             /* taskViewScale= */ 1.0f
         )
-        assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display1WindowRadius)
+        assertThat(spyParams.currentDrawnCornerRadius).isEqualTo(display1WindowRadius)
 
         spyParams.updateCornerRadius(display2Context)
         spyParams.setProgress(
@@ -155,6 +155,6 @@
             /* parentScale= */ 1.0f,
             /* taskViewScale= */ 1.0f,
         )
-        assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display2WindowRadius)
+        assertThat(spyParams.currentDrawnCornerRadius).isEqualTo(display2WindowRadius)
     }
 }
diff --git a/quickstep/tests/src/com/android/quickstep/HotseatWidthCalculationTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/HotseatWidthCalculationTest.kt
similarity index 100%
rename from quickstep/tests/src/com/android/quickstep/HotseatWidthCalculationTest.kt
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/HotseatWidthCalculationTest.kt
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeRecentTasksDataSource.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeRecentTasksDataSource.kt
new file mode 100644
index 0000000..eaeb513
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeRecentTasksDataSource.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 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.recents.data
+
+import com.android.quickstep.util.GroupTask
+import java.util.function.Consumer
+
+class FakeRecentTasksDataSource : RecentTasksDataSource {
+    var taskList: List<GroupTask> = listOf()
+
+    override fun getTasks(callback: Consumer<List<GroupTask>>?): Int {
+        callback?.accept(taskList)
+        return 0
+    }
+
+    fun seedTasks(tasks: List<GroupTask>) {
+        taskList = tasks
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTaskThumbnailDataSource.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTaskThumbnailDataSource.kt
new file mode 100644
index 0000000..b66b735
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTaskThumbnailDataSource.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 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.recents.data
+
+import android.graphics.Bitmap
+import com.android.launcher3.util.CancellableTask
+import com.android.quickstep.task.thumbnail.data.TaskThumbnailDataSource
+import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.ThumbnailData
+import java.util.function.Consumer
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+
+class FakeTaskThumbnailDataSource : TaskThumbnailDataSource {
+
+    val taskIdToBitmap: Map<Int, Bitmap> = (0..10).associateWith { mock() }
+    val taskIdToUpdatingTask: MutableMap<Int, () -> Unit> = mutableMapOf()
+    var shouldLoadSynchronously: Boolean = true
+
+    /** Retrieves and sets a thumbnail on [task] from [taskIdToBitmap]. */
+    override fun updateThumbnailInBackground(
+        task: Task,
+        callback: Consumer<ThumbnailData>
+    ): CancellableTask<ThumbnailData>? {
+        val thumbnailData = mock<ThumbnailData>()
+        whenever(thumbnailData.thumbnail).thenReturn(taskIdToBitmap[task.key.id])
+        val wrappedCallback = {
+            task.thumbnail = thumbnailData
+            callback.accept(thumbnailData)
+        }
+        if (shouldLoadSynchronously) {
+            wrappedCallback()
+        } else {
+            taskIdToUpdatingTask[task.key.id] = wrappedCallback
+        }
+        return null
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/TasksRepositoryTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/TasksRepositoryTest.kt
new file mode 100644
index 0000000..c28a85a
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/TasksRepositoryTest.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2024 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.recents.data
+
+import android.content.ComponentName
+import android.content.Intent
+import com.android.quickstep.TaskIconCache
+import com.android.quickstep.util.DesktopTask
+import com.android.quickstep.util.GroupTask
+import com.android.systemui.shared.recents.model.Task
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.drop
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.toList
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.mockito.kotlin.mock
+
+@OptIn(ExperimentalCoroutinesApi::class)
+class TasksRepositoryTest {
+    private val tasks = (0..5).map(::createTaskWithId)
+    private val defaultTaskList =
+        listOf(
+            GroupTask(tasks[0]),
+            GroupTask(tasks[1], tasks[2], null),
+            DesktopTask(tasks.subList(3, 6))
+        )
+    private val recentsModel = FakeRecentTasksDataSource()
+    private val taskThumbnailDataSource = FakeTaskThumbnailDataSource()
+    private val taskIconCache = mock<TaskIconCache>()
+
+    private val systemUnderTest =
+        TasksRepository(recentsModel, taskThumbnailDataSource, taskIconCache)
+
+    @Test
+    fun getAllTaskDataReturnsFlattenedListOfTasks() = runTest {
+        recentsModel.seedTasks(defaultTaskList)
+
+        assertThat(systemUnderTest.getAllTaskData(forceRefresh = true).first()).isEqualTo(tasks)
+    }
+
+    @Test
+    fun getTaskDataByIdReturnsSpecificTask() = runTest {
+        recentsModel.seedTasks(defaultTaskList)
+        systemUnderTest.getAllTaskData(forceRefresh = true)
+
+        assertThat(systemUnderTest.getTaskDataById(2).first()).isEqualTo(tasks[2])
+    }
+
+    @Test
+    fun setVisibleTasksPopulatesThumbnails() = runTest {
+        recentsModel.seedTasks(defaultTaskList)
+        val bitmap1 = taskThumbnailDataSource.taskIdToBitmap[1]
+        val bitmap2 = taskThumbnailDataSource.taskIdToBitmap[2]
+        systemUnderTest.getAllTaskData(forceRefresh = true)
+
+        systemUnderTest.setVisibleTasks(listOf(1, 2))
+
+        // .drop(1) to ignore initial null content before from thumbnail was loaded.
+        assertThat(systemUnderTest.getTaskDataById(1).drop(1).first()!!.thumbnail!!.thumbnail)
+            .isEqualTo(bitmap1)
+        assertThat(systemUnderTest.getTaskDataById(2).first()!!.thumbnail!!.thumbnail)
+            .isEqualTo(bitmap2)
+    }
+
+    @Test
+    fun changingVisibleTasksContainsAlreadyPopulatedThumbnails() = runTest {
+        recentsModel.seedTasks(defaultTaskList)
+        val bitmap2 = taskThumbnailDataSource.taskIdToBitmap[2]
+        systemUnderTest.getAllTaskData(forceRefresh = true)
+
+        systemUnderTest.setVisibleTasks(listOf(1, 2))
+
+        // .drop(1) to ignore initial null content before from thumbnail was loaded.
+        assertThat(systemUnderTest.getTaskDataById(2).drop(1).first()!!.thumbnail!!.thumbnail)
+            .isEqualTo(bitmap2)
+
+        // Prevent new loading of Bitmaps
+        taskThumbnailDataSource.shouldLoadSynchronously = false
+        systemUnderTest.setVisibleTasks(listOf(2, 3))
+
+        assertThat(systemUnderTest.getTaskDataById(2).first()!!.thumbnail!!.thumbnail)
+            .isEqualTo(bitmap2)
+    }
+
+    @Test
+    fun retrievedThumbnailsAreDiscardedWhenTaskBecomesInvisible() = runTest {
+        recentsModel.seedTasks(defaultTaskList)
+        val bitmap2 = taskThumbnailDataSource.taskIdToBitmap[2]
+        systemUnderTest.getAllTaskData(forceRefresh = true)
+
+        systemUnderTest.setVisibleTasks(listOf(1, 2))
+
+        // .drop(1) to ignore initial null content before from thumbnail was loaded.
+        assertThat(systemUnderTest.getTaskDataById(2).drop(1).first()!!.thumbnail!!.thumbnail)
+            .isEqualTo(bitmap2)
+
+        // Prevent new loading of Bitmaps
+        taskThumbnailDataSource.shouldLoadSynchronously = false
+        systemUnderTest.setVisibleTasks(listOf(0, 1))
+
+        assertThat(systemUnderTest.getTaskDataById(2).first()!!.thumbnail).isNull()
+    }
+
+    @Test
+    fun retrievedThumbnailsCauseEmissionOnTaskDataFlow() = runTest {
+        // Setup fakes
+        recentsModel.seedTasks(defaultTaskList)
+        val bitmap2 = taskThumbnailDataSource.taskIdToBitmap[2]
+        taskThumbnailDataSource.shouldLoadSynchronously = false
+
+        // Setup TasksRepository
+        systemUnderTest.getAllTaskData(forceRefresh = true)
+        systemUnderTest.setVisibleTasks(listOf(1, 2))
+
+        // Assert there is no bitmap in first emission
+        val taskFlow = systemUnderTest.getTaskDataById(2)
+        val taskFlowValuesList = mutableListOf<Task?>()
+        backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
+            taskFlow.toList(taskFlowValuesList)
+        }
+        assertThat(taskFlowValuesList[0]!!.thumbnail).isNull()
+
+        // Simulate bitmap loading after first emission
+        taskThumbnailDataSource.taskIdToUpdatingTask.getValue(2).invoke()
+
+        // Check for second emission
+        assertThat(taskFlowValuesList[1]!!.thumbnail!!.thumbnail).isEqualTo(bitmap2)
+    }
+
+    private fun createTaskWithId(taskId: Int) =
+        Task(Task.TaskKey(taskId, 0, Intent(), ComponentName("", ""), 0, 2000))
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
index e71192f..efd7bec 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
@@ -17,38 +17,63 @@
 package com.android.quickstep.task.thumbnail
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.quickstep.recents.viewmodel.RecentsViewData
+import com.android.quickstep.task.viewmodel.TaskViewData
 import com.android.systemui.shared.recents.model.Task
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.runTest
 import org.junit.Test
 import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
 class TaskThumbnailViewModelTest {
-    private val systemUnderTest = TaskThumbnailViewModel()
+    private val recentsViewData = RecentsViewData()
+    private val taskViewData = TaskViewData()
+    private val systemUnderTest = TaskThumbnailViewModel(recentsViewData, taskViewData)
 
     @Test
-    fun initialStateIsUninitialized() {
-        assertThat(systemUnderTest.uiState.value).isEqualTo(TaskThumbnailUiState.Uninitialized)
+    fun initialStateIsUninitialized() = runTest {
+        assertThat(systemUnderTest.uiState.first()).isEqualTo(TaskThumbnailUiState.Uninitialized)
     }
 
     @Test
-    fun bindRunningTask_thenStateIs_LiveTile() {
+    fun bindRunningTask_thenStateIs_LiveTile() = runTest {
         val taskThumbnail = TaskThumbnail(Task(), isRunning = true)
         systemUnderTest.bind(taskThumbnail)
 
-        assertThat(systemUnderTest.uiState.value).isEqualTo(TaskThumbnailUiState.LiveTile)
+        assertThat(systemUnderTest.uiState.first()).isEqualTo(TaskThumbnailUiState.LiveTile)
     }
 
     @Test
-    fun bindRunningTaskThenStoppedTask_thenStateIs_Uninitialized() {
+    fun setRecentsFullscreenProgress_thenProgressIsPassedThrough() = runTest {
+        recentsViewData.fullscreenProgress.value = 0.5f
+
+        assertThat(systemUnderTest.recentsFullscreenProgress.first()).isEqualTo(0.5f)
+
+        recentsViewData.fullscreenProgress.value = 0.6f
+
+        assertThat(systemUnderTest.recentsFullscreenProgress.first()).isEqualTo(0.6f)
+    }
+
+    @Test
+    fun setAncestorScales_thenScaleIsCalculated() = runTest {
+        recentsViewData.scale.value = 0.5f
+        taskViewData.scale.value = 0.6f
+
+        assertThat(systemUnderTest.inheritedScale.first()).isEqualTo(0.3f)
+    }
+
+    @Test
+    fun bindRunningTaskThenStoppedTask_thenStateIs_Uninitialized() = runTest {
         // TODO(b/334825222): Change the expectation here when snapshot state is implemented
         val task = Task()
         val runningTask = TaskThumbnail(task, isRunning = true)
         val stoppedTask = TaskThumbnail(task, isRunning = false)
         systemUnderTest.bind(runningTask)
-        assertThat(systemUnderTest.uiState.value).isEqualTo(TaskThumbnailUiState.LiveTile)
+        assertThat(systemUnderTest.uiState.first()).isEqualTo(TaskThumbnailUiState.LiveTile)
 
         systemUnderTest.bind(stoppedTask)
-        assertThat(systemUnderTest.uiState.value).isEqualTo(TaskThumbnailUiState.Uninitialized)
+        assertThat(systemUnderTest.uiState.first()).isEqualTo(TaskThumbnailUiState.Uninitialized)
     }
 }
diff --git a/quickstep/tests/src/com/android/quickstep/util/AppPairsControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/AppPairsControllerTest.kt
similarity index 100%
rename from quickstep/tests/src/com/android/quickstep/util/AppPairsControllerTest.kt
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/util/AppPairsControllerTest.kt
diff --git a/quickstep/tests/src/com/android/quickstep/util/RecentsOrientedStateTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/RecentsOrientedStateTest.java
similarity index 100%
rename from quickstep/tests/src/com/android/quickstep/util/RecentsOrientedStateTest.java
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/util/RecentsOrientedStateTest.java
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
similarity index 77%
rename from quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
index 4ffb6bd..250dc7b 100644
--- a/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
@@ -17,6 +17,8 @@
 
 package com.android.quickstep.util
 
+import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
+import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW
 import android.graphics.Bitmap
 import android.graphics.drawable.Drawable
 import android.view.ContextThemeWrapper
@@ -33,14 +35,16 @@
 import com.android.quickstep.views.IconView
 import com.android.quickstep.views.TaskThumbnailViewDeprecated
 import com.android.quickstep.views.TaskView
-import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
+import com.android.quickstep.views.TaskView.TaskContainer
 import com.android.systemui.shared.recents.model.Task
 import org.junit.Assert.assertEquals
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
 import org.mockito.kotlin.any
 import org.mockito.kotlin.doNothing
+import org.mockito.kotlin.doReturn
 import org.mockito.kotlin.mock
 import org.mockito.kotlin.spy
 import org.mockito.kotlin.verify
@@ -63,7 +67,7 @@
     private val mockGroupedTaskView: GroupedTaskView = mock()
     private val mockTask: Task = mock()
     private val mockTaskKey: Task.TaskKey = mock()
-    private val mockTaskIdAttributeContainer: TaskIdAttributeContainer = mock()
+    private val mockTaskContainer: TaskContainer = mock()
     // AppPairIcon
     private val mockAppPairIcon: AppPairIcon = mock()
     private val mockContextThemeWrapper: ContextThemeWrapper = mock()
@@ -79,14 +83,15 @@
     private val transitionInfo: TransitionInfo = mock()
     private val transaction: Transaction = mock()
 
-    lateinit var splitAnimationController: SplitAnimationController
+    private lateinit var splitAnimationController: SplitAnimationController
 
     @Before
     fun setup() {
-        whenever(mockTaskView.thumbnail).thenReturn(mockThumbnailView)
+        whenever(mockTaskContainer.thumbnailViewDeprecated).thenReturn(mockThumbnailView)
         whenever(mockThumbnailView.thumbnail).thenReturn(mockBitmap)
-        whenever(mockTaskView.iconView).thenReturn(mockIconView)
+        whenever(mockTaskContainer.iconView).thenReturn(mockIconView)
         whenever(mockIconView.drawable).thenReturn(mockTaskViewDrawable)
+        whenever(mockTaskView.taskContainers).thenReturn(List(1) { mockTaskContainer })
 
         whenever(splitSelectSource.drawable).thenReturn(mockSplitSourceDrawable)
         whenever(splitSelectSource.view).thenReturn(mockSplitSourceView)
@@ -173,14 +178,13 @@
         // Remove icon view from GroupedTaskView
         whenever(mockIconView.drawable).thenReturn(null)
 
-        whenever(mockTaskIdAttributeContainer.task).thenReturn(mockTask)
-        whenever(mockTaskIdAttributeContainer.iconView).thenReturn(mockIconView)
-        whenever(mockTaskIdAttributeContainer.thumbnailView).thenReturn(mockThumbnailView)
+        whenever(mockTaskContainer.task).thenReturn(mockTask)
+        whenever(mockTaskContainer.iconView).thenReturn(mockIconView)
+        whenever(mockTaskContainer.thumbnailViewDeprecated).thenReturn(mockThumbnailView)
         whenever(mockTask.getKey()).thenReturn(mockTaskKey)
         whenever(mockTaskKey.getId()).thenReturn(taskId)
         whenever(mockSplitSelectStateController.initialTaskId).thenReturn(taskId)
-        whenever(mockGroupedTaskView.taskIdAttributeContainers)
-            .thenReturn(Array(1) { mockTaskIdAttributeContainer })
+        whenever(mockGroupedTaskView.taskContainers).thenReturn(List(1) { mockTaskContainer })
         val splitAnimInitProps: SplitAnimationController.Companion.SplitAnimInitProps =
             splitAnimationController.getFirstAnimInitViews(
                 { mockGroupedTaskView },
@@ -273,6 +277,7 @@
         doNothing()
             .whenever(spySplitAnimationController)
             .composeIconSplitLaunchAnimator(any(), any(), any(), any())
+        doReturn(-1).whenever(spySplitAnimationController).hasChangesForBothAppPairs(any(), any())
 
         spySplitAnimationController.playSplitLaunchAnimation(
             null /* launchingTaskView */,
@@ -294,12 +299,13 @@
     }
 
     @Test
-    fun playsAppropriateSplitLaunchAnimation_playsIconLaunchFromTaskbarContextCorrectly() {
+    fun playsAppropriateSplitLaunchAnimation_playsIconFullscreenLaunchCorrectly() {
         val spySplitAnimationController = spy(splitAnimationController)
-        whenever(mockAppPairIcon.context).thenReturn(mockTaskbarActivityContext)
+        whenever(mockAppPairIcon.context).thenReturn(mockContextThemeWrapper)
         doNothing()
             .whenever(spySplitAnimationController)
-            .composeScaleUpLaunchAnimation(any(), any(), any())
+            .composeFullscreenIconSplitLaunchAnimator(any(), any(), any(), any(), any())
+        doReturn(0).whenever(spySplitAnimationController).hasChangesForBothAppPairs(any(), any())
 
         spySplitAnimationController.playSplitLaunchAnimation(
             null /* launchingTaskView */,
@@ -316,7 +322,62 @@
             {} /* finishCallback */
         )
 
-        verify(spySplitAnimationController).composeScaleUpLaunchAnimation(any(), any(), any())
+        verify(spySplitAnimationController)
+            .composeFullscreenIconSplitLaunchAnimator(any(), any(), any(), any(), eq(0))
+    }
+
+    @Test
+    fun playsAppropriateSplitLaunchAnimation_playsIconLaunchFromTaskbarCMultiWindow() {
+        val spySplitAnimationController = spy(splitAnimationController)
+        whenever(mockAppPairIcon.context).thenReturn(mockTaskbarActivityContext)
+        doNothing()
+            .whenever(spySplitAnimationController)
+            .composeScaleUpLaunchAnimation(any(), any(), any(), any())
+        doReturn(-1).whenever(spySplitAnimationController).hasChangesForBothAppPairs(any(), any())
+        spySplitAnimationController.playSplitLaunchAnimation(
+            null /* launchingTaskView */,
+            mockAppPairIcon,
+            taskId,
+            taskId2,
+            null /* apps */,
+            null /* wallpapers */,
+            null /* nonApps */,
+            stateManager,
+            depthController,
+            transitionInfo,
+            transaction,
+            {} /* finishCallback */
+        )
+
+        verify(spySplitAnimationController)
+            .composeScaleUpLaunchAnimation(any(), any(), any(), eq(WINDOWING_MODE_MULTI_WINDOW))
+    }
+
+    @Test
+    fun playsAppropriateSplitLaunchAnimation_playsIconLaunchFromTaskbarFullscreen() {
+        val spySplitAnimationController = spy(splitAnimationController)
+        whenever(mockAppPairIcon.context).thenReturn(mockTaskbarActivityContext)
+        doNothing()
+            .whenever(spySplitAnimationController)
+            .composeScaleUpLaunchAnimation(any(), any(), any(), any())
+        doReturn(0).whenever(spySplitAnimationController).hasChangesForBothAppPairs(any(), any())
+        spySplitAnimationController.playSplitLaunchAnimation(
+            null /* launchingTaskView */,
+            mockAppPairIcon,
+            taskId,
+            taskId2,
+            null /* apps */,
+            null /* wallpapers */,
+            null /* nonApps */,
+            stateManager,
+            depthController,
+            transitionInfo,
+            transaction,
+            {} /* finishCallback */
+        )
+
+        verify(spySplitAnimationController)
+            .composeScaleUpLaunchAnimation(any(), any(), any(), eq(WINDOWING_MODE_FULLSCREEN))
     }
 
     @Test
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
index 0de5f19..aa08ca4 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
@@ -31,7 +31,6 @@
 import com.android.launcher3.model.data.ItemInfo
 import com.android.launcher3.statehandlers.DepthController
 import com.android.launcher3.statemanager.StateManager
-import com.android.launcher3.statemanager.StatefulActivity
 import com.android.launcher3.util.ComponentKey
 import com.android.launcher3.util.SplitConfigurationOptions
 import com.android.quickstep.RecentsModel
@@ -121,7 +120,7 @@
 
         // Capture callback from recentsModel#getTasks()
         val consumer =
-            argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+            argumentCaptor<Consumer<List<GroupTask>>> {
                     splitSelectStateController.findLastActiveTasksAndRunCallback(
                         listOf(nonMatchingComponent),
                         false /* findExactPairMatch */,
@@ -174,7 +173,7 @@
 
         // Capture callback from recentsModel#getTasks()
         val consumer =
-            argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+            argumentCaptor<Consumer<List<GroupTask>>> {
                     splitSelectStateController.findLastActiveTasksAndRunCallback(
                         listOf(matchingComponent),
                         false /* findExactPairMatch */,
@@ -215,7 +214,7 @@
 
         // Capture callback from recentsModel#getTasks()
         val consumer =
-            argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+            argumentCaptor<Consumer<List<GroupTask>>> {
                     splitSelectStateController.findLastActiveTasksAndRunCallback(
                         listOf(nonPrimaryUserComponent),
                         false /* findExactPairMatch */,
@@ -271,7 +270,7 @@
 
         // Capture callback from recentsModel#getTasks()
         val consumer =
-            argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+            argumentCaptor<Consumer<List<GroupTask>>> {
                     splitSelectStateController.findLastActiveTasksAndRunCallback(
                         listOf(nonPrimaryUserComponent),
                         false /* findExactPairMatch */,
@@ -324,7 +323,7 @@
 
         // Capture callback from recentsModel#getTasks()
         val consumer =
-            argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+            argumentCaptor<Consumer<List<GroupTask>>> {
                     splitSelectStateController.findLastActiveTasksAndRunCallback(
                         listOf(matchingComponent),
                         false /* findExactPairMatch */,
@@ -378,7 +377,7 @@
 
         // Capture callback from recentsModel#getTasks()
         val consumer =
-            argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+            argumentCaptor<Consumer<List<GroupTask>>> {
                     splitSelectStateController.findLastActiveTasksAndRunCallback(
                         listOf(nonMatchingComponent, matchingComponent),
                         false /* findExactPairMatch */,
@@ -431,7 +430,7 @@
 
         // Capture callback from recentsModel#getTasks()
         val consumer =
-            argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+            argumentCaptor<Consumer<List<GroupTask>>> {
                     splitSelectStateController.findLastActiveTasksAndRunCallback(
                         listOf(matchingComponent, matchingComponent),
                         false /* findExactPairMatch */,
@@ -497,7 +496,7 @@
 
         // Capture callback from recentsModel#getTasks()
         val consumer =
-            argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+            argumentCaptor<Consumer<List<GroupTask>>> {
                     splitSelectStateController.findLastActiveTasksAndRunCallback(
                         listOf(matchingComponent, matchingComponent),
                         false /* findExactPairMatch */,
@@ -549,7 +548,7 @@
 
         // Capture callback from recentsModel#getTasks()
         val consumer =
-            argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+            argumentCaptor<Consumer<List<GroupTask>>> {
                     splitSelectStateController.findLastActiveTasksAndRunCallback(
                         listOf(matchingComponent2, matchingComponent),
                         true /* findExactPairMatch */,
diff --git a/quickstep/tests/multivalentTestsForDeviceless b/quickstep/tests/multivalentTestsForDeviceless
deleted file mode 120000
index fa0fabf..0000000
--- a/quickstep/tests/multivalentTestsForDeviceless
+++ /dev/null
@@ -1 +0,0 @@
-./multivalentTests
\ No newline at end of file
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsControllerTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsControllerTest.kt
index 2cfcf38..5b56710 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsControllerTest.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsControllerTest.kt
@@ -23,7 +23,6 @@
 import android.os.Process
 import android.os.UserHandle
 import android.testing.AndroidTestingRunner
-import android.util.SparseArray
 import com.android.launcher3.model.data.AppInfo
 import com.android.launcher3.model.data.ItemInfo
 import com.android.launcher3.statehandlers.DesktopVisibilityController
@@ -55,7 +54,9 @@
         super.setup()
         userHandle = Process.myUserHandle()
         taskbarRunningAppsController =
-            DesktopTaskbarRunningAppsController(mockRecentsModel, mockDesktopVisibilityController)
+            DesktopTaskbarRunningAppsController(mockRecentsModel) {
+                mockDesktopVisibilityController
+            }
         taskbarRunningAppsController.init(taskbarControllers)
         taskbarRunningAppsController.setApps(
             ALL_APP_PACKAGES.map { createTestAppInfo(packageName = it) }.toTypedArray()
@@ -63,20 +64,13 @@
     }
 
     @Test
-    fun updateHotseatItemInfos_null_returnsNull() {
-        assertThat(taskbarRunningAppsController.updateHotseatItemInfos(/* hotseatItems= */ null))
-            .isNull()
-    }
-
-    @Test
     fun updateHotseatItemInfos_notInDesktopMode_returnsExistingHotseatItems() {
         setInDesktopMode(false)
         val hotseatItems =
             createHotseatItemsFromPackageNames(listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2))
-                .toTypedArray()
 
-        assertThat(taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems))
-            .isEqualTo(hotseatItems)
+        assertThat(taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
+            .isEqualTo(hotseatItems.toTypedArray())
     }
 
     @Test
@@ -87,23 +81,23 @@
         val runningTasks =
             createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
         whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
-        taskbarRunningAppsController.updateRunningApps(createSparseArray(hotseatItems))
+        taskbarRunningAppsController.updateRunningApps()
 
         val newHotseatItems =
             taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
 
-        assertThat(newHotseatItems?.map { it.targetPackage }).isEqualTo(hotseatPackages)
+        assertThat(newHotseatItems.map { it?.targetPackage })
+            .containsExactlyElementsIn(hotseatPackages)
     }
 
     @Test
     fun updateHotseatItemInfos_noRunningApps_returnsExistingHotseatItems() {
         setInDesktopMode(true)
-        val hotseatItems: Array<ItemInfo> =
+        val hotseatItems =
             createHotseatItemsFromPackageNames(listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2))
-                .toTypedArray()
 
-        assertThat(taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems))
-            .isEqualTo(hotseatItems)
+        assertThat(taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
+            .isEqualTo(hotseatItems.toTypedArray())
     }
 
     @Test
@@ -114,7 +108,7 @@
         val runningTasks =
             createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
         whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
-        taskbarRunningAppsController.updateRunningApps(createSparseArray(hotseatItems))
+        taskbarRunningAppsController.updateRunningApps()
 
         val newHotseatItems =
             taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
@@ -126,7 +120,8 @@
                 RUNNING_APP_PACKAGE_1,
                 RUNNING_APP_PACKAGE_2,
             )
-        assertThat(newHotseatItems?.map { it.targetPackage }).isEqualTo(expectedPackages)
+        assertThat(newHotseatItems.map { it?.targetPackage })
+            .containsExactlyElementsIn(expectedPackages)
     }
 
     @Test
@@ -139,7 +134,7 @@
                 listOf(HOTSEAT_PACKAGE_1, RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)
             )
         whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
-        taskbarRunningAppsController.updateRunningApps(createSparseArray(hotseatItems))
+        taskbarRunningAppsController.updateRunningApps()
 
         val newHotseatItems =
             taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
@@ -151,7 +146,8 @@
                 RUNNING_APP_PACKAGE_1,
                 RUNNING_APP_PACKAGE_2,
             )
-        assertThat(newHotseatItems?.map { it.targetPackage }).isEqualTo(expectedPackages)
+        assertThat(newHotseatItems.map { it?.targetPackage })
+            .containsExactlyElementsIn(expectedPackages)
     }
 
     @Test
@@ -160,9 +156,10 @@
         val runningTasks =
             createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
         whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
-        taskbarRunningAppsController.updateRunningApps(createSparseArray(emptyList()))
+        taskbarRunningAppsController.updateRunningApps()
 
-        assertThat(taskbarRunningAppsController.runningApps).isEqualTo(emptySet<String>())
+        assertThat(taskbarRunningAppsController.runningApps).isEmpty()
+        assertThat(taskbarRunningAppsController.minimizedApps).isEmpty()
     }
 
     @Test
@@ -171,10 +168,31 @@
         val runningTasks =
             createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
         whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
-        taskbarRunningAppsController.updateRunningApps(createSparseArray(emptyList()))
+        taskbarRunningAppsController.updateRunningApps()
 
         assertThat(taskbarRunningAppsController.runningApps)
-            .isEqualTo(setOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
+            .containsExactly(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)
+        assertThat(taskbarRunningAppsController.minimizedApps).isEmpty()
+    }
+
+    @Test
+    fun getMinimizedApps_inDesktopMode_returnsAllAppsRunningAndInvisibleAppsMinimized() {
+        setInDesktopMode(true)
+        val runningTasks =
+            ArrayList(
+                listOf(
+                    createDesktopTaskInfo(RUNNING_APP_PACKAGE_1) { isVisible = true },
+                    createDesktopTaskInfo(RUNNING_APP_PACKAGE_2) { isVisible = true },
+                    createDesktopTaskInfo(RUNNING_APP_PACKAGE_3) { isVisible = false },
+                )
+            )
+        whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
+        taskbarRunningAppsController.updateRunningApps()
+
+        assertThat(taskbarRunningAppsController.runningApps)
+            .containsExactly(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2, RUNNING_APP_PACKAGE_3)
+        assertThat(taskbarRunningAppsController.minimizedApps)
+            .containsExactly(RUNNING_APP_PACKAGE_3)
     }
 
     private fun createHotseatItemsFromPackageNames(packageNames: List<String>): List<ItemInfo> {
@@ -187,11 +205,15 @@
         return ArrayList(packageNames.map { createDesktopTaskInfo(packageName = it) })
     }
 
-    private fun createDesktopTaskInfo(packageName: String): RunningTaskInfo {
+    private fun createDesktopTaskInfo(
+        packageName: String,
+        init: RunningTaskInfo.() -> Unit = { isVisible = true },
+    ): RunningTaskInfo {
         return RunningTaskInfo().apply {
             taskId = nextTaskId++
             configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM
             realActivity = ComponentName(packageName, "TestActivity")
+            init()
         }
     }
 
@@ -204,12 +226,6 @@
         whenever(mockDesktopVisibilityController.areDesktopTasksVisible()).thenReturn(inDesktopMode)
     }
 
-    private fun createSparseArray(itemInfos: List<ItemInfo>): SparseArray<ItemInfo> {
-        val sparseArray = SparseArray<ItemInfo>()
-        itemInfos.forEachIndexed { index, itemInfo -> sparseArray[index] = itemInfo }
-        return sparseArray
-    }
-
     private companion object {
         const val HOTSEAT_PACKAGE_1 = "hotseat1"
         const val HOTSEAT_PACKAGE_2 = "hotseat2"
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarKeyguardControllerTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarKeyguardControllerTest.kt
index ed88c29..e619e7c 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarKeyguardControllerTest.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarKeyguardControllerTest.kt
@@ -105,7 +105,7 @@
         verify(navbarButtonsViewController, times(1)).setBackForBouncer(false)
     }
 
-    private fun setFlags(flags: Int) {
+    private fun setFlags(flags: Long) {
         taskbarKeyguardController.updateStateForSysuiFlags(flags)
     }
 }
diff --git a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
index 0f9d96c..36f2ccf 100644
--- a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
@@ -16,12 +16,12 @@
 
 package com.android.quickstep
 
-import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
-import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
-import com.android.dx.mockito.inline.extended.StaticMockitoSession
 import android.content.ComponentName
 import android.content.Intent
 import android.platform.test.flag.junit.SetFlagsRule
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
+import com.android.dx.mockito.inline.extended.StaticMockitoSession
 import com.android.launcher3.AbstractFloatingView
 import com.android.launcher3.AbstractFloatingViewHelper
 import com.android.launcher3.logging.StatsLogManager
@@ -29,22 +29,29 @@
 import com.android.launcher3.model.data.WorkspaceItemInfo
 import com.android.launcher3.uioverrides.QuickstepLauncher
 import com.android.launcher3.util.SplitConfigurationOptions
+import com.android.launcher3.util.TransformingTouchDelegate
+import com.android.quickstep.TaskOverlayFactory.TaskOverlay
 import com.android.quickstep.views.LauncherRecentsView
+import com.android.quickstep.views.TaskThumbnailViewDeprecated
 import com.android.quickstep.views.TaskView
+import com.android.quickstep.views.TaskViewIcon
 import com.android.systemui.shared.recents.model.Task
 import com.android.systemui.shared.recents.model.Task.TaskKey
 import com.android.window.flags.Flags
+import com.android.wm.shell.shared.DesktopModeStatus
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
-import org.mockito.quality.Strictness
 import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
 import org.mockito.kotlin.eq
 import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
 import org.mockito.kotlin.verify
 import org.mockito.kotlin.whenever
+import org.mockito.quality.Strictness
 
 /** Test for DesktopSystemShortcut */
 class DesktopSystemShortcutTest {
@@ -58,21 +65,30 @@
     private val taskView: TaskView = mock()
     private val workspaceItemInfo: WorkspaceItemInfo = mock()
     private val abstractFloatingViewHelper: AbstractFloatingViewHelper = mock()
+    private val thumbnailViewDeprecated: TaskThumbnailViewDeprecated = mock()
+    private val iconView: TaskViewIcon = mock()
+    private val transformingTouchDelegate: TransformingTouchDelegate = mock()
     private val factory: TaskShortcutFactory =
         DesktopSystemShortcut.createFactory(abstractFloatingViewHelper)
+    private val overlayFactory: TaskOverlayFactory = mock()
+    private val overlay: TaskOverlay<*> = mock()
 
     private lateinit var mockitoSession: StaticMockitoSession
 
     @Before
-    fun setUp(){
-        mockitoSession = mockitoSession().strictness(Strictness.LENIENT)
-                .spyStatic(DesktopModeStatus::class.java).startMocking()
-        doReturn(true).`when` { DesktopModeStatus.enforceDeviceRestrictions() }
-        doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+    fun setUp() {
+        mockitoSession =
+            mockitoSession()
+                .strictness(Strictness.LENIENT)
+                .spyStatic(DesktopModeStatus::class.java)
+                .startMocking()
+        ExtendedMockito.doReturn(true).`when` { DesktopModeStatus.enforceDeviceRestrictions() }
+        ExtendedMockito.doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+        whenever(overlayFactory.createOverlay(any())).thenReturn(overlay)
     }
 
     @After
-    fun tearDown(){
+    fun tearDown() {
         mockitoSession.finishMocking()
     }
 
@@ -84,13 +100,7 @@
             Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
                 isDockable = true
             }
-        val taskContainer =
-            taskView.TaskIdAttributeContainer(
-                task,
-                null,
-                null,
-                SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
-            )
+        val taskContainer = createTaskContainer(task)
 
         val shortcuts = factory.getShortcuts(launcher, taskContainer)
         assertThat(shortcuts).isNull()
@@ -99,19 +109,9 @@
     @Test
     fun createDesktopTaskShortcutFactory_desktopModeEnabled_DeviceNotSupported() {
         setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
-        doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+        ExtendedMockito.doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
 
-        val task =
-            Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
-                isDockable = true
-            }
-        val taskContainer =
-            taskView.TaskIdAttributeContainer(
-                task,
-                null,
-                null,
-                SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
-            )
+        val taskContainer = createTaskContainer(createTask())
 
         val shortcuts = factory.getShortcuts(launcher, taskContainer)
         assertThat(shortcuts).isNull()
@@ -120,20 +120,11 @@
     @Test
     fun createDesktopTaskShortcutFactory_desktopModeEnabled_DeviceNotSupported_OverrideEnabled() {
         setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
-        doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
-        doReturn(false).`when` { DesktopModeStatus.enforceDeviceRestrictions() }
+        ExtendedMockito.doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+        ExtendedMockito.doReturn(false).`when` { DesktopModeStatus.enforceDeviceRestrictions() }
 
-        val task =
-            Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
-                isDockable = true
-            }
-        val taskContainer =
-            taskView.TaskIdAttributeContainer(
-                task,
-                null,
-                null,
-                SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
-            )
+        val taskContainer = spy(createTaskContainer(createTask()))
+        doReturn(workspaceItemInfo).whenever(taskContainer).itemInfo
 
         val shortcuts = factory.getShortcuts(launcher, taskContainer)
         assertThat(shortcuts).isNotNull()
@@ -143,17 +134,8 @@
     fun createDesktopTaskShortcutFactory_undockable() {
         setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
 
-        val task =
-            Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
-                isDockable = false
-            }
-        val taskContainer =
-            taskView.TaskIdAttributeContainer(
-                task,
-                null,
-                null,
-                SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
-            )
+        val unDockableTask = createTask().apply { isDockable = false }
+        val taskContainer = createTaskContainer(unDockableTask)
 
         val shortcuts = factory.getShortcuts(launcher, taskContainer)
         assertThat(shortcuts).isNull()
@@ -163,27 +145,18 @@
     fun desktopSystemShortcutClicked() {
         setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
 
-        val task =
-            Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
-                isDockable = true
-            }
-        val taskContainer =
-            taskView.TaskIdAttributeContainer(
-                task,
-                null,
-                null,
-                SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
-            )
+        val task = createTask()
+        val taskContainer = spy(createTaskContainer(task))
 
         whenever(launcher.getOverviewPanel<LauncherRecentsView>()).thenReturn(recentsView)
         whenever(launcher.statsLogManager).thenReturn(statsLogManager)
         whenever(statsLogManager.logger()).thenReturn(statsLogger)
         whenever(statsLogger.withItemInfo(any())).thenReturn(statsLogger)
-        whenever(taskView.getItemInfo(task)).thenReturn(workspaceItemInfo)
         whenever(recentsView.moveTaskToDesktop(any(), any())).thenAnswer {
             val successCallback = it.getArgument<Runnable>(1)
             successCallback.run()
         }
+        doReturn(workspaceItemInfo).whenever(taskContainer).itemInfo
 
         val shortcuts = factory.getShortcuts(launcher, taskContainer)
         assertThat(shortcuts).hasSize(1)
@@ -200,4 +173,24 @@
         verify(statsLogger).withItemInfo(workspaceItemInfo)
         verify(statsLogger).log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DESKTOP_TAP)
     }
+
+    private fun createTask(): Task {
+        return Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
+            isDockable = true
+        }
+    }
+
+    private fun createTaskContainer(task: Task): TaskView.TaskContainer {
+        return taskView.TaskContainer(
+            task,
+            thumbnailView = null,
+            thumbnailViewDeprecated,
+            iconView,
+            transformingTouchDelegate,
+            SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
+            digitalWellBeingToast = null,
+            showWindowsView = null,
+            overlayFactory
+        )
+    }
 }
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index df88726..4459ed6 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -162,8 +162,8 @@
             final Context targetContext = getInstrumentation().getTargetContext();
             final DisplayController.DisplayInfoChangeListener listener =
                     (context, info, flags) -> {
-                        if (LauncherInstrumentation.getNavigationModel(info.navigationMode.resValue)
-                                == expectedMode) {
+                        if (LauncherInstrumentation.getNavigationModel(
+                                info.getNavigationMode().resValue) == expectedMode) {
                             latch.countDown();
                         }
                     };
@@ -205,11 +205,10 @@
             boolean condition, Description description) {
         launcher.checkForAnomaly(true, true);
         if (!condition) {
-            final AssertionError assertionError = new AssertionError(message);
             if (description != null) {
-                FailureWatcher.onError(launcher, description, assertionError);
+                FailureWatcher.onError(launcher, description);
             }
-            throw assertionError;
+            throw new AssertionError(message);
         }
     }
 }
diff --git a/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt b/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt
index 2916952..5157c71 100644
--- a/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt
@@ -18,6 +18,7 @@
 import org.mockito.Mockito.reset
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.doReturn
 import org.mockito.kotlin.verifyZeroInteractions
 import org.mockito.kotlin.whenever
 
@@ -79,7 +80,7 @@
 
     @Test
     fun onDisplayInfoChanged_noButton_registerExclusionListener() {
-        whenever(windowManagerProxy.getNavigationMode(context)).thenReturn(NavigationMode.NO_BUTTON)
+        doReturn(NavigationMode.NO_BUTTON).whenever(info).getNavigationMode()
 
         underTest.onDisplayInfoChanged(context, info, CHANGE_ROTATION or CHANGE_NAVIGATION_MODE)
 
diff --git a/quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java b/quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java
index 4aa7cb0..07d8f61 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java
@@ -86,9 +86,10 @@
         final TaskView task = getOnceNotNull("No latest task", launcher -> getLatestTask(launcher));
 
         return getFromLauncher(launcher -> {
-            assertTrue("Latest task is not Calculator",
-                    CALCULATOR_PACKAGE.equals(task.getTask().getTopComponent().getPackageName()));
-            return task.getDigitalWellBeingToast();
+            TaskView.TaskContainer taskContainer = task.getTaskContainers().get(0);
+            assertTrue("Latest task is not Calculator", CALCULATOR_PACKAGE.equals(
+                    taskContainer.getTask().getTopComponent().getPackageName()));
+            return taskContainer.getDigitalWellBeingToast();
         });
     }
 
diff --git a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
index 7708233..8290508 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
@@ -27,12 +27,15 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
 
+import com.android.launcher3.allapps.PrivateProfileManager;
+import com.android.launcher3.tapl.HomeAllApps;
 import com.android.launcher3.tapl.LauncherInstrumentation;
 import com.android.launcher3.tapl.PrivateSpaceContainer;
 import com.android.launcher3.util.TestUtil;
 import com.android.launcher3.util.rule.ScreenRecordRule;
 
 import org.junit.After;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -96,14 +99,21 @@
     }
 
     @Test
-    @ScreenRecordRule.ScreenRecord // b/334946529
     public void testPrivateSpaceContainerIsPresent() {
         // Scroll to the bottom of All Apps
         executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader());
+        // Freeze All Apps
+        HomeAllApps homeAllApps = mLauncher.getAllApps();
+        homeAllApps.freeze();
 
-        // Verify Unlocked View elements are present.
-        assertNotNull("Private Space Unlocked View not found, or is not correct",
-                mLauncher.getAllApps().getPrivateSpaceUnlockedView());
+        try {
+            // Verify Unlocked View elements are present.
+            assertNotNull("Private Space Unlocked View not found, or is not correct",
+                    homeAllApps.getPrivateSpaceUnlockedView());
+        } finally {
+            // UnFreeze
+            homeAllApps.unfreeze();
+        }
     }
 
     @Test
@@ -117,10 +127,18 @@
         waitForLauncherUIUpdate();
         // Scroll to the bottom of All Apps
         executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader());
+        // Freeze All Apps
+        HomeAllApps homeAllApps = mLauncher.getAllApps();
+        homeAllApps.freeze();
 
-        // Verify the Installed App is displayed in correct position.
-        PrivateSpaceContainer psContainer = mLauncher.getAllApps().getPrivateSpaceUnlockedView();
-        psContainer.verifyInstalledAppIsPresent(INSTALLED_APP_NAME);
+        try {
+            // Verify the Installed App is displayed in correct position.
+            PrivateSpaceContainer psContainer = homeAllApps.getPrivateSpaceUnlockedView();
+            psContainer.verifyInstalledAppIsPresent(INSTALLED_APP_NAME);
+        } finally {
+            // UnFreeze
+            homeAllApps.unfreeze();
+        }
     }
 
     @Test
@@ -134,8 +152,71 @@
         waitForLauncherUIUpdate();
         // Scroll to the bottom of All Apps
         executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader());
-        // Get the "uninstall" menu item.
-        mLauncher.getAllApps().getAppIcon(INSTALLED_APP_NAME).openMenu().getMenuItem("Uninstall");
+        // Freeze All Apps
+        HomeAllApps homeAllApps = mLauncher.getAllApps();
+        homeAllApps.freeze();
+
+        try {
+            // Get the "uninstall" menu item.
+            homeAllApps.getAppIcon(INSTALLED_APP_NAME).openMenu().getMenuItem("Uninstall app");
+        } finally {
+            // UnFreeze
+            homeAllApps.unfreeze();
+        }
+    }
+
+    @Test
+    @ScreenRecordRule.ScreenRecord // b/334946529
+    @Ignore("b/339179262")
+    public void testPrivateSpaceLockingBehaviour() throws IOException {
+        // Scroll to the bottom of All Apps
+        executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader());
+        HomeAllApps homeAllApps = mLauncher.getAllApps();
+
+        // Disable Private Space
+        togglePrivateSpace(PrivateProfileManager.STATE_DISABLED, homeAllApps);
+
+        homeAllApps.freeze();
+        try {
+            // Verify Locked View elements are present.
+            homeAllApps.getPrivateSpaceLockedView();
+        } finally {
+            // UnFreeze
+            homeAllApps.unfreeze();
+        }
+
+        // Enable Private Space
+        togglePrivateSpace(PrivateProfileManager.STATE_ENABLED, homeAllApps);
+
+        homeAllApps.freeze();
+        try {
+            // Verify UnLocked View elements are present.
+            homeAllApps.getPrivateSpaceUnlockedView();
+        } finally {
+            // UnFreeze
+            homeAllApps.unfreeze();
+        }
+    }
+
+    private void togglePrivateSpace(int state, HomeAllApps homeAllApps) {
+        homeAllApps.freeze();
+        try {
+            // Try Toggling Private Space
+            homeAllApps.togglePrivateSpace();
+        }  finally {
+            // UnFreeze
+            homeAllApps.unfreeze();
+        }
+        PrivateProfileManager manager = getFromLauncher(l -> l.getAppsView()
+                .getPrivateProfileManager());
+        waitForLauncherCondition("Private profile toggle to state: " + state + " failed",
+                launcher -> {
+                    manager.reset();
+                    return manager.getCurrentState() == state;
+                },
+                LauncherInstrumentation.WAIT_TIME_MS);
+        // Wait for Launcher UI to be updated with Private Space Items.
+        waitForLauncherUIUpdate();
     }
 
     private void waitForPrivateSpaceSetup() {
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 81a2d54..7877e8a 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -181,12 +181,6 @@
     public void testOverviewActions() throws Exception {
         assumeFalse("Skipping Overview Actions tests for grid only overview",
                 mLauncher.isTablet() && mLauncher.isGridOnlyOverviewEnabled());
-        // Experimenting for b/165029151:
-        final Overview overview = mLauncher.goHome().switchToOverview();
-        if (overview.hasTasks()) overview.dismissAllTasks();
-        mLauncher.goHome();
-        //
-
         startTestAppsWithCheck();
         OverviewActions actionsView =
                 mLauncher.goHome().switchToOverview().getOverviewActions();
@@ -434,9 +428,7 @@
     @Test
     @PortraitLandscape
     @TaskbarModeSwitch()
-    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/309820115
     @Ignore("b/315376057")
-    @ScreenRecord // b/309820115
     public void testOverviewForTablet() throws Exception {
         assumeTrue(mLauncher.isTablet());
 
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
index 2a54057..bfd7bdb 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
@@ -130,7 +130,7 @@
                             .tapMenu()
                             .hasMenuItem("Save app pair"));
         } else {
-            overview.getOverviewActions().assertHasAction("Save app pair");
+            overview.getOverviewGroupActions().assertHasAction("Save app pair");
         }
     }
 
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
index 1556aa5..e4f8b6c 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
@@ -16,6 +16,8 @@
 
 package com.android.quickstep;
 
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
 import static com.android.quickstep.NavigationModeSwitchRule.Mode.ZERO_BUTTON;
 
 import static org.junit.Assert.assertNotNull;
@@ -31,6 +33,7 @@
 import com.android.launcher3.tapl.Workspace;
 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.util.rule.ScreenRecordRule;
+import com.android.launcher3.util.rule.TestStabilityRule;
 import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
 
 import org.junit.After;
@@ -85,7 +88,8 @@
     @Test
     @PortraitLandscape
     @NavigationModeSwitch
-    @ScreenRecordRule.ScreenRecord // b/335674307
+    @ScreenRecordRule.ScreenRecord // b/336606166
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/336606166
     public void switchToOverview() throws Exception {
         assumeTrue(mLauncher.isTablet());
 
diff --git a/quickstep/tests/src/com/android/quickstep/TaskViewTest.java b/quickstep/tests/src/com/android/quickstep/TaskViewTest.java
index 8eec903..512557b 100644
--- a/quickstep/tests/src/com/android/quickstep/TaskViewTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaskViewTest.java
@@ -17,9 +17,11 @@
 package com.android.quickstep;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -34,7 +36,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.quickstep.util.BorderAnimator;
 import com.android.quickstep.views.TaskView;
@@ -74,6 +75,7 @@
 
     @Test
     public void notShowBorderOnBorderDisabled() {
+        presetBorderStatus(/* enabled= */ true);
         mTaskView.setBorderEnabled(/* enabled= */ false);
         MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0);
         mTaskView.onHoverEvent(MotionEvent.obtain(event));
@@ -86,7 +88,7 @@
     }
 
     @Test
-    public void showBorderOnBorderEnabled() {
+    public void showBorderOnHoverEvent() {
         mTaskView.setBorderEnabled(/* enabled= */ true);
         MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0);
         mTaskView.onHoverEvent(MotionEvent.obtain(event));
@@ -98,7 +100,18 @@
     }
 
     @Test
+    public void showBorderOnBorderEnabled() {
+        presetBorderStatus(/* enabled= */ false);
+        mTaskView.setBorderEnabled(/* enabled= */ true);
+        verify(mHoverAnimator, times(1)).setBorderVisibility(/* visible= */ true, /* animated= */
+                true);
+        verify(mFocusAnimator, times(1)).setBorderVisibility(/* visible= */ true, /* animated= */
+                true);
+    }
+
+    @Test
     public void hideBorderOnBorderDisabled() {
+        presetBorderStatus(/* enabled= */ true);
         mTaskView.setBorderEnabled(/* enabled= */ false);
         verify(mHoverAnimator, times(1)).setBorderVisibility(/* visible= */ false, /* animated= */
                 true);
@@ -107,13 +120,35 @@
     }
 
     @Test
+    public void notTriggerAnimatorWhenEnableStatusUnchanged() {
+        presetBorderStatus(/* enabled= */ false);
+        // Border is disabled by default, no animator is triggered after it is disabled again
+        mTaskView.setBorderEnabled(/* enabled= */ false);
+        verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */
+                anyBoolean(), /* animated= */ anyBoolean());
+        verify(mFocusAnimator, never()).setBorderVisibility(/* visible= */
+                anyBoolean(), /* animated= */ anyBoolean());
+    }
+
+    private void presetBorderStatus(boolean enabled) {
+        // Make the task view focused and hovered
+        MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0);
+        mTaskView.onHoverEvent(MotionEvent.obtain(event));
+        mTaskView.requestFocus();
+        mTaskView.setBorderEnabled(/* enabled= */ enabled);
+        // Reset invocation count after presetting status
+        reset(mHoverAnimator);
+        reset(mFocusAnimator);
+    }
+
+    @Test
     public void notShowBorderByDefault() {
         MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0);
         mTaskView.onHoverEvent(MotionEvent.obtain(event));
-        verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */ false, /* animated= */
-                true);
+        verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */
+                anyBoolean(), /* animated= */ anyBoolean());
         mTaskView.onFocusChanged(true, 0, new Rect());
-        verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */ false, /* animated= */
-                true);
+        verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */
+                anyBoolean(), /* animated= */ anyBoolean());
     }
 }
diff --git a/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java
index e5657fb..84ceb33 100644
--- a/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java
@@ -130,11 +130,10 @@
             boolean condition, Description description) {
         launcher.checkForAnomaly(true, true);
         if (!condition) {
-            final AssertionError assertionError = new AssertionError(message);
             if (description != null) {
-                FailureWatcher.onError(launcher, description, assertionError);
+                FailureWatcher.onError(launcher, description);
             }
-            throw assertionError;
+            throw new AssertionError(message);
         }
     }
 }
diff --git a/quickstep/tests/src/com/android/quickstep/taskbar/controllers/TaskbarPinningControllerTest.kt b/quickstep/tests/src/com/android/quickstep/taskbar/controllers/TaskbarPinningControllerTest.kt
index dbe4624..4d10f0f 100644
--- a/quickstep/tests/src/com/android/quickstep/taskbar/controllers/TaskbarPinningControllerTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/taskbar/controllers/TaskbarPinningControllerTest.kt
@@ -22,6 +22,7 @@
 import androidx.test.filters.SmallTest
 import com.android.launcher3.LauncherPrefs
 import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING
+import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING_IN_DESKTOP_MODE
 import com.android.launcher3.logging.StatsLogManager
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_CLOSE
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_OPEN
@@ -53,7 +54,13 @@
 class TaskbarPinningControllerTest : TaskbarBaseTestCase() {
     private val taskbarDragLayer = mock<TaskbarDragLayer>()
     private val taskbarSharedState = mock<TaskbarSharedState>()
-    private val launcherPrefs = mock<LauncherPrefs> { on { get(TASKBAR_PINNING) } doReturn false }
+    private var isInDesktopMode = false
+    private val isInDesktopModeProvider = { isInDesktopMode }
+    private val launcherPrefs =
+        mock<LauncherPrefs> {
+            on { get(TASKBAR_PINNING) } doReturn false
+            on { get(TASKBAR_PINNING_IN_DESKTOP_MODE) } doReturn false
+        }
     private val statsLogger = mock<StatsLogManager.StatsLogger>()
     private val statsLogManager = mock<StatsLogManager> { on { logger() } doReturn statsLogger }
     private lateinit var pinningController: TaskbarPinningController
@@ -64,7 +71,8 @@
         whenever(taskbarActivityContext.launcherPrefs).thenReturn(launcherPrefs)
         whenever(taskbarActivityContext.dragLayer).thenReturn(taskbarDragLayer)
         whenever(taskbarActivityContext.statsLogManager).thenReturn(statsLogManager)
-        pinningController = spy(TaskbarPinningController(taskbarActivityContext))
+        pinningController =
+            spy(TaskbarPinningController(taskbarActivityContext, isInDesktopModeProvider))
         pinningController.init(taskbarControllers, taskbarSharedState)
     }
 
@@ -95,7 +103,7 @@
     }
 
     @Test
-    fun testOnCloseCallback_whenPreferenceChanged_shouldAnimateToPinnedTaskbar() {
+    fun testOnCloseCallback_whenLauncherPreferenceChanged_shouldAnimateToPinnedTaskbar() {
         whenever(launcherPrefs.get(TASKBAR_PINNING)).thenReturn(false)
         doNothing().whenever(pinningController).animateTaskbarPinning(any())
 
@@ -106,7 +114,7 @@
     }
 
     @Test
-    fun testOnCloseCallback_whenPreferenceChanged_shouldAnimateToTransientTaskbar() {
+    fun testOnCloseCallback_whenLauncherPreferenceChanged_shouldAnimateToTransientTaskbar() {
         whenever(launcherPrefs.get(TASKBAR_PINNING)).thenReturn(true)
         doNothing().whenever(pinningController).animateTaskbarPinning(any())
 
@@ -199,4 +207,13 @@
         assertThat(pinningController.isAnimatingTaskbarPinning).isFalse()
         verify(launcherPrefs, times(1)).put(TASKBAR_PINNING, true)
     }
+
+    @Test
+    fun testRecreateTaskbarAndUpdatePinningValue_whenAnimationEnds_shouldUpdateTaskbarPinningDesktopModePref() {
+        isInDesktopMode = true
+        pinningController.recreateTaskbarAndUpdatePinningValue()
+        verify(taskbarDragLayer, times(1)).setAnimatingTaskbarPinning(false)
+        assertThat(pinningController.isAnimatingTaskbarPinning).isFalse()
+        verify(launcherPrefs, times(1)).put(TASKBAR_PINNING_IN_DESKTOP_MODE, true)
+    }
 }
diff --git a/res/drawable/bg_ps_mask_left_corner.xml b/res/drawable/bg_ps_mask_left_corner.xml
new file mode 100644
index 0000000..43eeedb
--- /dev/null
+++ b/res/drawable/bg_ps_mask_left_corner.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 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.
+  -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <vector
+            android:viewportWidth="28"
+            android:viewportHeight="28"
+            android:width="@dimen/ps_floating_mask_corner_radius"
+            android:height="@dimen/ps_floating_mask_corner_radius">
+            <path
+                android:pathData="M0 28H28C24.3228 28 20.6821 27.2759 17.2847 25.8687C13.8877 24.4614 10.8013 22.3989 8.20117 19.7988C5.60107 17.1987 3.53857 14.1123 2.13135 10.7153C0.724121 7.31787 0 3.67725 0 0V28Z"
+                android:fillType="evenOdd"
+                android:fillColor="?attr/allAppsScrimColor" />
+        </vector>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/bg_ps_mask_right_corner.xml b/res/drawable/bg_ps_mask_right_corner.xml
new file mode 100644
index 0000000..d63b866
--- /dev/null
+++ b/res/drawable/bg_ps_mask_right_corner.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2024 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.
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <vector
+            android:viewportWidth="28"
+            android:viewportHeight="28"
+            android:width="@dimen/ps_floating_mask_corner_radius"
+            android:height="@dimen/ps_floating_mask_corner_radius">
+            <path
+                android:pathData="M28 28V0C28 3.67725 27.2759 7.31787 25.8687 10.7153C24.4614 14.1123 22.3989 17.1987 19.7988 19.7988C17.1987 22.3989 14.1123 24.4614 10.7153 25.8687C7.31787 27.2759 3.67725 28 0 28H28Z"
+                android:fillType="evenOdd"
+                android:fillColor="?attr/allAppsScrimColor" />
+        </vector>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/ic_plus.xml b/res/drawable/ic_plus.xml
index 3ab926a..d004f42 100644
--- a/res/drawable/ic_plus.xml
+++ b/res/drawable/ic_plus.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="19dp"
+    android:width="@dimen/widget_cell_add_button_drawable_width"
     android:height="18dp"
     android:viewportWidth="19"
     android:viewportHeight="18">
diff --git a/res/drawable/private_space_app_divider.xml b/res/drawable/private_space_app_divider.xml
index 7d069ef..1ea12b3 100644
--- a/res/drawable/private_space_app_divider.xml
+++ b/res/drawable/private_space_app_divider.xml
@@ -17,5 +17,5 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
     <solid android:color="?attr/materialColorOutlineVariant"/>
-    <size android:height="1dp" />
+    <size android:height="@dimen/all_apps_divider_height" />
 </shape>
\ No newline at end of file
diff --git a/res/drawable/private_space_install_app_icon.xml b/res/drawable/private_space_install_app_icon.xml
index 4c167ba..cfec2b1 100644
--- a/res/drawable/private_space_install_app_icon.xml
+++ b/res/drawable/private_space_install_app_icon.xml
@@ -23,9 +23,9 @@
             android:pathData="M30 0H30A30 30 0 0 1 60 30V30A30 30 0 0 1 30 60H30A30 30 0 0 1 0 30V30A30 30 0 0 1 30 0Z" />
         <path
             android:pathData="M30 0H30A30 30 0 0 1 60 30V30A30 30 0 0 1 30 60H30A30 30 0 0 1 0 30V30A30 30 0 0 1 30 0Z"
-            android:fillColor="@color/material_color_surface_bright" />
+            android:fillColor="@color/material_color_surface_container_lowest" />
         <path
             android:pathData="M29 31h-6v-2h6v-6h2v6h6v2h-6v6h-2v-6Z"
-            android:fillColor="@color/material_color_on_surface_variant" />
+            android:fillColor="@color/material_color_on_surface" />
     </group>
 </vector>
diff --git a/res/layout/private_space_divider.xml b/res/layout/private_space_divider.xml
index fff8629..f72e139 100644
--- a/res/layout/private_space_divider.xml
+++ b/res/layout/private_space_divider.xml
@@ -18,8 +18,8 @@
     android:importantForAccessibility="no"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:paddingLeft="@dimen/ps_app_divider_padding"
-    android:paddingRight="@dimen/ps_app_divider_padding"
+    android:paddingHorizontal="@dimen/ps_app_divider_horizontal_padding"
+    android:paddingVertical="@dimen/ps_app_divider_vertical_padding"
     android:src="@drawable/private_space_app_divider"
     android:scaleType="fitXY"
     android:focusable="false" />
\ No newline at end of file
diff --git a/res/layout/private_space_mask_view.xml b/res/layout/private_space_mask_view.xml
new file mode 100644
index 0000000..44e2797
--- /dev/null
+++ b/res/layout/private_space_mask_view.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<com.android.launcher3.allapps.FloatingMaskView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_alignParentBottom="true"
+    android:layout_marginLeft="@dimen/ps_floating_mask_end_padding"
+    android:layout_marginRight="@dimen/ps_floating_mask_end_padding"
+    android:importantForAccessibility="noHideDescendants"
+    android:orientation="horizontal">
+
+    <ImageView
+        android:id="@+id/left_corner"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:layout_constraintStart_toStartOf="parent"
+        android:importantForAccessibility="no"
+        android:background="@drawable/bg_ps_mask_left_corner"/>
+
+    <ImageView
+        android:id="@+id/right_corner"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:scaleType="centerCrop"
+        app:layout_constraintEnd_toEndOf="parent"
+        android:importantForAccessibility="no"
+        android:background="@drawable/bg_ps_mask_right_corner"/>
+
+    <ImageView
+        android:id="@+id/bottom_box"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_constraintStart_toStartOf="@id/left_corner"
+        app:layout_constraintEnd_toEndOf="@id/right_corner"
+        app:layout_constraintTop_toBottomOf="@id/left_corner"
+        android:importantForAccessibility="no"
+        android:background="?attr/allAppsScrimColor"/>
+
+</com.android.launcher3.allapps.FloatingMaskView>
\ No newline at end of file
diff --git a/res/layout/widget_cell_content.xml b/res/layout/widget_cell_content.xml
index 8f786bf..b6412db 100644
--- a/res/layout/widget_cell_content.xml
+++ b/res/layout/widget_cell_content.xml
@@ -46,20 +46,22 @@
             android:layout_gravity="center_vertical"
             android:id="@+id/widget_text_container"
             android:orientation="vertical">
-            <!-- The name of the widget. -->
-            <TextView
-                android:id="@+id/widget_name"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:ellipsize="end"
-                android:fadingEdge="horizontal"
-                android:layout_gravity="center_horizontal"
-                android:gravity="center_horizontal|center_vertical"
-                android:singleLine="true"
-                android:maxLines="1"
-                android:textColor="?android:attr/textColorPrimary"
-                android:drawablePadding="@dimen/widget_cell_app_icon_padding"
-                android:textSize="@dimen/widget_cell_font_size" />
+                <!-- The name of the widget. -->
+                <TextView
+                    android:id="@+id/widget_name"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:ellipsize="end"
+                    android:fadingEdge="horizontal"
+                    android:layout_gravity="center_horizontal"
+                    android:gravity="center_horizontal|center_vertical"
+                    android:singleLine="true"
+                    android:maxLines="1"
+                    android:textColor="?attr/widgetCellTitleColor"
+                    android:textSize="@dimen/widget_cell_title_font_size"
+                    android:textFontWeight="@integer/widget_cell_title_font_weight"
+                    android:lineHeight="@dimen/widget_cell_title_line_height"
+                    android:drawablePadding="@dimen/widget_cell_app_icon_padding" />
 
                 <!-- The original dimensions of the widget -->
                 <TextView
@@ -67,21 +69,23 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:gravity="center_horizontal"
-                    android:textColor="?android:attr/textColorSecondary"
-                    android:textSize="@dimen/widget_cell_font_size"
-                    android:alpha="0.7" />
+                    android:textColor="?attr/widgetCellSubtitleColor"
+                    android:textSize="@dimen/widget_cell_dims_font_size"
+                    android:textFontWeight="@integer/widget_cell_dims_font_weight"
+                    android:lineHeight="@dimen/widget_cell_dims_line_height" />
 
                 <TextView
                     android:id="@+id/widget_description"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:gravity="center_horizontal"
-                    android:textSize="@dimen/widget_cell_font_size"
-                    android:textColor="?android:attr/textColorSecondary"
+                    android:textColor="?attr/widgetCellSubtitleColor"
+                    android:textSize="@dimen/widget_cell_description_font_size"
+                    android:textFontWeight="@integer/widget_cell_description_font_weight"
+                    android:lineHeight="@dimen/widget_cell_description_line_height"
                     android:maxLines="3"
                     android:ellipsize="end"
-                    android:fadingEdge="horizontal"
-                    android:alpha="0.7" />
+                    android:fadingEdge="horizontal" />
         </LinearLayout>
 
         <Button
@@ -94,12 +98,16 @@
             android:paddingEnd="@dimen/widget_cell_add_button_end_padding"
             android:text="@string/widget_add_button_label"
             android:textColor="?attr/widgetPickerAddButtonTextColor"
-            android:textSize="@dimen/widget_cell_font_size"
+            android:textSize="@dimen/widget_cell_add_button_font_size"
+            android:fontWeight="@integer/widget_cell_add_button_font_weight"
+            android:lineHeight="@dimen/widget_cell_add_button_line_height"
             android:gravity="center"
             android:visibility="gone"
             android:drawableStart="@drawable/ic_plus"
-            android:drawablePadding="8dp"
+            android:drawablePadding="@dimen/widget_cell_add_button_drawable_padding"
             android:drawableTint="?attr/widgetPickerAddButtonTextColor"
+            android:maxLines="1"
+            style="@style/Button.Rounded.Colored"
             android:background="@drawable/widget_cell_add_button_background" />
     </FrameLayout>
 </merge>
diff --git a/res/layout/widgets_list_row_header.xml b/res/layout/widgets_list_row_header.xml
index 6d26ce3..98f9dac 100644
--- a/res/layout/widgets_list_row_header.xml
+++ b/res/layout/widgets_list_row_header.xml
@@ -48,8 +48,10 @@
             android:layout_gravity="start|center_vertical"
             android:ellipsize="end"
             android:maxLines="1"
-            android:textColor="?android:attr/textColorPrimary"
-            android:textSize="16sp"
+            android:textColor="?attr/widgetPickerHeaderAppTitleColor"
+            android:textSize="@dimen/widget_picker_header_app_title_font_size"
+            android:textFontWeight="@integer/widget_picker_header_app_title_font_weight"
+            android:lineHeight="@dimen/widget_picker_header_app_title_line_height"
             tools:text="App name" />
 
         <TextView
@@ -58,8 +60,10 @@
             android:layout_height="wrap_content"
             android:ellipsize="end"
             android:maxLines="1"
-            android:textColor="?android:attr/textColorSecondary"
-            android:alpha="0.7"
+            android:textColor="?attr/widgetPickerHeaderAppSubtitleColor"
+            android:textSize="@dimen/widget_picker_header_app_subtitle_font_size"
+            android:textFontWeight="@integer/widget_picker_header_app_subtitle_font_weight"
+            android:lineHeight="@dimen/widget_picker_header_app_subtitle_line_height"
             tools:text="m widgets, n shortcuts" />
 
     </LinearLayout>
diff --git a/res/layout/widgets_list_row_header_two_pane.xml b/res/layout/widgets_list_row_header_two_pane.xml
index bdb2aed..d4baf0a 100644
--- a/res/layout/widgets_list_row_header_two_pane.xml
+++ b/res/layout/widgets_list_row_header_two_pane.xml
@@ -51,7 +51,9 @@
             android:ellipsize="end"
             android:maxLines="1"
             android:textColor="?attr/widgetPickerHeaderAppTitleColor"
-            android:textSize="16sp"
+            android:textSize="@dimen/widget_picker_header_app_title_font_size"
+            android:textFontWeight="@integer/widget_picker_header_app_title_font_weight"
+            android:lineHeight="@dimen/widget_picker_header_app_title_line_height"
             android:duplicateParentState="true"
             tools:text="App name" />
 
@@ -62,7 +64,9 @@
             android:ellipsize="end"
             android:maxLines="1"
             android:textColor="?attr/widgetPickerHeaderAppSubtitleColor"
-            android:alpha="0.7"
+            android:textSize="@dimen/widget_picker_header_app_subtitle_font_size"
+            android:textFontWeight="@integer/widget_picker_header_app_subtitle_font_weight"
+            android:lineHeight="@dimen/widget_picker_header_app_subtitle_line_height"
             android:duplicateParentState="true"
             tools:text="m widgets, n shortcuts" />
 
diff --git a/res/layout/work_apps_edu.xml b/res/layout/work_apps_edu.xml
index f557fb6..99db8c6 100644
--- a/res/layout/work_apps_edu.xml
+++ b/res/layout/work_apps_edu.xml
@@ -50,9 +50,9 @@
                 android:id="@+id/action_btn"
                 android:layout_width="@dimen/x_icon_size"
                 android:layout_height="@dimen/x_icon_size"
+                android:scaleType="centerInside"
                 android:layout_gravity="center"
                 android:contentDescription="@string/accessibility_close"
-                android:padding="@dimen/x_icon_padding"
                 android:background="@android:color/transparent"
                 android:src="@drawable/ic_remove_no_shadow" />
         </FrameLayout>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index d6b6a62..1d333fd 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Voorstelle"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Noodsaaklikhede"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nuus en tydskrifte"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Jou ontspansone"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Vermaak"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosiaal"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Gesondheid en fiksheid"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weer"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Voorgestel vir jou"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-legstukke aan die regterkant, soektog en opsies aan die linkerkant"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# legstuk}other{# legstukke}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deïnstalleer"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Appinligting"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installeer privaat"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Deïnstalleer app"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Installeer"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Moenie voorstel nie"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Vasspeldvoorspelling"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installeer tans; <xliff:g id="PROGRESS">%2$s</xliff:g> voltooi"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> laai tans af, <xliff:g id="PROGRESS">%2$s</xliff:g> voltooid"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> wag tans om te installeer"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> is geargiveer. Tik om af te laai."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> is geargiveer. Tik om af te laai en terug te stel."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Programopdatering word vereis"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Die program vir hierdie ikoon is nie opgedateer nie. Jy kan dit handmatig opdateer om hierdie kortpad weer te aktiveer, of die ikoon verwyder."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Dateer op"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Tik om op te stel of oop te maak"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privaat"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Privaat Ruimte-instellings"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privaat, ontsluit."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privaat, gesluit."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Sluit"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Privaat Ruimte-oorgang"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Installeer apps"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Installeer"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Installeer apps in privaat ruimte"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Oorvloei"</string>
 </resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 3f48d38..f57812e 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"የአስተያየት ጥቆማዎች"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ጠቃሚ ነገሮች"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ዜና እና መጽሔቶች"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"የሚያርፉበት ቦታዎ"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"መዝናኛ"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ማህበራዊ"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ጤና እና የአካል ብቃት"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"የአየር ሁኔታ"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ለእርስዎ የተጠቆሙ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ምግብሮች በቀኝ በኩል፣ ፍለጋ እና አማራጮች በግራ በኩል"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ምግብር}one{# ምግብሮች}other{# ምግብሮች}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"አራግፍ"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"የመተግበሪያ መረጃ"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"በግል ይጫኑ"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"መተግበሪያን አራግፍ"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ጫን"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"መተግበሪያውን አይጠቁሙ"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"የፒን ግምት"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> በመጫን ላይ፣ <xliff:g id="PROGRESS">%2$s</xliff:g> ተጠናቅቋል"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> በመውረድ ላይ፣ <xliff:g id="PROGRESS">%2$s</xliff:g> ተጠናቋል"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ለመጫን በመጠበቅ ላይ"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> በማህደር ተቀምጧል። ለማውረድ መታ ያድርጉ።"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> በማህደር ተቀምጧል። ለማወረድ እና ወደነበረበት ለመመለስ መታ ያድርጉ።"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"መተግበሪያ ማዘመን አስፈላጊ ነው"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"የዚህ አዶ መተግበሪያ አልተዘመነም። ይህን አቋራጭ ዳግም ለማንቃት በራስዎ ማዘመን ወይም አዶውን ማስወገድ ይችላሉ።"</string>
     <string name="dialog_update" msgid="2178028071796141234">"አዘምን"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"ለማዋቀር ወይም ለመክፈት መታ ያድርጉ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"የግል"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"የግል ቦታ ቅንብሮች"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"የግል፣ የተከፈተ።"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"የግል፣ የተቆለፈ።"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"ቆልፍ"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"የግል ቦታ ሽግግር"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"መተግበሪያዎችን ይጫኑ"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ይጫኑ"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"መተግበሪያዎችን ወደ የግል ቦታ ይጫኑ"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ትርፍ ፍሰት"</string>
 </resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 3b6fc7c..e6f8d4a 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"اقتراحات"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"الأساسيات"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"الأخبار والمجلات"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"محتوى ترفيهي مقترَح"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"الترفيه"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"التواصل الاجتماعي"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"الصحة واللياقة البدنية"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"الطقس"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"اقتراحاتنا لك"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"تطبيقات \"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>\" المصغّرة على اليسار، والبحث والخيارات على اليمين"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{تطبيق مصغّر واحد}zero{# تطبيق مصغّر}two{تطبيقان مصغّران}few{# تطبيقات مصغّرة}many{# تطبيقًا مصغّرًا}other{# تطبيق مصغّر}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"إلغاء التثبيت"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"معلومات عن التطبيق"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"تثبيت في مساحة خاصّة"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"إلغاء تثبيت التطبيق"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"تثبيت"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"عدم اقتراح التطبيق"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"تثبيت التطبيق المتوقّع"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"جارٍ تثبيت <xliff:g id="NAME">%1$s</xliff:g>، مستوى التقدم: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"جارٍ تنزيل <xliff:g id="NAME">%1$s</xliff:g>، اكتمل <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> في انتظار التثبيت"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"تمت أرشفة تطبيق <xliff:g id="NAME">%1$s</xliff:g>. انقر للتنزيل."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"تمت أرشفة تطبيق \"<xliff:g id="NAME">%1$s</xliff:g>\". انقر لتنزيله واستعادته."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"مطلوب تحديث التطبيق"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"لم يتمّ تحديث التطبيق الخاص بهذا الرمز. يمكنك تحديث التطبيق يدويًا لإعادة تفعيل هذا الاختصار أو إزالة الرمز."</string>
     <string name="dialog_update" msgid="2178028071796141234">"تحديث"</string>
@@ -186,16 +184,14 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"فلتر"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"تعذَّر <xliff:g id="WHAT">%1$s</xliff:g>."</string>
     <string name="private_space_label" msgid="2359721649407947001">"مساحة خاصة"</string>
-    <string name="private_space_secondary_label" msgid="9203933341714508907">"النقر للإعداد أو الفتح"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"انقر للإعداد أو الفتح"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"المساحة الخاصة"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"إعدادات المساحة الخاصة"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"المساحة الخاصة غير مُقفلة."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"المساحة الخاصة مُقفلة."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"قفل"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"النقل إلى المساحة الخاصة"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"تثبيت التطبيقات"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"تثبيت"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"تثبيت التطبيقات في المساحة الخاصّة"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"القائمة الكاملة"</string>
 </resources>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 8107dd4..54cc638 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"পৰামৰ্শ"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"অত্যাৱশ্যকীয়সমূহ"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"বাতৰি আৰু আলোচনী"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"আপোনাৰ পচন্দৰ স্থান"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"মনোৰঞ্জন"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"সামাজিক"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"স্বাস্থ্য আৰু সুস্থতা"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"বতৰ"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"আপোনাৰ বাবে পৰামৰ্শ হিচাপে আগবঢ়োৱা"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ৱিজেট সোঁফালে, সন্ধান আৰু বিকল্পসমূহ বাওঁফালে"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# টা ৱিজেট}one{# টা ৱিজেট}other{# টা ৱিজেট}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"আনইনষ্টল কৰক"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"এপ্‌ সম্পৰ্কীয় তথ্য"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"গোপনে ইনষ্টল কৰক"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"এপ্‌ আনইনষ্টল কৰক"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ইনষ্টল কৰক"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"পৰামৰ্শ নিদিব"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"পূৰ্বানুমান কৰা এপ্‌টো পিন কৰক"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ইনষ্টল কৰি থকা হৈছে, <xliff:g id="PROGRESS">%2$s</xliff:g> সম্পূৰ্ণ হৈছে"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ডাউনল’ড কৰি থকা হৈছে, <xliff:g id="PROGRESS">%2$s</xliff:g> সম্পূৰ্ণ হ’ল"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ইনষ্টল হোৱালৈ অপেক্ষা কৰি থকা হৈছে"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> আৰ্কাইভ কৰা হৈছে। ডাউনল’ড কৰিবলৈ টিপক।"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> আৰ্কাইভ কৰা হৈছে। ডাউনল’ড আৰু পুনঃস্থাপন কৰিবলৈ টিপক।"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"এপ্‌টো আপডে’ট কৰা প্ৰয়োজন"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"এই চিহ্নটোৰ এপ্‌টো আপডে’ট কৰা হোৱা নাই। আপুনি এই শ্বৰ্টকাটটো পুনৰ সক্ষম কৰিবলৈ মেনুৱেলী আপডে’ট কৰিব পাৰে অথবা চিহ্নটো আঁতৰাব পাৰে।"</string>
     <string name="dialog_update" msgid="2178028071796141234">"আপডে’ট কৰক"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"ছেট আপ কৰিবলৈ টিপক অথবা খোলক"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ব্যক্তিগত"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ব্যক্তিগত স্পে’চৰ ছেটিং"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"ব্যক্তিগত, আনলক কৰা আছে।"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ব্যক্তিগত, লক কৰা আছে।"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"লক কৰক"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"ব্যক্তিগত স্পে’চৰ স্থানান্তৰণ"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"এপ্‌ ইনষ্টল কৰক"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ইনষ্টল কৰক"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"এপ্‌সমূহ প্ৰাইভেট স্পেচত ইনষ্টল কৰক"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"অ’ভাৰফ্ল’"</string>
 </resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index d2d0c2b..2f71bbd 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Təkliflər"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Əsaslar"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Xəbər və jurnallar"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"İstirahət zonası"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Əyləncə"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosial"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sağlamlıq və fitnes"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Hava"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Təklif edirik"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vidcetləri sağda, axtarış və seçimlər solda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidcet}other{# vidcet}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Sistemdən sil"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Tətbiq haqqında"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Məxfi quraşdırın"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Tətbiqi sistemdən silin"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Quraşdırın"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Tətbiq təklif olunmasın"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Proqnozlaşdırılan tətbiqi bərkidin"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> quraşdırır, <xliff:g id="PROGRESS">%2$s</xliff:g> tamamlanıb"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> endirilir, <xliff:g id="PROGRESS">%2$s</xliff:g> tamamlandı"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> yüklənmək üçün gözləyir"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> arxivləndi. Endirmək üçün toxunun."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> arxivləndi. Toxunaraq endirin və bərpa edin."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Tətbiqin güncəllənməsi tələb edilir"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Bu ikona üçün tətbiq güncəllənməyib. Bu qısayolu yenidən aktivləşdirmək üçün manual olaraq güncəlləyə və ya ikonanı silə bilərsiniz."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Güncəlləyin"</string>
@@ -185,17 +183,15 @@
     <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Davam etdirin"</string>
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtr"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Alınmadı: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
-    <string name="private_space_label" msgid="2359721649407947001">"Şəxsi yer"</string>
+    <string name="private_space_label" msgid="2359721649407947001">"Məxfi sahə"</string>
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Toxunaraq ayarlayın və ya açın"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Şəxsi"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Şəxsi məkan ayarları"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Şəxsi, kilidli deyil."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Şəxsi, kilidli."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Kilidləyin"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Şəxsi məkana keçid"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Tətbiqlər quraşdırın"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Quraşdırın"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Tətbiqləri şəxsi sahədə quraşdırın"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Kənara çıxma"</string>
 </resources>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index d37c241..7858529 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -44,13 +44,10 @@
     <string name="add_to_home_screen" msgid="9168649446635919791">"Dodaj na početni ekran"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Dodali ste vidžet <xliff:g id="WIDGET_NAME">%1$s</xliff:g> na početni ekran"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Predlozi"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Neophodne aplikacije"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Osnovno"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Novosti i časopisi"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona za opuštanje"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zabava"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Društvene mreže"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravlje i fitnes"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vreme"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Predloženo za vas"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Vidžeti <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> sa desne strane, pretraga i opcije sa leve strane"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidžet}one{# vidžet}few{# vidžeta}other{# vidžeta}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deinstaliraj"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Podaci o aplikaciji"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instaliraj na privatni"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Deinstalirajte aplikaciju"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instaliraj"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne predlaži aplikaciju"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Zakači predviđanje"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> se instalira, <xliff:g id="PROGRESS">%2$s</xliff:g> gotovo"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> se preuzima, završeno je <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> čeka na instaliranje"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> je arhivirana. Dodirnite da biste je preuzeli."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> je arhivirana. Dodirnite da biste je preuzeli i vratili."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Treba da ažurirate aplikaciju"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Aplikacija za ovu ikonu nije ažurirana. Možete da je ručno ažurirate da biste ponovo omogućili ovu prečicu ili uklonite ikonu."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Ažuriraj"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Dodirnite da biste podesili ili otvorili"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privatno"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Podešavanja privatnog prostora"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privatno, otključano."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privatno, zaključano."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Zaključavanje"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Prenos privatnog prostora"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instalirajte aplikacije"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instalirajte"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instaliraj aplikacije u privatan prostor"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Preklopno"</string>
 </resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index d52ed4f..c3359c8 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Прапановы"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Асноўнае"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Навіны і часопісы"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Зона адпачынку"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Забавы"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Сацыяльныя сеткі"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здароўе і фітнес"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Надвор\'е"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Рэкамендавана для вас"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Віджэты праграмы \"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>\" справа, пошук і параметры злева"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# віджэт}one{# віджэт}few{# віджэты}many{# віджэтаў}other{# віджэта}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Дэінсталяваць"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Звесткі аб праграме"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Усталяваць прыватна"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Выдаліць праграму"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Усталяваць"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Не прапаноўваць праграму"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Замацаваць прапанаваную праграму"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Усталёўваецца праграма \"<xliff:g id="NAME">%1$s</xliff:g>\", завершана <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Ідзе спампоўка <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> завершана"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> чакае ўсталёўкі"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Праграма \"<xliff:g id="NAME">%1$s</xliff:g>\" знаходзіцца ў архіве. Націсніце, каб спампаваць."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Праграма \"<xliff:g id="NAME">%1$s</xliff:g>\" знаходзіцца ў архіве. Націсніце, каб спампаваць яе і аднавіць."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Неабходна абнавіць праграму"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Гэта версія праграмы састарэла. Абнавіце праграму ўручную, каб зноў карыстацца гэтым ярлыком, або выдаліце значок."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Абнавіць"</string>
@@ -185,17 +183,15 @@
     <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Актываваць"</string>
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Фільтр"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Не ўдалося: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
-    <string name="private_space_label" msgid="2359721649407947001">"Прыватная вобласць"</string>
+    <string name="private_space_label" msgid="2359721649407947001">"Прыватная прастора"</string>
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Націсніце, каб наладзіць або адкрыць"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Прыватная"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Налады прыватнай вобласці"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Прыватная прастора, разблакіравана."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Прыватная прастора, заблакіравана."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Заблакіраваць"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Пераход у прыватную вобласць"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Усталяваць праграмы"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Усталяваць"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Усталяваць праграмы ў прыватнай прасторы"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Дадатковае меню"</string>
 </resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index e4f5e5a..26044e7 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Предложения"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Приспособления, които трябва да изпробвате"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Новини и списания"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Зоната ви за разпускане"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Развлечения"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Социални мрежи"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здраве и фитнес"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Времето"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Предложено за вас"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Приспособленията за <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> са отдясно, търсенето и опциите – отляво"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# приспособление}other{# приспособления}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Деинсталиране"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Информация за прилож."</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Инстал. в частно простр."</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Деинсталиране на приложението"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Инсталиране"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Без предлагане на приложение"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Фиксиране на предвиждането"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> се инсталира, <xliff:g id="PROGRESS">%2$s</xliff:g> завършено"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> се изтегля. Завършено: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> изчаква инсталиране"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Приложението <xliff:g id="NAME">%1$s</xliff:g> е архивирано. Докоснете за изтегляне."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Приложението <xliff:g id="NAME">%1$s</xliff:g> е архивирано. Докоснете за изтегляне и възстановяване."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Изисква се актуализация на приложението"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Приложението за тази икона не е актуализирано. Можете да го актуализирате ръчно, за да активирате отново този пряк път, или да премахнете иконата."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Актуализиране"</string>
@@ -185,17 +183,15 @@
     <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Отмяна на паузата"</string>
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Филтър"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Неуспешно: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
-    <string name="private_space_label" msgid="2359721649407947001">"Лично пространство"</string>
+    <string name="private_space_label" msgid="2359721649407947001">"Частно пространство"</string>
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Докоснете за настройване или отваряне"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Лично"</string>
-    <string name="ps_container_settings" msgid="6059734123353320479">"Настройки за личното пространство"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_settings" msgid="6059734123353320479">"Настройки за частното пространство"</string>
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Частно, отключено."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Частно, заключено."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Заключване"</string>
-    <string name="ps_container_transition" msgid="8667331812048014412">"Преминаване към личното пространство"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Инсталиране на приложения"</string>
+    <string name="ps_container_transition" msgid="8667331812048014412">"Преминаване към частното пространство"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Инсталиране"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Инсталиране на приложения в частно пространство"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Препълване"</string>
 </resources>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 3da344d..a159bd9 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"সাজেশন"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"প্রয়োজনীয় জিনিস"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"খবর ও ম্যাগাজিন"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"আপনার চিল জোন"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"বিনোদন"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"সোশ্যাল"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"স্বাস্থ্য ও ফিটনেস"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"আবহাওয়া"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"আপনার জন্য সাজেস্ট করা হয়েছে"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> উইজেট ডানদিকে, সার্চ ও বিকল্প বাঁদিকে রয়েছে"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{#টি উইজেট}one{#টি উইজেট}other{#টি উইজেট}}"</string>
@@ -86,7 +83,8 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"সরান"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"আনইনস্টল করুন"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"অ্যাপের তথ্য"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ব্যক্তিগত প্রোফাইলে ইনস্টল করুন"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"প্রাইভেট প্রোফাইলে ইনস্টল করুন"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"অ্যাপ আনইনস্টল করুন"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ইনস্টল করুন"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"অ্যাপ সাজেস্ট করবেন না"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"আপনার প্রয়োজন হতে পারে এমন অ্যাপ পিন করুন"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ইনস্টল করা হচ্ছে, <xliff:g id="PROGRESS">%2$s</xliff:g> সম্পূর্ণ হয়েছে"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ডাউনলোড হচ্ছে <xliff:g id="PROGRESS">%2$s</xliff:g> সম্পন্ন হয়েছে"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ইনস্টলের অপেক্ষায় রয়েছে"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> আর্কাইভ করা হয়েছে। ডাউনলোড করতে ট্যাপ করুন।"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> আর্কাইভ করা হয়েছে। ডাউনলোড করতে এবং ফিরিয়ে আনতে ট্যাপ করুন।"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"অ্যাপটি আপডেট করা প্রয়োজন"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"এই আইকনের জন্য অ্যাপটি আপডেট করা নেই। এই শর্টকার্ট আবার চালু করতে, আপনি ম্যানুয়ালি আপডেট করতে বা সরিয়ে দিতে পারবেন।"</string>
     <string name="dialog_update" msgid="2178028071796141234">"আপডেট করুন"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"সেট-আপ করতে বা খুলতে ট্যাপ করুন"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ব্যক্তিগত"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ব্যক্তিগত স্পেসের সেটিংস"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"ব্যক্তিগত, আনলক করা আছে।"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ব্যক্তিগত, লক করা আছে।"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"লক"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"ব্যক্তিগত স্পেস ট্রানজিট করা"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"অ্যাপ ইনস্টল করুন"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ইনস্টল করুন"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"প্রাইভেট স্পেসে অ্যাপ ইনস্টল করুন"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ওভারফ্লো"</string>
 </resources>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index a150428..8b2e821 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Prijedlozi"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Osnovne aplikacije"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Vijesti i časopisi"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaša zona opuštanja"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zabava"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Društvene mreže"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravlje i fitnes"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vrijeme"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Predloženo za vas"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Vidžeti aplikacije <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> su na desnoj, a pretraživanje i opcije na lijevoj strani"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidžet}one{# vidžet}few{# vidžeta}other{# vidžeta}}"</string>
@@ -65,7 +62,7 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Posao"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Razgovori"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Pisanje bilješki"</string>
-    <string name="widget_add_button_label" msgid="2761267068711937179">"Dodaj"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Dodajte"</string>
     <string name="widget_add_button_content_description" msgid="1810530016360039643">"Dodavanje vidžeta <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Dodirnite da promijenite postavke vidžeta"</string>
     <string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Promjena postavki vidžeta"</string>
@@ -86,7 +83,8 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"Ukloni"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deinstaliraj"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Inform. o aplikaciji"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instaliraj u priv. pr."</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instaliraj u Privatno"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Deinstalirajte aplikaciju"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instaliraj"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne predlaži aplikaciju"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Zakači predviđanje"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Instaliranje aplikacije <xliff:g id="NAME">%1$s</xliff:g>, završeno je <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> se preuzima, završeno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> čeka da se instalira"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Arhivirana je aplikacija <xliff:g id="NAME">%1$s</xliff:g>. Dodirnite je da je preuzmete."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Arhivirana je aplikacija <xliff:g id="NAME">%1$s</xliff:g>. Dodirnite da je preuzmete i vratite."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Potrebno je ažurirati aplikaciju"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Aplikacija za ovu ikonu nije ažurirana. Možete je ažurirati ručno da ponovo omogućite ovu prečicu ili možete ukloniti ikonu."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Ažuriraj"</string>
@@ -185,17 +183,15 @@
     <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Ponovo pokreni"</string>
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrirajte"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Nije uspjelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
-    <string name="private_space_label" msgid="2359721649407947001">"Privatan prostor"</string>
+    <string name="private_space_label" msgid="2359721649407947001">"Privatni prostor"</string>
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Dodirnite da postavite ili otvorite"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privatno"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Postavke privatnog prostora"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privatno, otključano."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privatno, zaključano."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Zaključaj"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Prelazak u privatan prostor"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instaliranje aplikacija"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instaliraj"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instaliranje aplikacija u privatni prostor"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Preklopni meni"</string>
 </resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index a284738..c621b1c 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggeriments"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essencials"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Notícies i revistes"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"La teva zona de relax"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entreteniment"</string>
-    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salut i fitnes"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Temps"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Xarxes socials"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggeriments per a tu"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> a la dreta, cerca i opcions a l\'esquerra"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstal·la"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Informació de l\'aplicació"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instal·la en privat"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstal·la l\'aplicació"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instal·la"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"No suggereixis l\'aplicació"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Fixa la predicció"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"S\'està instal·lant <xliff:g id="NAME">%1$s</xliff:g>; s\'ha completat un <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"S\'està baixant <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> completat"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"S\'està esperant per instal·lar <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"L\'aplicació <xliff:g id="NAME">%1$s</xliff:g> està arxivada. Toca per baixar."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"L\'aplicació <xliff:g id="NAME">%1$s</xliff:g> està arxivada. Toca per baixar-la i restaurar-la."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Cal actualitzar l\'aplicació"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"L\'aplicació d\'aquesta icona no està actualitzada. Pots actualitzar-la manualment per tornar a activar aquesta drecera o pots suprimir la icona."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Actualitza"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Toca per configurar o obrir"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privat"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Configuració d\'Espai privat"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privat, desbloquejat."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privat, bloquejat."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Bloqueja"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Canvia a Espai privat"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instal·la apps"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instal·la"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instal·la les aplicacions a Espai privat"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Menú addicional"</string>
 </resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 1b43fe3..8b2e716 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -44,13 +44,10 @@
     <string name="add_to_home_screen" msgid="9168649446635919791">"Přidat na plochu"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> byl přidán na plochu"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Návrhy"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Základní"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Nejdůležitější aplikace"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Zprávy a časopisy"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaše klidová zóna"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zábava"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sociální sítě"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdraví a fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Počasí"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Návrhy pro vás"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgety <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vpravo, vyhledávání a možnosti vlevo"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ # widget}few{# widgety}many{# widgetu}other{# widgetů}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Odinstalovat"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"O aplikaci"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalovat soukromě"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Odinstalovat aplikaci"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Nainstalovat"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Nenavrhovat aplikaci"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Připnout předpověď"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Instalace aplikace <xliff:g id="NAME">%1$s</xliff:g>, dokončeno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Stahování aplikace <xliff:g id="NAME">%1$s</xliff:g> (dokončeno <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Instalace aplikace <xliff:g id="NAME">%1$s</xliff:g> čeká na zahájení"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Aplikace <xliff:g id="NAME">%1$s</xliff:g> je archivována. Klepnutím ji stáhnete."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Aplikace <xliff:g id="NAME">%1$s</xliff:g> je archivována. Klepnutím ji můžete stáhnout a obnovit."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Je nutná aktualizace aplikace"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Aplikace pro tuto ikonu není nainstalována. Můžete ji ručně aktualizovat, aby zkratka znovu fungovala, případně můžete ikonu odstranit."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Aktualizovat"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Klepnutím nastavíte nebo otevřete"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Soukromé"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Nastavení soukromého prostoru"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Soukromé, odemčeno."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Soukromé, uzamčeno."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Zamknout"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Převádění soukromého prostoru"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instalovat aplikace"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instalovat"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalovat aplikace do soukromého prostoru"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Rozbalovací nabídka"</string>
 </resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 0cc7d2e..b413440 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Forslag"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Vigtige ting"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Aviser og blade"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Dit afslapningshjørne"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Underholdning"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Socialt"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sundhed og fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vejr"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Forslag til dig"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-widgets til højre, søgning og valgmuligheder til venstre"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Afinstaller"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Appinfo"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installer (privat)"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Afinstaller appen"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Installer"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Foreslå ikke en app"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Fastgør forslaget"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installeres. <xliff:g id="PROGRESS">%2$s</xliff:g> fuldført"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloades. <xliff:g id="PROGRESS">%2$s</xliff:g> er gennemført"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> venter på at installere"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> er arkiveret Tryk for at downloade."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> er arkiveret Tryk for at downloade og gendanne."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Appen skal opdateres"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Appen, der tilhører dette ikon, er ikke opdateret. Du kan opdatere appen manuelt for at genaktivere denne genvej, eller du kan fjerne ikonet."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Opdater"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Tryk for at konfigurere eller åbne"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privat"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Indstillinger for privat rum"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privat, oplåst."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privat, låst."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Lås"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Ændringer af tilstanden for det private område"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Installer apps"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Installer"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Installer apps i privat område"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overløb"</string>
 </resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 88cefc8..42e3bac 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Vorschläge"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Must-haves"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nachrichten und Zeitschriften"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zum Entspannen"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Unterhaltung"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Soziale Netzwerke"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Gesundheit und Fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Wetter"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Vorschläge für dich"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-Widgets rechts, Suche und Optionen links"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# Widget}other{# Widgets}}"</string>
@@ -86,7 +83,8 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"Entfernen"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deinstallieren"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"App-Info"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Privat installieren"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Vertraul. installieren"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"App deinstallieren"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Installieren"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"App nicht vorschlagen"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Vorgeschlagene App fixieren"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> wird installiert, <xliff:g id="PROGRESS">%2$s</xliff:g> abgeschlossen"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> wird heruntergeladen, <xliff:g id="PROGRESS">%2$s</xliff:g> abgeschlossen"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Warten auf Installation von <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ist archiviert. Zum Herunterladen tippen."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ist archiviert. Tippe, um die App herunterzuladen und wiederherzustellen."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"App-Update erforderlich"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Die App für dieses Symbol wurde noch nicht aktualisiert. Du kannst sie manuell aktualisieren, um die Verknüpfung wieder zu aktivieren, oder das Symbol entfernen."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Aktualisieren"</string>
@@ -185,17 +183,15 @@
     <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Nicht mehr pausieren"</string>
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Fehler: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
-    <string name="private_space_label" msgid="2359721649407947001">"Privates Profil"</string>
+    <string name="private_space_label" msgid="2359721649407947001">"Vertrauliches Profil"</string>
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Zum Einrichten oder Öffnen tippen"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privat"</string>
-    <string name="ps_container_settings" msgid="6059734123353320479">"Einstellungen für privaten Bereich"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_settings" msgid="6059734123353320479">"Einstellungen für vertrauliches Profil"</string>
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privat, entsperrt."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privat, gesperrt."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Sperren"</string>
-    <string name="ps_container_transition" msgid="8667331812048014412">"Sperrzustand des privaten Bereichs wird gerade geändert"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Apps installieren"</string>
-    <string name="ps_add_button_content_description" msgid="3254274107740952556">"Apps im privaten Bereich installieren"</string>
+    <string name="ps_container_transition" msgid="8667331812048014412">"Sperrzustand des vertraulichen Profils wird gerade geändert"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Installieren"</string>
+    <string name="ps_add_button_content_description" msgid="3254274107740952556">"Apps im vertraulichen Profil installieren"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Weitere Optionen"</string>
 </resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 650d814..4eac9ca 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Προτάσεις"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Απαραίτητα"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Ειδήσεις και περιοδικά"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ο δικός σας τρόπος χαλάρωσης"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Ψυχαγωγία"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Κοινωνικά δίκτυα"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Υγεία και φυσική κατάσταση"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Καιρός"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Προτεινόμενα για εσάς"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Γραφικά στοιχεία <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> στα δεξιά, αναζήτηση και επιλογές στα αριστερά"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# γραφικό στοιχείο}other{# γραφικά στοιχεία}}"</string>
@@ -87,8 +84,9 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Απεγκατάσταση"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Πληροφ. εφαρμογής"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Εγκατ. στο απόρρητο"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Απεγκατάσταση εφαρμογής"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Εγκατάσταση"</string>
-    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Να μην προτείνεται η εφαρμογή"</string>
+    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Να μην προτείνεται"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Καρφίτσωμα πρόβλεψης"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"εγκατάσταση συντομεύσεων"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Επιτρέπει σε μια εφαρμογή την προσθήκη συντομεύσεων χωρίς την παρέμβαση του χρήστη."</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Έχει ολοκληρωθεί το <xliff:g id="PROGRESS">%2$s</xliff:g> της εγκατάστασης της εφαρμογής <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Λήψη <xliff:g id="NAME">%1$s</xliff:g>, ολοκληρώθηκε <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> σε αναμονή για εγκατάσταση"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Η εφαρμογή <xliff:g id="NAME">%1$s</xliff:g> είναι αρχειοθετημένη. Πατήστε για λήψη."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Η εφαρμογή <xliff:g id="NAME">%1$s</xliff:g> είναι αρχειοθετημένη. Πατήστε για λήψη και επαναφορά."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Απαιτείται ενημέρωση της εφαρμογής"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Η εφαρμογή για αυτό το εικονίδιο δεν έχει ενημερωθεί. Μπορείτε να την ενημερώσετε μη αυτόματα για να ενεργοποιήσετε ξανά τη συγκεκριμένη συντόμευση ή να καταργήσετε το εικονίδιο."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Ενημέρωση"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Πάτημα για ρύθμιση ή άνοιγμα"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Ιδιωτικό"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Ρυθμίσεις Ιδιωτικού χώρου"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Ιδιωτικό, ξεκλειδωμένο."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Ιδιωτικό, κλειδωμένο."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Κλείδωμα"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Μετάβαση στον Ιδιωτικό χώρο"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Εγκατάσταση εφαρμογών"</string>
-    <string name="ps_add_button_content_description" msgid="3254274107740952556">"Εγκατάσταση εφαρμογών στον απόρρητο χώρο"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Εγκατάσταση"</string>
+    <string name="ps_add_button_content_description" msgid="3254274107740952556">"Εγκατάσταση εφαρμογών στον ιδιωτικό χώρο"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Υπερχείλιση"</string>
 </resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 90de272..7c78fc7 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"News and magazines"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Your chill zone"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Health and fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weather"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggested for you"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgets on right, search and options on left"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstall"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"App info"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Install in private"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Uninstall app"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Install"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Don\'t suggest app"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Pin prediction"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download and restore."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Update"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Tap to set up or open"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Private"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Private Space Settings"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Private, unlocked."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Private, locked."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Lock"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Private Space transitioning"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Install apps"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Install"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Install apps to private space"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overflow"</string>
 </resources>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index c06300d..e6a7ea1 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"News &amp; magazines"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Your Chill Zone"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Health &amp; fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weather"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggested for you"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgets on right, search and options on left"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstall"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"App info"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Install in private"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Uninstall app"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Install"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Don\'t suggest app"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Pin Prediction"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download and restore."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut, or remove the icon."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Update"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Tap to set up or open"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Private"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Private Space Settings"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Private, unlocked."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Private, locked."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Lock"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Private Space Transitioning"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Install apps"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Install"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Install apps to Private Space"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overflow"</string>
 </resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 90de272..7c78fc7 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"News and magazines"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Your chill zone"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Health and fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weather"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggested for you"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgets on right, search and options on left"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstall"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"App info"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Install in private"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Uninstall app"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Install"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Don\'t suggest app"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Pin prediction"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download and restore."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Update"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Tap to set up or open"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Private"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Private Space Settings"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Private, unlocked."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Private, locked."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Lock"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Private Space transitioning"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Install apps"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Install"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Install apps to private space"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overflow"</string>
 </resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 90de272..7c78fc7 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"News and magazines"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Your chill zone"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Health and fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weather"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggested for you"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgets on right, search and options on left"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstall"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"App info"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Install in private"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Uninstall app"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Install"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Don\'t suggest app"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Pin prediction"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download and restore."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Update"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Tap to set up or open"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Private"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Private Space Settings"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Private, unlocked."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Private, locked."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Lock"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Private Space transitioning"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Install apps"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Install"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Install apps to private space"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overflow"</string>
 </resources>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index 36fa136..13616d6 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‎‎Suggestions‎‏‎‎‏‎"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎Essentials‎‏‎‎‏‎"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‏‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎News &amp; magazines‎‏‎‎‏‎"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‏‎Your Chill Zone‎‏‎‎‏‎"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎Entertainment‎‏‎‎‏‎"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‎‎‏‏‏‎‎‏‏‎‎‏‎‎‎‏‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‏‎‏‎Social‎‏‎‎‏‎"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‎‎‎Health &amp; fitness‎‏‎‎‏‎"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎Weather‎‏‎‎‏‎"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎Suggested for you‎‏‎‎‏‎"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>‎‏‎‎‏‏‏‎ widgets on right, search and options on left‎‏‎‎‏‎"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‎‎‎# widget‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‎‎‎# widgets‎‏‎‎‏‎}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‎Uninstall‎‏‎‎‏‎"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎App info‎‏‎‎‏‎"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‎‎‏‏‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎‎‏‎Install in private‎‏‎‎‏‎"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‎‏‏‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‎‎Uninstall app‎‏‎‎‏‎"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‎‏‎Install‎‏‎‎‏‎"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎Don\'t suggest app‎‏‎‎‏‎"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‎‏‎‏‎‎‏‎‎Pin Prediction‎‏‎‎‏‎"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ installing, ‎‏‎‎‏‏‎<xliff:g id="PROGRESS">%2$s</xliff:g>‎‏‎‎‏‏‏‎ complete‎‏‎‎‏‎"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ downloading, ‎‏‎‎‏‏‎<xliff:g id="PROGRESS">%2$s</xliff:g>‎‏‎‎‏‏‏‎ complete‎‏‎‎‏‎"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‎‎‏‎‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ waiting to install‎‏‎‎‏‎"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is archived. Tap to download.‎‏‎‎‏‎"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is archived. Tap to download and restore.‎‏‎‎‏‎"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‎‎‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‎App update required‎‏‎‎‏‎"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‏‎‎‎‎‏‎‎The app for this icon isn\'t updated. You can update manually to re-enable this shortcut, or remove the icon.‎‏‎‎‏‎"</string>
     <string name="dialog_update" msgid="2178028071796141234">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‏‏‎‎‏‎‎Update‎‏‎‎‏‎"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‏‎Tap to set up or open‎‏‎‎‏‎"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‏‎‏‎Private‎‏‎‎‏‎"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‏‏‏‏‎Private Space Settings‎‏‎‎‏‎"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‎‏‏‏‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‎‏‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎Private, unlocked.‎‏‎‎‏‎"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‎‏‎‎Private, locked.‎‏‎‎‏‎"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‎‎‏‎‏‎‎Lock‎‏‎‎‏‎"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‎Private Space Transitioning‎‏‎‎‏‎"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‎‏‎‎‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‏‏‎‎‎‏‏‎‎‎‎‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎Install apps‎‏‎‎‏‎"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎Install‎‏‎‎‏‎"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‎Install apps to Private Space‎‏‎‎‏‎"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎Overflow‎‏‎‎‏‎"</string>
 </resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 932fcd8..71a48cb 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugerencias"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Imprescindibles"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Noticias y revistas"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona de descanso"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretenimiento"</string>
-    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salud y bienestar"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Clima"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Redes sociales"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugerencias para ti"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> a la derecha, búsqueda y opciones a la izquierda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -61,7 +58,7 @@
     <string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"Borra el texto del cuadro de búsqueda"</string>
     <string name="no_widgets_available" msgid="4337693382501046170">"Los widgets y accesos directos no están disponibles"</string>
     <string name="no_search_results" msgid="3787956167293097509">"No se encontraron widgets ni accesos directos"</string>
-    <string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personales"</string>
+    <string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personal"</string>
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabajo"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversaciones"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Tomar notas"</string>
@@ -86,7 +83,8 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"Quitar"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalar"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Información de app"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instala en privado"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalar en privado"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalar app"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instalar"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"No sugerir app"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Fijar predicción"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Se está instalando <xliff:g id="NAME">%1$s</xliff:g>; <xliff:g id="PROGRESS">%2$s</xliff:g> completado"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Se completó el <xliff:g id="PROGRESS">%2$s</xliff:g> de la descarga de <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Instalación de <xliff:g id="NAME">%1$s</xliff:g> en espera"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> está archivada. Presiona para descargar."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> está archivada. Presiona para descargar y restablecer."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Es necesario actualizar la app"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"No se actualizó la app de este ícono. Puedes actualizarla manualmente para rehabilitar el acceso directo, o bien quitar el ícono."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Actualizar"</string>
@@ -170,8 +168,8 @@
     <string name="action_deep_shortcut" msgid="2864038805849372848">"Accesos directos"</string>
     <string name="action_dismiss_notification" msgid="5909461085055959187">"Descartar"</string>
     <string name="accessibility_close" msgid="2277148124685870734">"Cerrar"</string>
-    <string name="all_apps_personal_tab" msgid="4190252696685155002">"Personales"</string>
-    <string name="all_apps_work_tab" msgid="4884822796154055118">"De trabajo"</string>
+    <string name="all_apps_personal_tab" msgid="4190252696685155002">"Personal"</string>
+    <string name="all_apps_work_tab" msgid="4884822796154055118">"Trabajo"</string>
     <string name="work_profile_toggle_label" msgid="3081029915775481146">"Perfil de trabajo"</string>
     <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Las apps de trabajo tienen una insignia y el administrador de TI las puede ver"</string>
     <string name="work_profile_edu_accept" msgid="6069788082535149071">"Entendido"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Presiona para configurar o abrir"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privado"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Configuración de Espacio privado"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privado (desbloqueado)"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privado (bloqueado)"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Bloqueo"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Pasar a Espacio privado"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instala apps"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instalar"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instala las apps en el espacio privado"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Ampliada"</string>
 </resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index f7daeb3..b5208bd 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugerencias"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Imprescindibles"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Noticias y revistas"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Tu zona de descanso"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretenimiento"</string>
-    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salud y actividad física"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"El tiempo"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Redes sociales"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugerencias para ti"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> a la derecha, búsqueda y opciones a la izquierda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalar"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Información de la aplicación"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Descargar en privado"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalar aplicación"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instalar"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"No sugerir aplicación"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Fijar predicción"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Instalando <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> completado"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Descargando <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="PROGRESS">%2$s</xliff:g> completado)"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Esperando para instalar <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> está archivada. Toca para descargarla."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> está archivada. Toca para descargar y restaurar."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Debes actualizar la aplicación"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"La aplicación de este icono no está actualizada. Puedes actualizarla manualmente para volver a habilitar este acceso directo o puedes eliminar el icono."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Actualizar"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Toca para configurarlo o abrirlo"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privado"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Ajustes del espacio privado"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privado, desbloqueado."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privado, bloqueado."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Bloquear"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Cambiar a espacio privado"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Descarg. apps"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instalar"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Descargar aplicaciones en el espacio privado"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Desplegable"</string>
 </resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 6ebdff0..20a99d3 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Soovitused"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Põhiasjad"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Uudised ja ajakirjad"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Teie lõõgastumiskoht"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Meelelahutus"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Suhtlus"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Tervis ja vormisolek"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Ilm"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Teile soovitatud"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Teenuse <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vidinad paremal, otsing ja valikud vasakul"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidin}other{# vidinat}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalli"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Rakenduse teave"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Privaatselt installimine"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalli rakendus"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Installimine"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ära soovita rakendust"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Kinnita ennustus"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Üksust <xliff:g id="NAME">%1$s</xliff:g> installitakse, <xliff:g id="PROGRESS">%2$s</xliff:g> on valmis"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Rakenduse <xliff:g id="NAME">%1$s</xliff:g> allalaadimine, <xliff:g id="PROGRESS">%2$s</xliff:g> on valmis"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> on installimise ootel"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> on arhiivitud. Puudutage allalaadimiseks."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> on arhiivitud. Puudutage allalaadimiseks ja taastamiseks."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Rakendust tuleb värskendada"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Selle ikooni rakendust pole värskendatud. Otsetee uuesti lubamiseks võite rakendust käsitsi värskendada või ikooni eemaldada."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Värskenda"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Seadistamiseks või avamiseks puudutage"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privaatne"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Privaatse ruumi seaded"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privaatne, võrgulukuta."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privaatne, lukustatud."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Lukk"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Privaatse ruumi üleviimine"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Rakenduste installimine"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Installi"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Rakenduste installimine privaatses ruumis"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Ületäide"</string>
 </resources>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 9bd26e6..a477580 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Iradokizunak"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Oinarrizkoak"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Albisteak eta aldizkariak"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Lasaitzeko gunea"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Aisia"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sare sozialak"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Osasuna eta ongizatea"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Eguraldia"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Zuri iradokiak"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> zerbitzuaren widgetak eskuinean, bilaketa eta aukerak ezkerrean"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalatu"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Aplikazioaren informazioa"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalatu pribatuan"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalatu aplikazioa"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instalatu"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ez iradoki aplikazioa"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Ainguratu iragarpena"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> instalatzen, <xliff:g id="PROGRESS">%2$s</xliff:g> osatuta"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> deskargatzen, <xliff:g id="PROGRESS">%2$s</xliff:g> osatuta"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> instalatzeko zain"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> artxibatuta dago. Deskargatzeko, sakatu hau."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> artxibatuta dago. Sakatu deskargatzeko eta leheneratzeko."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Aplikazioa eguneratu egin behar da"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Ikonoaren aplikazioa ez dago eguneratuta. Lasterbidea berriro gaitzeko, eskuz egunera dezakezu aplikazioa. Bestela, kendu ikonoa."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Eguneratu"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Sakatu konfiguratzeko edo irekitzeko"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Pribatua"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Eremu pribatuaren ezarpenak"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Pribatua, desblokeatuta."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Pribatua, blokeatuta."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Blokeatu"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Eremu pribaturako trantsizioa"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instalatu aplikazioak"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instalatu"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalatu aplikazioak eremu pribatuan"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Luzapena"</string>
 </resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 46f5859..bdf4736 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"پیشنهادها"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"بایدها"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"اخبار و مجله"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"منطقه آرامش شما"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"سرگرمی"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"اجتماعی"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"سلامتی و تناسب اندام"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"آب‌وهوا"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"پیشنهاداتی برای شما"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ابزارک‌های <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> در سمت چپ، جستجو و گزینه‌ها در سمت راست"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{‏# ابزارک}one{‏# ابزارک}other{‏# ابزارک}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"حذف نصب"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"اطلاعات برنامه"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"نصب در نمایه خصوصی"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"حذف نصب برنامه"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"نصب"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"برنامه پیشنهاد داده نشود"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"سنجاق کردن پیشنهاد"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> درحال نصب است، <xliff:g id="PROGRESS">%2$s</xliff:g> تکمیل شده است"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"درحال بارگیری <xliff:g id="NAME">%1$s</xliff:g>، <xliff:g id="PROGRESS">%2$s</xliff:g> کامل شد"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> درانتظار نصب"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> بایگانی شده است. برای بارگیری ضربه بزنید."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> بایگانی شده است. برای بارگیری و بازیابی ضربه بزنید."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"برنامه باید به‌روز شود"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"برنامه برای این نماد به‌روز نشده است. می‌توانید آن را به‌صورت دستی به‌روز کنید تا میان‌بر دوباره فعال شود، یا نماد را بردارید."</string>
     <string name="dialog_update" msgid="2178028071796141234">"به‌روزرسانی"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"برای راه‌اندازی یا باز کردن، ضربه بزنید"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"خصوصی"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"تنظیمات «فضای خصوصی»"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"خصوصی، باز."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"خصوصی، قفل."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"قفل کردن"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"انتقال «فضای خصوصی»"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"نصب برنامه‌ها"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"نصب"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"نصب برنامه‌ها در «فضای خصوصی»"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"سرریز"</string>
 </resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index b27f654..e934044 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Ehdotukset"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Kaikki tarvittava"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Uutiset ja aikakauslehdet"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ota rennosti"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Viihde"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosiaalinen"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Terveys ja kuntoilu"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Sää"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sinulle ehdotetut"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgetit oikealla, haku ja vaihtoehdot vasemmalla"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgetiä}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Poista asennus"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Sovelluksen tiedot"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Asenna yksityisesti"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Sovelluksen poistaminen"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Asenna"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Älä ehdota sovellusta"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Kiinnitä sovellus"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> asennetaan, <xliff:g id="PROGRESS">%2$s</xliff:g> valmis"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> latautuu, valmiina <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> odottaa asennusta"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> on arkistoitu. Lataa napauttamalla."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> on arkistoitu. Lataa ja palauta napauttamalla."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Sovelluspäivitys vaaditaan"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Kuvakkeen sovellusta ei ole päivitetty. Voit ottaa pikakuvakkeen uudelleen käyttöön päivittämällä sovelluksen tai poistaa kuvakkeen."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Päivitä"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Ota käyttöön tai avaa napauttamalla"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Yksityinen"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Yksityisen tilan asetukset"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Yksityinen, lukitsematon."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Yksityinen, lukittu."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Lukko"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Yksityisen tilan siirtäminen"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Asenna sovelluksia"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Asenna"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Asenna sovelluksia yksityiseen tilaan"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Ylivuoto"</string>
 </resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index c99a0fd..4372caa 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentiels"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Actualités et magazines"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zone de divertissement"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Divertissement"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Médias sociaux"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Santé et mise en forme"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Météo"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggestions personnalisées"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> à droite, recherche et options à gauche"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
@@ -87,8 +84,9 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Désinstaller"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Détails de l\'appli"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installer dans privé"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Désinstaller l\'appli"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Installer"</string>
-    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne pas suggérer d\'application"</string>
+    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne pas suggérer d\'appli"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Épingler la prédiction"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"installer des raccourcis"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Permet à une application d\'ajouter des raccourcis sans l\'intervention de l\'utilisateur."</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Installation de l\'application <xliff:g id="NAME">%1$s</xliff:g> en cours, <xliff:g id="PROGRESS">%2$s</xliff:g> terminée"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Téléchargement de <xliff:g id="NAME">%1$s</xliff:g> : <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> en attente d\'installation"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"L\'application <xliff:g id="NAME">%1$s</xliff:g> est archivée. Toucher pour télécharger."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"L\'appli <xliff:g id="NAME">%1$s</xliff:g> est archivée. Touchez le bouton pour télécharger et restaurer l\'appli."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Mise à jour de l\'application requise"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"L\'application pour cette icône n\'est pas à jour. Vous pouvez soit la mettre à jour manuellement pour réactiver ce raccourci, soit retirer l\'icône."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Mettre à jour"</string>
@@ -186,16 +184,14 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrer"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Échec : <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Espace privé"</string>
-    <string name="private_space_secondary_label" msgid="9203933341714508907">"Toucher pour configurer ou ouvrir"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Touchez pour configurer ou ouvrir"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privé"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Paramètres de l\'Espace privé"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privé, déverrouillé."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privé, verrouillé."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Verrouiller"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Transition vers l\'Espace privé"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Installer des applications"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Installer"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Installer des applications dans l\'Espace privé"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Menu à développer"</string>
 </resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index fa80186..841fc84 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -44,13 +44,10 @@
     <string name="add_to_home_screen" msgid="9168649446635919791">"Ajouter à l\'écran d\'accueil"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ajouté à l\'écran d\'accueil"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Les bases"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Indispensables"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Actualités et magazines"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Votre espace détente"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Divertissement"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Réseaux sociaux"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Santé et bien-être"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Météo"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Recommandations"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> à droite, recherche et options à gauche"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
@@ -87,8 +84,9 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Désinstaller"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Infos sur l\'appli"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installer en mode privé"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Désinstaller l\'application"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Installer"</string>
-    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne pas suggérer d\'application"</string>
+    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne pas suggérer d\'appli"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Épingler la prédiction"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"installer des raccourcis"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Permettre à une application d\'ajouter des raccourcis sans l\'intervention de l\'utilisateur"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Installation de <xliff:g id="NAME">%1$s</xliff:g>… (<xliff:g id="PROGRESS">%2$s</xliff:g> terminés)"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> en cours de téléchargement, <xliff:g id="PROGRESS">%2$s</xliff:g> effectué(s)"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> en attente d\'installation"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"L\'application <xliff:g id="NAME">%1$s</xliff:g> est archivée. Appuyez pour télécharger."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"L\'application <xliff:g id="NAME">%1$s</xliff:g> est archivée. Appuyez pour la télécharger et la restaurer."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Mise à jour de l\'appli requise"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"L\'appli correspondant à cette icône n\'est pas mise à jour. Vous pouvez la mettre à jour manuellement pour réactiver le raccourci ou supprimer l\'icône."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Modifier"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Appuyer pour ouvrir ou configurer"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privé"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Paramètres d\'Espace privé"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privé, déverrouillé"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privé, verrouillé"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Verrouiller"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Transition vers Espace privé"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Installer applis"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Installer"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Installer des applis dans l\'espace privé"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Dépassement"</string>
 </resources>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index cf50f41..83fcbcd 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suxestións"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Esenciais"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Noticias e revistas"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Reláxate"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretemento"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Redes sociais"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Saúde e forma física"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"O tempo"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suxestións personalizadas"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> á dereita, busca e opcións á esquerda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,8 +84,9 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalar"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Información da app"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalar en privado"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalar aplicación"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instalar"</string>
-    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Non suxerir aplicación"</string>
+    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Non suxerir app"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Fixar predición"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar atallos"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite a unha aplicación engadir atallos sen intervención do usuario."</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Instalando <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> completado"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Descargando <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="PROGRESS">%2$s</xliff:g> completado)"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Esperando para instalar <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> está no arquivo. Toca para descargar esta aplicación."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> está no arquivo. Toca para descargar e restaurar."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"É necesario actualizar a aplicación"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"A aplicación á que corresponde esta icona non está actualizada. Podes actualizala manualmente para activar de novo este atallo, ou ben quitar a icona."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Actualizar"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Toca para configuralo ou abrilo"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privado"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Configuración do espazo privado"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privado, desbloqueado."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privado, bloqueado."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Bloquear"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Transición ao espazo privado"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instalar apps"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instalar"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalar as aplicacións no espazo privado"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Menú adicional"</string>
 </resources>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 72a8b47..963c6d1 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"સૂચનો"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"આવશ્યક"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ન્યૂઝ અને સામાયિકો"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"તમારો આરામદાયક ઝોન"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"મનોરંજન"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"સામાજિક"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"આરોગ્ય અને ફિટનેસ"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"હવામાન"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"તમારા માટે સૂચવેલી સેવાઓ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>ની વિજેટ જમણે, શોધ અને વિકલ્પો ડાબે"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# વિજેટ}one{# વિજેટ}other{# વિજેટ}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"અનઇન્સ્ટૉલ કરો"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"ઍપની માહિતી"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ખાનગીમાં ઇન્સ્ટૉલ કરો"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ઍપ અનઇન્સ્ટૉલ કરો"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ઇન્સ્ટૉલ કરો"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"ઍપ સૂચવશો નહીં"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"પૂર્વાનુમાનને પિન કરો"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ઇન્સ્ટૉલ કરી રહ્યાં છીએ, <xliff:g id="PROGRESS">%2$s</xliff:g> પૂર્ણ થયું"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ડાઉનલોડ કરી રહ્યાં છે, <xliff:g id="PROGRESS">%2$s</xliff:g> પૂર્ણ"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>, ઇન્સ્ટૉલ થવાની રાહ જોઈ રહ્યું છે"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> આર્કાઇવ કરી છે. ડાઉનલોડ કરવા માટે ટૅપ કરો."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g>ને આર્કાઇવ કર્યું છે. ડાઉનલોડ અને રિસ્ટોર કરવા માટે ટૅપ કરો."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"ઍપને અપડેટ કરવી જરૂરી છે"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"આ આઇકન માટે ઍપ અપડેટ કરવામાં આવી નથી. તમે આ શૉર્ટકટ ફરી ચાલુ કરવા અથવા આઇકન કાઢી નાખવા માટે ઍપને મેન્યુઅલી અપડેટ કરી શકો છો."</string>
     <string name="dialog_update" msgid="2178028071796141234">"અપડેટ કરો"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"સેટઅપ કરવા કે ખોલવા માટે ટૅપ કરો"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ખાનગી"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ખાનગી સ્પેસના સેટિંગ"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"ખાનગી સ્પેસ, અનલૉક કરેલી છે."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ખાનગી સ્પેસ, લૉક કરેલી છે."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"લૉક"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"ખાનગી સ્પેસ પર સ્થાનાંતરણ"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"ઍપ ઇન્સ્ટૉલ કરો"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ઇન્સ્ટૉલ કરો"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"ખાનગી સ્પેસમાં ઍપ ઇન્સ્ટૉલ કરો"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ઓવરફ્લો"</string>
 </resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 2e81ea6..0a381c8 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"सुझाव"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ज़रूरी ऐप्लिकेशन"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"खबरों और पत्रिकाओं वाले ऐप्लिकेशन"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"आपके मनोरंजन के लिए"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"मनोरंजन से जुड़े ऐप्लिकेशन"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"सोशल मीडिया ऐप्लिकेशन"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"हेल्थ और फ़िटनेस वाले ऐप्लिकेशन"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"मौसम"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"आपके लिए सुझाए गए ऐप्लिकेशन"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> के विजेट दाईं ओर, खोज का विजेट और अन्य विकल्प बाईं ओर"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}one{# विजेट}other{# विजेट}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"अनइंस्टॉल करें"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"ऐप्लिकेशन की जानकारी"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"निजी तौर पर इंस्टॉल करें"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ऐप्लिकेशन अनइंस्टॉल करें"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"इंस्‍टॉल करें"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"ऐप्लिकेशन का सुझाव न दें"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"सुझाए गए ऐप्लिकेशन को पिन करें"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> इंस्टॉल किया जा रहा है, <xliff:g id="PROGRESS">%2$s</xliff:g> पूरा हो गया"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> डाउनलोड हो रहा है, <xliff:g id="PROGRESS">%2$s</xliff:g> पूरी हुई"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> के इंस्टॉल होने की प्रतीक्षा की जा रही है"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> को संग्रहित किया गया. डाउनलोड करने के लिए टैप करें."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> को संग्रहित किया गया. ऐप्लिकेशन को वापस लाने और डाउनलोड करने के लिए टैप करें."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"ऐप्लिकेशन को अपडेट करना ज़रूरी है"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"इस आइकॉन का ऐप्लिकेशन अपडेट नहीं है. इस शॉर्टकट को फिर से चालू करने या आइकॉन को हटाने के लिए, ऐप्लिकेशन को मैन्युअल रूप से अपडेट किया जा सकता है."</string>
     <string name="dialog_update" msgid="2178028071796141234">"अपडेट करें"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"सेट अप करने या खोलने के लिए टैप करें"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"निजी"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"प्राइवेट स्पेस सेटिंग"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"प्राइवेट स्पेस को अनलॉक किया गया."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"प्राइवेट स्पेस को लॉक किया गया."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"लॉक"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"प्राइवेट स्पेस की सेटिंग में बदलाव किया जा रहा है"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"ऐप्लिकेशन इंस्टॉल करें"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"इंस्टॉल करें"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"प्राइवेट स्पेस में ऐप्लिकेशन इंस्टॉल करें"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ओवरफ़्लो"</string>
 </resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index bf24a1d..fec8e28 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Prijedlozi"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Osnovno"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Vijesti i časopisi"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaša zona za opuštanje"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zabava"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Društvene mreže"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravlje i fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vrijeme"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Prijedlozi za vas"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> –widgeti zdesna, pretraživanje i opcije slijeva"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}few{# widgeta}other{# widgeta}}"</string>
@@ -86,7 +83,8 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"Ukloni"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deinstaliraj"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Podaci o aplikaciji"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instaliranje u privatni profil"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instaliraj u privatno"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Deinstaliraj aplikaciju"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instaliraj"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne predlaži aplikaciju"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Prikvači predviđenu apl."</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Instaliranje aplikacije <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> dovršeno"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Preuzimanje aplikacije <xliff:g id="NAME">%1$s</xliff:g>, dovršeno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Čekanje na instaliranje aplikacije <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> je arhivirana. Dodirnite za preuzimanje."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> je arhivirana. Dodirnite da biste je preuzeli i vratili."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Aplikacija se treba ažurirati"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Aplikacija ove ikone nije ažurirana. Možete ručno ažurirati da biste ponovo omogućili ovaj prečac ili uklonite ikonu."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Ažuriraj"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Dodirnite da biste postavili ili otvorili"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privatno"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Postavke privatnog prostora"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privatno, otključano."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privatno, zaključano."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Zaključavanje"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Prelazak na privatni prostor"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instalirajte aplikacije"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instaliraj"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instaliranje aplikacija u privatni prostor"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Dodatni izbornik"</string>
 </resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 324cced..f69e1fb 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Javaslatok"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Legfontosabbak"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Újságok és magazinok"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Az Ön relaxáló zónája"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Szórakozás"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Közösségi"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Egészség és fitnesz"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Időjárás"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Neked javasolt"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"A <xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-modulok a jobb, a kereső és a beállítások pedig a bal oldalon találhatók"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# modul}other{# modul}}"</string>
@@ -86,9 +83,10 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"Törlés"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Eltávolítás"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Alkalmazásinfó"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Telepítés privátra"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Privát telepítés"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Alkalmazás eltávolítása"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Telepítés"</string>
-    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne javasoljon alkalmazást"</string>
+    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne javasoljon appot"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Várható kitűzése"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"parancsikonok telepítése"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Lehetővé teszi egy alkalmazás számára, hogy felhasználói beavatkozás nélkül adjon hozzá parancsikonokat."</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Folyamatban van a(z) <xliff:g id="NAME">%1$s</xliff:g> telepítése, <xliff:g id="PROGRESS">%2$s</xliff:g> kész"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"A(z) <xliff:g id="NAME">%1$s</xliff:g> letöltése, <xliff:g id="PROGRESS">%2$s</xliff:g> kész"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"A(z) <xliff:g id="NAME">%1$s</xliff:g> telepítésre vár"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> archiválva. Koppintson a letöltéshez."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> archiválva. Koppintson a letöltéshez és a visszaállításhoz."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Alkalmazásfrissítés szükséges"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Az ikonhoz tartozó alkalmazás nincs frissítve. A parancsikon újbóli engedélyezéséhez frissítse az alkalmazást, vagy távolítsa ez az ikont."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Frissítés"</string>
@@ -187,15 +185,13 @@
     <string name="remote_action_failed" msgid="1383965239183576790">"Sikertelen: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privát terület"</string>
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Koppintson a beállításhoz vagy a megnyitáshoz"</string>
-    <string name="ps_container_title" msgid="4391796149519594205">"Magánterület"</string>
+    <string name="ps_container_title" msgid="4391796149519594205">"Privát terület"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Privát terület beállításai"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privát, feloldott."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privát, zárolt."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Zárolás"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Átállás privát területre…"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"App telepítése"</string>
-    <string name="ps_add_button_content_description" msgid="3254274107740952556">"Alkalmazások telepítése magánterületre"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Telepítés"</string>
+    <string name="ps_add_button_content_description" msgid="3254274107740952556">"Alkalmazások telepítése privát területre"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Túlcsordulás"</string>
 </resources>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index f1a3a6c..7e220bf 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Առաջարկներ"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Հիմնական"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Նորություններ և ամսագրեր"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ձեր հանգստի գոտին"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Զվարճանք"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Սոցցանցեր"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Առողջություն և ֆիթնես"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Եղանակ"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Առաջարկում ենք"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"«<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>» հավելվածի վիջեթներն աջ կողմում են, իսկ որոնման դաշտը և կարգավորումները՝ ձախ կողմում"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# վիջեթ}one{# վիջեթ}other{# վիջեթ}}"</string>
@@ -86,7 +83,8 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"Հեռացնել"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Ապատեղադրել"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Հավելվածի մասին"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Տեղադրել անձնականում"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Տեղադրել մասնավորում"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Ապատեղադրել հավելվածը"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Տեղադրել"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Չառաջարկել"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Ամրացնել առաջարկվող հավելվածը"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> հավելվածը տեղադրվում է, կատարված է <xliff:g id="PROGRESS">%2$s</xliff:g>-ը"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g>–ի ներբեռնում (<xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>-ի տեղադրման սպասում"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> հավելվածն արխիվացված է։ Հպեք՝ ներբեռնելու համար:"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> հավելվածն արխիվացված է։ Հպեք՝ ներբեռնելու և վերականգնելու համար։"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Պահանջվում է թարմացնել հավելվածը"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Հավելվածը հնացել է։ Թարմացրեք այն ձեռքով, որպեսզի շարունակեք օգտագործել դյուրանցումը, կամ հեռացրեք հավելվածի պատկերակը։"</string>
     <string name="dialog_update" msgid="2178028071796141234">"Թարմացնել"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Հպեք կարգավորելու կամ բացելու համար"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Մասնավոր"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Անձնական տարածքի կարգավորումներ"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Անձնական, ապակողպված է։"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Անձնական, կողպված է։"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Կողպում"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Անցում մասնավոր տարածք"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Հավելվածների տեղադրում"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Տեղադրել"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Հավելվածների տեղադրում անձնական տարածքում"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Լրացուցիչ ընտրացանկ"</string>
 </resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index acdbc46..fc81717 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Saran"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Penting"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Berita &amp; majalah"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona Nyaman Anda"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Hiburan"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosial"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Kesehatan &amp; kebugaran"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Cuaca"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Disarankan untuk Anda"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widget <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> di bagian kanan, penelusuran dan opsi di bagian kiri"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
@@ -86,9 +83,10 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"Hapus"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstal"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Info aplikasi"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instal secara pribadi"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instal di ruang privasi"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Uninstal aplikasi"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instal"</string>
-    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Jangan sarankan aplikasi"</string>
+    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Jangan sarankan apl"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Pin Prediksi"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"memasang pintasan"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Mengizinkan aplikasi menambahkan pintasan tanpa campur tangan pengguna."</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> sedang diinstal, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> sedang didownload, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> menunggu dipasang"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> diarsipkan. Ketuk untuk mendownload."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> diarsipkan. Ketuk untuk mendownload dan memulihkan."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Aplikasi perlu diupdate"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Aplikasi untuk ikon ini belum diupdate. Anda dapat mengupdate secara manual untuk mengaktifkan kembali pintasan ini, atau hapus ikon."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Update"</string>
@@ -185,17 +183,15 @@
     <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Aktifkan lagi"</string>
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Gagal: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
-    <string name="private_space_label" msgid="2359721649407947001">"Ruang pribadi"</string>
+    <string name="private_space_label" msgid="2359721649407947001">"Ruang privasi"</string>
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Ketuk untuk menyiapkan atau membuka"</string>
-    <string name="ps_container_title" msgid="4391796149519594205">"Pribadi"</string>
+    <string name="ps_container_title" msgid="4391796149519594205">"Privasi"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Setelan Ruang Pribadi"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Pribadi, tidak terkunci."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Pribadi, dikunci."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Kunci"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Ruang Pribadi Bertransisi"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instal aplikasi"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instal"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instal aplikasi ke Ruang Pribadi"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Menu tambahan"</string>
 </resources>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index a815d7a..5339b93 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Tillögur"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Það nauðsynlegasta"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Fréttir og tímarit"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Slakaðu á"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Afþreying"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Samfélag"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Heilsa og líkamsrækt"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Veður"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Tillögur fyrir þig"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-græjur til hægri, leit og valkostir til vinstri"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# græja}one{# græja}other{# græjur}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Fjarlægja"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Forritsupplýsingar"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Setja upp á lokuðum prófíl"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Fjarlægja forrit"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Setja upp"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ekki fá tillögu að forriti"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Festa tillögu"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Setur upp <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> lokið"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> í niðurhali, <xliff:g id="PROGRESS">%2$s</xliff:g> lokið"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> bíður uppsetningar"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> er í geymslu. Ýttu til að sækja."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> er í geymslu. Ýttu til að sækja og endurheimta."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Uppfæra þarf forritið"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Forritið fyrir þetta tákn er ekki uppfært. Þú getur uppfært það handvirkt til að kveikja aftur á þessari flýtileið eða fjarlægt táknið."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Uppfæra"</string>
@@ -185,17 +183,15 @@
     <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Ljúka hléi"</string>
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Sía"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Mistókst: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
-    <string name="private_space_label" msgid="2359721649407947001">"Einkarými"</string>
+    <string name="private_space_label" msgid="2359721649407947001">"Leynirými"</string>
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Ýttu til að setja upp eða opna"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Lokað"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Stillingar einkarýmis"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Lokað, ólæst."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Lokað, læst."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Læsa"</string>
-    <string name="ps_container_transition" msgid="8667331812048014412">"Einkarými að breytast"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Setja upp forrit"</string>
+    <string name="ps_container_transition" msgid="8667331812048014412">"Leynirými að breytast"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Setja upp"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Setja upp forrit í leynirými"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Yfirflæði"</string>
 </resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 0a76bcf..5ef0145 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggerimenti"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essenziali"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Notizie e riviste"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Il tuo angolo di tranquillità"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Intrattenimento"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salute e fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Meteo"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Consigliati per te"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widget di <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> a destra, ricerca e opzioni a sinistra"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Disinstalla"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Informazioni app"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installa in privato"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Disinstalla app"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Installa"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Non suggerire app"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Blocca previsione"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Installazione di <xliff:g id="NAME">%1$s</xliff:g>, completamento: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Download di <xliff:g id="NAME">%1$s</xliff:g> in corso, <xliff:g id="PROGRESS">%2$s</xliff:g> completato"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> in attesa di installazione"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"App <xliff:g id="NAME">%1$s</xliff:g> archiviata. Tocca per scaricare."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"App <xliff:g id="NAME">%1$s</xliff:g> archiviata. Tocca per scaricare e ripristinare."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"È necessario aggiornare l\'app"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"L\'app relativa a questa icona non è aggiornata. Puoi eseguire manualmente l\'aggiornamento per riattivare questa scorciatoia oppure rimuovere l\'icona."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Aggiorna"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Tocca per configurare o aprire"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privato"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Impostazioni dello Spazio privato"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privato, sbloccato."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privato, bloccato."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Blocca"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Transizione dello Spazio privato in corso…"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Installa app"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Installa"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Installa le app su spazi privati"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Extra"</string>
 </resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 87c8a22..0d18cdf 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -44,13 +44,10 @@
     <string name="add_to_home_screen" msgid="9168649446635919791">"הוספה למסך הבית"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"הווידג\'ט <xliff:g id="WIDGET_NAME">%1$s</xliff:g> נוסף למסך הבית"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"הצעות"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"האפליקציות שחייבים להכיר"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"הכי חשוב"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"חדשות וכתבי עת"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"המקום שלך לרגיעה"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"בידור"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"רשתות חברתיות"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"בריאות וכושר"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"מזג אוויר"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"הצעות בשבילך"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"‫<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ווידג\'טים מימין, חיפוש ואפשרויות משמאל"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ווידג\'ט אחד}one{# ווידג\'טים}two{# ווידג\'טים}other{# ווידג\'טים}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"להסרת התקנה"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"פרטי אפליקציה"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"התקנה במרחב הפרטי"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"הסרת האפליקציה"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"התקנה"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"בלי להציע את האפליקציה"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"הצמדת החיזוי"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> בתהליך התקנה, <xliff:g id="PROGRESS">%2$s</xliff:g> הושלמו"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"הורדת <xliff:g id="NAME">%1$s</xliff:g> מתבצעת, <xliff:g id="PROGRESS">%2$s</xliff:g> הושלמו"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"מחכה להתקנה של <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"אפליקציית <xliff:g id="NAME">%1$s</xliff:g> הועברה לארכיון. יש להקיש כדי להוריד."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"אפליקציית <xliff:g id="NAME">%1$s</xliff:g> הועברה לארכיון. אפשר להקיש כדי להוריד ולשחזר אותה."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"נדרש עדכון לאפליקציה"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"האפליקציה של הסמל הזה לא מעודכנת. אפשר לעדכן אותה ידנית כדי להפעיל מחדש את קיצור הדרך הזה, או להסיר את הסמל."</string>
     <string name="dialog_update" msgid="2178028071796141234">"עדכון"</string>
@@ -186,16 +184,14 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"סינון"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"הפעולה נכשלה: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"מרחב פרטי"</string>
-    <string name="private_space_secondary_label" msgid="9203933341714508907">"אפשר להקיש כדי להגדיר או לפתוח"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"יש להקיש כדי להגדיר או לפתוח"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"פרטי"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"הגדרות המרחב הפרטי"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"פרטי, פתוח."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"פרטי, נעול."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"נעילה"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"מעבר למרחב הפרטי"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"התקנת אפליקציות"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"התקנה"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"התקנת אפליקציות במרחב הפרטי"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"אפשרויות נוספות"</string>
 </resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index d91f0ee..163afd4 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"候補"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"基本"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ニュース&雑誌"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"休憩エリア"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"エンタメ"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ソーシャル"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"健康&フィットネス"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"天気"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"おすすめ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> のウィジェットは右側に、検索とオプションは左側にあります"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 件のウィジェット}other{# 件のウィジェット}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"アンインストール"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"アプリ情報"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"非公開インストール"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"アプリをアンインストール"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"インストール"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"アプリを表示しない"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"アプリの候補を固定"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> をインストールしています: <xliff:g id="PROGRESS">%2$s</xliff:g> 完了"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g>をダウンロード中、<xliff:g id="PROGRESS">%2$s</xliff:g>完了"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>のインストール待ち"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> はアーカイブ済みです。ダウンロードするにはタップします。"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g>はアーカイブ済みです。ダウンロードして復元するには、タップしてください。"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"アプリの更新が必要"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"このアイコンのアプリは更新されていません。手動で更新して、このショートカットを再度有効にできます。また、アイコンを削除することもできます。"</string>
     <string name="dialog_update" msgid="2178028071796141234">"更新"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"設定したり開いたりするにはタップしてください"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"プライベート"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"プライベート スペースの設定"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"非公開で、ロックが解除されています。"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"非公開で、ロックされています。"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"ロック"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"プライベート スペース移行中"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"アプリをインストールする"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"インストール"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"プライベート スペースにアプリをインストールします"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"オーバーフロー"</string>
 </resources>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index ef74286..d7157e9 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"შეთავაზებები"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"უმნიშვნელოვანესები"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ახალი ამბები და ჟურნალები"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"განტვირთვის ადგილი"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"გართობა"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"სოციალური"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ჯანმრთელობა და ფიტნესი"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ამინდი"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"თქვენთვის შემოთავაზებული"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ვიჯეტები მდებარეობს მარჯვნივ, ძებნა და პარამეტრები — მარცხნივ"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ვიჯეტი}other{# ვიჯეტი}}"</string>
@@ -86,7 +83,8 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"ამოშლა"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"დეინსტალაცია"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"აპის შესახებ"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"პირადში ინსტალაცია"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"კერძოში ინსტალაცია"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"აპის დეინსტალაცია"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ინსტალაცია"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"არ შემომთავაზო აპი"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"ჩამაგრების პროგნოზირება"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"ინსტალირდება <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> დასრულებულია"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"მიმდინარეობს <xliff:g id="NAME">%1$s</xliff:g>-ის ჩამოტვირთვა, <xliff:g id="PROGRESS">%2$s</xliff:g> დასრულდა"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ელოდება ინსტალაციას"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> დაარქივებულია. შეეხეთ ჩამოსატვირთად."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> დაარქივებულია. შეეხეთ გადმოსაწერად და აღსადგენად."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"საჭიროა აპის განახლება"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"ამ ხატულის აპი განახლებული არ არის. შეგიძლიათ, ხელით განაახლოთ ამ მალსახმობის ხელახლა გასააქტიურებლად, ან ამოშალოთ ხატულა."</string>
     <string name="dialog_update" msgid="2178028071796141234">"განახლება"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"დასაყენებლად ან გასახსნელად შეეხეთ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"პირადი"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"პირადი სივრცის პარამეტრები"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"პირადი (განბლოკილი)."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"პირადი (ჩაკეტილი)."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"ჩაკეტვა"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"პირად სივრცეზე გადასვლა"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"აპების ინსტალაცია"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ინსტალაცია"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"კერძო სივრცეში აპების ინსტალაცია"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"გადავსება"</string>
 </resources>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index ff379c8..c53cd03 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Ұсыныстар"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Ең қажетті"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Жаңалықтар мен журналдар"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Жанға жайлы жер"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Ойын-сауық"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Қоғам"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Денсаулық және фитнес"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Ауа райы"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Сізге ұсынылғандар"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> виджеттері оң жақта, іздеу мен опциялар сол жақта"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
@@ -86,7 +83,8 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"Алып тастау"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Жою"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Қолданба ақпараты"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Жеке профильге орнату"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Құпия профильге орнату"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Қолданбаны жою"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Орнату"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Қолданба ұсынбау"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Болжанған қолданбаны бекіту"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> орнатылуда, <xliff:g id="PROGRESS">%2$s</xliff:g> аяқталды"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> жүктелуде, <xliff:g id="PROGRESS">%2$s</xliff:g> аяқталды"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> орнату күтілуде"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> мұрағатталды. Жүктеп алу үшін түртіңіз."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> мұрағатталды. Жүктеп алу және қалпына келтіру үшін түртіңіз."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Қолданбаны жаңарту қажет"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Осы белгіше үшін қолданба жаңартылмаған. Оны қолмен жаңартып, осы таңбашаны қайта іске қоса аласыз немесе белгішені өшіріп тастаңыз."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Жаңарту"</string>
@@ -185,17 +183,15 @@
     <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Қайта қосу"</string>
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Сүзгі"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Қате шықты: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
-    <string name="private_space_label" msgid="2359721649407947001">"Жеке бөлме"</string>
+    <string name="private_space_label" msgid="2359721649407947001">"Құпия кеңістік"</string>
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Реттеу немесе ашу үшін түртіңіз"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Жеке"</string>
-    <string name="ps_container_settings" msgid="6059734123353320479">"Жеке бөлме параметрлері"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_settings" msgid="6059734123353320479">"Құпия кеңістік параметрлері"</string>
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Құпия (құлыпталмаған)."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Құпия (құлыптаулы)."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Құлыптау"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Жеке бөлмеге өту"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Қолданбалар орнату"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Орнату"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Қолданбаларды \"Құпия кеңістікке\" орнатыңыз."</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Қосымша мәзір"</string>
 </resources>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index e738e6e..f0c9fd9 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ការណែនាំ"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"សំខាន់"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ព័ត៌មាន និង​ទស្សនាវដ្ដី"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"តំបន់បន្ធូរ​អារម្មណ៍របស់អ្នក"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"កម្សាន្ត"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"សង្គម"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"សុខភាព និង​សម្បទា"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"អាកាសធាតុ"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ណែនាំជូនអ្នក"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ធាតុក្រាហ្វិក <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> នៅខាងស្ដាំ ការស្វែងរក និងជម្រើសនៅខាងឆ្វេង"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ធាតុ​ក្រាហ្វិក #}other{ធាតុ​ក្រាហ្វិក #}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"លុប"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"ព័ត៌មាន​កម្មវិធី"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ដំឡើងជាលក្ខណៈឯកជន"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"លុប​កម្មវិធី"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ដំឡើង"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"កុំណែនាំកម្មវិធី"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"ខ្ទាស់ការ​ព្យាករ"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"កំពុង​ដំឡើង <xliff:g id="NAME">%1$s</xliff:g>, បាន​បញ្ចប់ <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"កំពុងដោនឡូត <xliff:g id="NAME">%1$s</xliff:g> បានបញ្ចប់ <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> កំពុងរង់ចាំការដំឡើង"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ត្រូវបានទុក​ក្នុង​បណ្ណសារ។ សូមចុចដើម្បីទាញយក។"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ត្រូវបានទុក​ក្នុង​បណ្ណសារ។ សូមចុចដើម្បីទាញយក និងស្ដារ។"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"តម្រូវឱ្យមាន​កំណែកម្មវិធីថ្មី"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"កម្មវិធីសម្រាប់​រូបតំណាងនេះ​មិនត្រូវបានដំឡើងកំណែ​ទេ។ អ្នកអាច​ដំឡើងកំណែ​ដោយផ្ទាល់ ដើម្បីបើក​ផ្លូវកាត់នេះឡើងវិញ ឬលុបរូបតំណាងនេះ។"</string>
     <string name="dialog_update" msgid="2178028071796141234">"ដំឡើងកំណែ"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"ចុចដើម្បីរៀបចំ ឬបើក"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ឯកជន"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ការកំណត់ Private Space"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"ឯកជន បានដោះសោ។"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ឯកជន ជាប់សោ។"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"ចាក់សោ"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"ការផ្លាស់ប្ដូរ Private Space"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"ដំឡើង​កម្មវិធី"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ដំឡើង"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"ដំឡើងកម្មវិធីទៅលំហឯកជន"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ម៉ឺនុយបន្ថែម"</string>
 </resources>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 7eeae34..9a81382 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ಸಲಹೆಗಳು"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ಅಗತ್ಯತೆಗಳು"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ಸುದ್ದಿ ಮತ್ತು ನಿಯತಕಾಲಿಕೆಗಳು"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ನೀವು ವಿಶ್ರಾಂತಿ ಪಡೆಯುವ ಸ್ಥಳ"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ಮನರಂಜನೆ"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ಸಾಮಾಜಿಕ"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ಆರೋಗ್ಯ ಮತ್ತು ಫಿಟ್‌ನೆಸ್"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ಹವಾಮಾನ"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ನಿಮಗಾಗಿ ಸೂಚಿಸಲಾಗಿರುವುದು"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ಬಲಭಾಗದಲ್ಲಿ <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ವಿಜೆಟ್‌ಗಳು, ಎಡಭಾಗದಲ್ಲಿ ಹುಡುಕಾಟ ಮತ್ತು ಆಯ್ಕೆಗಳು"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ವಿಜೆಟ್}one{# ವಿಜೆಟ್‌ಗಳು}other{# ವಿಜೆಟ್‌ಗಳು}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"ಆ್ಯಪ್ ಮಾಹಿತಿ"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ಖಾಸಗಿಯಾಗಿ ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ಆ್ಯಪ್‌ ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ಸ್ಥಾಪಿಸಿ"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"ಆ್ಯಪ್ ಅನ್ನು ಸೂಚಿಸಬೇಡಿ"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"ಮುನ್ನೋಟ ಪಿನ್ ಮಾಡಿ"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲಾಗುತ್ತಿದೆ, <xliff:g id="PROGRESS">%2$s</xliff:g> ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ಡೌನ್‌ಲೋಡ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ, <xliff:g id="PROGRESS">%2$s</xliff:g> ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ಸ್ಥಾಪಿಸಲು ಕಾಯಲಾಗುತ್ತಿದೆ"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ಅನ್ನು ಆರ್ಕೈವ್ ಮಾಡಲಾಗಿದೆ. ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ಅನ್ನು ಆರ್ಕೈವ್ ಮಾಡಲಾಗಿದೆ. ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಮತ್ತು ಮರುಸ್ಥಾಪಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"ಆ್ಯಪ್ ಅಪ್‌ಡೇಟ್ ಅಗತ್ಯವಿದೆ"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"ಈ ಐಕಾನ್‌ಗಾಗಿ ಆ್ಯಪ್ ಅನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡಲಾಗಿಲ್ಲ. ಈ ಶಾರ್ಟ್‌ಕಟ್ ಅನ್ನು ಮರು-ಸಕ್ರಿಯಗೊಳಿಸಲು ನೀವು ಹಸ್ತಚಾಲಿತವಾಗಿ ಅಪ್‌ಡೇಟ್ ಮಾಡಬಹುದು ಅಥವಾ ಐಕಾನ್ ಅನ್ನು ತೆಗೆದುಹಾಕಬಹುದು."</string>
     <string name="dialog_update" msgid="2178028071796141234">"ಅಪ್‌ಡೇಟ್ ಮಾಡಿ"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"ಸೆಟಪ್ ಮಾಡಲು ಅಥವಾ ತೆರೆಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ಖಾಸಗಿ"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ಖಾಸಗಿ ಸ್ಪೇಸ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"ಖಾಸಗಿ, ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ಖಾಸಗಿ, ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"ಖಾಸಗಿ ಸ್ಪೇಸ್ ಪರಿವರ್ತನೆಯಾಗುತ್ತಿದೆ"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"ಆ್ಯಪ್‌ಗಳನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"ಆ್ಯಪ್‌ಗಳನ್ನು ಪ್ರೈವೇಟ್ ಸ್ಪೇಸ್‌ನಲ್ಲಿ ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ಓವರ್‌ಫ್ಲೋ"</string>
 </resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 3672434..6ff9d90 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"추천"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"필수"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"뉴스 및 잡지"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"휴식 공간"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"엔터테인먼트"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"소셜"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"건강 및 피트니스"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"날씨"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"추천"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"오른쪽에 <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> 위젯, 왼쪽에 검색 및 옵션"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{위젯 #개}other{위젯 #개}}"</string>
@@ -86,7 +83,8 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"삭제"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"제거"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"앱 정보"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"비공개 설치"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"비공개 스페이스에 설치"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"앱 제거"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"설치"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"앱 제안 받지 않음"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"예상 앱 고정"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> 설치 중, <xliff:g id="PROGRESS">%2$s</xliff:g> 완료"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> 다운로드 중, <xliff:g id="PROGRESS">%2$s</xliff:g> 완료"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> 설치 대기 중"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> 앱이 보관처리되었습니다. 다운로드하려면 탭하세요."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> 앱이 보관처리되었습니다. 탭하여 다운로드하고 복원하세요"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"앱 업데이트 필요"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"바로가기 아이콘의 앱이 업데이트되지 않았습니다. 직접 업데이트하여 앱 바로가기를 다시 사용할 수 있도록 하거나 아이콘을 삭제하세요."</string>
     <string name="dialog_update" msgid="2178028071796141234">"업데이트"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"탭하여 설정 또는 열기"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"비공개"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"비공개 스페이스 설정"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"비공개, 잠금 해제됨."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"비공개, 잠김."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"잠금"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"비공개 스페이스 전환"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"앱 설치"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"설치"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"비공개 스페이스에 앱 설치"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"오버플로"</string>
 </resources>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index c9731a5..44ef720 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Сунуштар"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Эң зарыл параметрлер"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Жаңылыктар жана журналдар"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Чер жазуу"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Көңүл ачуу"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Коомдук тармактар"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Ден соолук жана дене-бойду чыңдоо"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Аба ырайы"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Сизге сунушталат"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> виджеттери оң, ал эми издөө жана параметрлер сол жакта"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Чыгарып салуу"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Колдонмо тууралуу"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Жеке мейкиндикке орнотуу"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Колдонмону чыгарып салуу"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Орнотуу"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Cунушталбасын"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Божомолдонгон колдонмону кадап коюу"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> орнотулууда, <xliff:g id="PROGRESS">%2$s</xliff:g> аткарылды"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> жүктөлүп алынууда, <xliff:g id="PROGRESS">%2$s</xliff:g> аяктады"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> орнотулушу күтүлүүдө"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> архивделди. Жүктөп алуу үчүн тийип коюңуз."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> архивделди. Жүктөп алуу жана калыбына келтирүү үчүн таптаңыз."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Колдонмону жаңыртыңыз"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Бул сүрөтчөнүн колдонмосу жаңыртылган эмес. Ыкчам баскычты кайра иштетүү үчүн аны кол менен жаңыртып же сүрөтчөнү өчүрүп койсоңуз болот."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Жаңыртуу"</string>
@@ -186,16 +184,14 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Чыпкалоо"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Аткарылган жок: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Жеке мейкиндик"</string>
-    <string name="private_space_secondary_label" msgid="9203933341714508907">"Тууралоо же ачуу үчүн таптап коюңуз"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Тууралоо же ачуу үчүн тийип коюңуз"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Жеке"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Жеке мейкиндиктин параметрлери"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Купуя, кулпусу ачык."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Купуя, кулпуланган."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Кулпулоо"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Жеке чөйрөгө өтүү"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Колдонмолорду орнотуу"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Орнотуу"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Колдонмолорду Жеке мейкиндикке орнотуe"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Кошумча меню"</string>
 </resources>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 90e3144..f8ecb7e 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ການແນະນຳ"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ສິ່ງຈຳເປັນ"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ຂ່າວ ແລະ ວາລະສານ"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ພື້ນທີ່ພັກຜ່ອນຂອງທ່ານ"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ຄວາມບັນເທີງ"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ສັງຄົມ"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ສຸຂະພາບ ແລະ ການອອກກຳລັງກາຍ"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ສະພາບອາກາດ"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ແນະນຳສຳລັບທ່ານ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ວິດເຈັດ <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ຢູ່ທາງຂວາ, ການຊອກຫາ ແລະ ຕົວເລືອກຢູ່ທາງຊ້າຍ"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ວິດເຈັດ}other{# ວິດເຈັດ}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"ຖອນ​ການ​ຕິດ​ຕັ້ງ"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"ຂໍ້ມູນແອັບ"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ຕິດຕັ້ງໃນສ່ວນຕົວ"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ຖອນການຕິດຕັ້ງແອັບ"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ຕິດຕັ້ງ"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"ຢ່າແນະນຳແອັບ"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"ປັກໝຸດການຄາດເດົາ"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"ກຳລັງຕິດຕັ້ງ <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> ສຳເລັດແລ້ວ"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ກຳ​ລັງ​ດາວ​ໂຫຼດ, <xliff:g id="PROGRESS">%2$s</xliff:g> ສຳ​ເລັດ"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ກຳ​ລັງ​ລໍ​ຖ້າ​ຕິດ​ຕັ້ງ"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ຖືກເກັບໄວ້ໃນແຟ້ມ. ແຕະເພື່ອດາວໂຫລດ."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ຖືກເກັບໄວ້ໃນແຟ້ມ. ແຕະເພື່ອດາວໂຫຼດ ແລະ ກູ້ຄືນ."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"ຈຳເປັນຕ້ອງອັບເດດແອັບ"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"ບໍ່ໄດ້ອັບເດດແອັບສຳລັບໄອຄອນນີ້. ທ່ານສາມາດອັບເດດເອງໄດ້ເພື່ອເປີດການນຳໃຊ້ທາງລັດນີ້ຄືນໃໝ່ ຫຼື ລຶບໄອຄອນດັ່ງກ່າວອອກ."</string>
     <string name="dialog_update" msgid="2178028071796141234">"ອັບເດດ"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"ແຕະເພື່ອຕັ້ງຄ່າ ຫຼື ເປີດ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ສ່ວນຕົວ"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ການຕັ້ງຄ່າພື້ນທີ່ສ່ວນຕົວ"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"ສ່ວນຕົວ, ປົດລັອກແລ້ວ."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ສ່ວນຕົວ, ລັອກແລ້ວ."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"ລັອກ"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"ການປ່ຽນແປງພື້ນທີ່ສ່ວນຕົວ"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"ຕິດຕັ້ງແອັບ"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ຕິດຕັ້ງ"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"ຕິດຕັ້ງແອັບໄປໃສ່ພື້ນທີ່ສ່ວນບຸກຄົນ"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ການດຳເນີນການເພີ່ມເຕີມ"</string>
 </resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index d763891..b851d55 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Pasiūlymai"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Būtiniausi"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Naujienos ir žurnalai"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Jūsų atsipalaidavimo zona"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Pramogos"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Socialiniai tinklai"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sveikata ir kūno rengyba"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Orai"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Siūloma jums"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> valdikliai dešinėje, paieška ir parinktys kairėje"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# valdiklis}one{# valdiklis}few{# valdikliai}many{# valdiklio}other{# valdiklių}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Pašalinti"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Programos inform."</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Įdiegti privačiai"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Pašalinti programą"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Įdiegti"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Nesiūlyti programos"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Prisegti numatymą"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Įdiegiama: „<xliff:g id="NAME">%1$s</xliff:g>“; baigta: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Atsisiunčiama programa „<xliff:g id="NAME">%1$s</xliff:g>“, <xliff:g id="PROGRESS">%2$s</xliff:g> baigta"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Laukiama, kol bus įdiegta programa „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"„<xliff:g id="NAME">%1$s</xliff:g>“ suarchyvuota. Palieskite, kad atsisiųstumėte."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Programa „<xliff:g id="NAME">%1$s</xliff:g>“ suarchyvuota. Palieskite, jei norite atsisiųsti ir atkurti."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Būtina atnaujinti programą"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Šios piktogramos programa neatnaujinta. Galite patys atnaujinti, kad iš naujo įgalintumėte šį spartųjį klavišą, arba pašalinkite piktogramą."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Atnaujinti"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Palieskite, kad nustatytumėte arba atidarytumėte"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privatus"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Privačios erdvės nustatymai"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privatus, atrakintas."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privatus, užrakintas."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Užrakinti"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Privačios erdvės perkėlimas"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Programų diegimas"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Įdiegti"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Įdiegti programas privačioje erdvėje"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Perpildymas"</string>
 </resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 919158c..2c1ec75 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Ieteikumi"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Produktivitātei"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Ziņas un žurnāli"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Jūsu atpūtas stūrītis"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Izklaide"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sociālie tīkli"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Veselība un fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Laikapstākļi"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Ieteikumi jums"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Pa labi logrīki <xliff:g id="SELECTED_HEADER">%1$s</xliff:g>, pa kreisi meklēšana un iespējas"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# logrīks}zero{# logrīku}one{# logrīks}other{# logrīki}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Atinstalēt"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Par lietotni"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalēt privāti"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Atinstalēt lietotni"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instalēt"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Neieteikt lietotni"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Piespraust prognozēto lietotni"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Notiek lietotnes “<xliff:g id="NAME">%1$s</xliff:g>” instalēšana. Norise: <xliff:g id="PROGRESS">%2$s</xliff:g>."</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Lietotnes <xliff:g id="NAME">%1$s</xliff:g> lejupielāde (<xliff:g id="PROGRESS">%2$s</xliff:g> pabeigti)"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Notiek <xliff:g id="NAME">%1$s</xliff:g> instalēšana"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Lietotne <xliff:g id="NAME">%1$s</xliff:g> ir arhivēta. Pieskarieties, lai lejupielādētu."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Lietotne <xliff:g id="NAME">%1$s</xliff:g> ir arhivēta; lai lejupielādētu un atjaunotu, pieskarieties"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Lietotne ir jāatjaunina"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Šai ikonai paredzētā lietotne nav atjaunināta. Varat to atjaunināt manuāli, lai atkārtoti iespējotu šo saīsni, vai noņemt ikonu."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Atjaunināt"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Pieskarieties, lai iestatītu vai atvērtu"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privātā mape"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Privātās mapes iestatījumi"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privāta un nav bloķēta."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privāta un bloķēta."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Bloķēšana"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Pāriet uz privāto mapi"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Lietotņu instalēšana"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instalēt"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalējiet lietotnes privātajā telpā."</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Pārpilde"</string>
 </resources>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 4f00819..b87c2ce 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Предлози"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Неопходни"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Вести и списанија"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Вашата зона за релаксација"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Забава"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Друштвени"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здравје и фитнес"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Време"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Препорачано за вас"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> виџети оддесно, „Пребарување“ и „Опции“ одлево"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виџет}one{# виџет}other{# виџети}}"</string>
@@ -87,8 +84,9 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Деинсталирај"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Инф. за апликација"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Инстал. во приватен"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Деинсталирај ја апликацијата"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Инсталирај"</string>
-    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Не предлагај апликација"</string>
+    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Не предлагај апл."</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Закачи го предвидувањето"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"инсталирање кратенки"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Овозможува апликацијата да додава кратенки без интервенција на корисникот."</string>
@@ -127,7 +125,7 @@
     <string name="msg_missing_notification_access" msgid="281113995110910548">"За да се прикажуваат „Точки за известување“, вклучете ги известувањата за апликацијата <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="title_change_settings" msgid="1376365968844349552">"Промени ги поставките"</string>
     <string name="notification_dots_service_title" msgid="4284221181793592871">"Прикажувај точки за известување"</string>
-    <string name="developer_options_title" msgid="700788437593726194">"Опции за програмери"</string>
+    <string name="developer_options_title" msgid="700788437593726194">"Програмерски опции"</string>
     <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Додавај икони за апликации на почетниот екран"</string>
     <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"За нови апликации"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Непознато"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> се инсталира, <xliff:g id="PROGRESS">%2$s</xliff:g> завршено"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Се презема <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> завршено"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> чека да се инсталира"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> е архивирана. Допрете за преземање."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Апликацијата <xliff:g id="NAME">%1$s</xliff:g> е архивирана. Допрете за да преземете и вратите."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Потребно е ажурирање на апликацијата"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Апликацијата за оваа икона не е ажурирана. Може да ажурирате рачно за да повторно се овозможи кратенкава или отстранете ја иконата."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Ажурирај"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Допрете за да поставите или отворите"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Приватен простор"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Поставки за „Приватен простор“"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Приватно, отклучено."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Приватно, заклучено."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Заклучи"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Префрлање на „Приватен простор“"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Инсталирајте апликации"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Инсталирајте"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Инсталирање апликации во „Приватен простор“"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Проширено балонче"</string>
 </resources>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 1fc4572..beb2f6f 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"നിർദ്ദേശങ്ങൾ"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ആവശ്യമായവ"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"വാർത്തകളും മാസികകളും"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"നിങ്ങൾക്ക് സുഖപ്രദമായ സ്ഥലം"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"വിനോദം"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"സാമൂഹികം"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ആരോഗ്യവും ശാരീരികക്ഷമതയും"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"കാലാവസ്ഥ"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"നിങ്ങൾക്കായി നിർദ്ദേശിച്ചവ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"വലതുവശത്ത് <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> വിജറ്റുകളും ഇടതുവശത്ത് തിരയൽ, ഓപ്ഷനുകൾ എന്നിവയും"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# വിജറ്റ്}other{# വിജറ്റുകൾ}}"</string>
@@ -87,8 +84,9 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"അൺഇൻസ്റ്റാൾ"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"ആപ്പ് വിവരങ്ങൾ"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"സ്വകാര്യമായി ഇൻസ്റ്റാൾ ചെയ്യൂ"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ആപ്പ് അൺഇൻസ്റ്റാൾ ചെയ്യുക"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ഇൻസ്‌റ്റാൾ ചെയ്യുക"</string>
-    <string name="dismiss_prediction_label" msgid="3357562989568808658">"ആപ്പ് നിർദ്ദേശിക്കരുത്"</string>
+    <string name="dismiss_prediction_label" msgid="3357562989568808658">"ആപ്പ് നിർദ്ദേശിക്കേണ്ട"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"പ്രവചനം പിൻ ചെയ്യുക"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"കുറുക്കുവഴികൾ ഇൻസ്റ്റാളുചെയ്യുക"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"ഉപയോക്തൃ ഇടപെടൽ ഇല്ലാതെ കുറുക്കുവഴികൾ ചേർക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ഇൻസ്‌റ്റാൾ ചെയ്യുന്നു, <xliff:g id="PROGRESS">%2$s</xliff:g> പൂർത്തിയായി"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ഡൗൺലോഡ് ചെയ്യുന്നു, <xliff:g id="PROGRESS">%2$s</xliff:g> പൂർത്തിയായി"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"ഇൻസ്റ്റാൾ ചെയ്യാൻ <xliff:g id="NAME">%1$s</xliff:g> കാക്കുന്നു"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ആർക്കൈവ് ചെയ്തു. ഡൗൺലോഡ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ആർക്കൈവ് ചെയ്തു. ഡൗൺലോഡ് ചെയ്യാനും പുനഃസ്ഥാപിക്കാനും ടാപ്പ് ചെയ്യുക."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"ആപ്പ് അപ്‌ഡേറ്റ് ചെയ്യേണ്ടതുണ്ട്"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"ഈ ഐക്കണിനുള്ള ആപ്പ് അപ്‌ഡേറ്റ് ചെയ്തിട്ടില്ല. ഈ കുറുക്കുവഴി വീണ്ടും പ്രവർത്തനക്ഷമമാക്കാൻ നിങ്ങൾക്ക് നേരിട്ട് അപ്‌ഡേറ്റ് ചെയ്യാം അല്ലെങ്കിൽ ഐക്കൺ നീക്കം ചെയ്യാം."</string>
     <string name="dialog_update" msgid="2178028071796141234">"അപ്ഡേറ്റ് ചെയ്യുക"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"സജ്ജീകരിക്കാനോ തുറക്കാനോ ടാപ്പ് ചെയ്യുക"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"സ്വകാര്യം"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"സ്വകാര്യ സ്‌പേസ് ക്രമീകരണം"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"സ്വകാര്യം, അൺലോക്ക് ചെയ്തിരിക്കുന്നു."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"സ്വകാര്യം, ലോക്ക് ചെയ്തു."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"ലോക്ക് ചെയ്യുക"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"പ്രൈവറ്റ് സ്‌പേസ് ട്രാൻസിഷനിംഗ്"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"ആപ്പുകൾ ഇൻസ്റ്റാൾ ചെയ്യുക"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ഇൻസ്റ്റാൾ ചെയ്യുക"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"സ്വകാര്യ സ്പേസിലേക്ക് ആപ്പുകൾ ഇൻസ്റ്റാൾ ചെയ്യുക"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ഓവർഫ്ലോ"</string>
 </resources>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 33096c0..7b4bce7 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Зөвлөмжүүд"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Зайлшгүй хэрэгтэй"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Мэдээ, сэтгүүлүүд"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Таны амралтын бүс"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Энтертэйнмент"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Сошиал"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Эрүүл мэнд, фитнес"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Цаг агаар"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Танд санал болгосон"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Баруун талд <xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-н виджет, зүүн талд хайлт болон сонгуултууд байна"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Устгах"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Аппын мэдээлэл"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Хувийнхад суулгах"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Аппыг устгах"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Суулгах"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Апп бүү санал болго"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Таамаглалыг бэхлэх"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g>-г суулгаж байна. <xliff:g id="PROGRESS">%2$s</xliff:g> дууссан"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g>-г татаж байна, <xliff:g id="PROGRESS">%2$s</xliff:g> татсан"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> нь суулгахыг хүлээж байна"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g>-г архивласан. Татахын тулд товшино уу."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g>-г архивласан. Татаж, сэргээхийн тулд товшино уу."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Аппын шинэчлэлт шаардлагатай"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Энэ дүрс тэмдгийн аппыг шинэчлээгүй. Та энэ товчлолыг дахин идэвхжүүлэх эсвэл дүрсийг хасахын тулд гараар шинэчлэх боломжтой."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Шинэчлэх"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Тохируулах эсвэл нээхийн тулд товших"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Хувийн"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Private Space-н тохиргоо"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Хувийн, түгжээг тайлсан."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Хувийн, түгжээтэй."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Түгжээ"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Private Space-н шилжилт"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Аппуудыг суулгах"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Суулгах"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Хувийн орон зайд аппууд суулгана уу"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Урт цэс"</string>
 </resources>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 1108c45..8adb240 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"सूचना"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"आवश्यक गोष्टी"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"बातम्‍या आणि मासिके"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"तुमचा आरामदायक झोन"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"मनोरंजन"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"सोशल"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"आरोग्य आणि फिटनेस"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"हवामान"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"तुमच्यासाठी सुचवलेले"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"उजवीकडे <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> विजेट, डावीकडे शोध आणि पर्याय"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}other{# विजेट}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"अनइंस्टॉल करा"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"अ‍ॅप माहिती"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"खाजगीत इंस्टॉल करा"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"अ‍ॅप अनइंस्टॉल करा"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"इंस्टॉल करा"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"ॲप सुचवू नका"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"पूर्वानुमान पिन करा"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> इंस्टॉल करत आहे, <xliff:g id="PROGRESS">%2$s</xliff:g> पूर्ण झाले"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> डाउनलोड होत आहे , <xliff:g id="PROGRESS">%2$s</xliff:g> पूर्ण झाले"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> इंस्टॉल करण्याची प्रतिक्षा करत आहे"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> संग्रहित केले आहे. डाउनलोड करण्यासाठी टॅप करा."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> संग्रहित केले आहे. डाउनलोड करून रिस्टोअर करण्यासाठी टॅप करा."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"अ‍ॅप अपडेट करणे आवश्‍यक आहे"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"या आयकनसाठी अ‍ॅप अपडेट केलेले नाही. हा शॉटकर्ट पुन्हा सुरू करण्यासाठी तुम्ही मॅन्युअली अपडेट करू शकता किंवा आयकन काढून टाका."</string>
     <string name="dialog_update" msgid="2178028071796141234">"अपडेट करा"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"सेट करण्यासाठी किंवा उघडण्यासाठी टॅप करा"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"खाजगी"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"खाजगी स्पेस ची सेटिंग्ज"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"खाजगी, अनलॉक केलेली."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"खाजगी, लॉक केलेली."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"लॉक"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"खाजगी स्पेस वर स्विच करणे"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"अ‍ॅप्स इंस्टॉल करा"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"इंस्टॉल करा"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"अ‍ॅप्स खाजगी स्पेस मध्ये इंस्टॉल करा"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ओव्हरफ्लो"</string>
 </resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index b0d4fcf..f194bc1 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -44,13 +44,10 @@
     <string name="add_to_home_screen" msgid="9168649446635919791">"Tambahkan pada skrin utama"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ditambahkan pada skrin utama"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Cadangan"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Apl Asas"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Penting"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Berita &amp; majalah"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zon Santai Anda"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Hiburan"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosial"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Kesihatan &amp; kecergasan"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Cuaca"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Dicadangkan untuk anda"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widget <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> pada sebelah kanan, carian dan pilihan pada sebelah kiri"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
@@ -86,7 +83,8 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"Alih keluar"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Nyahpasang"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Maklumat apl"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Pasang dalam peribadi"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Pasang dalam persendirian"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Nyahpasang apl"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Pasang"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Jangan cadangkan apl"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Sematkan Ramalan"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> dipasang, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> memuat turun, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> menunggu untuk dipasang"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> diarkibkan. Ketik untuk muat turun."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> diarkibkan. Ketik untuk memuat turun dan memulihkan apl tersebut."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Kemas kini apl diperlukan"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Apl untuk ikon ini tidak dikemas kini. Anda boleh mengemas kini secara manual untuk mendayakan semula pintasan atau mengalih keluar ikon."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Kemas kini"</string>
@@ -187,15 +185,13 @@
     <string name="remote_action_failed" msgid="1383965239183576790">"Gagal: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Ruang privasi"</string>
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Ketik untuk menyediakan atau membuka"</string>
-    <string name="ps_container_title" msgid="4391796149519594205">"Peribadi"</string>
+    <string name="ps_container_title" msgid="4391796149519594205">"Persendirian"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Tetapan Ruang Peribadi"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Peribadi, tidak berkunci."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Peribadi, dikunci."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Kunci"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Peralihan Ruang Peribadi"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Pasang apl"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Pasang"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Pasang apl pada Ruang Peribadi"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Limpahan"</string>
 </resources>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 386965f..7dc3b5a 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"အကြံပြုချက်"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"မရှိမဖြစ်များ"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"သတင်းနှင့် မဂ္ဂဇင်း"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"သင်အနားယူသောနေရာ"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ဖျော်ဖြေရေး"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"လူမှုရေး"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ကျန်းမာကြံ့ခိုင်ရေး"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"မိုးလေဝသ"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"သင့်အတွက် အကြံပြုထားသည်များ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ဝိဂျက်များသည် ညာဘက်တွင်ရှိပြီး ရှာဖွေမှုနှင့် ရွေးစရာများသည် ဘယ်ဘက်တွင်ရှိသည်"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ဝိဂျက် # ခု}other{ဝိဂျက် # ခု}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"ဖယ်ရှားရန်"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"အက်ပ်အချက်အလက်"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"သီးသန့်တွင် ထည့်သွင်းရန်"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"အက်ပ်ကို ဖယ်ရှားရန်"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ထည့်သွင်းရန်"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"အက်ပ်အကြံမပြုပါနှင့်"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"ခန့်မှန်းချက်ကို ပင်ထိုးရန်"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ကို ထည့်သွင်းနေသည်၊ <xliff:g id="PROGRESS">%2$s</xliff:g> ပြီးပါပြီ"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ဒေါင်းလုဒ်လုပ်နေသည်၊ <xliff:g id="PROGRESS">%2$s</xliff:g> ပြီးပါပြီ"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ကိုထည့်သွင်းရန်စောင့်နေသည်"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ကို သိမ်းထားသည်။ ဒေါင်းလုဒ်လုပ်ရန် တို့ပါ။"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ကို သိမ်းထားသည်။ ဒေါင်းလုဒ်လုပ်ပြီး ပြန်ယူရန် တို့ပါ။"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"အက်ပ်ကို အပ်ဒိတ်လုပ်ရန် လိုအပ်သည်"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"ဤသင်္ကေတအတွက် အက်ပ်ကို အပ်ဒိတ်လုပ်မထားပါ။ ဤဖြတ်လမ်းလင့်ခ်ကို ပြန်ဖွင့်ရန် ကိုယ်တိုင်အပ်ဒိတ်လုပ်နိုင်သည် (သို့) သင်္ကေတကို ဖယ်ရှားနိုင်သည်။"</string>
     <string name="dialog_update" msgid="2178028071796141234">"အပ်ဒိတ်လုပ်ရန်"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"စနစ်ထည့်သွင်းရန် (သို့) ဖွင့်ရန် တို့ပါ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"သီးသန့်"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"သီးသန့်ချတ်ခန်း ဆက်တင်များ"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"သီးသန့် လော့ခ်ဖွင့်ထားသည်။"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"သီးသန့် လော့ခ်ချထားသည်။"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"လော့ခ်ချခြင်း"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"သီးသန့်ချတ်ခန်း အပြောင်းအလဲ"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"အက်ပ်ထည့်ခြင်း"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ထည့်သွင်းရန်"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"‘သီးသန့်နေရာ’ တွင် အက်ပ်များ ထည့်သွင်းနိုင်သည်"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"မီနူးအပို"</string>
 </resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 86699de..856ce9f 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Forslag"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Anbefalt"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nyheter og tidsskrifter"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Avslappingssonen din"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Underholdning"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosialt"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Kropp og helse"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Været"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Foreslått for deg"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> moduler til høyre, søk og alternativer til venstre"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# modul}other{# moduler}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Avinstaller"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Info om appen"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installer privat"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Avinstaller appen"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Installer"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ikke foreslå app"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Fest forslaget"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installerer, <xliff:g id="PROGRESS">%2$s</xliff:g> er fullført"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Laster ned <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> er fullført"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Venter på å installere <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> er arkivert. Trykk for å laste den ned."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> er arkivert. Trykk for å laste ned og gjenopprette."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Appen må oppdateres"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Appen for dette ikonet er ikke oppdatert. Du kan oppdatere manuelt for å aktivere denne snarveien igjen, eller du kan fjerne ikonet."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Oppdater"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Trykk for å konfigurere eller åpne"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privat"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Innstillinger for Private Space"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privat (ulåst)."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privat (låst)."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Lås"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Private Space-overgang"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Installer apper"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Installer"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Installer apper i privat område"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overflyt"</string>
 </resources>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 6e8727b..2197a8b 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"सुझावहरू"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"अत्यावश्यक कुराहरू"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"समाचार तथा पत्रपत्रिकाहरू"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"तपाईंको Chill Zone"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"मनोरञ्जन"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"सोसल मिडिया"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"स्वास्थ्य तथा तन्दुरुस्ती"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"मौसम"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"तपाईंका लागि सिफारिस गरिएका"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"दायाँ भागमा <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> विजेटहरू, बायाँ भागमा खोज र विकल्पहरू"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}other{# वटा विजेट}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"अनइन्स्टल गर्नुहोस्"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"एपसम्बन्धी जानकारी"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"निजी प्रोफाइलमा इन्स्टल गर्नुहोस्"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"एप अनइन्स्टल गर्नुहोस्"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"स्थापना गर्नुहोस्"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"एप सिफारिस नगर्नुहोस्"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"सिफारिस गरिएको एप पिन गर्नुहोस्"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> इन्स्टल गरिँदै छ, <xliff:g id="PROGRESS">%2$s</xliff:g> पूरा भयो"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> डाउनलोड गर्दै, <xliff:g id="PROGRESS">%2$s</xliff:g> सम्पन्‍न"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> स्थापना गर्न प्रतीक्षा गर्दै"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> अभिलेखमा राखिएको छ। डाउनलोड गर्न ट्याप गर्नुहोस्।"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> अभिलेखमा राखिएको छ। डाउनलोड गरी रिस्टोर गर्न ट्याप गर्नुहोस्।"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"एप अपडेट गरिनु पर्छ"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"यो आइकनले जनाउने एप अपडेट गरिएको छैन। तपाईं यो सर्टकट फेरि अन गर्न म्यानुअल रूपमा अपडेट गर्न सक्नुहुन्छ वा आइकन नै हटाउनुहोस्।"</string>
     <string name="dialog_update" msgid="2178028071796141234">"अपडेट गर्नुहोस्"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"सेटअप गर्न वा खोल्न ट्याप गर्नुहोस्"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"निजी"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"निजी स्पेससम्बन्धी सेटिङ"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"निजी, अनलक गरिएको।"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"निजी, लक गरिएको।"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"लक गर्नुहोस्"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"निजी स्पेस ट्रान्जिसन गरिँदै छ"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"एपहरू इन्स्टल गर्नुहोस्"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"इन्स्टल गर्नुहोस्"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"निजी स्पेसमा एपहरू इन्स्टल गर्नुहोस्"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ओभरफ्लो"</string>
 </resources>
diff --git a/res/values-night-v34/colors.xml b/res/values-night-v34/colors.xml
new file mode 100644
index 0000000..af28119
--- /dev/null
+++ b/res/values-night-v34/colors.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2024, 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  xmlns:android="http://schemas.android.com/apk/res/android">
+    <color name="widget_picker_secondary_surface_color_dark">
+        @android:color/system_surface_bright_dark</color>
+    <color name="widget_picker_header_app_title_color_dark">
+        @android:color/system_on_surface_dark</color>
+    <color name="widget_picker_header_app_subtitle_color_dark">
+        @android:color/system_on_surface_variant_dark</color>
+    <color name="widget_cell_title_color_dark">
+        @android:color/system_on_surface_dark</color>
+    <color name="widget_cell_subtitle_color_dark">
+        @android:color/system_on_surface_variant_dark</color>
+</resources>
diff --git a/res/values-night/styles.xml b/res/values-night/styles.xml
index 613c2e9..c95722f 100644
--- a/res/values-night/styles.xml
+++ b/res/values-night/styles.xml
@@ -21,6 +21,9 @@
     <style name="AddItemActivityTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
         <item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item>
         <item name="android:windowTranslucentStatus">true</item>
+        <!-- Add the dim background here, rather than in the activity layout as the window slides
+             in from the bottom, and we don't want the scrim to slide. -->
+        <item name="android:backgroundDimEnabled">true</item>
     </style>
 
     <style name="WidgetPickerActivityTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 675a1b5..bd4508c 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggesties"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nieuws en tijdschriften"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Je chillzone"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sociaal"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Gezondheid en fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weer"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Voorgesteld voor jou"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-widgets aan de rechterkant, zoeken en opties aan de linkerkant"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deïnstalleren"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"App-info"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Privé installeren"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"App verwijderen"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Installeren"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Geen app voorstellen"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Vastzetvoorspelling"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installeren, <xliff:g id="PROGRESS">%2$s</xliff:g> voltooid"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> wordt gedownload, <xliff:g id="PROGRESS">%2$s</xliff:g> voltooid"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> wacht op installatie"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> is gearchiveerd Tik om te downloaden."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> is gearchiveerd. Tik om te downloaden en te herstellen."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"App-update vereist"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"De app voor dit icoon is niet geüpdatet. Je kunt handmatig updaten om deze snelkoppeling weer aan te zetten of het icoon verwijderen."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Updaten"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Tik om in te stellen of te openen"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privé"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Instellingen voor privéruimte"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privé, niet vergrendeld."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privé, vergrendeld."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Vergrendelen"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Overschakelen naar privéruimte"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Apps installeren"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Installeren"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Apps installeren in privégedeelte"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overloop"</string>
 </resources>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 5b37919..e2035a2 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ପରାମର୍ଶଗୁଡ଼ିକ"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ଅତ୍ୟାବଶ୍ୟକୀୟ"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ନ୍ୟୁଜ ଓ ମାଗାଜିନ"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ଆପଣଙ୍କ ଚିଲ ଜୋନ"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ମନୋରଞ୍ଜନ"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ସୋସିଆଲ"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ସ୍ୱାସ୍ଥ୍ୟ ଓ ଫିଟନେସ"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ପାଣିପାଗ"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ଆପଣଙ୍କ ପାଇଁ ପ୍ରସ୍ତାବିତ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ଡାହାଣରେ <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ୱିଜେଟଗୁଡ଼ିକ ଅଛି, ବାମରେ ସର୍ଚ୍ଚ ଓ ବିକଳ୍ପଗୁଡ଼ିକ ଅଛି"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ୱିଜେଟ}other{# ୱିଜେଟ}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"ଅନଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"ଆପ ସୂଚନା"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ପ୍ରାଇଭେଟରେ ଇନଷ୍ଟଲ କର"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ଆପ ଅନଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"ଆପ ପରାମର୍ଶ ଦିଅନ୍ତୁ ନାହିଁ"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"ପୂର୍ବାନୁମାନକୁ ପିନ୍ କରନ୍ତୁ"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ଇନଷ୍ଟଲ୍ କରାଯାଉଛି, <xliff:g id="PROGRESS">%2$s</xliff:g> ସମ୍ପୂର୍ଣ୍ଣ ହୋଇଛି"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ଡାଉନଲୋଡ୍‌ ହେଉଛି, <xliff:g id="PROGRESS">%2$s</xliff:g> ସମ୍ପୂର୍ଣ୍ଣ"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ଇନଷ୍ଟଲ୍‌ ହେବାକୁ ଅପେକ୍ଷା କରିଛି"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g>କୁ ଆର୍କାଇଭ କରାଯାଇଛି। ଡାଉନଲୋଡ୍ କରିବା ପାଇଁ ଟାପ୍‌ କରନ୍ତୁ।"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g>କୁ ଆର୍କାଇଭ କରାଯାଇଛି। ଡାଉନଲୋଡ ଏବଂ ରିଷ୍ଟୋର କରିବା ପାଇଁ ଟାପ କରନ୍ତୁ।"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"ଆପକୁ ଅପଡେଟ କରିବା ଆବଶ୍ୟକ"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"ଏହି ଆଇକନ ପାଇଁ ଆପକୁ ଅପଡେଟ କରାଯାଇନାହିଁ। ଏହି ସର୍ଟକଟକୁ ପୁଣି-ସକ୍ଷମ କରିବା ପାଇଁ ଆପଣ ମାନୁଆଲୀ ଅପଡେଟ କରିପାରିବେ କିମ୍ବା ଆଇକନଟିକୁ କାଢ଼ି ଦେଇପାରିବେ।"</string>
     <string name="dialog_update" msgid="2178028071796141234">"ଅପଡେଟ କରନ୍ତୁ"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"ସେଟ ଅପ କରିବା କିମ୍ବା ଖୋଲିବାକୁ ଟାପ କରନ୍ତୁ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ପ୍ରାଇଭେଟ"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ପ୍ରାଇଭେଟ ସ୍ପେସ ସେଟିଂସ"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"ପ୍ରାଇଭେଟ, ଅନଲକ କରାଯାଇଛି।"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ପ୍ରାଇଭେଟ, ଲକ କରାଯାଇଛି।"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"ଲକ କରନ୍ତୁ"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"ପ୍ରାଇଭେଟ ସ୍ପେସ ଟ୍ରାଞ୍ଜିସନିଂ"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"ଆପ୍ ଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"ଆପ୍ସକୁ ପ୍ରାଇଭେଟ ସ୍ପେସରେ ଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ଓଭରଫ୍ଲୋ"</string>
 </resources>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 911b702..f412820 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ਸੁਝਾਅ"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ਲੋੜੀਂਦੀਆਂ"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ਖਬਰਾਂ ਅਤੇ ਰਸਾਲੇ"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ਤੁਹਾਡੇ ਲਈ ਸਕੂਨਮਈ ਖੇਤਰ"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ਮਨੋਰੰਜਨ"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ਸੋਸ਼ਲ"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ਸਿਹਤ ਅਤੇ ਫਿੱਟਨੈੱਸ"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ਮੌਸਮ"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ਤੁਹਾਡੇ ਲਈ ਸੁਝਾਅ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ਵਿਜੇਟ ਸੱਜੇ ਪਾਸੇ ਹਨ, ਖੋਜ ਵਿਜੇਟ ਅਤੇ ਹੋਰ ਵਿਕਲਪ ਖੱਬੇ ਪਾਸੇ ਹਨ"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ਵਿਜੇਟ}one{# ਵਿਜੇਟ}other{# ਵਿਜੇਟ}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"ਅਣਸਥਾਪਤ ਕਰੋ"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"ਐਪ ਜਾਣਕਾਰੀ"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ਨਿੱਜੀ ਵਜੋਂ ਸਥਾਪਤ ਕਰੋ"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ਐਪ ਅਣਸਥਾਪਤ ਕਰੋ"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ਸਥਾਪਤ ਕਰੋ"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"ਐਪ ਦਾ ਸੁਝਾਅ ਨਾ ਦਿਓ"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"ਪੂਰਵ-ਅਨੁਮਾਨ ਪਿੰਨ ਕਰੋ"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ਨੂੰ ਸਥਾਪਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ, <xliff:g id="PROGRESS">%2$s</xliff:g> ਪੂਰਾ ਹੋਇਆ"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ਡਾਉਨਲੋਡ ਹੋਰ ਰਿਹਾ ਹੈ, <xliff:g id="PROGRESS">%2$s</xliff:g> ਸੰਪੂਰਣ"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ਸਥਾਪਤ ਕਰਨ ਦੀ ਉਡੀਕ ਕਰ ਰਿਹਾ ਹੈ"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ਪੁਰਾਲੇਖਬੱਧ ਹੈ। ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ਪੁਰਾਲੇਖਬੱਧ ਹੈ। ਡਾਊਨਲੋਡ ਅਤੇ ਮੁੜ-ਬਹਾਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"ਐਪ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"ਇਸ ਪ੍ਰਤੀਕ ਲਈ ਐਪ ਨੂੰ ਅੱਪਡੇਟ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਇਸ ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਮੁੜ-ਚਾਲੂ ਕਰਨ ਜਾਂ ਪ੍ਰਤੀਕ ਨੂੰ ਹਟਾਉਣ ਲਈ ਤੁਸੀਂ ਹੱਥੀਂ ਅੱਪਡੇਟ ਕਰ ਸਕਦੇ ਹੋ।"</string>
     <string name="dialog_update" msgid="2178028071796141234">"ਅੱਪਡੇਟ ਕਰੋ"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"ਸੈੱਟਅੱਪ ਕਰਨ ਜਾਂ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ਨਿੱਜੀ"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ਨਿੱਜੀ ਸਪੇਸ ਸੰਬੰਧੀ ਸੈਟਿੰਗਾਂ"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"ਨਿੱਜੀ, ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ।"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ਨਿੱਜੀ, ਲਾਕ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"ਲਾਕ ਕਰੋ"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"ਨਿੱਜੀ ਸਪੇਸ ਨੂੰ ਤਬਦੀਲ ਕਰਨਾ"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"ਐਪਾਂ ਸਥਾਪਤ ਕਰੋ"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ਸਥਾਪਤ ਕਰੋ"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"ਪ੍ਰਾਈਵੇਟ ਸਪੇਸ ਵਿੱਚ ਐਪਾਂ ਸਥਾਪਤ ਕਰੋ"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ਓਵਰਫ਼ਲੋ"</string>
 </resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 578127d..a97d56e 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -44,13 +44,10 @@
     <string name="add_to_home_screen" msgid="9168649446635919791">"Dodaj do ekranu głównego"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widżet <xliff:g id="WIDGET_NAME">%1$s</xliff:g> został dodany do ekranu głównego"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestie"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Niezbędne"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Najbardziej przydatne"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Wiadomości i czasopisma"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Strefa relaksu"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Rozrywka"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Społecznościowe"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdrowie i fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Pogoda"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Proponowane dla Ciebie"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widżety (<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>) po prawej, wyszukiwanie i opcje po lewej"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widżet}few{# widżety}many{# widżetów}other{# widżetu}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Odinstaluj"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"O aplikacji"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Zainstaluj prywatnie"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Odinstaluj aplikację"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Zainstaluj"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Nie proponuj aplikacji"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Przypnij podpowiedź"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Instaluję aplikację <xliff:g id="NAME">%1$s</xliff:g>, postęp: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Pobieranie elementu <xliff:g id="NAME">%1$s</xliff:g>, ukończono: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> oczekuje na instalację"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Aplikacja <xliff:g id="NAME">%1$s</xliff:g> jest zarchiwizowana. Kliknij, aby ją pobrać."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Aplikacja <xliff:g id="NAME">%1$s</xliff:g> jest zarchiwizowana. Kliknij, aby ją pobrać i przywrócić."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Wymagana aktualizacja aplikacji"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Aplikacja z tą ikoną nie jest aktualizowana. Możesz zaktualizować ją ręcznie, aby ponownie uruchomić ten skrót, lub usunąć ikonę."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Aktualizuj"</string>
@@ -185,17 +183,15 @@
     <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Cofnij wstrzymywanie"</string>
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtruj"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Niepowodzenie: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
-    <string name="private_space_label" msgid="2359721649407947001">"Obszar prywatny"</string>
+    <string name="private_space_label" msgid="2359721649407947001">"Przestrzeń prywatna"</string>
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Kliknij, aby skonfigurować lub otworzyć"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Prywatne"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Ustawienia obszaru prywatnego"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Prywatna, bez blokady."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Prywatna, zablokowana."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Zablokuj"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Przenoszenie obszaru prywatnego"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instaluj aplikacje"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Zainstaluj"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Zainstaluj aplikacje w przestrzeni prywatnej"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Rozwiń menu"</string>
 </resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 9dde360..3257915 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestões"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essenciais"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Notícias e revistas"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"A sua zona de relaxamento"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretenimento"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Redes sociais"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Saúde e fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Meteorologia"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugestões para si"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> à direita, pesquisa e opções à esquerda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalar"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Info. da app"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalar em privado"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalar app"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instalar"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Não sugerir app"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Fixar previsão"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"A instalar <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"A transferir o <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"A aguardar a instalação do <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"A app <xliff:g id="NAME">%1$s</xliff:g> está arquivada. Toque para transferir."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"A app <xliff:g id="NAME">%1$s</xliff:g> está arquivada. Toque para transferir e restaurar."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Atualização da app necessária"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"A app deste ícone não está atualizada. Pode atualizar manualmente para reativar este atalho ou remover o ícone."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Atualizar"</string>
@@ -186,16 +184,14 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrar"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Falhou: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Espaço privado"</string>
-    <string name="private_space_secondary_label" msgid="9203933341714508907">"Tocar para configurar ou abrir"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Toque para configurar ou abrir"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privado"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Definições do espaço privado"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privado, desbloqueado."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privado, bloqueado."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Bloquear"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Transição do espaço privado"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instalar apps"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instalar"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instale apps no espaço privado"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Menu adicional"</string>
 </resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 7932424..27aa1ee 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestões"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essenciais"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Notícias e revistas"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Sua zona de relaxamento"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretenimento"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Saúde e bem-estar"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Clima"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugestões para você"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets da <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> à direita, pesquisa e opções à esquerda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalar"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Informações do app"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalar em particular"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalar app"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instalar"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Não sugerir esse app"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Fixar previsão"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Instalando <xliff:g id="NAME">%1$s</xliff:g>. <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Fazendo download de <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Aguardando instalação de <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"O app <xliff:g id="NAME">%1$s</xliff:g> está arquivado. Toque para baixar."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"O app <xliff:g id="NAME">%1$s</xliff:g> está arquivado. Toque para baixar e restaurar."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Atualização obrigatória do app"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"O app desse ícone não está atualizado. Você pode remover o ícone ou atualizar o app manualmente para reativar esse atalho."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Atualizar"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Toque para configurar ou abrir"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Particular"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Configurações do Espaço particular"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privada, desbloqueado."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privada, bloqueado."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Bloquear"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Espaço particular em transição"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instalar apps"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instalar"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalar apps no espaço privado"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Balão flutuante"</string>
 </resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 13ae5e3..959bb1c 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestii"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Esențiale"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Știri și reviste"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona de relaxare"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Divertisment"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Rețele sociale"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sănătate și fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Meteo"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugerate pentru tine"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgeturi pentru <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> în dreapta, căutare și opțiuni în stânga"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}few{# widgeturi}other{# de widgeturi}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Dezinstalează"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Informații despre aplicații"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalează în privat"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Dezinstalează aplicația"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instalează"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Nu sugera aplicația"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Fixează predicția"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> se instalează, <xliff:g id="PROGRESS">%2$s</xliff:g> finalizat"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> se descarcă (finalizat <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> așteaptă instalarea"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> s-a arhivat. Atinge pentru a descărca."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> s-a arhivat. Atinge pentru a descărca și restabili."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Este necesară actualizarea aplicației"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Aplicația pentru această pictogramă nu este actualizată. Poți să actualizezi manual ca să reactivezi comanda rapidă sau să elimini pictograma."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Actualizează"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Atinge pentru a configura sau a deschide"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privat"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Setări spațiu privat"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privat, deblocat."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privat, blocat."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Blochează"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Tranziție pentru spațiul privat"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instalează aplicații"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instalează"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalează aplicații în Spațiul privat"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Suplimentar"</string>
 </resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 4df4df0..96048eb 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Подсказки"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Основное"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Новости и журналы"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Развлечение и общение"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Развлечения"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Общение"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здоровье и спорт"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Погода"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Рекомендации"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Виджеты приложения \"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>\" находятся справа, а панель поиска и настройки – слева"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}one{# виджет}few{# виджета}many{# виджетов}other{# виджета}}"</string>
@@ -86,7 +83,8 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"Убрать"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Удалить"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"О приложении"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Приватная установка"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Частная установка"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Удалить приложение"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Установить"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Не рекомендовать"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Закрепить рекомендацию"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Установка приложения \"<xliff:g id="NAME">%1$s</xliff:g>\" (выполнено <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Скачивается \"<xliff:g id="NAME">%1$s</xliff:g>\" (<xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Ожидание установки \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Приложение \"<xliff:g id="NAME">%1$s</xliff:g>\" находится в архиве. Нажмите, чтобы скачать"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Приложение \"<xliff:g id="NAME">%1$s</xliff:g>\" находится в архиве. Нажмите, чтобы скачать его и восстановить"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Обновите приложение"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Эта версия приложения устарела. Обновите его вручную, чтобы снова пользоваться ярлыком, или удалите значок."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Обновить"</string>
@@ -185,17 +183,15 @@
     <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Возобновить"</string>
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Фильтр"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Не удалось выполнить действие (<xliff:g id="WHAT">%1$s</xliff:g>)."</string>
-    <string name="private_space_label" msgid="2359721649407947001">"Личное пространство"</string>
+    <string name="private_space_label" msgid="2359721649407947001">"Частное пространство"</string>
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Нажмите, чтобы настроить или открыть"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Доступно только вам"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Настройки личного пространства"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Личное, разблокировано."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Личное, заблокировано."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Блокировка"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Переход к личному пространству"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Установить приложения"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Установить"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Установить приложения в личном пространстве"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Дополнительное меню"</string>
 </resources>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 61ca4de..d5a0114 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"යෝජනා"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"අත්‍යවශ්‍යාංග"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"පුවත් සහ සඟරා"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ඔබේ නිවුණු කලාපය"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"විනෝදාස්වාදය"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"සමාජයීය"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"සෞඛ්‍යය සහ යෝග්‍යතාව"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"කාලගුණ"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ඔබ සඳහා යෝජිත"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"දකුණේ <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> විජට්, වමේ සෙවීම සහ විකල්ප"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{විජට් #}one{විජට් #}other{විජට් #}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"අස්ථාපනය කරන්න"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"යෙදුම් තොරතුරු"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"පෞද්ගලිකව ස්ථාපනය කරන්න"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"යෙදුම අස්ථාපනය කරන්න"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ස්ථාපනය කරන්න"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"යෙදුම යෝජනා නොකරන්න"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"පුරෝකථනය අමුණන්න"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ස්ථාපනය කරමින්, <xliff:g id="PROGRESS">%2$s</xliff:g> සම්පූර්ණයි"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> බාගත කරමින්, <xliff:g id="PROGRESS">%2$s</xliff:g> සම්පූර්ණයි"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ස්ථාපනය කිරීමට බලා සිටිමින්"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ලේඛනාරක්ෂණය කර ඇත. බාගැනීමට තට්ටු කරන්න"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> සංරක්‍ෂිතයි. බා ගෙන ප්‍රතිසාධන කිරීමට තට්ටු කරන්න."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"යෙදුම් යාවත්කාලීනයක් අවශ්‍යයි"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"මෙම නිරූපකය සඳහා යෙදුම යාවත්කාලීන කර නැත. ඔබට මෙම කෙටි මඟ යළි සබල කිරීමට හෝ නිරූපකය ඉවත් කිරීමට හස්තීයව යාවත්කාලීන කළ හැකිය."</string>
     <string name="dialog_update" msgid="2178028071796141234">"යාවත්කාලීන කරන්න"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"පිහිටුවීමට හෝ විවෘත කිරීමට තට්ටු කරන්න"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"පෞද්ගලික"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"පෞද්ගලික අවකාශ සැකසීම්"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"පුද්ගලි, අගුලු හරින ලදි."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"පුද්ගලික, අගුලු දමන ලදි."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"අගුළු දමන්න"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"පෞද්ගලික අවකාශ සංක්‍රමණය"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"යෙදුම් ස්ථාපනය කරන්න"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ස්ථාපන කරන්න"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"පෞද්ගලික අවකාශයට යෙදුම් ස්ථාපනය කරන්න"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"පිටාර යාම"</string>
 </resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 2711ec9..3d12a65 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Návrhy"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Všetko dôležité"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Noviny a časopisy"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaša komfortná zóna"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zábava"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sociálne siete"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravie a kondícia"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Počasie"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Navrhnuté pre vás"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Miniaplikácie <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vpravo, vyhľadávanie a možnosti vľavo"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# miniaplikácia}few{# miniaplikácie}many{# widgets}other{# miniaplikácií}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Odinštalovať"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Info o aplikácii"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Inštalovať v súkromí"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Odinštalovať aplikáciu"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Inštalovať"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Nenavrhovať aplikáciu"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Pripnúť predpoveď"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Inštaluje sa <xliff:g id="NAME">%1$s</xliff:g>. Dokončené: <xliff:g id="PROGRESS">%2$s</xliff:g>."</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Sťahuje sa aplikácia <xliff:g id="NAME">%1$s</xliff:g>. Stiahnuté: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Aplikácia <xliff:g id="NAME">%1$s</xliff:g> čaká na inštaláciu"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Aplikácia <xliff:g id="NAME">%1$s</xliff:g> je archivovaná. Stiahnite klepnutím."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Aplikácia <xliff:g id="NAME">%1$s</xliff:g> je archivovaná. Klepnutím ju stiahnite a obnovte."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Vyžaduje sa aktualizácia aplikácie"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Aplikácia, ktorú zastupuje táto ikona, nie je aktualizovaná. Môžete ju ručne aktualizovať, aby odkaz znova fungoval, prípadne môžete ikonu odstrániť."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Aktualizovať"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Klepnutím nastavte alebo otvorte"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Súkromné"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Nastavenia súkromného priestoru"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Súkromné, odomknuté."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Súkromné, uzamknuté."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Uzamknúť"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Prechod súkromného priestoru"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Inštalovať aplikácie"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Inštalovať"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Inštalácia aplikácií v súkromnom priestore"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Rozšírená ponuka"</string>
 </resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 7e13ac8..070ccbb 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Predlogi"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Osnove"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Novice in revije"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaš kotiček za sprostitev"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Razvedrilo"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Družbeno"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravje in fitnes"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vreme"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Predlagano za vas"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Pripomočki <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> na desni, iskanje in možnosti na levi"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# pripomoček}one{# pripomoček}two{# pripomočka}few{# pripomočki}other{# pripomočkov}}"</string>
@@ -87,8 +84,9 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Odmesti"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Podatki o aplikaciji"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Namesti v zasebno"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Odmesti aplikacijo"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Namesti"</string>
-    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne predlagaj aplikacij"</string>
+    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne predlagaj"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Predvidevanje pripenjanja"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"namestitev bližnjic"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Aplikaciji dovoli dodajanje bližnjic brez posredovanja uporabnika."</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> se namešča, dokončano: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Prenašanje aplikacije <xliff:g id="NAME">%1$s</xliff:g>; preneseno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> čaka na namestitev"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> je arhivirana. Dotaknite se za prenos."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> je arhivirana. Dotaknite se za prenos in obnovitev."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Zahtevana je posodobitev aplikacije"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Aplikacija za to ikono ni posodobljena. Lahko jo ročno posodobite, da znova omogočite to bližnjico, ali pa odstranite ikono."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Posodobi"</string>
@@ -186,16 +184,14 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtriranje"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Ni uspelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Zasebni prostor"</string>
-    <string name="private_space_secondary_label" msgid="9203933341714508907">"Dotaknite se, da nastavite ali odprete"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Dotaknite se, da ga nastavite ali odprete"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Zasebno"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Nastavitve zasebnega prostora"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Zasebno, odklenjeno."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Zasebno, zaklenjeno."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Zaklepanje"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Preklapljanje zasebnega prostora"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Nameščanje aplikacij"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Namestitev"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Nameščanje aplikacij v zasebni prostor"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Oblaček z dodatnimi elementi"</string>
 </resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 5f379447..df2395a 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugjerime"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Thelbësoret"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Lajme dhe revista"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona jote e qetësisë"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Argëtim"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Rrjetet sociale"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Shëndet dhe fitnes"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Moti"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugjeruar për ty"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Miniaplikacionet e <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> në të djathtë, kërkimi dhe opsionet në të majtë"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# miniaplikacion}other{# miniaplikacione}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Çinstalo"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Info mbi aplikacionin"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalo në private"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Çinstalo aplikacionin"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instalo"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Mos sugjero aplikacion"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Gozhdo parashikimin"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> po instalohet, <xliff:g id="PROGRESS">%2$s</xliff:g> i përfunduar"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> po shkarkohet, <xliff:g id="PROGRESS">%2$s</xliff:g> të përfunduara"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> po pret të instalohet"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> është arkivuar. Trokit për të shkarkuar."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> është arkivuar. Trokit për ta shkarkuar dhe restauruar."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Kërkohet përditësimi i aplikacionit"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Aplikacioni për këtë ikonë nuk është përditësuar. Mund ta përditësosh manualisht për të riaktivizuar këtë shkurtore ose hiq ikonën."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Përditëso"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Trokit për të konfiguruar ose për të hapur"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Private"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Cilësimet e \"Hapësirës private\""</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Private, e shkyçur."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Private, e kyçur."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Kyç"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Kalimi te \"Hapësira private\""</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Instalo aplikacionet"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Instalo"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalo aplikacionet në hapësirën private"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Tejkalimi"</string>
 </resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 4a71666..0721730 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -44,13 +44,10 @@
     <string name="add_to_home_screen" msgid="9168649446635919791">"Додај на почетни екран"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Додали сте виџет <xliff:g id="WIDGET_NAME">%1$s</xliff:g> на почетни екран"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Предлози"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Неопходне апликације"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Основно"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Новости и часописи"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Зона за опуштање"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Забава"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Друштвене мреже"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здравље и фитнес"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Време"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Предложено за вас"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Виџети <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> са десне стране, претрага и опције са леве стране"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виџет}one{# виџет}few{# виџета}other{# виџета}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Деинсталирај"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Подаци о апликацији"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Инсталирај на приватни"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Деинсталирајте апликацију"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Инсталирај"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Не предлажи апликацију"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Закачи предвиђање"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> се инсталира, <xliff:g id="PROGRESS">%2$s</xliff:g> готово"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> се преузима, завршено је <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> чека на инсталирање"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Апликација <xliff:g id="NAME">%1$s</xliff:g> је архивирана. Додирните да бисте је преузели."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Апликација <xliff:g id="NAME">%1$s</xliff:g> је архивирана. Додирните да бисте је преузели и вратили."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Треба да ажурирате апликацију"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Апликација за ову икону није ажурирана. Можете да је ручно ажурирате да бисте поново омогућили ову пречицу или уклоните икону."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Ажурирај"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Додирните да бисте подесили или отворили"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Приватно"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Подешавања приватног простора"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Приватно, откључано."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Приватно, закључано."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Закључавање"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Пренос приватног простора"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Инсталирајте апликације"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Инсталирајте"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Инсталирај апликације у приватан простор"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Преклопно"</string>
 </resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 4dc5365..2b6a9aa 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Förslag"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Viktigt"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nyheter och tidskrifter"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Koppla av"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Underhållning"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Socialt"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Hälsa och träning"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Väder"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Våra förslag"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgetar för <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> till höger, sökning och alternativ till vänster"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgetar}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Avinstallera"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Info om appen"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installera i privat"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Avinstallera appen"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Installera"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Föreslå inte app"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Fäst förslag"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installeras. <xliff:g id="PROGRESS">%2$s</xliff:g> har slutförts"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> laddas ned, <xliff:g id="PROGRESS">%2$s</xliff:g> klart"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> väntar på installation"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> har arkiverats. Tryck för att ladda ned."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> har arkiverats. Tryck för att ladda ner och återställa."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Du måste uppdatera appen"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Appen för den här ikonen har inte uppdaterats. Du kan uppdatera den manuellt för att återaktivera genvägen eller ta bort ikonen."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Uppdatera"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Tryck för att ställa in eller öppna"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privat"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Inställningar för privat rum"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privat, olåst."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privat, låst."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Lås"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Överföring av privat rum"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Installera appar"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Installera"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Installera appar i privat rum"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Fler alternativ"</string>
 </resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 7253483..d44eb13 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -44,13 +44,10 @@
     <string name="add_to_home_screen" msgid="9168649446635919791">"Weka kwenye skrini ya kwanza"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Umeongeza wijeti ya <xliff:g id="WIDGET_NAME">%1$s</xliff:g> kwenye skrini ya kwanza"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Mapendekezo"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Vya msingi"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Habari na magazeti"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Mahali Pako pa Kupumzika"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Burudani"</string>
-    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Mitandao jamii"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Afya na siha"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Hali ya Hewa"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Mitandao ya kijamii"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Unayopendekezewa"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Wijeti za <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ziko upande wa kulia, utafutaji na chaguo ziko upande wa kushoto"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{Wijeti #}other{Wijeti #}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Ondoa"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Maelezo ya programu"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Sakinisha faraghani"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Ondoa programu"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Sakinisha"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Isipendekeze programu"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Bandika Utabiri"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Inasakinisha <xliff:g id="NAME">%1$s</xliff:g>, imekamilika <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> inapakuliwa, <xliff:g id="PROGRESS">%2$s</xliff:g> imekamilika"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> inasubiri kusakinisha"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> imewekwa kwenye kumbukumbu. Gusa ili uipakue."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> imewekwa kwenye kumbukumbu. Gusa ili upakue na urejeshe."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Unahitaji kusasisha programu"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Programu ya aikoni hii haijasasishwa. Unaweza kusasisha mwenyewe ili uruhusu upya njia hii ya mkato au uondoe aikoni."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Sasisha"</string>
@@ -186,16 +184,14 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Kichujio"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Hitilafu: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Nafasi ya faragha"</string>
-    <string name="private_space_secondary_label" msgid="9203933341714508907">"Gusa ili uweke mipangilio au ufungue"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Gusa uweke mipangilio au ufungue"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Faragha"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Mipangilio ya Nafasi ya Faragha"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Ya faragha, imefunguliwa."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Ya faragha, imefungwa."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Funga"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Mabadiliko ya Nafasi ya Faragha"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Sakinisha programu"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Weka"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Sakinisha programu kwenye Sehemu ya Faragha"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Menyu ya vipengee vya ziada"</string>
 </resources>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index ebef2b4..efa4b85 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"பரிந்துரைகள்"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"அத்தியாவசியமானவை"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"செய்திகள் &amp; பத்திரிக்கைகள்"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"உங்கள் மனதுக்கு இதமானவை"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"பொழுதுபோக்கு"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"சமூகம்"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ஆரோக்கியம் &amp; உடற்பயிற்சி"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"வானிலை"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"உங்களுக்கான பரிந்துரைகள்"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> விட்ஜெட்கள் வலதுபுறத்தில் உள்ளன, தேடல் மற்றும் விருப்பங்கள் இடதுபுறத்தில் உள்ளன"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# விட்ஜெட்}other{# விட்ஜெட்டுகள்}}"</string>
@@ -87,6 +84,8 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"நிறுவல் நீக்கு"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"ஆப்ஸ் தகவல்"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"தனிப்பட்டதில் நிறுவு"</string>
+    <!-- no translation found for uninstall_private_system_shortcut_label (8423460530441627982) -->
+    <skip />
     <string name="install_drop_target_label" msgid="2539096853673231757">"நிறுவு"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"பரிந்துரைக்காதே"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"கணிக்கப்பட்ட ஆப்ஸைப் பின் செய்தல்"</string>
@@ -138,7 +137,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> நிறுவப்படுகிறது, <xliff:g id="PROGRESS">%2$s</xliff:g> முடிந்தது"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g>ஐப் பதிவிறக்குகிறது, <xliff:g id="PROGRESS">%2$s</xliff:g> முடிந்தது"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>ஐ நிறுவுவதற்காகக் காத்திருக்கிறது"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> காப்பிடப்பட்டுள்ளது. பதிவிறக்க தட்டுங்கள்."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> காப்பிடப்பட்டுள்ளது. அதைப் பதிவிறக்கி மீட்டெடுக்க தட்டுங்கள்."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"ஆப்ஸைப் புதுப்பியுங்கள்"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"இந்த ஐகானுக்கான ஆப்ஸ் புதுப்பிக்கப்படவில்லை. இந்த ஷார்ட்கட்டை மீண்டும் இயக்கவோ ஐகானை அகற்றவோ நீங்களாகவே புதுப்பிக்கலாம்."</string>
     <string name="dialog_update" msgid="2178028071796141234">"புதுப்பி"</string>
@@ -189,13 +188,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"அமைக்கவோ திறக்கவோ தட்டுங்கள்"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"தனிப்பட்டது"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"தனிப்பட்ட சேமிப்பிட அமைப்புகள்"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"தனிப்பட்டது, அன்லாக் செய்யப்பட்டுள்ளது."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"தனிப்பட்டது, லாக் செய்யப்பட்டுள்ளது."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"பூட்டு"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"தனிப்பட்ட சேமிப்பிடத்திற்கு மாற்றுகிறது"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"ஆப்ஸை நிறுவுதல்"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"நிறுவுதல்"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"தனிப்பட்ட சேமிப்பிடத்தில் ஆப்ஸை நிறுவும்"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"கூடுதல் விருப்பங்களைக் காட்டும்"</string>
 </resources>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 3c41daa..bd09562 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"సూచనలు"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"నిత్యావసరాలు"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"వార్తలు &amp; మ్యాగజైన్లు"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"మీరు ప్రశాంతంగా ఉండే ప్రదేశం"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"వినోదం"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"సామాజికం"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ఆరోగ్యం &amp; ఫిట్‌నెస్"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"వాతావరణం"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"మీ కోసం సూచించినవి"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"కుడి వైపున <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> విడ్జెట్‌లు, ఎడమ వైపున సెర్చ్, ఇతర ఆప్షన్‌లు"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# విడ్జెట్}other{# విడ్జెట్‌లు}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"అన్ఇన్‌స్టాల్ చేయండి"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"యాప్ సమాచారం"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ప్రైవేట్ ఇన్‌స్టాల్"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"యాప్‌ను అన్‌ఇన్‌స్టాల్ చేయండి"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ఇన్‌స్టాల్ చేయండి"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"యాప్ సూచించకు"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"సూచనను పిన్ చేయండి"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g>‌ను ఇన్‌స్టాల్ చేయడం, <xliff:g id="PROGRESS">%2$s</xliff:g> పూర్తయింది"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> డౌన్‌లోడ్ అవుతోంది, <xliff:g id="PROGRESS">%2$s</xliff:g> పూర్తయింది"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ఇన్‌స్టాల్ కావడానికి వేచి ఉంది"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ఆర్కైవ్ చేయబడింది. డౌన్‌లోడ్ చేయడానికి ట్యాప్ చేయండి."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ఆర్కైవ్ చేయబడింది. డౌన్‌లోడ్ చేయడానికి, రీస్టోర్ చేయడానికి ట్యాప్ చేయండి."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"యాప్‌ను అప్‌డేట్ చేయడం అవసరం"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"ఈ చిహ్నం కోసం యాప్ అప్‌డేట్ చేయబడలేదు. మీరు ఈ షార్ట్‌కట్‌ను మళ్లీ ఎనేబుల్ చేయడానికి మాన్యువల్‌గా అప్‌డేట్ చేయవచ్చు లేదా చిహ్నాన్ని తీసివేయవచ్చు."</string>
     <string name="dialog_update" msgid="2178028071796141234">"అప్‌డేట్ చేయండి"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"సెటప్ చేయడానికి లేదా తెరవడానికి ట్యాప్ చేయండి"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ప్రైవేట్"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ప్రైవేట్ స్పేస్ సెట్టింగ్‌లు"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"ప్రైవేట్, అన్‌లాక్ చేయబడింది."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ప్రైవేట్, లాక్ చేయబడింది."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"లాక్ చేయండి"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"ప్రైవేట్ స్పేస్ కేటాయించడం జరుగుతుంది"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"యాప్‌లను ఇన్‌స్టాల్ చేయండి"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ఇన్‌స్టాల్ చేయండి"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"ప్రైవేట్ స్పేస్‌కు యాప్‌లను ఇన్‌స్టాల్ చేయండి"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ఓవర్‌ఫ్లో"</string>
 </resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 880a58e..dcaa17b 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"คำแนะนำ"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"รายการที่ห้ามพลาด"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ข่าวสารและนิตยสาร"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"พื้นที่สบายๆ ของคุณ"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ความบันเทิง"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"โซเชียล"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"สุขภาพและการออกกำลังกาย"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"สภาพอากาศ"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"แนะนำให้คุณ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"วิดเจ็ต<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>ทางด้านขวา การค้นหาและตัวเลือกทางด้านซ้าย"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{วิดเจ็ต # รายการ}other{วิดเจ็ต # รายการ}}"</string>
@@ -86,7 +83,8 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"นำออก"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"ถอนการติดตั้ง"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"ข้อมูลแอป"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ติดตั้งในส่วนตัว"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ติดตั้งในแบบส่วนตัว"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ถอนการติดตั้งแอป"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ติดตั้ง"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"ไม่ต้องแนะนำแอป"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"ปักหมุดแอปที่คาดการณ์ไว้"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"กำลังติดตั้ง <xliff:g id="NAME">%1$s</xliff:g> เสร็จแล้ว <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"กำลังดาวน์โหลด <xliff:g id="NAME">%1$s</xliff:g> เสร็จแล้ว <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> กำลังรอติดตั้ง"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"เก็บถาวร <xliff:g id="NAME">%1$s</xliff:g> แล้ว แตะเพื่อดาวน์โหลด"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"เก็บถาวร <xliff:g id="NAME">%1$s</xliff:g> แล้ว แตะเพื่อดาวน์โหลดและกู้คืน"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"ต้องอัปเดตแอป"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"แอปสำหรับไอคอนนี้ยังไม่ได้อัปเดต คุณอัปเดตด้วยตนเองได้โดยเปิดใช้ทางลัดนี้อีกครั้งหรือนำไอคอนออก"</string>
     <string name="dialog_update" msgid="2178028071796141234">"อัปเดต"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"แตะเพื่อตั้งค่าหรือเปิด"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ส่วนตัว"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"การตั้งค่าพื้นที่ส่วนตัว"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"ส่วนตัว ปลดล็อกอยู่"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ส่วนตัว ล็อกอยู่"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"ล็อก"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"การเปลี่ยนไปใช้พื้นที่ส่วนตัว"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"ติดตั้งแอป"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"ติดตั้ง"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"ติดตั้งแอปไปยังพื้นที่ส่วนตัว"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"การดำเนินการเพิ่มเติม"</string>
 </resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 4ae6ee9..ba4b6aa 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Mga Suhestyon"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Mga essential"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Balita at mga magazine"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ang Iyong Chill Zone"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Kalusugan at fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Lagay ng panahon"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Iminumungkahi para sa iyo"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Mga widget ng <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> sa kanan, paghahanap at mga opsyon sa kaliwa"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# na widget}}"</string>
@@ -87,8 +84,9 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"I-uninstall"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Impormasyon ng app"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Pribadong i-install"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"I-uninstall ang app"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"I-install"</string>
-    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Huwag magmungkahi ng app"</string>
+    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Huwag magmungkahi"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"I-pin ang Hula"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"i-install ang mga shortcut"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Pinapayagan ang isang app na magdagdag ng mga shortcut nang walang panghihimasok ng user."</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Ini-install ang <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> kumpleto"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Dina-download na ang <xliff:g id="NAME">%1$s</xliff:g>, tapos na ang <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Hinihintay nang mag-install ang <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Naka-archive ang <xliff:g id="NAME">%1$s</xliff:g>. I-tap para i-download."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Naka-archive ang <xliff:g id="NAME">%1$s</xliff:g>. I-tap para i-download at i-restore."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Kinakailangang i-update ang app"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Hindi updated ang app para sa icon na ito. Puwede kang manual na mag-update para ma-enable ulit ang shortcut na ito, o alisin ang icon."</string>
     <string name="dialog_update" msgid="2178028071796141234">"I-update"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"I-tap para i-set up o buksan"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Pribado"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Mga Setting ng Pribadong Space"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Pribado, naka-unlock."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Pribado, naka-lock."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"I-lock"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Pag-transition ng Pribadong Space"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Mag-install ng mga app"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"I-install"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Mag-install ng mga app sa Pribadong Space"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overflow"</string>
 </resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index d526fc8..e46ffd1 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Öneriler"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Önemliler"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Haberler ve dergiler"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Huzur alanınız"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Eğlence"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosyal"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sağlık ve fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Hava durumu"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sizin için önerilenler"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widget\'ları sağda, arama ve seçenekler solda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
@@ -86,9 +83,10 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"Sil"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Kaldır"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Uygulama bilgileri"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Özel olarak yükleyin"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Özel olarak yükle"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Uygulamanın yüklemesini kaldır"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Yükle"</string>
-    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Uygulama önerme"</string>
+    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Uygulamayı önerme"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Tahmini Sabitle"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"kısayolları yükle"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Uygulamaya, kullanıcı müdahalesi olmadan kısayol ekleme izni verir."</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> yükleniyor, <xliff:g id="PROGRESS">%2$s</xliff:g> tamamlandı"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> indiriliyor, <xliff:g id="PROGRESS">%2$s</xliff:g> tamamlandı"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> uygulaması yüklenmek için bekliyor"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> arşivlendi. İndirmek için dokunun."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> arşivlendi. İndirip geri yüklemek için dokunun."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Uygulama güncellemesi gerekli"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Bu simgenin uygulaması güncellenmemiş. Simgeyi kaldırabilir ya da uygulamayı manuel olarak güncelleyerek bu kısayolu yeniden etkinleştirebilirsiniz."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Güncelle"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Kurmak veya açmak için dokunun"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Gizli"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Gizli Alan Ayarları"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Gizli, kilidi açık."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Gizli, kilitli."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Kilit"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Gizli Alana Geçiş"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Uygulamaları yükleme"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Yükle"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Uygulamaları özel alana yükleyin"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Taşma"</string>
 </resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index a81ce31..9cca61f 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Пропозиції"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Основне"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Новини й журнали"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ваша зона розваг"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Розваги"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Соціальні мережі"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здоров’я і фітнес"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Погода"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Пропозиції для вас"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>: віджети праворуч, пошук і опції ліворуч"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# віджет}one{# віджет}few{# віджети}many{# віджетів}other{# віджета}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Видалити додаток"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Про додаток"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Установити приватно"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Видалити додаток"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Установити"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Не пропонувати додаток"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Закріпити передбачений додаток"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> встановлюється, виконано <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> завантажується, <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> очікує на завантаження"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Додаток <xliff:g id="NAME">%1$s</xliff:g> заархівовано. Натисніть, щоб завантажити."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Додаток <xliff:g id="NAME">%1$s</xliff:g> заархівовано. Натисніть, щоб завантажити й відновити."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Потрібно оновити додаток"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Додаток для цього значка не оновлено. Ви можете оновити його вручну, щоб знову ввімкнути цю швидку команду, або можете вилучити значок."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Оновити"</string>
@@ -186,16 +184,14 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Фільтр"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Не вдалося <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Приватний простір"</string>
-    <string name="private_space_secondary_label" msgid="9203933341714508907">"Натисніть, щоб налаштувати або відкрити"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Натисніть, щоб налаштувати чи відкрити"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Приватні"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Налаштування приватного простору"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Приватний простір, розблоковано."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Приватний простір, заблоковано."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Заблокувати"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Перехід у приватний простір"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Установити додатки"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Установити"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Установити додатки в особистому просторі"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Додаткове меню"</string>
 </resources>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 7c73cab..5fbfc52 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"تجاویز"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"لوازمات"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"خبریں اور میگزینز"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"آپ کا آرام دہ زون"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"تفریح"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"سماجی"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"صحت اور تندرستی"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"موسم"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"آپ کے لیے تجویز کردہ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> دائیں طرف وجیٹس، بائیں طرف تلاش اور اختیارات"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ویجیٹ}other{# ویجیٹس}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"اَن انسٹال کریں"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"ایپ کی معلومات"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"پرائیویٹ میں انسٹال کریں"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ایپ کو اَن انسٹال کریں"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"انسٹال کریں"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"ایپ تجویز نہ کریں"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"پیشگوئی پن کریں"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> انسٹال کی جا رہی ہے، <xliff:g id="PROGRESS">%2$s</xliff:g> مکمل ہو گئی"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ڈاؤن لوڈ ہو رہا ہے، <xliff:g id="PROGRESS">%2$s</xliff:g> مکمل ہو گیا"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> انسٹال ہونے کا انتظار کر رہی ہے"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> کو آرکائیو کر لیا گیا ہے۔ ڈاؤن لوڈ کرنے کیلئے تھپتھپائیں۔"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> کو آرکائیو کر لیا گیا ہے۔ ڈاؤن لوڈ اور بحال کرنے کیلئے تھپتھپائیں۔"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"ایپ کی اپ ڈیٹ درکار ہے"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"اس آئیکن کیلئے ایپ کو اپ ڈیٹ نہیں کیا گیا ہے۔ آپ اس شارٹ کٹ کو دوبارہ فعال کرنے کے لیے دستی طور پر اپ ڈیٹ کر سکتے ہیں، یا آئیکن کو ہٹا سکتے ہیں۔"</string>
     <string name="dialog_update" msgid="2178028071796141234">"اپ ڈیٹ کریں"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"سیٹ اپ کرنے یا کھولنے کے لیے تھپتھپائیں"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"نجی"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"نجی اسپیس کی ترتیبات"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"نجی اسپیس غیر مقفل ہے۔"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"نجی اسپیس مقفل ہے۔"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"مقفل کریں"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"نجی اسپیس کی منتقلی"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"ایپس انسٹال کریں"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"انسٹال کریں"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"پرائیویٹ اسپیس میں ایپس انسٹال کریں"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"اوورفلو"</string>
 </resources>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 0ee989e..10e928b 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Takliflar"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Asosiy ilovalar"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Yangiliklar va jurnallar"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Sokin hududingiz"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Hordiq"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Ijtimoiy"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salomatlik va sport"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Ob-havo"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sizga tavsiya etiladi"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vidjetlari oʻngda, qidiruv va sozlamalar chapda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ta vidjet}other{# ta vidjet}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"O‘chirib tashlash"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Ilova haqida"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Maxfiy oʻrnatish"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Ilovani oʻchirish"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"O‘rnatish"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Tavsiya qilinmasin"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Tavsiyani mahkamlash"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> oʻrnatlmoqda, <xliff:g id="PROGRESS">%2$s</xliff:g> yakunlandi"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> yuklab olinmoqda, <xliff:g id="PROGRESS">%2$s</xliff:g> bajarildi"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ilovasi o‘rnatilishi kutilmoqda"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> arxivlangan. Yuklab olish uchun bosing."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> arxivlangan. Yuklab olish va tiklash uchun bosing."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Ilovani yangilash zarur"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Bu belgi uchun ilova yangilanmagan. Ushbu yorliqni qayta yoqish uchun oddiy usulda yangilashingiz yoki belgini olib tashlashingiz mumkin."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Yangilash"</string>
@@ -187,15 +185,13 @@
     <string name="remote_action_failed" msgid="1383965239183576790">"Xato: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Shaxsiy xona"</string>
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Sozlash yoki ochish uchun bosing"</string>
-    <string name="ps_container_title" msgid="4391796149519594205">"Yopiq"</string>
+    <string name="ps_container_title" msgid="4391796149519594205">"Maxfiy"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Shaxsiy xona sozlamalari"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Shaxsiy, ochildi."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Shaxsiy, qulflandi."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Qulflash"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Maxfiy joyga almashtirish"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Ilovalar oʻrnatish"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Oʻrnatish"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Ilovalarni Maxfiy makonga oʻrnatish"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Kengaytirish"</string>
 </resources>
diff --git a/res/values-v34/colors.xml b/res/values-v34/colors.xml
new file mode 100644
index 0000000..26d3712
--- /dev/null
+++ b/res/values-v34/colors.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2024, 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  xmlns:android="http://schemas.android.com/apk/res/android">
+    <color name="widget_picker_secondary_surface_color_light">
+        @android:color/system_surface_bright_light</color>
+    <color name="widget_picker_header_app_title_color_light">
+        @android:color/system_on_surface_light</color>
+    <color name="widget_picker_header_app_subtitle_color_light">
+        @android:color/system_on_surface_variant_light</color>
+    <color name="widget_cell_title_color_light">
+        @android:color/system_on_surface_light</color>
+    <color name="widget_cell_subtitle_color_light">
+        @android:color/system_on_surface_variant_light</color>
+</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 86226f0..9eebdd7 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Nội dung đề xuất"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Các tiện ích thiết yếu"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Tin tức và tạp chí"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Giai điệu thư giãn của bạn"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Giải trí"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Mạng xã hội"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sức khoẻ và thể chất"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Thời tiết"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Đề xuất cho bạn"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Tiện ích <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ở bên phải, công cụ tìm kiếm và tuỳ chọn ở bên trái"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# tiện ích}other{# tiện ích}}"</string>
@@ -87,8 +84,9 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Gỡ cài đặt"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Thông tin ứng dụng"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Cài đặt ở chế độ riêng tư"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Gỡ cài đặt ứng dụng"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Cài đặt"</string>
-    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Không đề xuất ứng dụng"</string>
+    <string name="dismiss_prediction_label" msgid="3357562989568808658">"Không gợi ý ứng dụng"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Ghim ứng dụng dự đoán"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"cài đặt lối tắt"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Cho phép ứng dụng thêm lối tắt mà không cần sự can thiệp của người dùng."</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"Đang cài đặt <xliff:g id="NAME">%1$s</xliff:g>, hoàn tất <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"Đang tải xuống <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> hoàn tất"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"Đang chờ cài đặt <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"Đã lưu trữ <xliff:g id="NAME">%1$s</xliff:g> Nhấn để tải xuống."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> đã được lưu trữ. Hãy nhấn để tải xuống và khôi phục."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Cần cập nhật ứng dụng"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"Ứng dụng cho biểu tượng này chưa được cập nhật. Bạn có thể cập nhật theo cách thủ công để bật lại phím tắt này hoặc xóa biểu tượng."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Cập nhật"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Nhấn để thiết lập hoặc mở"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Riêng tư"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Cài đặt không gian riêng tư"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Riêng tư, đã mở khoá."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Riêng tư, đã khoá."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Khoá"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Chuyển đổi sang không gian riêng tư"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Cài đặt ứng dụng"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Cài đặt"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Cài đặt ứng dụng vào Không gian riêng tư"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Bong bóng bổ sung"</string>
 </resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 40951e9..3c430c1 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -44,13 +44,10 @@
     <string name="add_to_home_screen" msgid="9168649446635919791">"添加到主屏幕"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"已将“<xliff:g id="WIDGET_NAME">%1$s</xliff:g>”微件添加到主屏幕"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"建议"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"必备"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"必备之选"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"新闻与杂志"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"您的休闲区"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"娱乐"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"社交"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"健康与健身"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"天气"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"为您推荐"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"右边是<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>微件,左边是搜索功能和选项"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 个微件}other{# 个微件}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"卸载"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"应用信息"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"安装到私密个人资料中"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"卸载应用"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"安装"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"不要提供应用建议"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"固定预测的应用"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"正在安装<xliff:g id="NAME">%1$s</xliff:g>,已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"正在下载<xliff:g id="NAME">%1$s</xliff:g>,已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>正在等待安装"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"已归档“<xliff:g id="NAME">%1$s</xliff:g>”。点按即可下载。"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"已归档“<xliff:g id="NAME">%1$s</xliff:g>”。点按即可进行下载并恢复。"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"需要更新应用"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"此图标对应的应用未更新。您可以手动更新以重新启用该快捷方式,或者移除此图标。"</string>
     <string name="dialog_update" msgid="2178028071796141234">"更新"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"点按即可设置或打开"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"私密"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"私密空间设置"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"私密,未锁定。"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"私密,已锁定。"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"锁定"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"私密空间转换"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"安装应用"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"安装"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"将应用安装到私密空间"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"菜单"</string>
 </resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index b6147fd..ce26039 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"建議"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"必備之選"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"新聞和雜誌"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"放鬆專區"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"娛樂"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"社交"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"健康和健身"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"天氣"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"為你推薦"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"右邊係「<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>」小工具,左邊係搜尋功能同選項"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 個小工具}other{# 個小工具}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"解除安裝"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"應用程式資料"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"安裝在私人資料夾中"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"解除安裝應用程式"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"安裝"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"不要提供應用程式建議"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"固定預測"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"正在安裝「<xliff:g id="NAME">%1$s</xliff:g>」(已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"正在下載 <xliff:g id="NAME">%1$s</xliff:g>,已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"正在等待安裝 <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"「<xliff:g id="NAME">%1$s</xliff:g>」已封存。輕按即可下載。"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"「<xliff:g id="NAME">%1$s</xliff:g>」已封存。輕按即可下載並還原。"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"必須更新應用程式"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"你尚未更新這個圖示代表的應用程式。你可以手動更新以重新啟用此快速鍵,或者移除圖示。"</string>
     <string name="dialog_update" msgid="2178028071796141234">"更新"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"輕按即可設定或開啟"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"私人"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"「私人空間」設定"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"私人,未鎖定。"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"私人,已鎖定。"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"上鎖"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"轉為「私人空間」"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"安裝應用程式"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"安裝"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"將應用程式安裝在「私人空間」中"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"顯示更多"</string>
 </resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 17573d9..fc0dddf 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"建議"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"常用項目"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"新聞與雜誌"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"放鬆專區"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"娛樂"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"社群"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"健康與塑身"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"天氣"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"個人化建議"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"右邊是「<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>」小工具,左邊是搜尋功能和選項"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 項小工具}other{# 項小工具}}"</string>
@@ -86,7 +83,8 @@
     <string name="remove_drop_target_label" msgid="7812859488053230776">"移除"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"解除安裝"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"應用程式資訊"</string>
-    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"安裝在私人資料夾中"</string>
+    <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"安裝在私人空間中"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"解除安裝應用程式"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"安裝"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"不要提供應用程式建議"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"固定預測的應用程式"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"正在安裝「<xliff:g id="NAME">%1$s</xliff:g>」(已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"正在下載「<xliff:g id="NAME">%1$s</xliff:g>」,已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"正在等待安裝「<xliff:g id="NAME">%1$s</xliff:g>」"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"已封存「<xliff:g id="NAME">%1$s</xliff:g>」。輕觸即可下載。"</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"「<xliff:g id="NAME">%1$s</xliff:g>」已封存。輕觸即可下載並還原。"</string>
     <string name="dialog_update_title" msgid="114234265740994042">"必須更新應用程式"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"這個圖示代表的應用程式未更新。手動更新即可重新啟用這個捷徑,你也可以移除圖示。"</string>
     <string name="dialog_update" msgid="2178028071796141234">"更新"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"輕觸即可設定或開啟"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"私人"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"私人空間設定"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"私人,未鎖定。"</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"私人,已鎖定。"</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"鎖定"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"轉換私人空間狀態"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"安裝應用程式"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"安裝"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"將應用程式安裝在私人空間中"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"溢位"</string>
 </resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index a24c0e9..1471564 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -46,11 +46,8 @@
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Iziphakamiso"</string>
     <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Okusemqoka"</string>
     <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Izindaba nomagazini"</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Indawo Ozipholela Kuyo"</string>
     <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Okokozijabulisa"</string>
     <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Okomphakathi"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Ezempilo nokufaneleka"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Isimo sezulu"</string>
     <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Okuphakanyiselwe wena"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Amawijethi okuthi <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> kwesokudla, ukusesha nokukhethwayo kwesobunxele"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{iwijethi #}one{amawijethi #}other{amawijethi #}}"</string>
@@ -87,6 +84,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Khipha"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"Ulwazi nge-app"</string>
     <string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Faka ngokugodliwe"</string>
+    <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Khipha i-app"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Faka"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ungaphakamisi uhlelo lokusebenza"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Ukubikezela Iphinikhodi"</string>
@@ -138,7 +136,7 @@
     <string name="app_installing_title" msgid="5864044122733792085">"I-<xliff:g id="NAME">%1$s</xliff:g> iyafakwa, seyiqede <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"I-<xliff:g id="NAME">%1$s</xliff:g> iyalandwa, <xliff:g id="PROGRESS">%2$s</xliff:g> kuqediwe"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ilinde ukufakwa"</string>
-    <string name="app_archived_title" msgid="9124290918876665128">"I-<xliff:g id="NAME">%1$s</xliff:g> ifakwe kungobo yomlando. Thepha ukuze udawunilode."</string>
+    <string name="app_archived_title" msgid="7717956158562544081">"Okuthi <xliff:g id="NAME">%1$s</xliff:g> kufakwe kungobo yomlando. Thepha ukuze udawunilode futhi ubuyisele."</string>
     <string name="dialog_update_title" msgid="114234265740994042">"Kudingeka isibuyekezo se-app"</string>
     <string name="dialog_update_message" msgid="4176784553982226114">"I-app yalesi sithonjana ibuyekeziwe. Ungabuyekeza mathupha ukuze uphinde unike amandla lesi sinqamuleli, noma ususe isithonjana."</string>
     <string name="dialog_update" msgid="2178028071796141234">"Vuselela"</string>
@@ -189,13 +187,11 @@
     <string name="private_space_secondary_label" msgid="9203933341714508907">"Thepha ukuze usethe noma uvule"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Okuyimfihlo"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Amasethingi Esikhala Esiyimfihlo"</string>
-    <!-- no translation found for ps_container_unlock_button_content_description (9181551784092204234) -->
-    <skip />
-    <!-- no translation found for ps_container_lock_button_content_description (5961993384382649530) -->
-    <skip />
+    <string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Iyimfihlo, ivuliwe."</string>
+    <string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Iyimfihlo, ikhiyiwe."</string>
     <string name="ps_container_lock_title" msgid="2640257399982364682">"Khiya"</string>
     <string name="ps_container_transition" msgid="8667331812048014412">"Ukuguqulwa Kwendawo Yangasese"</string>
-    <string name="ps_add_button_label" msgid="8611055839242385935">"Faka ama-app"</string>
+    <string name="ps_add_button_label" msgid="8127988716897128773">"Faka"</string>
     <string name="ps_add_button_content_description" msgid="3254274107740952556">"Faka ama-app Endaweni Engasese"</string>
     <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Ukugcwala kakhulu"</string>
 </resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index f23c790..be8b2e1 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -76,6 +76,8 @@
     <attr name="widgetPickerCollapseHandleColor" format="color"/>
     <attr name="widgetPickerAddButtonBackgroundColor" format="color"/>
     <attr name="widgetPickerAddButtonTextColor" format="color"/>
+    <attr name="widgetCellTitleColor" format="color" />
+    <attr name="widgetCellSubtitleColor" format="color" />
 
     <!-- BubbleTextView specific attributes. -->
     <declare-styleable name="BubbleTextView">
diff --git a/res/values/colors.xml b/res/values/colors.xml
index dfe40fc..ce80964 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -117,6 +117,8 @@
     <color name="widget_picker_collapse_handle_color_light">#C4C7C5</color>
     <color name="widget_picker_add_button_background_color_light">#0B57D0</color>
     <color name="widget_picker_add_button_text_color_light">#0B57D0</color>
+    <color name="widget_cell_title_color_light">@color/material_color_on_surface</color>
+    <color name="widget_cell_subtitle_color_light">@color/material_color_on_surface_variant</color>
 
     <color name="widget_picker_primary_surface_color_dark">#1F2020</color>
     <color name="widget_picker_secondary_surface_color_dark">#393939</color>
@@ -134,6 +136,8 @@
     <color name="widget_picker_collapse_handle_color_dark">#444746</color>
     <color name="widget_picker_add_button_background_color_dark">#062E6F</color>
     <color name="widget_picker_add_button_text_color_dark">#FFFFFF</color>
+    <color name="widget_cell_title_color_dark">@color/material_color_on_surface</color>
+    <color name="widget_cell_subtitle_color_dark">@color/material_color_on_surface_variant</color>
 
     <color name="material_color_on_secondary_fixed_variant">#3F4759</color>
     <color name="material_color_on_tertiary_fixed_variant">#583E5B</color>
diff --git a/res/values/config.xml b/res/values/config.xml
index 648a50c..2a3b588 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -103,8 +103,8 @@
     <item name="swipe_up_rect_scale_stiffness" type="dimen" format="float">200</item>
     <item name="swipe_up_rect_scale_higher_stiffness" type="dimen" format="float">400</item>
     <!-- Flag: enableScalingRevealHomeAnimation() -->
-    <item name="swipe_up_rect_scale_damping_ratio_v2" type="dimen" format="float">0.8</item>
-    <item name="swipe_up_rect_scale_stiffness_v2" type="dimen" format="float">650</item>
+    <item name="swipe_up_rect_scale_damping_ratio_v2" type="dimen" format="float">0.99</item>
+    <item name="swipe_up_rect_scale_stiffness_v2" type="dimen" format="float">500</item>
 
     <item name="swipe_up_rect_xy_fling_friction" type="dimen" format="float">1.5</item>
 
@@ -114,9 +114,9 @@
     <item name="swipe_up_rect_xy_stiffness" type="dimen" format="float">200</item>
     <!-- Flag: enableScalingRevealHomeAnimation() -->
     <item name="swipe_up_rect_x_damping_ratio" type="dimen" format="float">0.965</item>
-    <item name="swipe_up_rect_x_stiffness" type="dimen" format="float">300</item>
+    <item name="swipe_up_rect_x_stiffness" type="dimen" format="float">450</item>
     <item name="swipe_up_rect_y_damping_ratio" type="dimen" format="float">0.95</item>
-    <item name="swipe_up_rect_y_stiffness" type="dimen" format="float">190</item>
+    <item name="swipe_up_rect_y_stiffness" type="dimen" format="float">400</item>
 
     <!-- Taskbar -->
     <!-- This is a float because it is converted to dp later in DeviceProfile -->
@@ -155,11 +155,6 @@
 
     <string-array name="filtered_components" ></string-array>
 
-    <!-- Widget component names to be included in weather category of widget suggestions. -->
-    <string-array name="weather_recommendations"></string-array>
-    <!-- Widget component names to be included in fitness category of widget suggestions. -->
-    <string-array name="fitness_recommendations"></string-array>
-
     <!-- Swipe back to home related -->
     <dimen name="swipe_back_window_scale_x_margin">10dp</dimen>
     <dimen name="swipe_back_window_corner_radius">40dp</dimen>
@@ -223,4 +218,11 @@
     <string-array name="skip_private_profile_shortcut_packages" translatable="false">
         <item>com.android.settings</item>
     </string-array>
+
+    <!-- Legacy list of components supporting multiple instances.
+         DO NOT ADD TO THIS LIST.  Apps should use the PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI
+         property to declare multi-instance support in V+. This resource should match the resource
+         of the same name in SystemUI. -->
+    <string-array name="config_appsSupportMultiInstancesSplit">
+    </string-array>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 1bf59e8..2741158 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -167,7 +167,6 @@
     <!-- (x) icon button inside work edu card -->
     <dimen name="rounded_button_width">24dp</dimen>
     <dimen name="x_icon_size">16dp</dimen>
-    <dimen name="x_icon_padding">4dp</dimen>
 
     <!-- rounded button shown inside card views, and snack bars  -->
     <dimen name="padded_rounded_button_height">48dp</dimen>
@@ -179,19 +178,39 @@
     <!-- Widget tray -->
     <dimen name="widget_cell_vertical_padding">8dp</dimen>
     <dimen name="widget_cell_horizontal_padding">8dp</dimen>
-    <dimen name="widget_cell_font_size">14sp</dimen>
+    <dimen name="widget_cell_title_font_size">14sp</dimen>
+    <integer name="widget_cell_title_font_weight">500</integer>
+    <dimen name="widget_cell_title_line_height">20sp</dimen>
+    <dimen name="widget_cell_dims_font_size">14sp</dimen>
+    <integer name="widget_cell_dims_font_weight">400</integer>
+    <dimen name="widget_cell_dims_line_height">20sp</dimen>
+    <dimen name="widget_cell_description_font_size">12sp</dimen>
+    <integer name="widget_cell_description_font_weight">400</integer>
+    <dimen name="widget_cell_description_line_height">16sp</dimen>
     <dimen name="widget_cell_app_icon_size">24dp</dimen>
     <dimen name="widget_cell_app_icon_padding">8dp</dimen>
     <dimen name="widget_cell_add_button_height">48dp</dimen>
     <dimen name="widget_cell_add_button_start_padding">8dp</dimen>
+    <dimen name="widget_cell_add_icon_button_start_padding">16dp</dimen>
     <dimen name="widget_cell_add_button_end_padding">16dp</dimen>
     <dimen name="widget_cell_add_button_scroll_padding">24dp</dimen>
+    <dimen name="widget_cell_add_button_font_size">14sp</dimen>
+    <integer name="widget_cell_add_button_font_weight">500</integer>
+    <dimen name="widget_cell_add_button_line_height">20sp</dimen>
+    <dimen name="widget_cell_add_button_drawable_padding">8dp</dimen>
+    <dimen name="widget_cell_add_button_drawable_width">19dp</dimen>
 
     <dimen name="widget_tabs_button_horizontal_padding">4dp</dimen>
     <dimen name="widget_tabs_horizontal_padding">16dp</dimen>
     <dimen name="widget_apps_tabs_vertical_padding">6dp</dimen>
     <dimen name="widget_picker_landscape_tablet_left_right_margin">117dp</dimen>
     <dimen name="widget_picker_two_panels_left_right_margin">0dp</dimen>
+    <dimen name="widget_picker_header_app_title_font_size">16sp</dimen>
+    <integer name="widget_picker_header_app_title_font_weight">500</integer>
+    <dimen name="widget_picker_header_app_title_line_height">24sp</dimen>
+    <dimen name="widget_picker_header_app_subtitle_font_size">14sp</dimen>
+    <integer name="widget_picker_header_app_subtitle_font_weight">400</integer>
+    <dimen name="widget_picker_header_app_subtitle_line_height">20sp</dimen>
     <dimen name="widget_recommendations_table_vertical_padding">8dp</dimen>
     <!-- Bottom margin for the search and recommended widgets container without work profile -->
     <dimen name="search_and_recommended_widgets_container_bottom_margin">16dp</dimen>
@@ -397,6 +416,9 @@
     <dimen name="taskbar_running_app_indicator_height">0dp</dimen>
     <dimen name="taskbar_running_app_indicator_width">0dp</dimen>
     <dimen name="taskbar_running_app_indicator_top_margin">0dp</dimen>
+    <dimen name="taskbar_minimized_app_indicator_height">0dp</dimen>
+    <dimen name="taskbar_minimized_app_indicator_width">0dp</dimen>
+    <dimen name="taskbar_minimized_app_indicator_top_margin">0dp</dimen>
 
     <!-- Transient taskbar (placeholders to compile in Launcher3 without Quickstep) -->
     <dimen name="transient_taskbar_padding">0dp</dimen>
@@ -496,7 +518,7 @@
     <dimen name="default_ime_height">300dp</dimen>
 
     <!-- Private Space parameters -->
-    <dimen name="ps_container_corner_radius">24dp</dimen>
+    <dimen name="ps_container_corner_radius">28dp</dimen>
     <dimen name="ps_header_height">72dp</dimen>
     <dimen name="ps_header_relative_layout_height">48dp</dimen>
     <dimen name="ps_header_image_height">48dp</dimen>
@@ -507,7 +529,8 @@
     <dimen name="ps_button_height">40dp</dimen>
     <dimen name="ps_button_width">40dp</dimen>
     <dimen name="ps_lock_button_width">89dp</dimen>
-    <dimen name="ps_app_divider_padding">16dp</dimen>
+    <dimen name="ps_app_divider_horizontal_padding">16dp</dimen>
+    <dimen name="ps_app_divider_vertical_padding">32dp</dimen>
     <dimen name="ps_extra_bottom_padding">16dp</dimen>
     <dimen name="ps_lock_corner_radius">20dp</dimen>
     <dimen name="ps_lock_icon_size">20dp</dimen>
@@ -516,6 +539,8 @@
     <dimen name="ps_lock_icon_text_margin_start_expanded">8dp</dimen>
     <dimen name="ps_lock_icon_text_margin_end_expanded">6dp</dimen>
     <dimen name="ps_lock_button_background_padding">10dp</dimen>
+    <dimen name="ps_floating_mask_corner_radius">28dp</dimen>
+    <dimen name="ps_floating_mask_end_padding">16dp</dimen>
 
     <!-- WindowManagerProxy -->
     <dimen name="max_width_and_height_of_small_display_cutout">136px</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c971223..ef0f0d8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -83,13 +83,20 @@
     <!-- Widget suggestions header title in the full widgets picker for large screen devices
     in landscape mode. [CHAR_LIMIT=50] -->
     <string name="suggested_widgets_header_title">Suggestions</string>
+    <!-- Title for the widget suggestions category that displays widgets provided by
+    productivity apps for daily use [CHAR_LIMIT=50] -->
     <string name="productivity_widget_recommendation_category_label">Essentials</string>
+    <!-- Title for the widget suggestions category that displays widgets provided by
+    news and magazines related apps [CHAR_LIMIT=50] -->
     <string name="news_widget_recommendation_category_label">News &amp; magazines</string>
-    <string name="social_and_entertainment_widget_recommendation_category_label">Your Chill Zone</string>
+    <!-- Title for the widget suggestions category that displays widgets provided by
+    entertainment apps [CHAR_LIMIT=50] -->
     <string name="entertainment_widget_recommendation_category_label">Entertainment</string>
+    <!-- Title for the widget suggestions category that displays widgets provided by
+    social apps [CHAR_LIMIT=50] -->
     <string name="social_widget_recommendation_category_label">Social</string>
-    <string name="fitness_widget_recommendation_category_label">Health &amp; fitness</string>
-    <string name="weather_widget_recommendation_category_label">Weather</string>
+    <!-- Title for the widget suggestions category that displays general widget suggestions
+    [CHAR_LIMIT=50] -->
     <string name="others_widget_recommendation_category_label">Suggested for you</string>
     <!-- accessibilityPaneTitle for the right pane when showing suggested widgets. -->
     <string name="widget_picker_right_pane_accessibility_title"><xliff:g id="selected_header" example="Calendar">%1$s</xliff:g> widgets on right, search and options on left</string>
@@ -191,6 +198,8 @@
     <string name="app_info_drop_target_label">App info</string>
     <!-- Label for install to private profile shortcut label. [CHAR_LIMIT=20] -->
     <string name="install_private_system_shortcut_label">Install in private</string>
+    <!-- Label for uninstall app private profile shortcut.-->
+    <string name="uninstall_private_system_shortcut_label">Uninstall app</string>
     <!-- Label for install drop target. [CHAR_LIMIT=20] -->
     <string name="install_drop_target_label">Install</string>
     <!-- Label for dismiss prediction. -->
@@ -333,7 +342,7 @@
     <!-- Title for an app whose download has been started. -->
     <string name="app_waiting_download_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> waiting to install</string>
     <!-- Title for an app which is archived. -->
-    <string name="app_archived_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> is archived. Tap to download.</string>
+    <string name="app_archived_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> is archived. Tap to download and restore.</string>
 
 
     <!-- Title shown on the alert dialog prompting the user to update the application in market
@@ -485,7 +494,7 @@
     <!-- Description for Private Space Transition button -->
     <string name="ps_container_transition">Private Space Transitioning</string>
     <!-- Title for Private Space install app icon -->
-    <string name="ps_add_button_label">Install apps</string>
+    <string name="ps_add_button_label">Install</string>
     <!-- Content description for install app icon -->
     <string name="ps_add_button_content_description">Install apps to Private Space</string>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 00b962e..ae3d3b3 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -268,6 +268,10 @@
             @color/widget_picker_add_button_background_color_light</item>
         <item name="widgetPickerAddButtonTextColor">
             @color/widget_picker_add_button_text_color_light</item>
+        <item name="widgetCellTitleColor">
+            @color/widget_cell_title_color_light</item>
+        <item name="widgetCellSubtitleColor">
+            @color/widget_cell_subtitle_color_light</item>
     </style>
     <style name="WidgetContainerTheme.Dark" parent="AppTheme.Dark">
         <item name="android:colorEdgeEffect">?android:attr/textColorSecondary</item>
@@ -303,6 +307,10 @@
             @color/widget_picker_add_button_background_color_dark</item>
         <item name="widgetPickerAddButtonTextColor">
             @color/widget_picker_add_button_text_color_dark</item>
+        <item name="widgetCellTitleColor">
+            @color/widget_cell_title_color_dark</item>
+        <item name="widgetCellSubtitleColor">
+            @color/widget_cell_subtitle_color_dark</item>
     </style>
 
     <style name="FastScrollerPopup" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle">
@@ -419,6 +427,9 @@
         <item name="widgetsTheme">@style/WidgetContainerTheme</item>
         <item name="android:windowLightStatusBar">true</item>
         <item name="android:windowTranslucentStatus">true</item>
+        <!-- Add the dim background here, rather than in the activity layout as the window slides
+             in from the bottom, and we don't want the scrim to slide. -->
+        <item name="android:backgroundDimEnabled">true</item>
     </style>
 
     <style name="ProxyActivityStarterTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index b46d7e2..b51e850 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -136,6 +136,7 @@
     private final Rect mWidgetViewNewRect = new Rect();
     private final @Nullable LauncherAppWidgetHostView.CellChildViewPreLayoutListener
             mCellChildViewPreLayoutListener;
+    private final @NonNull OnLayoutChangeListener mWidgetViewLayoutListener;
 
     private int mXDown, mYDown;
 
@@ -177,6 +178,9 @@
         mDragAcrossTwoPanelOpacityMargin = mLauncher.getResources().getDimensionPixelSize(
                 R.dimen.resize_frame_invalid_drag_across_two_panel_opacity_margin);
         mDragLayerRelativeCoordinateHelper = new ViewGroupFocusHelper(mLauncher.getDragLayer());
+
+        mWidgetViewLayoutListener =
+                (v, l, t, r, b, oldL, oldT, oldR, oldB) -> setCornerRadiusFromWidget();
     }
 
     @Override
@@ -211,15 +215,6 @@
         DragLayer dl = launcher.getDragLayer();
         AppWidgetResizeFrame frame = (AppWidgetResizeFrame) launcher.getLayoutInflater()
                 .inflate(R.layout.app_widget_resize_frame, dl, false);
-        if (widget.hasEnforcedCornerRadius()) {
-            float enforcedCornerRadius = widget.getEnforcedCornerRadius();
-            ImageView imageView = frame.findViewById(R.id.widget_resize_frame);
-            Drawable d = imageView.getDrawable();
-            if (d instanceof GradientDrawable) {
-                GradientDrawable gd = (GradientDrawable) d.mutate();
-                gd.setCornerRadius(enforcedCornerRadius);
-            }
-        }
         frame.setupForWidget(widget, cellLayout, dl);
         ((DragLayer.LayoutParams) frame.getLayoutParams()).customPosition = true;
 
@@ -228,6 +223,18 @@
         frame.post(() -> frame.snapToWidget(false));
     }
 
+    private void setCornerRadiusFromWidget() {
+        if (mWidgetView != null && mWidgetView.hasEnforcedCornerRadius()) {
+            float enforcedCornerRadius = mWidgetView.getEnforcedCornerRadius();
+            ImageView imageView = findViewById(R.id.widget_resize_frame);
+            Drawable d = imageView.getDrawable();
+            if (d instanceof GradientDrawable) {
+                GradientDrawable gd = (GradientDrawable) d.mutate();
+                gd.setCornerRadius(enforcedCornerRadius);
+            }
+        }
+    }
+
     private void setupForWidget(LauncherAppWidgetHostView widgetView, CellLayout cellLayout,
             DragLayer dragLayer) {
         mCellLayout = cellLayout;
@@ -317,6 +324,9 @@
                 .log(LAUNCHER_WIDGET_RESIZE_STARTED);
 
         setOnKeyListener(this);
+
+        setCornerRadiusFromWidget();
+        mWidgetView.addOnLayoutChangeListener(mWidgetViewLayoutListener);
     }
 
     public boolean beginResizeIfPointInRegion(int x, int y) {
@@ -729,6 +739,7 @@
             mWidgetView.setLayoutTransition(null);
         }
         mDragLayer.removeView(this);
+        mWidgetView.removeOnLayoutChangeListener(mWidgetViewLayoutListener);
     }
 
     private void updateInvalidResizeEffect(CellLayout cellLayout, CellLayout pairedCellLayout,
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index cf86528..175d6ec 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -19,6 +19,8 @@
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
 import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
 import static com.android.launcher3.provider.LauncherDbUtils.itemIdMatch;
+import static com.android.launcher3.util.UserIconInfo.TYPE_CLONED;
+import static com.android.launcher3.util.UserIconInfo.TYPE_WORK;
 
 import android.content.ComponentName;
 import android.content.ContentValues;
@@ -34,6 +36,7 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.os.Bundle;
 import android.os.Process;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.AttributeSet;
@@ -56,6 +59,7 @@
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.Partner;
 import com.android.launcher3.util.Thunk;
+import com.android.launcher3.util.UserIconInfo;
 import com.android.launcher3.widget.LauncherWidgetHolder;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -63,6 +67,7 @@
 
 import java.io.IOException;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 import java.util.function.Supplier;
@@ -125,34 +130,38 @@
     private static final String TAG_INCLUDE = "include";
     public static final String TAG_WORKSPACE = "workspace";
     private static final String TAG_APP_ICON = "appicon";
-    private static final String TAG_AUTO_INSTALL = "autoinstall";
-    private static final String TAG_FOLDER = "folder";
-    private static final String TAG_APPWIDGET = "appwidget";
+    public static final String TAG_AUTO_INSTALL = "autoinstall";
+    public static final String TAG_FOLDER = "folder";
+    public static final String TAG_APPWIDGET = "appwidget";
     protected static final String TAG_SEARCH_WIDGET = "searchwidget";
-    private static final String TAG_SHORTCUT = "shortcut";
+    public static final String TAG_SHORTCUT = "shortcut";
     private static final String TAG_EXTRA = "extra";
 
-    private static final String ATTR_CONTAINER = "container";
-    private static final String ATTR_RANK = "rank";
+    public static final String ATTR_CONTAINER = "container";
+    public static final String ATTR_RANK = "rank";
 
-    private static final String ATTR_PACKAGE_NAME = "packageName";
-    private static final String ATTR_CLASS_NAME = "className";
-    private static final String ATTR_TITLE = "title";
-    private static final String ATTR_TITLE_TEXT = "titleText";
-    private static final String ATTR_SCREEN = "screen";
-    private static final String ATTR_SHORTCUT_ID = "shortcutId";
+    public static final String ATTR_PACKAGE_NAME = "packageName";
+    public static final String ATTR_CLASS_NAME = "className";
+    public static final String ATTR_TITLE = "title";
+    public static final String ATTR_TITLE_TEXT = "titleText";
+    public static final String ATTR_SCREEN = "screen";
+    public static final String ATTR_SHORTCUT_ID = "shortcutId";
 
     // x and y can be specified as negative integers, in which case -1 represents the
     // last row / column, -2 represents the second last, and so on.
-    private static final String ATTR_X = "x";
-    private static final String ATTR_Y = "y";
+    public static final String ATTR_X = "x";
+    public static final String ATTR_Y = "y";
 
-    private static final String ATTR_SPAN_X = "spanX";
-    private static final String ATTR_SPAN_Y = "spanY";
+    public static final String ATTR_SPAN_X = "spanX";
+    public static final String ATTR_SPAN_Y = "spanY";
 
     // Attrs for "Include"
     private static final String ATTR_WORKSPACE = "workspace";
 
+    public static final String ATTR_USER_TYPE = "userType";
+    public static final String USER_TYPE_WORK = "work";
+    public static final String USER_TYPE_CLONED = "cloned";
+
     // Style attrs -- "Extra"
     private static final String ATTR_KEY = "key";
     private static final String ATTR_VALUE = "value";
@@ -168,6 +177,8 @@
     protected final SourceResources mSourceRes;
     protected final Supplier<XmlPullParser> mInitialLayoutSupplier;
 
+    private final Map<String, Long> mUserTypeToSerial;
+
     private final InvariantDeviceProfile mIdp;
     private final int mRowCount;
     private final int mColumnCount;
@@ -204,15 +215,25 @@
         mRowCount = mIdp.numRows;
         mColumnCount = mIdp.numColumns;
         mActivityOverride = ApiWrapper.INSTANCE.get(context).getActivityOverrides();
+
+        mUserTypeToSerial = new HashMap<>();
+        UserCache cache = UserCache.getInstance(context);
+        for (UserHandle user : cache.getUserProfiles()) {
+            UserIconInfo uii = cache.getUserInfo(user);
+            switch (uii.type) {
+                case TYPE_WORK -> mUserTypeToSerial.put(USER_TYPE_WORK, uii.userSerial);
+                case TYPE_CLONED -> mUserTypeToSerial.put(USER_TYPE_CLONED, uii.userSerial);
+            }
+        }
     }
 
     /**
      * Loads the layout in the db and returns the number of entries added on the desktop.
      */
-    public int loadLayout(SQLiteDatabase db, IntArray screenIds) {
+    public int loadLayout(SQLiteDatabase db) {
         mDb = db;
         try {
-            return parseLayout(mInitialLayoutSupplier.get(), screenIds);
+            return parseLayout(mInitialLayoutSupplier.get());
         } catch (Exception e) {
             Log.e(TAG, "Error parsing layout: ", e);
             return -1;
@@ -222,7 +243,7 @@
     /**
      * Parses the layout and returns the number of elements added on the homescreen.
      */
-    protected int parseLayout(XmlPullParser parser, IntArray screenIds)
+    protected int parseLayout(XmlPullParser parser)
             throws XmlPullParserException, IOException {
         beginDocument(parser, mRootTag);
         final int depth = parser.getDepth();
@@ -235,7 +256,7 @@
             if (type != XmlPullParser.START_TAG) {
                 continue;
             }
-            count += parseAndAddNode(parser, tagParserMap, screenIds);
+            count += parseAndAddNode(parser, tagParserMap);
         }
         return count;
     }
@@ -259,14 +280,14 @@
      * Parses the current node and returns the number of elements added.
      */
     protected int parseAndAddNode(
-            XmlPullParser parser, ArrayMap<String, TagParser> tagParserMap, IntArray screenIds)
+            XmlPullParser parser, ArrayMap<String, TagParser> tagParserMap)
             throws XmlPullParserException, IOException {
 
         if (TAG_INCLUDE.equals(parser.getName())) {
             final int resId = getAttributeResourceValue(parser, ATTR_WORKSPACE, 0);
             if (resId != 0) {
                 // recursively load some more favorites, why not?
-                return parseLayout(mSourceRes.getXml(resId), screenIds);
+                return parseLayout(mSourceRes.getXml(resId));
             } else {
                 return 0;
             }
@@ -284,22 +305,17 @@
                 convertToDistanceFromEnd(getAttributeValue(parser, ATTR_X), mColumnCount));
         mValues.put(Favorites.CELLY,
                 convertToDistanceFromEnd(getAttributeValue(parser, ATTR_Y), mRowCount));
+        Long profileId = mUserTypeToSerial.get(getAttributeValue(parser, ATTR_USER_TYPE));
+        if (profileId != null) {
+            mValues.put(Favorites.PROFILE_ID, profileId);
+        }
 
         TagParser tagParser = tagParserMap.get(parser.getName());
         if (tagParser == null) {
             if (LOGD) Log.d(TAG, "Ignoring unknown element tag: " + parser.getName());
             return 0;
         }
-        int newElementId = tagParser.parseAndAdd(parser);
-        if (newElementId >= 0) {
-            // Keep track of the set of screens which need to be added to the db.
-            if (!screenIds.contains(screenId) &&
-                    container == Favorites.CONTAINER_DESKTOP) {
-                screenIds.add(screenId);
-            }
-            return 1;
-        }
-        return 0;
+        return tagParser.parseAndAdd(parser) >= 0 ? 1 : 0;
     }
 
     protected int addShortcut(String title, Intent intent, int type) {
@@ -311,10 +327,11 @@
         mValues.put(Favorites.SPANY, 1);
         mValues.put(Favorites._ID, id);
 
-        if (type == ITEM_TYPE_APPLICATION) {
-            ComponentName cn = intent.getComponent();
-            if (cn != null && mActivityOverride.containsKey(cn.getPackageName())) {
-                LauncherActivityInfo replacementInfo = mActivityOverride.get(cn.getPackageName());
+        ComponentName cn = intent.getComponent();
+        if (cn != null && type == ITEM_TYPE_APPLICATION
+                && !mValues.containsKey(Favorites.PROFILE_ID)) {
+            LauncherActivityInfo replacementInfo = mActivityOverride.get(cn.getPackageName());
+            if (replacementInfo != null) {
                 mValues.put(Favorites.PROFILE_ID, UserCache.INSTANCE.get(mContext)
                         .getSerialNumberForUser(replacementInfo.getUser()));
                 mValues.put(Favorites.INTENT, AppInfo.makeLaunchIntent(replacementInfo).toUri(0));
@@ -420,11 +437,7 @@
             }
 
             mValues.put(Favorites.RESTORED, WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON);
-            final Intent intent = new Intent(Intent.ACTION_MAIN, null)
-                    .addCategory(Intent.CATEGORY_LAUNCHER)
-                    .setComponent(new ComponentName(packageName, className))
-                    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                            | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+            Intent intent = AppInfo.makeLaunchIntent(new ComponentName(packageName, className));
             return addShortcut(mContext.getString(R.string.package_state_unknown), intent,
                     ITEM_TYPE_APPLICATION);
         }
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index 1049314..633091d 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -412,6 +412,8 @@
     public static <T extends BaseActivity> T fromContext(Context context) {
         if (context instanceof BaseActivity) {
             return (T) context;
+        } else if (context instanceof ActivityContextDelegate) {
+            return (T) ((ActivityContextDelegate) context).mDelegate;
         } else if (context instanceof ContextWrapper) {
             return fromContext(((ContextWrapper) context).getBaseContext());
         } else {
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 2a8298f..7d09164 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -186,9 +186,20 @@
     // These fields, related to showing running apps, are only used for Taskbar.
     private final Size mRunningAppIndicatorSize;
     private final int mRunningAppIndicatorTopMargin;
+    private final Size mMinimizedAppIndicatorSize;
+    private final int mMinimizedAppIndicatorTopMargin;
     private final Paint mRunningAppIndicatorPaint;
     private final Rect mRunningAppIconBounds = new Rect();
-    private boolean mIsRunning;
+    private RunningAppState mRunningAppState;
+
+    /**
+     * Various options for the running state of an app.
+     */
+    public enum RunningAppState {
+        NOT_RUNNING,
+        RUNNING,
+        MINIMIZED,
+    }
 
     @ViewDebug.ExportedProperty(category = "launcher")
     private boolean mStayPressed;
@@ -259,9 +270,16 @@
         mRunningAppIndicatorSize = new Size(
                 getResources().getDimensionPixelSize(R.dimen.taskbar_running_app_indicator_width),
                 getResources().getDimensionPixelSize(R.dimen.taskbar_running_app_indicator_height));
+        mMinimizedAppIndicatorSize = new Size(
+                getResources().getDimensionPixelSize(R.dimen.taskbar_minimized_app_indicator_width),
+                getResources().getDimensionPixelSize(
+                        R.dimen.taskbar_minimized_app_indicator_height));
         mRunningAppIndicatorTopMargin =
                 getResources().getDimensionPixelSize(
                         R.dimen.taskbar_running_app_indicator_top_margin);
+        mMinimizedAppIndicatorTopMargin =
+                getResources().getDimensionPixelSize(
+                        R.dimen.taskbar_minimized_app_indicator_top_margin);
         mRunningAppIndicatorPaint = new Paint();
         mRunningAppIndicatorPaint.setColor(getResources().getColor(
                 R.color.taskbar_running_app_indicator_color, context.getTheme()));
@@ -414,8 +432,8 @@
 
     /** Updates whether the app this view represents is currently running. */
     @UiThread
-    public void updateRunningState(boolean isRunning) {
-        mIsRunning = isRunning;
+    public void updateRunningState(RunningAppState runningAppState) {
+        mRunningAppState = runningAppState;
     }
 
     protected void setItemInfo(ItemInfoWithIcon itemInfo) {
@@ -667,18 +685,20 @@
 
     /** Draws a line under the app icon if this is representing a running app in Desktop Mode. */
     protected void drawRunningAppIndicatorIfNecessary(Canvas canvas) {
-        if (!mIsRunning || mDisplay != DISPLAY_TASKBAR) {
+        if (mRunningAppState == RunningAppState.NOT_RUNNING || mDisplay != DISPLAY_TASKBAR) {
             return;
         }
         getIconBounds(mRunningAppIconBounds);
         // TODO(b/333872717): update color, shape, and size of indicator
-        int indicatorTop = mRunningAppIconBounds.bottom + mRunningAppIndicatorTopMargin;
-        canvas.drawRect(
-                mRunningAppIconBounds.centerX() - mRunningAppIndicatorSize.getWidth() / 2,
-                indicatorTop,
-                mRunningAppIconBounds.centerX() + mRunningAppIndicatorSize.getWidth() / 2,
-                indicatorTop + mRunningAppIndicatorSize.getHeight(),
-                mRunningAppIndicatorPaint);
+        boolean isMinimized = mRunningAppState == RunningAppState.MINIMIZED;
+        int indicatorTop =
+                mRunningAppIconBounds.bottom + (isMinimized ? mMinimizedAppIndicatorTopMargin
+                        : mRunningAppIndicatorTopMargin);
+        final Size indicatorSize =
+                isMinimized ? mMinimizedAppIndicatorSize : mRunningAppIndicatorSize;
+        canvas.drawRect(mRunningAppIconBounds.centerX() - indicatorSize.getWidth() / 2,
+                indicatorTop, mRunningAppIconBounds.centerX() + indicatorSize.getWidth() / 2,
+                indicatorTop + indicatorSize.getHeight(), mRunningAppIndicatorPaint);
     }
 
     @Override
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 98dade5..7e9e864 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -33,7 +33,6 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Point;
-import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
@@ -115,7 +114,6 @@
     @Thunk final int[] mTempLocation = new int[2];
 
     @Thunk final Rect mTempOnDrawCellToRect = new Rect();
-    final PointF mTmpPointF = new PointF();
 
     protected GridOccupancy mOccupied;
     public GridOccupancy mTmpOccupied;
@@ -197,16 +195,11 @@
     public static final int REORDER_ANIMATION_DURATION = 150;
     @Thunk final float mReorderPreviewAnimationMagnitude;
 
-    private final ArrayList<View> mIntersectingViews = new ArrayList<>();
-    private final Rect mOccupiedRect = new Rect();
     public final int[] mDirectionVector = new int[2];
 
     ItemConfiguration mPreviousSolution = null;
-    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();
 
@@ -1163,9 +1156,6 @@
             mDragCellSpan[0] = spanX;
             mDragCellSpan[1] = spanY;
 
-            // Apply color extraction on a widget when dragging.
-            applyColorExtractionOnWidget(dragObject, mDragCell, spanX, spanY);
-
             final int oldIndex = mDragOutlineCurrent;
             mDragOutlineAnims[oldIndex].animateOut();
             mDragOutlineCurrent = (oldIndex + 1) % mDragOutlines.length;
@@ -1186,19 +1176,6 @@
         }
     }
 
-    /** Applies the local color extraction to a dragging widget object. */
-    private void applyColorExtractionOnWidget(DropTarget.DragObject dragObject, int[] targetCell,
-            int spanX, int spanY) {
-        // Apply local extracted color if the DragView is an AppWidgetHostViewDrawable.
-        View view = dragObject.dragView.getContentView();
-        if (view instanceof LauncherAppWidgetHostView) {
-            int screenId = mCellLayoutContainer.getCellLayoutId(this);
-            cellToRect(targetCell[0], targetCell[1], spanX, spanY, mTempRect);
-
-            ((LauncherAppWidgetHostView) view).handleDrag(mTempRect, this, screenId);
-        }
-    }
-
     @SuppressLint("StringFormatMatches")
     public String getItemMoveDescription(int cellX, int cellY) {
         if (mContainerType == HOTSEAT) {
diff --git a/src/com/android/launcher3/DevicePaddings.java b/src/com/android/launcher3/DevicePaddings.java
index 08fb47b..8494d11 100644
--- a/src/com/android/launcher3/DevicePaddings.java
+++ b/src/com/android/launcher3/DevicePaddings.java
@@ -47,7 +47,7 @@
     private static final String WORKSPACE_BOTTOM_PADDING = "workspaceBottomPadding";
     private static final String HOTSEAT_BOTTOM_PADDING = "hotseatBottomPadding";
 
-    private static final String TAG = DevicePaddings.class.getSimpleName();
+    private static final String TAG = "DevicePaddings";
     private static final boolean DEBUG = false;
 
     ArrayList<DevicePadding> mDevicePaddings = new ArrayList<>();
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index a667c96..0daabb1 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -32,6 +32,7 @@
 import static com.android.launcher3.testing.shared.ResourceUtils.INVALID_RESOURCE_HANDLE;
 import static com.android.launcher3.testing.shared.ResourceUtils.pxFromDp;
 import static com.android.launcher3.testing.shared.ResourceUtils.roundPxValueFromFloat;
+import static com.android.wm.shell.Flags.enableTinyTaskbar;
 
 import android.annotation.SuppressLint;
 import android.content.Context;
@@ -353,7 +354,7 @@
         isTablet = info.isTablet(windowBounds);
         isPhone = !isTablet;
         isTwoPanels = isTablet && isMultiDisplay;
-        isTaskbarPresent = isTablet
+        isTaskbarPresent = (isTablet || (enableTinyTaskbar() && isGestureMode))
                 && WindowManagerProxy.INSTANCE.get(context).isTaskbarDrawnInProcess();
 
         // Some more constants.
@@ -2402,7 +2403,7 @@
                 mTransposeLayoutWithOrientation = !mInfo.isTablet(mWindowBounds);
             }
             if (mIsGestureMode == null) {
-                mIsGestureMode = mInfo.navigationMode.hasGestures;
+                mIsGestureMode = mInfo.getNavigationMode().hasGestures;
             }
             if (mDotRendererCache == null) {
                 mDotRendererCache = new SparseArray<>();
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index f405b93..54aea38 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -20,6 +20,7 @@
 import static com.android.launcher3.Utilities.dpiFromPx;
 import static com.android.launcher3.testing.shared.ResourceUtils.INVALID_RESOURCE_HANDLE;
 import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
+import static com.android.launcher3.util.DisplayController.CHANGE_DESKTOP_MODE;
 import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
 import static com.android.launcher3.util.DisplayController.CHANGE_SUPPORTED_BOUNDS;
 import static com.android.launcher3.util.DisplayController.CHANGE_TASKBAR_PINNING;
@@ -236,7 +237,8 @@
         DisplayController.INSTANCE.get(context).setPriorityListener(
                 (displayContext, info, flags) -> {
                     if ((flags & (CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS
-                            | CHANGE_NAVIGATION_MODE | CHANGE_TASKBAR_PINNING)) != 0) {
+                            | CHANGE_NAVIGATION_MODE | CHANGE_TASKBAR_PINNING
+                            | CHANGE_DESKTOP_MODE)) != 0) {
                         onConfigChanged(displayContext);
                     }
                 });
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 4fe7234..b89d05e 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -28,6 +28,7 @@
 import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
 import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
 import static com.android.launcher3.Flags.enableAddAppWidgetViaConfigActivityV2;
+import static com.android.launcher3.Flags.enableSmartspaceRemovalToggle;
 import static com.android.launcher3.Flags.enableWorkspaceInflation;
 import static com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_WIDGET_TRANSITION;
@@ -66,7 +67,6 @@
 import static com.android.launcher3.LauncherState.NO_SCALE;
 import static com.android.launcher3.LauncherState.SPRING_LOADED;
 import static com.android.launcher3.Utilities.postAsyncCallback;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVAL;
 import static com.android.launcher3.config.FeatureFlags.FOLDABLE_SINGLE_PAGE;
 import static com.android.launcher3.config.FeatureFlags.MULTI_SELECT_EDIT_MODE;
 import static com.android.launcher3.logging.KeyboardStateManager.KeyboardState.HIDE;
@@ -96,7 +96,9 @@
 import static com.android.launcher3.popup.SystemShortcut.WIDGETS;
 import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
 import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
+import static com.android.launcher3.testing.shared.TestProtocol.CLOCK_ICON_DRAWABLE_LEAKING;
 import static com.android.launcher3.testing.shared.TestProtocol.LAUNCHER_ACTIVITY_STOPPED_MESSAGE;
+import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.ItemInfoMatcher.forFolderMatch;
 import static com.android.launcher3.util.SettingsCache.TOUCHPAD_NATURAL_SCROLLING;
@@ -421,6 +423,7 @@
     @Override
     @TargetApi(Build.VERSION_CODES.S)
     protected void onCreate(Bundle savedInstanceState) {
+        testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onCreate: instance=" + this);
         mStartupLatencyLogger = createStartupLatencyLogger(
                 sIsNewProcess
                         ? LockedUserState.get(this).isUserUnlockedAtLauncherStartup()
@@ -1079,6 +1082,7 @@
 
     @Override
     protected void onStart() {
+        testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onStart: instance=" + this);
         TraceHelper.INSTANCE.beginSection(ON_START_EVT);
         super.onStart();
         if (!mDeferOverlayCallbacks) {
@@ -1092,6 +1096,7 @@
     @Override
     @CallSuper
     protected void onDeferredResumed() {
+        testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onDeferredResumed: instance=" + this);
         logStopAndResume(true /* isResume */);
 
         // Process any items that were added while Launcher was away.
@@ -1279,6 +1284,7 @@
 
     @Override
     protected void onResume() {
+        testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onResume: instance=" + this);
         TraceHelper.INSTANCE.beginSection(ON_RESUME_EVT);
         super.onResume();
 
@@ -1294,6 +1300,7 @@
 
     @Override
     protected void onPause() {
+        testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onPause: instance=" + this);
         // Ensure that items added to Launcher are queued until Launcher returns
         ItemInstallQueue.INSTANCE.get(this).pauseModelPush(FLAG_ACTIVITY_PAUSED);
 
@@ -1368,7 +1375,7 @@
         // Until the workspace is bound, ensure that we keep the wallpaper offset locked to the
         // default state, otherwise we will update to the wrong offsets in RTL
         mWorkspace.lockWallpaperToDefaultPage();
-        if (!ENABLE_SMARTSPACE_REMOVAL.get()) {
+        if (!enableSmartspaceRemovalToggle()) {
             mWorkspace.bindAndInitFirstWorkspaceScreen();
         }
         mDragController.addDragListener(mWorkspace);
@@ -1708,7 +1715,7 @@
         AbstractFloatingView.closeAllOpenViews(this);
         getStateManager().goToState(ALL_APPS, alreadyOnHome);
         if (mAppsView.isSearching()) {
-            mAppsView.reset(alreadyOnHome);
+            mAppsView.getSearchUiManager().resetSearch();
         }
         if (mAppsView.getCurrentPage() != tab) {
             mAppsView.switchToTab(tab);
@@ -1776,6 +1783,7 @@
 
     @Override
     public void onDestroy() {
+        testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onDestroy: instance=" + this);
         super.onDestroy();
         ACTIVITY_TRACKER.onActivityDestroyed(this);
 
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 159e17f..a4ae1c8 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -19,9 +19,9 @@
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
 import static android.content.Context.RECEIVER_EXPORTED;
 
+import static com.android.launcher3.Flags.enableSmartspaceRemovalToggle;
 import static com.android.launcher3.LauncherPrefs.ICON_STATE;
 import static com.android.launcher3.LauncherPrefs.THEMED_ICONS;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVAL;
 import static com.android.launcher3.model.LoaderTask.SMARTSPACE_ON_HOME_SCREEN;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI;
@@ -52,6 +52,7 @@
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.util.LockedUserState;
 import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.Preconditions;
 import com.android.launcher3.util.RunnableList;
 import com.android.launcher3.util.SafeCloseable;
@@ -126,7 +127,7 @@
                 .addUserEventListener(mModel::onUserEvent);
         mOnTerminateCallback.add(userChangeListener::close);
 
-        if (ENABLE_SMARTSPACE_REMOVAL.get()) {
+        if (enableSmartspaceRemovalToggle()) {
             OnSharedPreferenceChangeListener firstPagePinnedItemListener =
                     new OnSharedPreferenceChangeListener() {
                         @Override
@@ -181,7 +182,7 @@
         mIconCache = new IconCache(mContext, mInvariantDeviceProfile,
                 iconCacheFileName, mIconProvider);
         mModel = new LauncherModel(context, this, mIconCache, new AppFilter(mContext),
-                iconCacheFileName != null);
+                PackageManagerHelper.INSTANCE.get(context), iconCacheFileName != null);
         mOnTerminateCallback.add(mIconCache::close);
         mOnTerminateCallback.add(mModel::destroy);
     }
@@ -206,7 +207,7 @@
     }
 
     private void refreshAndReloadLauncher() {
-        LauncherIcons.clearPool();
+        LauncherIcons.clearPool(mContext);
         mIconCache.updateIconParams(
                 mInvariantDeviceProfile.fillResIconDpi, mInvariantDeviceProfile.iconBitmapSize);
         mModel.forceReload();
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 9b0e0ec..47a7115 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -19,6 +19,7 @@
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
 
 import static com.android.launcher3.LauncherAppState.ACTION_FORCE_ROLOAD;
+import static com.android.launcher3.LauncherPrefs.WORK_EDU_STEP;
 import static com.android.launcher3.config.FeatureFlags.IS_STUDIO_BUILD;
 import static com.android.launcher3.icons.cache.BaseIconCache.EMPTY_CLASS_NAME;
 import static com.android.launcher3.model.PackageUpdatedTask.OP_UPDATE;
@@ -48,7 +49,6 @@
 import com.android.launcher3.model.AddWorkspaceItemsTask;
 import com.android.launcher3.model.AllAppsList;
 import com.android.launcher3.model.BaseLauncherBinder;
-import com.android.launcher3.model.BaseModelUpdateTask;
 import com.android.launcher3.model.BgDataModel;
 import com.android.launcher3.model.BgDataModel.Callbacks;
 import com.android.launcher3.model.CacheDataUpdatedTask;
@@ -57,6 +57,7 @@
 import com.android.launcher3.model.ModelDbController;
 import com.android.launcher3.model.ModelDelegate;
 import com.android.launcher3.model.ModelLauncherCallbacks;
+import com.android.launcher3.model.ModelTaskController;
 import com.android.launcher3.model.ModelWriter;
 import com.android.launcher3.model.PackageInstallStateChangedTask;
 import com.android.launcher3.model.PackageUpdatedTask;
@@ -82,7 +83,6 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.concurrent.CancellationException;
-import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 
@@ -99,6 +99,8 @@
     @NonNull
     private final LauncherAppState mApp;
     @NonNull
+    private final PackageManagerHelper mPmHelper;
+    @NonNull
     private final ModelDbController mModelDbController;
     @NonNull
     private final Object mLock = new Object();
@@ -153,12 +155,13 @@
 
     LauncherModel(@NonNull final Context context, @NonNull final LauncherAppState app,
             @NonNull final IconCache iconCache, @NonNull final AppFilter appFilter,
-            final boolean isPrimaryInstance) {
+            @NonNull final PackageManagerHelper pmHelper, final boolean isPrimaryInstance) {
         mApp = app;
+        mPmHelper = pmHelper;
         mModelDbController = new ModelDbController(context);
         mBgAllAppsList = new AllAppsList(iconCache, appFilter);
-        mModelDelegate = ModelDelegate.newInstance(context, app, mBgAllAppsList, mBgDataModel,
-                isPrimaryInstance);
+        mModelDelegate = ModelDelegate.newInstance(context, app, mPmHelper, mBgAllAppsList,
+                mBgDataModel, isPrimaryInstance);
     }
 
     @NonNull
@@ -274,6 +277,9 @@
             enqueueModelUpdateTask(new PackageUpdatedTask(
                     PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE, user));
         }
+        if (Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
+            LauncherPrefs.get(mApp.getContext()).put(WORK_EDU_STEP, 0);
+        }
     }
 
     /**
@@ -426,13 +432,9 @@
     @Override
     public void onInstallSessionCreated(@NonNull final PackageInstallInfo sessionInfo) {
         if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) {
-            enqueueModelUpdateTask(new BaseModelUpdateTask() {
-                @Override
-                public void execute(@NonNull final LauncherAppState app,
-                        @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
-                    apps.addPromiseApp(app.getContext(), sessionInfo);
-                    bindApplicationsIfNeeded();
-                }
+            enqueueModelUpdateTask((taskController, dataModel, apps) -> {
+                apps.addPromiseApp(mApp.getContext(), sessionInfo);
+                taskController.bindApplicationsIfNeeded();
             });
         }
     }
@@ -440,60 +442,56 @@
     @Override
     public void onSessionFailure(@NonNull final String packageName,
             @NonNull final UserHandle user) {
-        enqueueModelUpdateTask(new BaseModelUpdateTask() {
-            @Override
-            public void execute(@NonNull final LauncherAppState app,
-                    @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
-                IconCache iconCache = app.getIconCache();
-                final IntSet removedIds = new IntSet();
-                HashSet<WorkspaceItemInfo> archivedWorkspaceItemsToCacheRefresh = new HashSet<>();
-                boolean isAppArchived = PackageManagerHelper.INSTANCE.get(mApp.getContext())
-                        .isAppArchivedForUser(packageName, user);
-                synchronized (dataModel) {
-                    if (isAppArchived) {
-                        // Remove package icon cache entry for archived app in case of a session
-                        // failure.
-                        mApp.getIconCache().remove(
-                                new ComponentName(packageName, packageName + EMPTY_CLASS_NAME),
-                                user);
-                    }
+        enqueueModelUpdateTask((taskController, dataModel, apps) -> {
+            IconCache iconCache = mApp.getIconCache();
+            final IntSet removedIds = new IntSet();
+            HashSet<WorkspaceItemInfo> archivedWorkspaceItemsToCacheRefresh = new HashSet<>();
+            boolean isAppArchived = PackageManagerHelper.INSTANCE.get(mApp.getContext())
+                    .isAppArchivedForUser(packageName, user);
+            synchronized (dataModel) {
+                if (isAppArchived) {
+                    // Remove package icon cache entry for archived app in case of a session
+                    // failure.
+                    mApp.getIconCache().remove(
+                            new ComponentName(packageName, packageName + EMPTY_CLASS_NAME),
+                            user);
+                }
 
-                    for (ItemInfo info : dataModel.itemsIdMap) {
-                        if (info instanceof WorkspaceItemInfo
-                                && ((WorkspaceItemInfo) info).hasPromiseIconUi()
-                                && user.equals(info.user)
-                                && info.getIntent() != null) {
-                            if (TextUtils.equals(packageName, info.getIntent().getPackage())) {
-                                removedIds.add(info.id);
-                            }
-                            if (((WorkspaceItemInfo) info).isArchived()) {
-                                WorkspaceItemInfo workspaceItem = (WorkspaceItemInfo) info;
-                                // Refresh icons on the workspace for archived apps.
-                                iconCache.getTitleAndIcon(workspaceItem,
-                                        workspaceItem.usingLowResIcon());
-                                archivedWorkspaceItemsToCacheRefresh.add(workspaceItem);
-                            }
+                for (ItemInfo info : dataModel.itemsIdMap) {
+                    if (info instanceof WorkspaceItemInfo
+                            && ((WorkspaceItemInfo) info).hasPromiseIconUi()
+                            && user.equals(info.user)
+                            && info.getIntent() != null) {
+                        if (TextUtils.equals(packageName, info.getIntent().getPackage())) {
+                            removedIds.add(info.id);
+                        }
+                        if (((WorkspaceItemInfo) info).isArchived()) {
+                            WorkspaceItemInfo workspaceItem = (WorkspaceItemInfo) info;
+                            // Refresh icons on the workspace for archived apps.
+                            iconCache.getTitleAndIcon(workspaceItem,
+                                    workspaceItem.usingLowResIcon());
+                            archivedWorkspaceItemsToCacheRefresh.add(workspaceItem);
                         }
                     }
-
-                    if (isAppArchived) {
-                        apps.updateIconsAndLabels(new HashSet<>(List.of(packageName)), user);
-                    }
                 }
 
-                if (!removedIds.isEmpty()) {
-                    deleteAndBindComponentsRemoved(
-                            ItemInfoMatcher.ofItemIds(removedIds),
-                            "removed because install session failed");
-                }
-                if (!archivedWorkspaceItemsToCacheRefresh.isEmpty()) {
-                    bindUpdatedWorkspaceItems(
-                            archivedWorkspaceItemsToCacheRefresh.stream().toList());
-                }
                 if (isAppArchived) {
-                    bindApplicationsIfNeeded();
+                    apps.updateIconsAndLabels(new HashSet<>(List.of(packageName)), user);
                 }
             }
+
+            if (!removedIds.isEmpty()) {
+                taskController.deleteAndBindComponentsRemoved(
+                        ItemInfoMatcher.ofItemIds(removedIds),
+                        "removed because install session failed");
+            }
+            if (!archivedWorkspaceItemsToCacheRefresh.isEmpty()) {
+                taskController.bindUpdatedWorkspaceItems(
+                        archivedWorkspaceItemsToCacheRefresh.stream().toList());
+            }
+            if (isAppArchived) {
+                taskController.bindApplicationsIfNeeded();
+            }
         });
     }
 
@@ -583,13 +581,9 @@
      */
     public void onWidgetLabelsUpdated(@NonNull final HashSet<String> updatedPackages,
             @NonNull final UserHandle user) {
-        enqueueModelUpdateTask(new BaseModelUpdateTask() {
-            @Override
-            public void execute(@NonNull final LauncherAppState app,
-                    @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
-                dataModel.widgetsModel.onPackageIconsUpdated(updatedPackages, user, app);
-                bindUpdatedWidgets(dataModel);
-            }
+        enqueueModelUpdateTask((taskController, dataModel, apps) ->  {
+            dataModel.widgetsModel.onPackageIconsUpdated(updatedPackages, user, mApp);
+            taskController.bindUpdatedWidgets(dataModel);
         });
     }
 
@@ -597,8 +591,15 @@
         if (mModelDestroyed) {
             return;
         }
-        task.init(mApp, this, mBgDataModel, mBgAllAppsList, MAIN_EXECUTOR);
-        MODEL_EXECUTOR.execute(task);
+        MODEL_EXECUTOR.execute(() -> {
+            if (!isModelLoaded()) {
+                // Loader has not yet run.
+                return;
+            }
+            ModelTaskController controller = new ModelTaskController(
+                    mApp, mBgDataModel, mBgAllAppsList, this, MAIN_EXECUTOR);
+            task.execute(controller, mBgDataModel, mBgAllAppsList);
+        });
     }
 
     /**
@@ -610,18 +611,10 @@
         void execute(@NonNull Callbacks callbacks);
     }
 
-    /**
-     * A runnable which changes/updates the data model of the launcher based on certain events.
-     */
-    public interface ModelUpdateTask extends Runnable {
+    public interface ModelUpdateTask {
 
-        /**
-         * Called before the task is posted to initialize the internal state.
-         */
-        void init(@NonNull LauncherAppState app, @NonNull LauncherModel model,
-                @NonNull BgDataModel dataModel, @NonNull AllAppsList allAppsList,
-                @NonNull Executor uiExecutor);
-
+        void execute(@NonNull ModelTaskController taskController,
+                @NonNull BgDataModel dataModel, @NonNull AllAppsList apps);
     }
 
     public void updateAndBindWorkspaceItem(@NonNull final WorkspaceItemInfo si,
@@ -638,27 +631,19 @@
      */
     public void updateAndBindWorkspaceItem(
             @NonNull final Supplier<WorkspaceItemInfo> itemProvider) {
-        enqueueModelUpdateTask(new BaseModelUpdateTask() {
-            @Override
-            public void execute(@NonNull final LauncherAppState app,
-                    @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
-                WorkspaceItemInfo info = itemProvider.get();
-                getModelWriter().updateItemInDatabase(info);
-                ArrayList<WorkspaceItemInfo> update = new ArrayList<>();
-                update.add(info);
-                bindUpdatedWorkspaceItems(update);
-            }
+        enqueueModelUpdateTask((taskController, dataModel, apps) ->  {
+            WorkspaceItemInfo info = itemProvider.get();
+            taskController.getModelWriter().updateItemInDatabase(info);
+            ArrayList<WorkspaceItemInfo> update = new ArrayList<>();
+            update.add(info);
+            taskController.bindUpdatedWorkspaceItems(update);
         });
     }
 
     public void refreshAndBindWidgetsAndShortcuts(@Nullable final PackageUserKey packageUser) {
-        enqueueModelUpdateTask(new BaseModelUpdateTask() {
-            @Override
-            public void execute(@NonNull final LauncherAppState app,
-                    @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
-                dataModel.widgetsModel.update(app, packageUser);
-                bindUpdatedWidgets(dataModel);
-            }
+        enqueueModelUpdateTask((taskController, dataModel, apps) ->  {
+            dataModel.widgetsModel.update(taskController.getApp(), packageUser);
+            taskController.bindUpdatedWidgets(dataModel);
         });
     }
 
diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt
index 6a5001b..13181e8 100644
--- a/src/com/android/launcher3/LauncherPrefs.kt
+++ b/src/com/android/launcher3/LauncherPrefs.kt
@@ -253,6 +253,7 @@
         @JvmStatic fun get(context: Context): LauncherPrefs = INSTANCE.get(context)
 
         const val TASKBAR_PINNING_KEY = "TASKBAR_PINNING_KEY"
+        const val TASKBAR_PINNING_DESKTOP_MODE_KEY = "TASKBAR_PINNING_DESKTOP_MODE_KEY"
         const val SHOULD_SHOW_SMARTSPACE_KEY = "SHOULD_SHOW_SMARTSPACE_KEY"
         @JvmField
         val ICON_STATE = nonRestorableItem("pref_icon_shape_path", "", EncryptionType.ENCRYPTED)
@@ -272,6 +273,9 @@
         @JvmField
         val TASKBAR_PINNING =
             backedUpItem(TASKBAR_PINNING_KEY, false, EncryptionType.DEVICE_PROTECTED)
+        @JvmField
+        val TASKBAR_PINNING_IN_DESKTOP_MODE =
+            backedUpItem(TASKBAR_PINNING_DESKTOP_MODE_KEY, true, EncryptionType.DEVICE_PROTECTED)
 
         @JvmField
         val DEVICE_TYPE =
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 3bdd863..72a3c53 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -83,7 +83,7 @@
     public static final int FLAG_HAS_SYS_UI_SCRIM = BaseState.getFlag(4);
     // Flag to inticate that all popups should be closed when this state is enabled.
     public static final int FLAG_CLOSE_POPUPS = BaseState.getFlag(5);
-    public static final int FLAG_OVERVIEW_UI = BaseState.getFlag(6);
+    public static final int FLAG_RECENTS_VIEW_VISIBLE = BaseState.getFlag(6);
 
     // Flag indicating that hotseat and its contents are not accessible.
     public static final int FLAG_HOTSEAT_INACCESSIBLE = BaseState.getFlag(7);
@@ -158,14 +158,14 @@
     /**
      * True if the state has overview panel visible.
      */
-    public final boolean overviewUi;
+    public final boolean isRecentsViewVisible;
 
     private final int mFlags;
 
     public LauncherState(int id, int statsLogOrdinal, int flags) {
         this.statsLogOrdinal = statsLogOrdinal;
         this.mFlags = flags;
-        this.overviewUi = (flags & FLAG_OVERVIEW_UI) != 0;
+        this.isRecentsViewVisible = (flags & FLAG_RECENTS_VIEW_VISIBLE) != 0;
         this.ordinal = id;
         sAllStates[id] = this;
     }
diff --git a/src/com/android/launcher3/ModelCallbacks.kt b/src/com/android/launcher3/ModelCallbacks.kt
index f582be0..7d6d154 100644
--- a/src/com/android/launcher3/ModelCallbacks.kt
+++ b/src/com/android/launcher3/ModelCallbacks.kt
@@ -4,11 +4,12 @@
 import android.os.Build
 import android.os.Trace
 import androidx.annotation.UiThread
+import com.android.launcher3.Flags.enableSmartspaceRemovalToggle
 import com.android.launcher3.LauncherConstants.TraceEvents
+import com.android.launcher3.Utilities.SHOULD_SHOW_FIRST_PAGE_WIDGET
 import com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID
 import com.android.launcher3.allapps.AllAppsStore
 import com.android.launcher3.config.FeatureFlags
-import com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget
 import com.android.launcher3.model.BgDataModel
 import com.android.launcher3.model.StringCache
 import com.android.launcher3.model.data.AppInfo
@@ -34,7 +35,7 @@
     var pagesToBindSynchronously = LIntSet()
 
     private var isFirstPagePinnedItemEnabled =
-        (BuildConfig.QSB_ON_FIRST_SCREEN && !FeatureFlags.ENABLE_SMARTSPACE_REMOVAL.get())
+        (BuildConfig.QSB_ON_FIRST_SCREEN && !enableSmartspaceRemovalToggle())
 
     var stringCache: StringCache? = null
 
@@ -314,16 +315,16 @@
         )
         val firstScreenPosition = 0
         if (
-            (FeatureFlags.QSB_ON_FIRST_SCREEN &&
-                isFirstPagePinnedItemEnabled &&
-                !shouldShowFirstPageWidget()) &&
+            (isFirstPagePinnedItemEnabled &&
+                !SHOULD_SHOW_FIRST_PAGE_WIDGET) &&
                 orderedScreenIds.indexOf(FIRST_SCREEN_ID) != firstScreenPosition
         ) {
             orderedScreenIds.removeValue(FIRST_SCREEN_ID)
             orderedScreenIds.add(firstScreenPosition, FIRST_SCREEN_ID)
         } else if (
-            (!FeatureFlags.QSB_ON_FIRST_SCREEN && !isFirstPagePinnedItemEnabled ||
-                shouldShowFirstPageWidget()) && orderedScreenIds.isEmpty
+            (!isFirstPagePinnedItemEnabled ||
+                    SHOULD_SHOW_FIRST_PAGE_WIDGET)
+            && orderedScreenIds.isEmpty
         ) {
             // If there are no screens, we need to have an empty screen
             launcher.workspace.addExtraEmptyScreens()
@@ -379,9 +380,8 @@
         }
         orderedScreenIds
             .filterNot { screenId ->
-                FeatureFlags.QSB_ON_FIRST_SCREEN &&
                     isFirstPagePinnedItemEnabled &&
-                    !FeatureFlags.shouldShowFirstPageWidget() &&
+                    !SHOULD_SHOW_FIRST_PAGE_WIDGET &&
                     screenId == WorkspaceLayoutManager.FIRST_SCREEN_ID
             }
             .forEach { screenId ->
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index cc9f08e..365fbd3 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -788,7 +788,7 @@
         if (mScroller.isFinished() && pageScrollChanged) {
             // TODO(b/246283207): Remove logging once root cause of flake detected.
             if (Utilities.isRunningInTestHarness() && !(this instanceof Workspace)) {
-                Log.d("b/246283207", this.getClass().getSimpleName() + "#onLayout() -> "
+                Log.d("b/246283207", TAG + "#onLayout() -> "
                         + "if(mScroller.isFinished() && pageScrollChanged) -> getNextPage(): "
                         + getNextPage() + ", getScrollForPage(getNextPage()): "
                         + getScrollForPage(getNextPage()));
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 2b886e4..19a3002 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -18,6 +18,8 @@
 
 import static android.graphics.drawable.AdaptiveIconDrawable.getExtraInsetFraction;
 
+import static com.android.launcher3.BuildConfig.WIDGET_ON_FIRST_SCREEN;
+import static com.android.launcher3.Flags.enableSmartspaceAsAWidget;
 import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
@@ -68,6 +70,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
+import android.view.ViewGroup;
 import android.view.animation.Interpolator;
 
 import androidx.annotation.ChecksSdkIntAtLeast;
@@ -102,6 +105,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.util.function.Predicate;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -130,6 +134,10 @@
     @ChecksSdkIntAtLeast(api = VERSION_CODES.UPSIDE_DOWN_CAKE, codename = "U")
     public static final boolean ATLEAST_U = Build.VERSION.SDK_INT >= VERSION_CODES.UPSIDE_DOWN_CAKE;
 
+    @ChecksSdkIntAtLeast(api = VERSION_CODES.VANILLA_ICE_CREAM, codename = "V")
+    public static final boolean ATLEAST_V = Build.VERSION.SDK_INT
+            >= VERSION_CODES.VANILLA_ICE_CREAM;
+
     /**
      * Set on a motion event dispatched from the nav bar. See {@link MotionEvent#setEdgeFlags(int)}.
      */
@@ -148,6 +156,9 @@
     public static final int TRANSLATE_LEFT = 2;
     public static final int TRANSLATE_RIGHT = 3;
 
+    public static final boolean SHOULD_SHOW_FIRST_PAGE_WIDGET =
+            enableSmartspaceAsAWidget() && WIDGET_ON_FIRST_SCREEN;
+
     @IntDef({TRANSLATE_UP, TRANSLATE_DOWN, TRANSLATE_LEFT, TRANSLATE_RIGHT})
     public @interface AdjustmentDirection{}
 
@@ -634,7 +645,7 @@
         } else {
             // Wrap the main icon in AID
             try (LauncherIcons li = LauncherIcons.obtain(context)) {
-                result = li.wrapToAdaptiveIcon(mainIcon);
+                result = li.wrapToAdaptiveIcon(mainIcon, null);
             }
         }
         if (result == null) {
@@ -830,4 +841,27 @@
                 // No-Op
         }
     }
+
+    /**
+     * Does a depth-first search through the View hierarchy starting at root, to find a view that
+     * matches the predicate. Returns null if no View was found. View has a findViewByPredicate
+     * member function but it is currently a @hide API.
+     */
+    @Nullable
+    public static <T extends View> T findViewByPredicate(@NonNull View root,
+            @NonNull Predicate<View> predicate) {
+        if (predicate.test(root)) {
+            return (T) root;
+        }
+        if (root instanceof ViewGroup parent) {
+            int count = parent.getChildCount();
+            for (int i = 0; i < count; i++) {
+                View view = findViewByPredicate(parent.getChildAt(i), predicate);
+                if (view != null) {
+                    return (T) view;
+                }
+            }
+        }
+        return null;
+    }
 }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index f03dcab..584d089 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -17,6 +17,7 @@
 package com.android.launcher3;
 
 import static com.android.launcher3.BubbleTextView.DISPLAY_FOLDER;
+import static com.android.launcher3.Flags.enableSmartspaceRemovalToggle;
 import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
 import static com.android.launcher3.LauncherState.ALL_APPS;
@@ -28,10 +29,9 @@
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.SPRING_LOADED;
 import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
+import static com.android.launcher3.Utilities.SHOULD_SHOW_FIRST_PAGE_WIDGET;
 import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVAL;
 import static com.android.launcher3.config.FeatureFlags.FOLDABLE_SINGLE_PAGE;
-import static com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPELEFT;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPERIGHT;
@@ -126,7 +126,6 @@
 import com.android.launcher3.widget.PendingAddWidgetInfo;
 import com.android.launcher3.widget.PendingAppWidgetHostView;
 import com.android.launcher3.widget.WidgetManagerHelper;
-import com.android.launcher3.widget.dragndrop.AppWidgetHostViewDragListener;
 import com.android.launcher3.widget.util.WidgetSizes;
 import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlayCallbacks;
 import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlayTouchProxy;
@@ -600,7 +599,7 @@
     public void bindAndInitFirstWorkspaceScreen() {
         if ((!FeatureFlags.QSB_ON_FIRST_SCREEN
                 || !mLauncher.getIsFirstPagePinnedItemEnabled())
-                || shouldShowFirstPageWidget()) {
+                || SHOULD_SHOW_FIRST_PAGE_WIDGET) {
             mFirstPagePinnedItem = null;
             return;
         }
@@ -642,7 +641,7 @@
         mWorkspaceScreens.clear();
 
         // Ensure that the first page is always present
-        if (!ENABLE_SMARTSPACE_REMOVAL.get()) {
+        if (!enableSmartspaceRemovalToggle()) {
             bindAndInitFirstWorkspaceScreen();
         }
 
@@ -811,7 +810,7 @@
 
             // We don't want to remove the first screen even if it's empty because that's where
             // first page pinned item would go if it gets turned back on.
-            if (ENABLE_SMARTSPACE_REMOVAL.get() && screenId == FIRST_SCREEN_ID) {
+            if (enableSmartspaceRemovalToggle() && screenId == FIRST_SCREEN_ID) {
                 continue;
             }
 
@@ -1040,7 +1039,7 @@
             CellLayout cl = mWorkspaceScreens.valueAt(i);
             // FIRST_SCREEN_ID can never be removed.
             if (((!FeatureFlags.QSB_ON_FIRST_SCREEN
-                    || shouldShowFirstPageWidget())
+                    || SHOULD_SHOW_FIRST_PAGE_WIDGET)
                     || id > FIRST_SCREEN_ID)
                     && cl.getShortcutsAndWidgets().getChildCount() == 0) {
                 removeScreens.add(id);
@@ -1744,9 +1743,6 @@
 
         final DragView dv;
         if (contentView instanceof View) {
-            if (contentView instanceof LauncherAppWidgetHostView) {
-                mDragController.addDragListener(new AppWidgetHostViewDragListener(mLauncher));
-            }
             dv = mDragController.startDrag(
                     contentView,
                     draggableView,
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 8026d4a..56a7fef 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -470,8 +470,9 @@
      * @param exitSearch Whether to force exit the search state and return to A-Z apps list.
      */
     public void reset(boolean animate, boolean exitSearch) {
+        // Scroll Main and Work RV to top. Search RV is done in `resetSearch`.
         for (int i = 0; i < mAH.size(); i++) {
-            if (mAH.get(i).mRecyclerView != null) {
+            if (i != SEARCH && mAH.get(i).mRecyclerView != null) {
                 mAH.get(i).mRecyclerView.scrollToTop();
             }
         }
@@ -485,10 +486,8 @@
         // Reset the base recycler view after transitioning home.
         updateHeaderScroll(0);
         if (exitSearch) {
-            // Reset the search bar after transitioning home.
+            // Reset the search bar and search RV after transitioning home.
             MAIN_EXECUTOR.getHandler().post(mSearchUiManager::resetSearch);
-            // Animate to A-Z with 0 time to reset the animation with proper state management.
-            animateToSearchState(false, 0);
         }
         if (isSearching()) {
             mWorkManager.reset();
@@ -499,18 +498,15 @@
      * Exits search and returns to A-Z apps list. Scroll to the private space header.
      */
     public void resetAndScrollToPrivateSpaceHeader() {
-        if (mTouchHandler != null) {
-            mTouchHandler.endFastScrolling();
-        }
-
-        // Reset the base recycler view after transitioning home.
-        updateHeaderScroll(0);
-
         // Animate to A-Z with 0 time to reset the animation with proper state management.
+        // We can't rely on `animateToSearchState` with delay inside `resetSearch` because that will
+        // conflict with following scrolling to bottom, so we need it with 0 time here.
         animateToSearchState(false, 0);
 
         MAIN_EXECUTOR.getHandler().post(() -> {
             // Reset the search bar after transitioning home.
+            // When `resetSearch` is called after `animateToSearchState` is finished, the inside
+            // `animateToSearchState` with delay is a just no-op and return early.
             mSearchUiManager.resetSearch();
             // Switch to the main tab
             switchToTab(ActivityAllAppsContainerView.AdapterHolder.MAIN);
@@ -590,12 +586,6 @@
             return;
         }
 
-        if (!FeatureFlags.ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES.get()) {
-            RecyclerView.ItemDecoration decoration = getMainAdapterProvider().getDecorator();
-            getSearchRecyclerView().removeItemDecoration(decoration);
-            getSearchRecyclerView().addItemDecoration(decoration);
-        }
-
         // replaceAppsRVcontainer() needs to use both mUsingTabs value to remove the old view AND
         // showTabs value to create new view. Hence the mUsingTabs new value assignment MUST happen
         // after this call.
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
index a21d7be..16630967 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
@@ -44,7 +44,6 @@
 import com.android.launcher3.R;
 import com.android.launcher3.allapps.search.SearchAdapterProvider;
 import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.views.ActivityContext;
 
 /**
@@ -273,8 +272,8 @@
                             privateProfileManager.isPrivateSpaceItem(adapterItem);
                     if (icon.getAlpha() == 0 || icon.getAlpha() == 1) {
                         icon.setAlpha(isPrivateSpaceItem
-                                && privateProfileManager.getAnimationScrolling()
-                                && privateProfileManager.getAnimate()
+                                && (privateProfileManager.getAnimationScrolling() ||
+                                    privateProfileManager.getAnimate())
                                 && privateProfileManager.getCurrentState() == STATE_ENABLED
                                 ? 0 : 1);
                     }
diff --git a/src/com/android/launcher3/allapps/FloatingMaskView.java b/src/com/android/launcher3/allapps/FloatingMaskView.java
new file mode 100644
index 0000000..606eb03
--- /dev/null
+++ b/src/com/android/launcher3/allapps/FloatingMaskView.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 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.allapps;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import com.android.launcher3.R;
+import com.android.launcher3.views.ActivityContext;
+
+public class FloatingMaskView extends ConstraintLayout {
+
+    private final ActivityContext mActivityContext;
+    private ImageView mBottomBox;
+
+    public FloatingMaskView(Context context) {
+        this(context, null, 0);
+    }
+
+    public FloatingMaskView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public FloatingMaskView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        mActivityContext = ActivityContext.lookupContext(context);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mBottomBox = findViewById(R.id.bottom_box);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();
+        AllAppsRecyclerView allAppsContainerView =
+                mActivityContext.getAppsView().getActiveRecyclerView();
+        if (lp != null) {
+            lp.rightMargin = allAppsContainerView.getPaddingRight();
+            lp.leftMargin = allAppsContainerView.getPaddingLeft();
+            mBottomBox.setMinimumHeight(allAppsContainerView.getPaddingBottom());
+        }
+    }
+}
diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java
index 551fa94..27340a3 100644
--- a/src/com/android/launcher3/allapps/PrivateProfileManager.java
+++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java
@@ -20,7 +20,6 @@
 import static android.view.View.INVISIBLE;
 import static android.view.View.VISIBLE;
 
-import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PRIVATESPACE;
 import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.MAIN;
 import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_ICON;
@@ -28,8 +27,12 @@
 import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_SYS_APPS_DIVIDER;
 import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_NOTHING;
 import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_LOCK_ANIMATION_BEGIN;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_LOCK_ANIMATION_END;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_LOCK_TAP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_SETTINGS_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_BEGIN;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_END;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_UNLOCK_TAP;
 import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
 import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_NOT_PINNABLE;
@@ -57,6 +60,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.constraintlayout.widget.ConstraintLayout;
 import androidx.recyclerview.widget.LinearSmoothScroller;
 import androidx.recyclerview.widget.RecyclerView;
 
@@ -89,10 +93,21 @@
  */
 public class PrivateProfileManager extends UserProfileManager {
     private static final int EXPAND_COLLAPSE_DURATION = 800;
-    private static final int SETTINGS_OPACITY_DURATION = 160;
+    private static final int SETTINGS_OPACITY_DURATION = 400;
+    private static final int TEXT_UNLOCK_OPACITY_DURATION = 300;
+    private static final int TEXT_LOCK_OPACITY_DURATION = 50;
+    private static final int APP_OPACITY_DURATION = 400;
+    private static final int MASK_VIEW_DURATION = 200;
+    private static final int APP_OPACITY_DELAY = 400;
+    private static final int SETTINGS_AND_LOCK_GROUP_TRANSITION_DELAY = 400;
+    private static final int SETTINGS_OPACITY_DELAY = 400;
+    private static final int LOCK_TEXT_OPACITY_DELAY = 500;
+    private static final int MASK_VIEW_DELAY = 400;
+    private static final int NO_DELAY = 0;
     private final ActivityAllAppsContainerView<?> mAllApps;
     private final Predicate<UserHandle> mPrivateProfileMatcher;
     private final int mPsHeaderHeight;
+    private final int mFloatingMaskViewCornerRadius;
     private final RecyclerView.OnScrollListener mOnIdleScrollListener =
             new RecyclerView.OnScrollListener() {
         @Override
@@ -112,6 +127,7 @@
     private Runnable mOnPSHeaderAdded;
     @Nullable
     private RelativeLayout mPSHeader;
+    private ConstraintLayout mFloatingMaskView;
     private final String mLockedStateContentDesc;
     private final String mUnLockedStateContentDesc;
 
@@ -131,6 +147,8 @@
                 .getString(R.string.ps_container_lock_button_content_description);
         mUnLockedStateContentDesc = mAllApps.getContext()
                 .getString(R.string.ps_container_unlock_button_content_description);
+        mFloatingMaskViewCornerRadius = mAllApps.getContext().getResources().getDimensionPixelSize(
+                R.dimen.ps_floating_mask_corner_radius);
     }
 
     /** Adds Private Space Header to the layout. */
@@ -208,6 +226,7 @@
                 .hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED);
         int updatedState = isEnabled ? STATE_ENABLED : STATE_DISABLED;
         setCurrentState(updatedState);
+        mFloatingMaskView = null;
         if (mPSHeader != null) {
             mPSHeader.setAlpha(1);
         }
@@ -445,7 +464,6 @@
         if (getCurrentState() == STATE_ENABLED
                 && isPrivateSpaceSettingsAvailable()) {
             settingsButton.setVisibility(VISIBLE);
-            settingsButton.setAlpha(1f);
             settingsButton.setOnClickListener(
                     view -> {
                         logEvents(LAUNCHER_PRIVATE_SPACE_SETTINGS_TAP);
@@ -484,12 +502,15 @@
                 RecyclerView.LayoutManager layoutManager = allAppsRecyclerView.getLayoutManager();
                 if (layoutManager != null) {
                     startAnimationScroll(allAppsRecyclerView, layoutManager, smoothScroller);
-                    currentItem.decorationInfo = null;
+                    // Preserve decorator if floating mask view exists.
+                    if (mFloatingMaskView == null) {
+                        currentItem.decorationInfo = null;
+                    }
                 }
                 break;
             }
             // Make the private space apps gone to "collapse".
-            if (isPrivateSpaceItem(currentItem)) {
+            if (mFloatingMaskView == null && isPrivateSpaceItem(currentItem)) {
                 RecyclerView.ViewHolder viewHolder =
                         allAppsRecyclerView.findViewHolderForAdapterPosition(i);
                 if (viewHolder != null) {
@@ -590,7 +611,9 @@
         List<BaseAllAppsAdapter.AdapterItem> allAppsAdapterItems =
                 mAllApps.getActiveRecyclerView().getApps().getAdapterItems();
         ValueAnimator alphaAnim = ObjectAnimator.ofFloat(from, to);
-        alphaAnim.setDuration(EXPAND_COLLAPSE_DURATION);
+        alphaAnim.setDuration(APP_OPACITY_DURATION)
+                .setStartDelay(isExpanding ? APP_OPACITY_DELAY : NO_DELAY);
+        alphaAnim.setInterpolator(Interpolators.LINEAR);
         alphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator valueAnimator) {
@@ -625,28 +648,46 @@
             setAnimationRunning(false);
             return;
         }
+        attachFloatingMaskView(expand);
         ViewGroup settingsAndLockGroup = mPSHeader.findViewById(R.id.settingsAndLockGroup);
-        ViewGroup lockButton = mPSHeader.findViewById(R.id.ps_lock_unlock_button);
         if (settingsAndLockGroup.getLayoutTransition() == null) {
             // Set a new transition if the current ViewGroup does not already contain one as each
             // transition should only happen once when applied.
             enableLayoutTransition(settingsAndLockGroup);
         }
+        settingsAndLockGroup.getLayoutTransition().setStartDelay(
+                LayoutTransition.CHANGING,
+                expand ? SETTINGS_AND_LOCK_GROUP_TRANSITION_DELAY : NO_DELAY);
         PropertySetter headerSetter = new AnimatedPropertySetter();
-        ImageButton settingsButton = mPSHeader.findViewById(R.id.ps_settings_button);
-        updateSettingsGearAlpha(settingsButton, expand, headerSetter);
+        headerSetter.add(updateSettingsGearAlpha(expand));
+        headerSetter.add(updateLockTextAlpha(expand));
         AnimatorSet animatorSet = headerSetter.buildAnim();
         animatorSet.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
+                mStatsLogManager.logger().sendToInteractionJankMonitor(
+                        expand
+                                ? LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_BEGIN
+                                : LAUNCHER_PRIVATE_SPACE_LOCK_ANIMATION_BEGIN,
+                        mAllApps.getActiveRecyclerView());
                 // Animate the collapsing of the text at the same time while updating lock button.
-                lockButton.findViewById(R.id.lock_text).setVisibility(expand ? VISIBLE : GONE);
+                mPSHeader.findViewById(R.id.lock_text).setVisibility(expand ? VISIBLE : GONE);
                 setAnimationRunning(true);
             }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                detachFloatingMaskView();
+            }
         });
         animatorSet.addListener(forEndCallback(() -> {
             setAnimationRunning(false);
             getMainRecyclerView().setChildAttachedConsumer(child -> child.setAlpha(1));
+            mStatsLogManager.logger().sendToInteractionJankMonitor(
+                    expand
+                            ? LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_END
+                            : LAUNCHER_PRIVATE_SPACE_LOCK_ANIMATION_END,
+                    mAllApps.getActiveRecyclerView());
             if (!expand) {
                 // Call onAppsUpdated() because it may be canceled when this animation occurs.
                 mAllApps.getPersonalAppList().onAppsUpdated();
@@ -657,13 +698,17 @@
             }
         }));
         if (expand) {
-            animatorSet.playTogether(animateAlphaOfIcons(true));
+            animatorSet.playTogether(animateAlphaOfIcons(true),
+                    translateFloatingMaskView(false));
         } else {
             if (isPrivateSpaceHidden()) {
-                animatorSet.playSequentially(animateAlphaOfIcons(false),
-                        animateCollapseAnimation(), fadeOutHeaderAlpha());
+                animatorSet.playSequentially(translateFloatingMaskView(false),
+                        animateAlphaOfIcons(false),
+                        animateCollapseAnimation(),
+                        fadeOutHeaderAlpha());
             } else {
-                animatorSet.playSequentially(animateAlphaOfIcons(false),
+                animatorSet.playSequentially(translateFloatingMaskView(true),
+                        animateAlphaOfIcons(false),
                         animateCollapseAnimation());
             }
         }
@@ -691,11 +736,34 @@
         return alphaAnim;
     }
 
+    /** Fades out the private space container. */
+    private ValueAnimator translateFloatingMaskView(boolean animateIn) {
+        if (!Flags.privateSpaceFloatingMaskView() || mFloatingMaskView == null) {
+            return new ValueAnimator();
+        }
+        // Translate base on the height amount. Translates out on expand and in on collapse.
+        float floatingMaskViewHeight = getFloatingMaskViewHeight();
+        float from = animateIn ? floatingMaskViewHeight : 0;
+        float to = animateIn ? 0 : floatingMaskViewHeight;
+        ValueAnimator alphaAnim = ObjectAnimator.ofFloat(from, to);
+        alphaAnim.setDuration(MASK_VIEW_DURATION);
+        alphaAnim.setStartDelay(MASK_VIEW_DELAY);
+        alphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator valueAnimator) {
+                mFloatingMaskView.setTranslationY((float) valueAnimator.getAnimatedValue());
+            }
+        });
+        return alphaAnim;
+    }
+
     /** Animates the layout changes when the text of the button becomes visible/gone. */
     private void enableLayoutTransition(ViewGroup settingsAndLockGroup) {
         LayoutTransition settingsAndLockTransition = new LayoutTransition();
         settingsAndLockTransition.enableTransitionType(LayoutTransition.CHANGING);
         settingsAndLockTransition.setDuration(EXPAND_COLLAPSE_DURATION);
+        settingsAndLockTransition.setInterpolator(LayoutTransition.CHANGING,
+                Interpolators.STANDARD);
         settingsAndLockTransition.addTransitionListener(new LayoutTransition.TransitionListener() {
             @Override
             public void startTransition(LayoutTransition transition, ViewGroup viewGroup,
@@ -712,11 +780,44 @@
     }
 
     /** Change the settings gear alpha when expanded or collapsed. */
-    private void updateSettingsGearAlpha(ImageButton settingsButton, boolean expand,
-            PropertySetter setter) {
-        float toAlpha = expand ? 1 : 0;
-        setter.setFloat(settingsButton, VIEW_ALPHA, toAlpha, Interpolators.LINEAR)
-                .setDuration(SETTINGS_OPACITY_DURATION).setStartDelay(0);
+    private ValueAnimator updateSettingsGearAlpha(boolean expand) {
+        if (mPSHeader == null) {
+            return new ValueAnimator();
+        }
+        float from = expand ? 0 : 1;
+        float to = expand ? 1 : 0;
+        ValueAnimator settingsAlphaAnim = ObjectAnimator.ofFloat(from, to);
+        settingsAlphaAnim.setDuration(SETTINGS_OPACITY_DURATION);
+        settingsAlphaAnim.setStartDelay(expand ? SETTINGS_OPACITY_DELAY : NO_DELAY);
+        settingsAlphaAnim.setInterpolator(Interpolators.LINEAR);
+        settingsAlphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator valueAnimator) {
+                mPSHeader.findViewById(R.id.ps_settings_button)
+                        .setAlpha((float) valueAnimator.getAnimatedValue());
+            }
+        });
+        return settingsAlphaAnim;
+    }
+
+    private ValueAnimator updateLockTextAlpha(boolean expand) {
+        if (mPSHeader == null) {
+            return new ValueAnimator();
+        }
+        float from = expand ? 0 : 1;
+        float to = expand ? 1 : 0;
+        ValueAnimator alphaAnim = ObjectAnimator.ofFloat(from, to);
+        alphaAnim.setDuration(expand ? TEXT_UNLOCK_OPACITY_DURATION : TEXT_LOCK_OPACITY_DURATION);
+        alphaAnim.setStartDelay(expand ? LOCK_TEXT_OPACITY_DELAY : NO_DELAY);
+        alphaAnim.setInterpolator(Interpolators.LINEAR);
+        alphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator valueAnimator) {
+                mPSHeader.findViewById(R.id.lock_text).setAlpha(
+                        (float) valueAnimator.getAnimatedValue());
+            }
+        });
+        return alphaAnim;
     }
 
     void expandPrivateSpace() {
@@ -747,6 +848,28 @@
         });
     }
 
+    private void attachFloatingMaskView(boolean expand) {
+        if (!Flags.privateSpaceFloatingMaskView()) {
+            return;
+        }
+        mFloatingMaskView = (FloatingMaskView) mAllApps.getLayoutInflater().inflate(
+                R.layout.private_space_mask_view, mAllApps, false);
+        mAllApps.addView(mFloatingMaskView);
+        // Translate off the screen first if its collapsing so this header view isn't visible to
+        // user when animation starts.
+        if (!expand) {
+            mFloatingMaskView.setTranslationY(getFloatingMaskViewHeight());
+        }
+        mFloatingMaskView.setVisibility(VISIBLE);
+    }
+
+    private void detachFloatingMaskView() {
+        if (mFloatingMaskView != null) {
+            mAllApps.removeView(mFloatingMaskView);
+        }
+        mFloatingMaskView = null;
+    }
+
     /** Starts the smooth scroll with the provided smoothScroller and add idle listener. */
     private void startAnimationScroll(AllAppsRecyclerView allAppsRecyclerView,
             RecyclerView.LayoutManager layoutManager, RecyclerView.SmoothScroller smoothScroller) {
@@ -756,6 +879,10 @@
         allAppsRecyclerView.addOnScrollListener(mOnIdleScrollListener);
     }
 
+    private float getFloatingMaskViewHeight() {
+        return mFloatingMaskViewCornerRadius + getMainRecyclerView().getPaddingBottom();
+    }
+
     AllAppsRecyclerView getMainRecyclerView() {
         return mAllApps.mAH.get(ActivityAllAppsContainerView.AdapterHolder.MAIN).mRecyclerView;
     }
diff --git a/src/com/android/launcher3/allapps/UserProfileManager.java b/src/com/android/launcher3/allapps/UserProfileManager.java
index 6a1f37a..3351ee3 100644
--- a/src/com/android/launcher3/allapps/UserProfileManager.java
+++ b/src/com/android/launcher3/allapps/UserProfileManager.java
@@ -52,11 +52,11 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface UserProfileState { }
 
+    protected final StatsLogManager mStatsLogManager;
     @UserProfileState
     private int mCurrentState;
 
     private final UserManager mUserManager;
-    private final StatsLogManager mStatsLogManager;
     private final UserCache mUserCache;
 
     protected UserProfileManager(UserManager userManager,
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index 19c3ebe..ec45415 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -31,6 +31,7 @@
 import com.android.launcher3.ExtendedEditText;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.search.SearchAlgorithm;
 import com.android.launcher3.search.SearchCallback;
 import com.android.launcher3.views.ActivityContext;
@@ -143,7 +144,7 @@
 
     @Override
     public void onFocusChange(View view, boolean hasFocus) {
-        if (!hasFocus) {
+        if (!hasFocus && !FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
             mInput.hideKeyboard();
         }
     }
diff --git a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
index ab47097..8121d2a 100644
--- a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
+++ b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
@@ -22,13 +22,9 @@
 import android.os.Handler;
 
 import androidx.annotation.AnyThread;
-import androidx.annotation.NonNull;
 
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
-import com.android.launcher3.model.AllAppsList;
-import com.android.launcher3.model.BaseModelUpdateTask;
-import com.android.launcher3.model.BgDataModel;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.search.SearchAlgorithm;
 import com.android.launcher3.search.SearchCallback;
@@ -67,16 +63,12 @@
 
     @Override
     public void doSearch(String query, SearchCallback<AdapterItem> callback) {
-        mAppState.getModel().enqueueModelUpdateTask(new BaseModelUpdateTask() {
-            @Override
-            public void execute(@NonNull final LauncherAppState app,
-                    @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
-                ArrayList<AdapterItem> result = getTitleMatchResult(apps.data, query);
-                if (mAddNoResultsMessage && result.isEmpty()) {
-                    result.add(getEmptyMessageAdapterItem(query));
-                }
-                mResultHandler.post(() -> callback.onSearchResult(query, result));
+        mAppState.getModel().enqueueModelUpdateTask((taskController, dataModel, apps) ->  {
+            ArrayList<AdapterItem> result = getTitleMatchResult(apps.data, query);
+            if (mAddNoResultsMessage && result.isEmpty()) {
+                result.add(getEmptyMessageAdapterItem(query));
             }
+            mResultHandler.post(() -> callback.onSearchResult(query, result));
         });
     }
 
diff --git a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
index 64fd237..4a8c96b 100644
--- a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
@@ -19,8 +19,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import androidx.recyclerview.widget.RecyclerView;
-
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.allapps.AllAppsGridAdapter;
 import com.android.launcher3.model.data.ItemInfo;
@@ -30,13 +28,10 @@
  * Provides views for local search results.
  */
 public class DefaultSearchAdapterProvider extends SearchAdapterProvider<ActivityContext> {
-
-    private final RecyclerView.ItemDecoration mDecoration;
     private View mHighlightedView;
 
     public DefaultSearchAdapterProvider(ActivityContext launcher) {
         super(launcher);
-        mDecoration = new RecyclerView.ItemDecoration() { };
     }
 
     @Override
@@ -74,11 +69,6 @@
     }
 
     @Override
-    public RecyclerView.ItemDecoration getDecorator() {
-        return mDecoration;
-    }
-
-    @Override
     public void clearHighlightedItem() {
         mHighlightedView = null;
     }
diff --git a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
index 15756f5..82c9c90 100644
--- a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
@@ -20,8 +20,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import androidx.recyclerview.widget.RecyclerView;
-
 import com.android.launcher3.allapps.AllAppsGridAdapter;
 import com.android.launcher3.views.ActivityContext;
 
@@ -50,11 +48,6 @@
     public abstract View getHighlightedItem();
 
     /**
-     * Returns the item decorator.
-     */
-    public abstract RecyclerView.ItemDecoration getDecorator();
-
-    /**
      * Clear the highlighted view.
      */
     public abstract void clearHighlightedItem();
diff --git a/src/com/android/launcher3/apppairs/AppPairIcon.java b/src/com/android/launcher3/apppairs/AppPairIcon.java
index 1f73241..32445ec 100644
--- a/src/com/android/launcher3/apppairs/AppPairIcon.java
+++ b/src/com/android/launcher3/apppairs/AppPairIcon.java
@@ -30,6 +30,8 @@
 
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Flags;
+import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
 import com.android.launcher3.Reorderable;
@@ -85,6 +87,11 @@
                 : activity.getLayoutInflater();
         AppPairIcon icon = (AppPairIcon) inflater.inflate(resId, group, false);
 
+        if (Flags.enableFocusOutline() && activity instanceof Launcher) {
+            icon.setOnFocusChangeListener(((Launcher) activity).getFocusHandler());
+            icon.setDefaultFocusHighlightEnabled(false);
+        }
+
         // Sort contents, so that left-hand app comes first
         appPairInfo.getContents().sort(Comparator.comparingInt(a -> a.rank));
 
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 3badc64..4b908bf 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -16,7 +16,6 @@
 
 package com.android.launcher3.config;
 
-import static com.android.launcher3.BuildConfig.WIDGET_ON_FIRST_SCREEN;
 import static com.android.launcher3.config.FeatureFlags.BooleanFlag.DISABLED;
 import static com.android.launcher3.config.FeatureFlags.BooleanFlag.ENABLED;
 import static com.android.wm.shell.Flags.enableTaskbarNavbarUnification;
@@ -62,15 +61,6 @@
      * and set a default value for the flag. This will be the default value on Debug builds.
      * <p>
      */
-    // TODO(Block 1): Clean up flags
-    public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = getReleaseFlag(
-            270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", ENABLED,
-            "Enable option to replace decorator-based search result backgrounds with drawables");
-
-    public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = getReleaseFlag(
-            270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", ENABLED,
-            "Enable option to launch search results using the new view container transitions");
-
     // TODO(Block 2): Clean up flags
     public static final BooleanFlag ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH = getDebugFlag(270395073,
             "ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH", DISABLED,
@@ -135,17 +125,6 @@
             "MULTI_SELECT_EDIT_MODE", DISABLED, "Enable new multi-select edit mode "
                     + "for home screen");
 
-    public static final BooleanFlag SMARTSPACE_AS_A_WIDGET = getDebugFlag(299181941,
-            "SMARTSPACE_AS_A_WIDGET", DISABLED, "Enable SmartSpace as a widget");
-
-    public static boolean shouldShowFirstPageWidget() {
-        return SMARTSPACE_AS_A_WIDGET.get() && WIDGET_ON_FIRST_SCREEN;
-    }
-
-    public static final BooleanFlag ENABLE_SMARTSPACE_REMOVAL = getDebugFlag(290799975,
-            "ENABLE_SMARTSPACE_REMOVAL", DISABLED, "Enable SmartSpace removal for "
-            + "home screen");
-
     // TODO(Block 11): Clean up flags
     public static final BooleanFlag FOLDABLE_SINGLE_PAGE = getDebugFlag(270395274,
             "FOLDABLE_SINGLE_PAGE", DISABLED, "Use a single page for the workspace");
@@ -215,9 +194,6 @@
             "ENABLE_EXPANDING_PAUSE_WORK_BUTTON", DISABLED,
             "Expand and collapse pause work button while scrolling");
 
-    public static final BooleanFlag COLLECT_SEARCH_HISTORY = getReleaseFlag(270391455,
-            "COLLECT_SEARCH_HISTORY", DISABLED, "Allow launcher to collect search history for log");
-
     // Aconfig migration complete for ENABLE_TWOLINE_ALLAPPS.
     public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(270390937,
             "ENABLE_TWOLINE_ALLAPPS", DISABLED, "Enables two line label inside all apps.");
diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java
index 5d2bb3a..be5f8f7 100644
--- a/src/com/android/launcher3/folder/FolderNameProvider.java
+++ b/src/com/android/launcher3/folder/FolderNameProvider.java
@@ -28,11 +28,12 @@
 import androidx.annotation.WorkerThread;
 
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.model.AllAppsList;
-import com.android.launcher3.model.BaseModelUpdateTask;
 import com.android.launcher3.model.BgDataModel;
+import com.android.launcher3.model.ModelTaskController;
 import com.android.launcher3.model.StringCache;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.CollectionInfo;
@@ -191,10 +192,11 @@
         nameInfos.setLabel(labels.length - 1, label, 1.0f);
     }
 
-    private class FolderNameWorker extends BaseModelUpdateTask {
+    private class FolderNameWorker implements ModelUpdateTask {
+
         @Override
-        public void execute(@NonNull final LauncherAppState app,
-                @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
+        public void execute(@NonNull ModelTaskController taskController,
+                @NonNull BgDataModel dataModel, @NonNull AllAppsList apps) {
             mCollectionInfos = dataModel.collections.clone();
             mAppInfos = Arrays.asList(apps.copyData());
         }
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 50d2b43..ae8f1d5 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -24,7 +24,7 @@
 import static com.android.launcher3.BubbleTextView.DISPLAY_WORKSPACE;
 import static com.android.launcher3.DeviceProfile.DEFAULT_SCALE;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
-import static com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget;
+import static com.android.launcher3.Utilities.SHOULD_SHOW_FIRST_PAGE_WIDGET;
 import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
 import static com.android.launcher3.model.ModelUtils.getMissingHotseatRanks;
 
@@ -76,7 +76,6 @@
 import com.android.launcher3.celllayout.CellPosMapper;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.folder.FolderIcon;
-import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.model.BgDataModel;
 import com.android.launcher3.model.BgDataModel.FixedContainerItems;
 import com.android.launcher3.model.WidgetItem;
@@ -107,7 +106,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.ConcurrentLinkedQueue;
 
 /**
  * Utility class for generating the preview of Launcher for a given InvariantDeviceProfile.
@@ -126,44 +124,12 @@
      */
     public static class PreviewContext extends SandboxContext {
 
-        private final InvariantDeviceProfile mIdp;
-        private final ConcurrentLinkedQueue<LauncherIconsForPreview> mIconPool =
-                new ConcurrentLinkedQueue<>();
-
         public PreviewContext(Context base, InvariantDeviceProfile idp) {
             super(base);
-            mIdp = idp;
             putObject(InvariantDeviceProfile.INSTANCE, idp);
             putObject(LauncherAppState.INSTANCE,
                     new LauncherAppState(this, null /* iconCacheFileName */));
         }
-
-        /**
-         * Creates a new LauncherIcons for the preview, skipping the global pool
-         */
-        public LauncherIcons newLauncherIcons(Context context) {
-            LauncherIconsForPreview launcherIconsForPreview = mIconPool.poll();
-            if (launcherIconsForPreview != null) {
-                return launcherIconsForPreview;
-            }
-            return new LauncherIconsForPreview(context, mIdp.fillResIconDpi, mIdp.iconBitmapSize,
-                    -1 /* poolId */);
-        }
-
-        private final class LauncherIconsForPreview extends LauncherIcons {
-
-            private LauncherIconsForPreview(Context context, int fillResIconDpi, int iconBitmapSize,
-                    int poolId) {
-                super(context, fillResIconDpi, iconBitmapSize, poolId);
-            }
-
-            @Override
-            public void recycle() {
-                // Clear any temporary state variables
-                clear();
-                mIconPool.offer(this);
-            }
-        }
     }
 
     private final List<OnDeviceProfileChangeListener> mDpChangeListeners = new ArrayList<>();
@@ -221,10 +187,11 @@
                 launcherWidgetSpanInfo;
 
         CellLayout firstScreen = mRootView.findViewById(R.id.workspace);
-        firstScreen.setPadding(mDp.workspacePadding.left + mDp.cellLayoutPaddingPx.left,
+        firstScreen.setPadding(
+                mDp.workspacePadding.left + mDp.cellLayoutPaddingPx.left,
                 mDp.workspacePadding.top + mDp.cellLayoutPaddingPx.top,
-                (mDp.isTwoPanels ? mDp.cellLayoutBorderSpacePx.x / 2
-                        : mDp.workspacePadding.right) + mDp.cellLayoutPaddingPx.right,
+                mDp.isTwoPanels ? (mDp.cellLayoutBorderSpacePx.x / 2)
+                        : (mDp.workspacePadding.right + mDp.cellLayoutPaddingPx.right),
                 mDp.workspacePadding.bottom + mDp.cellLayoutPaddingPx.bottom
         );
         mWorkspaceScreens.put(FIRST_SCREEN_ID, firstScreen);
@@ -232,7 +199,7 @@
         if (mDp.isTwoPanels) {
             CellLayout rightPanel = mRootView.findViewById(R.id.workspace_right);
             rightPanel.setPadding(
-                    mDp.cellLayoutBorderSpacePx.x / 2  + mDp.cellLayoutPaddingPx.left,
+                    mDp.cellLayoutBorderSpacePx.x / 2,
                     mDp.workspacePadding.top + mDp.cellLayoutPaddingPx.top,
                     mDp.workspacePadding.right + mDp.cellLayoutPaddingPx.right,
                     mDp.workspacePadding.bottom + mDp.cellLayoutPaddingPx.bottom
@@ -538,7 +505,7 @@
 
         // Add first page QSB
         if (FeatureFlags.QSB_ON_FIRST_SCREEN && dataModel.isFirstPagePinnedItemEnabled
-                && !shouldShowFirstPageWidget()) {
+                && !SHOULD_SHOW_FIRST_PAGE_WIDGET) {
             CellLayout firstScreen = mWorkspaceScreens.get(FIRST_SCREEN_ID);
             View qsb = mHomeElementInflater.inflate(R.layout.qsb_preview, firstScreen, false);
             CellLayoutLayoutParams lp = new CellLayoutLayoutParams(
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 329f717..04d8ac0 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -373,8 +373,13 @@
                     infoInOut.user, activityInfoProvider, mLauncherActivityInfoCachingLogic,
                     usePkgIcon, useLowResIcon);
             applyPackageEntry(packageEntry, infoInOut, entry);
-        } else {
+        } else if (useLowResIcon || !entry.bitmap.isNullOrLowRes()
+                || infoInOut.bitmap.isNullOrLowRes()) {
+            // Only use cache entry if it will not downgrade the current bitmap in infoInOut
             applyCacheEntry(entry, infoInOut);
+        } else {
+            Log.d(TAG, "getTitleAndIcon: Cache entry bitmap was a downgrade of existing bitmap"
+                    + " in ItemInfo. Skipping.");
         }
     }
 
diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java
index 7331c6f..884d448 100644
--- a/src/com/android/launcher3/icons/LauncherIcons.java
+++ b/src/com/android/launcher3/icons/LauncherIcons.java
@@ -17,6 +17,7 @@
 package com.android.launcher3.icons;
 
 import android.content.Context;
+import android.graphics.drawable.AdaptiveIconDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
 
@@ -25,83 +26,57 @@
 import com.android.launcher3.Flags;
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.graphics.IconShape;
-import com.android.launcher3.graphics.LauncherPreviewRenderer;
 import com.android.launcher3.pm.UserCache;
+import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.SafeCloseable;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.UserIconInfo;
 
+import java.util.concurrent.ConcurrentLinkedQueue;
+
 /**
  * Wrapper class to provide access to {@link BaseIconFactory} and also to provide pool of this class
  * that are threadsafe.
  */
 public class LauncherIcons extends BaseIconFactory implements AutoCloseable {
 
-    private static final Object sPoolSync = new Object();
-    private static LauncherIcons sPool;
-    private static int sPoolId = 0;
+    private static final MainThreadInitializedObject<Pool> POOL =
+            new MainThreadInitializedObject<>(Pool::new);
 
     /**
      * Return a new Message instance from the global pool. Allows us to
      * avoid allocating new objects in many cases.
      */
     public static LauncherIcons obtain(Context context) {
-        if (context instanceof LauncherPreviewRenderer.PreviewContext) {
-            return ((LauncherPreviewRenderer.PreviewContext) context).newLauncherIcons(context);
-        }
-
-        int poolId;
-        synchronized (sPoolSync) {
-            if (sPool != null) {
-                LauncherIcons m = sPool;
-                sPool = m.next;
-                m.next = null;
-                return m;
-            }
-            poolId = sPoolId;
-        }
-
-        InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(context);
-        return new LauncherIcons(context, idp.fillResIconDpi, idp.iconBitmapSize, poolId);
+        return POOL.get(context).obtain();
     }
 
-    public static void clearPool() {
-        synchronized (sPoolSync) {
-            sPool = null;
-            sPoolId++;
-        }
+    public static void clearPool(Context context) {
+        POOL.get(context).close();
     }
 
-    private final int mPoolId;
-
-    private LauncherIcons next;
+    private final ConcurrentLinkedQueue<LauncherIcons> mPool;
 
     private MonochromeIconFactory mMonochromeIconFactory;
 
-    protected LauncherIcons(Context context, int fillResIconDpi, int iconBitmapSize, int poolId) {
+    protected LauncherIcons(Context context, int fillResIconDpi, int iconBitmapSize,
+            ConcurrentLinkedQueue<LauncherIcons> pool) {
         super(context, fillResIconDpi, iconBitmapSize,
                 IconShape.INSTANCE.get(context).getShape().enableShapeDetection());
         mMonoIconEnabled = Themes.isThemedIconEnabled(context);
-        mPoolId = poolId;
+        mPool = pool;
     }
 
     /**
      * Recycles a LauncherIcons that may be in-use.
      */
     public void recycle() {
-        synchronized (sPoolSync) {
-            if (sPoolId != mPoolId) {
-                return;
-            }
-            // Clear any temporary state variables
-            clear();
-
-            next = sPool;
-            sPool = this;
-        }
+        clear();
+        mPool.add(this);
     }
 
     @Override
-    protected Drawable getMonochromeDrawable(Drawable base) {
+    protected Drawable getMonochromeDrawable(AdaptiveIconDrawable base) {
         Drawable mono = super.getMonochromeDrawable(base);
         if (mono != null || !Flags.forceMonochromeAppIcons()) {
             return mono;
@@ -122,4 +97,33 @@
     public void close() {
         recycle();
     }
+
+    private static class Pool implements SafeCloseable {
+
+        private final Context mContext;
+
+        @NonNull
+        private ConcurrentLinkedQueue<LauncherIcons> mPool = new ConcurrentLinkedQueue<>();
+
+        private Pool(Context context) {
+            mContext = context;
+        }
+
+        public LauncherIcons obtain() {
+            ConcurrentLinkedQueue<LauncherIcons> pool = mPool;
+            LauncherIcons m = pool.poll();
+
+            if (m == null) {
+                InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mContext);
+                return new LauncherIcons(mContext, idp.fillResIconDpi, idp.iconBitmapSize, pool);
+            } else {
+                return m;
+            }
+        }
+
+        @Override
+        public void close() {
+            mPool = new ConcurrentLinkedQueue<>();
+        }
+    }
 }
diff --git a/src/com/android/launcher3/icons/MonochromeIconFactory.java b/src/com/android/launcher3/icons/MonochromeIconFactory.java
index 511dcc7..2854d51 100644
--- a/src/com/android/launcher3/icons/MonochromeIconFactory.java
+++ b/src/com/android/launcher3/icons/MonochromeIconFactory.java
@@ -100,20 +100,12 @@
      * Creates a monochrome version of the provided drawable
      */
     @WorkerThread
-    public Drawable wrap(Drawable icon) {
-        if (icon instanceof AdaptiveIconDrawable) {
-            AdaptiveIconDrawable aid = (AdaptiveIconDrawable) icon;
-            mFlatCanvas.drawColor(Color.BLACK);
-            drawDrawable(aid.getBackground());
-            drawDrawable(aid.getForeground());
-            generateMono();
-            return new ClippedMonoDrawable(this);
-        } else {
-            mFlatCanvas.drawColor(Color.WHITE);
-            drawDrawable(icon);
-            generateMono();
-            return this;
-        }
+    public Drawable wrap(AdaptiveIconDrawable icon) {
+        mFlatCanvas.drawColor(Color.BLACK);
+        drawDrawable(icon.getBackground());
+        drawDrawable(icon.getForeground());
+        generateMono();
+        return new ClippedMonoDrawable(this);
     }
 
     @WorkerThread
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 441bbb5..861631d 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -769,7 +769,31 @@
         LAUNCHER_PRIVATE_SPACE_USER_INSTALLED_APPS_COUNT(1672),
 
         @UiEvent(doc = "Number of preinstalled Private profile apps, shown under separator line")
-        LAUNCHER_PRIVATE_SPACE_PREINSTALLED_APPS_COUNT(1673)
+        LAUNCHER_PRIVATE_SPACE_PREINSTALLED_APPS_COUNT(1673),
+
+        @UiEvent(doc = "Private space lock animation started")
+        LAUNCHER_PRIVATE_SPACE_LOCK_ANIMATION_BEGIN(1725),
+
+        @UiEvent(doc = "Private space lock animation finished")
+        LAUNCHER_PRIVATE_SPACE_LOCK_ANIMATION_END(1726),
+
+        @UiEvent(doc = "Private space unlock animation started")
+        LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_BEGIN(1727),
+
+        @UiEvent(doc = "Private space unlock animation finished")
+        LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_END(1728),
+
+        @UiEvent(doc = "User rotates whilst in Overview / RecentsView")
+        LAUNCHER_OVERVIEW_ORIENTATION_CHANGED(1762),
+
+        @UiEvent(doc = "User launches Overview from 3 button navigation")
+        LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_3_BUTTON(1763),
+
+        @UiEvent(doc = "User launches Overview from alt+tab keyboard quick switch")
+        LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_QUICK_SWITCH(1764),
+
+        @UiEvent(doc = "User launches Overview from meta+tab keyboard shortcut")
+        LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_SHORTCUT(1765),
 
         // ADD MORE
         ;
@@ -1205,7 +1229,7 @@
      * Creates a new instance of {@link StatsLogManager} based on provided context.
      */
     public static StatsLogManager newInstance(Context context) {
-        return Overrides.getObject(StatsLogManager.class,
-                context.getApplicationContext(), R.string.stats_log_manager_class);
+        return Overrides.getObject(
+                StatsLogManager.class, context, R.string.stats_log_manager_class);
     }
 }
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index 3fa6da4..427fb97 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -26,9 +26,10 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
-import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherModel.CallbackTask;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
 import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.logging.FileLog;
 import com.android.launcher3.model.BgDataModel.Callbacks;
 import com.android.launcher3.model.data.AppInfo;
@@ -50,7 +51,7 @@
 /**
  * Task to add auto-created workspace items.
  */
-public class AddWorkspaceItemsTask extends BaseModelUpdateTask {
+public class AddWorkspaceItemsTask implements ModelUpdateTask {
 
     private static final String LOG = "AddWorkspaceItemsTask";
 
@@ -77,16 +78,17 @@
         mItemSpaceFinder = itemSpaceFinder;
     }
 
+
     @Override
-    public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
-            @NonNull final AllAppsList apps) {
+    public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
+            @NonNull AllAppsList apps) {
         if (mItemList.isEmpty()) {
             return;
         }
 
         final ArrayList<ItemInfo> addedItemsFinal = new ArrayList<>();
         final IntArray addedWorkspaceScreensFinal = new IntArray();
-        final Context context = app.getContext();
+        final Context context = taskController.getApp().getContext();
 
         synchronized (dataModel) {
             IntArray workspaceScreens = dataModel.collectWorkspaceScreens();
@@ -128,8 +130,8 @@
 
             for (ItemInfo item : filteredItems) {
                 // Find appropriate space for the item.
-                int[] coords = mItemSpaceFinder.findSpaceForItem(app, dataModel, workspaceScreens,
-                        addedWorkspaceScreensFinal, item.spanX, item.spanY);
+                int[] coords = mItemSpaceFinder.findSpaceForItem(taskController.getApp(), dataModel,
+                        workspaceScreens, addedWorkspaceScreensFinal, item.spanX, item.spanY);
                 int screenId = coords[0];
 
                 ItemInfo itemInfo;
@@ -176,8 +178,8 @@
                     if (hasActivity) {
                         // App was installed while launcher was in the background,
                         // or app was already installed for another user.
-                        itemInfo = new AppInfo(app.getContext(), activities.get(0), item.user)
-                                .makeWorkspaceItem(app.getContext());
+                        itemInfo = new AppInfo(context, activities.get(0), item.user)
+                                .makeWorkspaceItem(context);
 
                         if (shortcutExists(dataModel, itemInfo.getIntent(), itemInfo.user)) {
                             // We need this additional check here since we treat all auto added
@@ -187,16 +189,17 @@
                             continue;
                         }
 
+                        IconCache cache = taskController.getApp().getIconCache();
                         WorkspaceItemInfo wii = (WorkspaceItemInfo) itemInfo;
                         wii.title = "";
-                        wii.bitmap = app.getIconCache().getDefaultIcon(item.user);
-                        app.getIconCache().getTitleAndIcon(wii,
+                        wii.bitmap = cache.getDefaultIcon(item.user);
+                        cache.getTitleAndIcon(wii,
                                 ((WorkspaceItemInfo) itemInfo).usingLowResIcon());
                     }
                 }
 
                 // Add the shortcut to the db
-                getModelWriter().addItemToDatabase(itemInfo,
+                taskController.getModelWriter().addItemToDatabase(itemInfo,
                         LauncherSettings.Favorites.CONTAINER_DESKTOP, screenId,
                         coords[1], coords[2]);
 
@@ -209,7 +212,7 @@
         }
 
         if (!addedItemsFinal.isEmpty()) {
-            scheduleCallbackTask(new CallbackTask() {
+            taskController.scheduleCallbackTask(new CallbackTask() {
                 @Override
                 public void execute(@NonNull Callbacks callbacks) {
                     final ArrayList<ItemInfo> addAnimated = new ArrayList<>();
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java
index 39c1243..64ebbf3 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -60,7 +60,7 @@
 
     private static final String TAG = "AllAppsList";
     private static final Consumer<AppInfo> NO_OP_CONSUMER = a -> { };
-
+    private static final boolean DEBUG = true;
 
     public static final int DEFAULT_APPLICATIONS_NUMBER = 42;
 
@@ -220,6 +220,11 @@
                     updatedAppInfos.add(appInfo);
                 } else if (installInfo.state == PackageInstallInfo.STATUS_FAILED
                         && !appInfo.isAppStartable()) {
+                    if (DEBUG) {
+                        Log.w(TAG, "updatePromiseInstallInfo: removing app due to install"
+                                + " failure and appInfo not startable."
+                                + " package=" + appInfo.getTargetPackage());
+                    }
                     removeApp(i);
                 }
             }
@@ -301,6 +306,7 @@
             Context context, String packageName, UserHandle user) {
         final ApiWrapper apiWrapper = ApiWrapper.INSTANCE.get(context);
         final UserCache userCache = UserCache.getInstance(context);
+        final PackageManagerHelper pmHelper = PackageManagerHelper.INSTANCE.get(context);
         final List<LauncherActivityInfo> matches = context.getSystemService(LauncherApps.class)
                 .getActivityList(packageName, user);
         if (matches.size() > 0) {
@@ -311,7 +317,10 @@
                 if (user.equals(applicationInfo.user)
                         && packageName.equals(applicationInfo.componentName.getPackageName())) {
                     if (!findActivity(matches, applicationInfo.componentName)) {
-                        Log.w(TAG, "Changing shortcut target due to app component name change.");
+                        if (DEBUG) {
+                            Log.w(TAG, "Changing shortcut target due to app component name change."
+                                    + " package=" + packageName);
+                        }
                         removeApp(i);
                     }
                 }
@@ -330,12 +339,16 @@
                     applicationInfo.sectionName = mIndex.computeSectionName(applicationInfo.title);
                     applicationInfo.intent = launchIntent;
                     AppInfo.updateRuntimeFlagsForActivityTarget(applicationInfo, info,
-                            userCache.getUserInfo(user), apiWrapper);
+                            userCache.getUserInfo(user), apiWrapper, pmHelper);
                     mDataChanged = true;
                 }
             }
         } else {
             // Remove all data for this package.
+            if (DEBUG) {
+                Log.w(TAG, "updatePromiseInstallInfo: no Activities matched updated package,"
+                        + " removing all apps from package=" + packageName);
+            }
             for (int i = data.size() - 1; i >= 0; i--) {
                 final AppInfo applicationInfo = data.get(i);
                 if (user.equals(applicationInfo.user)
diff --git a/src/com/android/launcher3/model/BaseLauncherBinder.java b/src/com/android/launcher3/model/BaseLauncherBinder.java
index 41dbe4e..e6ade61 100644
--- a/src/com/android/launcher3/model/BaseLauncherBinder.java
+++ b/src/com/android/launcher3/model/BaseLauncherBinder.java
@@ -17,8 +17,8 @@
 package com.android.launcher3.model;
 
 import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
+import static com.android.launcher3.Flags.enableSmartspaceRemovalToggle;
 import static com.android.launcher3.Flags.enableWorkspaceInflation;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVAL;
 import static com.android.launcher3.model.ItemInstallQueue.FLAG_LOADER_RUNNING;
 import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -327,7 +327,7 @@
             executeCallbacksTask(c -> {
                 c.clearPendingBinds();
                 c.startBinding();
-                if (ENABLE_SMARTSPACE_REMOVAL.get()) {
+                if (enableSmartspaceRemovalToggle()) {
                     c.setIsFirstPagePinnedItemEnabled(
                             mBgDataModel.isFirstPagePinnedItemEnabled);
                 }
diff --git a/src/com/android/launcher3/model/BaseModelUpdateTask.java b/src/com/android/launcher3/model/BaseModelUpdateTask.java
deleted file mode 100644
index 529c30a..0000000
--- a/src/com/android/launcher3/model/BaseModelUpdateTask.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2016 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.model;
-
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel;
-import com.android.launcher3.LauncherModel.CallbackTask;
-import com.android.launcher3.LauncherModel.ModelUpdateTask;
-import com.android.launcher3.celllayout.CellPosMapper;
-import com.android.launcher3.model.BgDataModel.Callbacks;
-import com.android.launcher3.model.BgDataModel.FixedContainerItems;
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.PackageUserKey;
-import com.android.launcher3.widget.model.WidgetsListBaseEntry;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-/**
- * Extension of {@link ModelUpdateTask} with some utility methods
- */
-public abstract class BaseModelUpdateTask implements ModelUpdateTask {
-
-    private static final boolean DEBUG_TASKS = false;
-    private static final String TAG = "BaseModelUpdateTask";
-
-    // Nullabilities are explicitly omitted here because these are late-init fields,
-    // They will be non-null after init(), which is always the case in enqueueModelUpdateTask().
-    private LauncherAppState mApp;
-    private LauncherModel mModel;
-    private BgDataModel mDataModel;
-    private AllAppsList mAllAppsList;
-    private Executor mUiExecutor;
-
-    public void init(@NonNull final LauncherAppState app, @NonNull final LauncherModel model,
-            @NonNull final BgDataModel dataModel, @NonNull final AllAppsList allAppsList,
-            @NonNull final Executor uiExecutor) {
-        mApp = app;
-        mModel = model;
-        mDataModel = dataModel;
-        mAllAppsList = allAppsList;
-        mUiExecutor = uiExecutor;
-    }
-
-    @Override
-    public final void run() {
-        boolean isModelLoaded = Objects.requireNonNull(mModel).isModelLoaded();
-        if (!isModelLoaded) {
-            if (DEBUG_TASKS) {
-                Log.d(TAG, "Ignoring model task since loader is pending=" + this);
-            }
-            // Loader has not yet run.
-            return;
-        }
-        execute(mApp, mDataModel, mAllAppsList);
-    }
-
-    /**
-     * Execute the actual task. Called on the worker thread.
-     */
-    public abstract void execute(@NonNull LauncherAppState app,
-            @NonNull BgDataModel dataModel, @NonNull AllAppsList apps);
-
-    /**
-     * Schedules a {@param task} to be executed on the current callbacks.
-     */
-    public final void scheduleCallbackTask(@NonNull final CallbackTask task) {
-        for (final Callbacks cb : mModel.getCallbacks()) {
-            mUiExecutor.execute(() -> task.execute(cb));
-        }
-    }
-
-    public ModelWriter getModelWriter() {
-        // Updates from model task, do not deal with icon position in hotseat. Also no need to
-        // verify changes as the ModelTasks always push the changes to callbacks
-        return mModel.getWriter(false /* verifyChanges */, CellPosMapper.DEFAULT, null);
-    }
-
-    public void bindUpdatedWorkspaceItems(@NonNull final List<WorkspaceItemInfo> allUpdates) {
-        // Bind workspace items
-        List<WorkspaceItemInfo> workspaceUpdates = allUpdates.stream()
-                .filter(info -> info.id != ItemInfo.NO_ID)
-                .collect(Collectors.toList());
-        if (!workspaceUpdates.isEmpty()) {
-            scheduleCallbackTask(c -> c.bindWorkspaceItemsChanged(workspaceUpdates));
-        }
-
-        // Bind extra items if any
-        allUpdates.stream()
-                .mapToInt(info -> info.container)
-                .distinct()
-                .mapToObj(mDataModel.extraItems::get)
-                .filter(Objects::nonNull)
-                .forEach(this::bindExtraContainerItems);
-    }
-
-    public void bindExtraContainerItems(@NonNull final FixedContainerItems item) {
-        scheduleCallbackTask(c -> c.bindExtraContainerItems(item));
-    }
-
-    public void bindDeepShortcuts(@NonNull final BgDataModel dataModel) {
-        final HashMap<ComponentKey, Integer> shortcutMapCopy =
-                new HashMap<>(dataModel.deepShortcutMap);
-        scheduleCallbackTask(callbacks -> callbacks.bindDeepShortcutMap(shortcutMapCopy));
-    }
-
-    public void bindUpdatedWidgets(@NonNull final BgDataModel dataModel) {
-        final ArrayList<WidgetsListBaseEntry> widgets =
-                dataModel.widgetsModel.getWidgetsListForPicker(mApp.getContext());
-        scheduleCallbackTask(c -> c.bindAllWidgets(widgets));
-    }
-
-    public void deleteAndBindComponentsRemoved(final Predicate<ItemInfo> matcher,
-            @Nullable final String reason) {
-        getModelWriter().deleteItemsFromDatabase(matcher, reason);
-
-        // Call the components-removed callback
-        scheduleCallbackTask(c -> c.bindWorkspaceComponentsRemoved(matcher));
-    }
-
-    public void bindApplicationsIfNeeded() {
-        if (mAllAppsList.getAndResetChangeFlag()) {
-            AppInfo[] apps = mAllAppsList.copyData();
-            int flags = mAllAppsList.getFlags();
-            Map<PackageUserKey, Integer> packageUserKeytoUidMap = Arrays.stream(apps).collect(
-                    Collectors.toMap(
-                            appInfo -> new PackageUserKey(appInfo.componentName.getPackageName(),
-                                    appInfo.user), appInfo -> appInfo.uid, (a, b) -> a));
-            scheduleCallbackTask(c -> c.bindAllApplications(apps, flags, packageUserKeytoUidMap));
-        }
-    }
-}
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index d5de4ce..9a9fa5b 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -19,8 +19,8 @@
 
 import static com.android.launcher3.BuildConfig.QSB_ON_FIRST_SCREEN;
 import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVAL;
-import static com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget;
+import static com.android.launcher3.Flags.enableSmartspaceRemovalToggle;
+import static com.android.launcher3.Utilities.SHOULD_SHOW_FIRST_PAGE_WIDGET;
 import static com.android.launcher3.shortcuts.ShortcutRequest.PINNED;
 
 import static java.util.stream.Collectors.groupingBy;
@@ -138,7 +138,7 @@
      */
     public int lastLoadId = -1;
     public boolean isFirstPagePinnedItemEnabled = QSB_ON_FIRST_SCREEN
-            && !ENABLE_SMARTSPACE_REMOVAL.get();
+            && !enableSmartspaceRemovalToggle();
 
     /**
      * Clears all the data
@@ -163,7 +163,7 @@
             }
         }
         if ((FeatureFlags.QSB_ON_FIRST_SCREEN
-                && !shouldShowFirstPageWidget())
+                && !SHOULD_SHOW_FIRST_PAGE_WIDGET)
                 || screenSet.isEmpty()) {
             screenSet.add(Workspace.FIRST_SCREEN_ID);
         }
diff --git a/src/com/android/launcher3/model/CacheDataUpdatedTask.java b/src/com/android/launcher3/model/CacheDataUpdatedTask.java
index 57fefaa..66b4fd9 100644
--- a/src/com/android/launcher3/model/CacheDataUpdatedTask.java
+++ b/src/com/android/launcher3/model/CacheDataUpdatedTask.java
@@ -20,7 +20,7 @@
 
 import androidx.annotation.NonNull;
 
-import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -31,7 +31,7 @@
 /**
  * Handles changes due to cache updates.
  */
-public class CacheDataUpdatedTask extends BaseModelUpdateTask {
+public class CacheDataUpdatedTask implements ModelUpdateTask {
 
     public static final int OP_CACHE_UPDATE = 1;
     public static final int OP_SESSION_UPDATE = 2;
@@ -52,9 +52,9 @@
     }
 
     @Override
-    public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
-            @NonNull final AllAppsList apps) {
-        IconCache iconCache = app.getIconCache();
+    public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
+            @NonNull AllAppsList apps) {
+        IconCache iconCache = taskController.getApp().getIconCache();
         ArrayList<WorkspaceItemInfo> updatedShortcuts = new ArrayList<>();
 
         synchronized (dataModel) {
@@ -69,8 +69,8 @@
             });
             apps.updateIconsAndLabels(mPackages, mUser);
         }
-        bindUpdatedWorkspaceItems(updatedShortcuts);
-        bindApplicationsIfNeeded();
+        taskController.bindUpdatedWorkspaceItems(updatedShortcuts);
+        taskController.bindApplicationsIfNeeded();
     }
 
     public boolean isValidShortcut(@NonNull final WorkspaceItemInfo si) {
diff --git a/src/com/android/launcher3/model/DatabaseHelper.java b/src/com/android/launcher3/model/DatabaseHelper.java
index 88ca009..8368256 100644
--- a/src/com/android/launcher3/model/DatabaseHelper.java
+++ b/src/com/android/launcher3/model/DatabaseHelper.java
@@ -16,7 +16,7 @@
 package com.android.launcher3.model;
 
 import static com.android.launcher3.LauncherSettings.Favorites.addTableToDb;
-import static com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget;
+import static com.android.launcher3.Utilities.SHOULD_SHOW_FIRST_PAGE_WIDGET;
 import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
 
 import android.content.ContentValues;
@@ -259,7 +259,7 @@
             }
             case 30: {
                 if (FeatureFlags.QSB_ON_FIRST_SCREEN
-                        && !shouldShowFirstPageWidget()) {
+                        && !SHOULD_SHOW_FIRST_PAGE_WIDGET) {
                     // Clean up first row in screen 0 as it might contain junk data.
                     Log.d(TAG, "Cleaning up first row");
                     db.delete(Favorites.TABLE_NAME,
@@ -505,7 +505,7 @@
 
     public int loadFavorites(SQLiteDatabase db, AutoInstallsLayout loader) {
         // TODO: Use multiple loaders with fall-back and transaction.
-        int count = loader.loadLayout(db, new IntArray());
+        int count = loader.loadLayout(db);
 
         // Ensure that the max ids are initialized
         mMaxItemId = initializeMaxItemId(db);
diff --git a/src/com/android/launcher3/model/GridSizeMigrationUtil.java b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
index f24a7c1..ad32fc2 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationUtil.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
@@ -16,10 +16,10 @@
 
 package com.android.launcher3.model;
 
+import static com.android.launcher3.Flags.enableSmartspaceRemovalToggle;
 import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
 import static com.android.launcher3.LauncherSettings.Favorites.TMP_TABLE;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVAL;
-import static com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget;
+import static com.android.launcher3.Utilities.SHOULD_SHOW_FIRST_PAGE_WIDGET;
 import static com.android.launcher3.model.LoaderTask.SMARTSPACE_ON_HOME_SCREEN;
 import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
 import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
@@ -348,9 +348,9 @@
         final Point trg = new Point(trgX, trgY);
         final Point next = new Point(0, screenId == 0
                 && (FeatureFlags.QSB_ON_FIRST_SCREEN
-                && (!ENABLE_SMARTSPACE_REMOVAL.get() || LauncherPrefs.getPrefs(destReader.mContext)
+                && (!enableSmartspaceRemovalToggle() || LauncherPrefs.getPrefs(destReader.mContext)
                 .getBoolean(SMARTSPACE_ON_HOME_SCREEN, true))
-                && !shouldShowFirstPageWidget())
+                && !SHOULD_SHOW_FIRST_PAGE_WIDGET)
                 ? 1 /* smartspace */ : 0);
         List<DbEntry> existedEntries = destReader.mWorkspaceEntriesByScreenId.get(screenId);
         if (existedEntries != null) {
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index b17684c..84130c7 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -17,7 +17,7 @@
 package com.android.launcher3.model;
 
 import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
-import static com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget;
+import static com.android.launcher3.Utilities.SHOULD_SHOW_FIRST_PAGE_WIDGET;
 
 import android.content.ComponentName;
 import android.content.ContentValues;
@@ -57,6 +57,7 @@
 import com.android.launcher3.util.GridOccupancy;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.IntSparseArrayMap;
+import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.UserIconInfo;
 
 import java.net.URISyntaxException;
@@ -73,6 +74,7 @@
 
     private final LauncherAppState mApp;
     private final Context mContext;
+    private final PackageManagerHelper mPmHelper;
     private final IconCache mIconCache;
     private final InvariantDeviceProfile mIDP;
     private final @Nullable LauncherRestoreEventLogger mRestoreEventLogger;
@@ -114,6 +116,7 @@
     public int restoreFlag;
 
     public LoaderCursor(Cursor cursor, LauncherAppState app, UserManagerState userManagerState,
+            PackageManagerHelper pmHelper,
             @Nullable LauncherRestoreEventLogger restoreEventLogger) {
         super(cursor);
 
@@ -121,6 +124,7 @@
         allUsers = userManagerState.allUsers;
         mContext = app.getContext();
         mIconCache = app.getIconCache();
+        mPmHelper = pmHelper;
         mIDP = app.getInvariantDeviceProfile();
         mRestoreEventLogger = restoreEventLogger;
 
@@ -368,7 +372,7 @@
 
         if (mActivityInfo != null) {
             AppInfo.updateRuntimeFlagsForActivityTarget(info, mActivityInfo, userIconInfo,
-                    ApiWrapper.INSTANCE.get(mContext));
+                    ApiWrapper.INSTANCE.get(mContext), mPmHelper);
         }
 
         // from the db
@@ -550,7 +554,8 @@
         if (!mOccupied.containsKey(item.screenId)) {
             GridOccupancy screen = new GridOccupancy(countX + 1, countY + 1);
             if (item.screenId == Workspace.FIRST_SCREEN_ID && (FeatureFlags.QSB_ON_FIRST_SCREEN
-                    && !shouldShowFirstPageWidget() && isFirstPagePinnedItemEnabled)) {
+                    && !SHOULD_SHOW_FIRST_PAGE_WIDGET
+                    && isFirstPagePinnedItemEnabled)) {
                 // Mark the first X columns (X is width of the search container) in the first row as
                 // occupied (if the feature is enabled) in order to account for the search
                 // container.
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 77bc32e..0d40a24 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -18,11 +18,11 @@
 
 import static com.android.launcher3.BuildConfig.WIDGET_ON_FIRST_SCREEN;
 import static com.android.launcher3.Flags.enableLauncherBrMetricsFixed;
+import static com.android.launcher3.Flags.enableSmartspaceAsAWidget;
+import static com.android.launcher3.Flags.enableSmartspaceRemovalToggle;
 import static com.android.launcher3.LauncherPrefs.IS_FIRST_LOAD_AFTER_RESTORE;
 import static com.android.launcher3.LauncherPrefs.SHOULD_SHOW_SMARTSPACE;
 import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVAL;
-import static com.android.launcher3.config.FeatureFlags.SMARTSPACE_AS_A_WIDGET;
 import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
 import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
 import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION;
@@ -322,13 +322,13 @@
             verifyNotStopped();
             LauncherPrefs prefs = LauncherPrefs.get(mApp.getContext());
 
-            if (SMARTSPACE_AS_A_WIDGET.get() && prefs.get(SHOULD_SHOW_SMARTSPACE)) {
+            if (enableSmartspaceAsAWidget() && prefs.get(SHOULD_SHOW_SMARTSPACE)) {
                 mLauncherBinder.bindSmartspaceWidget();
                 // Turn off pref.
                 prefs.putSync(SHOULD_SHOW_SMARTSPACE.to(false));
                 logASplit("bindSmartspaceWidget");
                 verifyNotStopped();
-            } else if (!SMARTSPACE_AS_A_WIDGET.get() && WIDGET_ON_FIRST_SCREEN
+            } else if (!enableSmartspaceAsAWidget() && WIDGET_ON_FIRST_SCREEN
                     && !prefs.get(LauncherPrefs.SHOULD_SHOW_SMARTSPACE)) {
                 // Turn on pref.
                 prefs.putSync(SHOULD_SHOW_SMARTSPACE.to(true));
@@ -399,7 +399,7 @@
             logASplit("workspaceDelegateItems");
         }
         mBgDataModel.isFirstPagePinnedItemEnabled = FeatureFlags.QSB_ON_FIRST_SCREEN
-                && (!ENABLE_SMARTSPACE_REMOVAL.get() || LauncherPrefs.getPrefs(
+                && (!enableSmartspaceRemovalToggle() || LauncherPrefs.getPrefs(
                 mApp.getContext()).getBoolean(SMARTSPACE_ON_HOME_SCREEN, true));
     }
 
@@ -435,7 +435,8 @@
             mShortcutKeyToPinnedShortcuts = new HashMap<>();
             final LoaderCursor c = new LoaderCursor(
                     dbController.query(TABLE_NAME, null, selection, null, null),
-                    mApp, mUserManagerState, mIsRestoreFromBackup ? restoreEventLogger : null);
+                    mApp, mUserManagerState, mPmHelper,
+                    mIsRestoreFromBackup ? restoreEventLogger : null);
             final Bundle extras = c.getExtras();
             mDbName = extras == null ? null : extras.getString(ModelDbController.EXTRA_DB_NAME);
             try {
@@ -697,7 +698,7 @@
             for (int i = 0; i < apps.size(); i++) {
                 LauncherActivityInfo app = apps.get(i);
                 AppInfo appInfo = new AppInfo(app, mUserCache.getUserInfo(user),
-                        ApiWrapper.INSTANCE.get(mApp.getContext()), quietMode);
+                        ApiWrapper.INSTANCE.get(mApp.getContext()), mPmHelper, quietMode);
                 if (Flags.enableSupportForArchiving() && app.getApplicationInfo().isArchived) {
                     // For archived apps, include progress info in case there is a pending
                     // install session post restart of device.
diff --git a/src/com/android/launcher3/model/ModelDelegate.java b/src/com/android/launcher3/model/ModelDelegate.java
index 8360b14..2264d35 100644
--- a/src/com/android/launcher3/model/ModelDelegate.java
+++ b/src/com/android/launcher3/model/ModelDelegate.java
@@ -26,6 +26,7 @@
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
 import com.android.launcher3.shortcuts.ShortcutKey;
+import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.ResourceBasedOverride;
 
 import java.io.FileDescriptor;
@@ -41,15 +42,16 @@
      * Creates and initializes a new instance of the delegate
      */
     public static ModelDelegate newInstance(
-            Context context, LauncherAppState app, AllAppsList appsList, BgDataModel dataModel,
-            boolean isPrimaryInstance) {
+            Context context, LauncherAppState app, PackageManagerHelper pmHelper,
+            AllAppsList appsList, BgDataModel dataModel, boolean isPrimaryInstance) {
         ModelDelegate delegate = Overrides.getObject(
                 ModelDelegate.class, context, R.string.model_delegate_class);
-        delegate.init(app, appsList, dataModel, isPrimaryInstance);
+        delegate.init(app, pmHelper, appsList, dataModel, isPrimaryInstance);
         return delegate;
     }
 
     protected final Context mContext;
+    protected PackageManagerHelper mPmHelper;
     protected LauncherAppState mApp;
     protected AllAppsList mAppsList;
     protected BgDataModel mDataModel;
@@ -62,9 +64,10 @@
     /**
      * Initializes the object with the given params.
      */
-    private void init(LauncherAppState app, AllAppsList appsList,
+    private void init(LauncherAppState app, PackageManagerHelper pmHelper, AllAppsList appsList,
             BgDataModel dataModel, boolean isPrimaryInstance) {
         this.mApp = app;
+        this.mPmHelper = pmHelper;
         this.mAppsList = appsList;
         this.mDataModel = dataModel;
         this.mIsPrimaryInstance = isPrimaryInstance;
diff --git a/src/com/android/launcher3/model/ModelTaskController.kt b/src/com/android/launcher3/model/ModelTaskController.kt
new file mode 100644
index 0000000..266ed0c
--- /dev/null
+++ b/src/com/android/launcher3/model/ModelTaskController.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2024 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.model
+
+import com.android.launcher3.LauncherAppState
+import com.android.launcher3.LauncherModel
+import com.android.launcher3.LauncherModel.CallbackTask
+import com.android.launcher3.celllayout.CellPosMapper
+import com.android.launcher3.model.BgDataModel.FixedContainerItems
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.WorkspaceItemInfo
+import com.android.launcher3.util.PackageUserKey
+import java.util.Objects
+import java.util.concurrent.Executor
+import java.util.function.Predicate
+
+/** Class with utility methods and properties for running a LauncherModel Task */
+class ModelTaskController(
+    val app: LauncherAppState,
+    val dataModel: BgDataModel,
+    val allAppsList: AllAppsList,
+    private val model: LauncherModel,
+    private val uiExecutor: Executor
+) {
+
+    /** Schedules a {@param task} to be executed on the current callbacks. */
+    fun scheduleCallbackTask(task: CallbackTask) {
+        for (cb in model.callbacks) {
+            uiExecutor.execute { task.execute(cb) }
+        }
+    }
+
+    /**
+     * Updates from model task, do not deal with icon position in hotseat. Also no need to verify
+     * changes as the ModelTasks always push the changes to callbacks
+     */
+    fun getModelWriter() = model.getWriter(false /* verifyChanges */, CellPosMapper.DEFAULT, null)
+
+    fun bindUpdatedWorkspaceItems(allUpdates: List<WorkspaceItemInfo>) {
+        // Bind workspace items
+        val workspaceUpdates =
+            allUpdates.stream().filter { info -> info.id != ItemInfo.NO_ID }.toList()
+        if (workspaceUpdates.isNotEmpty()) {
+            scheduleCallbackTask { it.bindWorkspaceItemsChanged(workspaceUpdates) }
+        }
+
+        // Bind extra items if any
+        allUpdates
+            .stream()
+            .mapToInt { info: WorkspaceItemInfo -> info.container }
+            .distinct()
+            .mapToObj { dataModel.extraItems.get(it) }
+            .filter { Objects.nonNull(it) }
+            .forEach { bindExtraContainerItems(it) }
+    }
+
+    fun bindExtraContainerItems(item: FixedContainerItems) {
+        scheduleCallbackTask { it.bindExtraContainerItems(item) }
+    }
+
+    fun bindDeepShortcuts(dataModel: BgDataModel) {
+        val shortcutMapCopy = HashMap(dataModel.deepShortcutMap)
+        scheduleCallbackTask { it.bindDeepShortcutMap(shortcutMapCopy) }
+    }
+
+    fun bindUpdatedWidgets(dataModel: BgDataModel) {
+        val widgets = dataModel.widgetsModel.getWidgetsListForPicker(app.context)
+        scheduleCallbackTask { it.bindAllWidgets(widgets) }
+    }
+
+    fun deleteAndBindComponentsRemoved(matcher: Predicate<ItemInfo?>, reason: String?) {
+        getModelWriter().deleteItemsFromDatabase(matcher, reason)
+
+        // Call the components-removed callback
+        scheduleCallbackTask { it.bindWorkspaceComponentsRemoved(matcher) }
+    }
+
+    fun bindApplicationsIfNeeded() {
+        if (allAppsList.getAndResetChangeFlag()) {
+            val apps = allAppsList.copyData()
+            val flags = allAppsList.flags
+            val packageUserKeyToUidMap =
+                apps.associateBy(
+                    keySelector = { PackageUserKey(it.componentName!!.packageName, it.user) },
+                    valueTransform = { it.uid }
+                )
+            scheduleCallbackTask { it.bindAllApplications(apps, flags, packageUserKeyToUidMap) }
+        }
+    }
+}
diff --git a/src/com/android/launcher3/model/PackageIncrementalDownloadUpdatedTask.java b/src/com/android/launcher3/model/PackageIncrementalDownloadUpdatedTask.java
index b9fba9d..f924a9f 100644
--- a/src/com/android/launcher3/model/PackageIncrementalDownloadUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageIncrementalDownloadUpdatedTask.java
@@ -19,7 +19,7 @@
 
 import androidx.annotation.NonNull;
 
-import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -31,7 +31,7 @@
 /**
  * Handles updates due to incremental download progress updates.
  */
-public class PackageIncrementalDownloadUpdatedTask extends BaseModelUpdateTask {
+public class PackageIncrementalDownloadUpdatedTask implements ModelUpdateTask {
 
     @NonNull
     private final UserHandle mUser;
@@ -49,8 +49,8 @@
     }
 
     @Override
-    public void execute(@NonNull LauncherAppState app, @NonNull final BgDataModel dataModel,
-            @NonNull final AllAppsList appsList) {
+    public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
+            @NonNull AllAppsList appsList) {
         PackageInstallInfo downloadInfo = new PackageInstallInfo(
                 mPackageName,
                 PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING,
@@ -62,11 +62,11 @@
             if (!updatedAppInfos.isEmpty()) {
                 for (AppInfo appInfo : updatedAppInfos) {
                     appInfo.runtimeStatusFlags &= ~ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
-                    scheduleCallbackTask(
+                    taskController.scheduleCallbackTask(
                             c -> c.bindIncrementalDownloadProgressUpdated(appInfo));
                 }
             }
-            bindApplicationsIfNeeded();
+            taskController.bindApplicationsIfNeeded();
         }
 
         final ArrayList<WorkspaceItemInfo> updatedWorkspaceItems = new ArrayList<>();
@@ -79,6 +79,6 @@
                 }
             });
         }
-        bindUpdatedWorkspaceItems(updatedWorkspaceItems);
+        taskController.bindUpdatedWorkspaceItems(updatedWorkspaceItems);
     }
 }
diff --git a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
index 2457a42..d238213 100644
--- a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
+++ b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
@@ -15,12 +15,13 @@
  */
 package com.android.launcher3.model;
 
+import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 
 import androidx.annotation.NonNull;
 
-import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@@ -33,7 +34,7 @@
 /**
  * Handles changes due to a sessions updates for a currently installing app.
  */
-public class PackageInstallStateChangedTask extends BaseModelUpdateTask {
+public class PackageInstallStateChangedTask implements ModelUpdateTask {
 
     @NonNull
     private final PackageInstallInfo mInstallInfo;
@@ -43,16 +44,17 @@
     }
 
     @Override
-    public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
-            @NonNull final AllAppsList apps) {
+    public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
+            @NonNull AllAppsList apps) {
         if (mInstallInfo.state == PackageInstallInfo.STATUS_INSTALLED) {
             try {
                 // For instant apps we do not get package-add. Use setting events to update
                 // any pinned icons.
-                ApplicationInfo ai = app.getContext()
+                Context context = taskController.getApp().getContext();
+                ApplicationInfo ai = context
                         .getPackageManager().getApplicationInfo(mInstallInfo.packageName, 0);
-                if (InstantAppResolver.newInstance(app.getContext()).isInstantApp(ai)) {
-                    app.getModel().newModelCallbacks()
+                if (InstantAppResolver.newInstance(context).isInstantApp(ai)) {
+                    taskController.getApp().getModel().newModelCallbacks()
                             .onPackageAdded(ai.packageName, mInstallInfo.user);
                 }
             } catch (PackageManager.NameNotFoundException e) {
@@ -66,10 +68,11 @@
             List<AppInfo> updatedAppInfos = apps.updatePromiseInstallInfo(mInstallInfo);
             if (!updatedAppInfos.isEmpty()) {
                 for (AppInfo appInfo : updatedAppInfos) {
-                    scheduleCallbackTask(c -> c.bindIncrementalDownloadProgressUpdated(appInfo));
+                    taskController.scheduleCallbackTask(
+                            c -> c.bindIncrementalDownloadProgressUpdated(appInfo));
                 }
             }
-            bindApplicationsIfNeeded();
+            taskController.bindApplicationsIfNeeded();
         }
 
         synchronized (dataModel) {
@@ -90,7 +93,8 @@
             }
 
             if (!updates.isEmpty()) {
-                scheduleCallbackTask(callbacks -> callbacks.bindRestoreItemsChange(updates));
+                taskController.scheduleCallbackTask(
+                        callbacks -> callbacks.bindRestoreItemsChange(updates));
             }
         }
     }
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 6432d33..079987b 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -36,9 +36,9 @@
 
 import com.android.launcher3.Flags;
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.Utilities;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.logging.FileLog;
@@ -71,11 +71,11 @@
  * or when a user availability changes.
  */
 @SuppressWarnings("NewApi")
-public class PackageUpdatedTask extends BaseModelUpdateTask {
+public class PackageUpdatedTask implements ModelUpdateTask {
 
     // TODO(b/290090023): Set to false after root causing is done.
-    private static final boolean DEBUG = true;
     private static final String TAG = "PackageUpdatedTask";
+    private static final boolean DEBUG = true;
 
     public static final int OP_NONE = 0;
     public static final int OP_ADD = 1;
@@ -102,8 +102,9 @@
     }
 
     @Override
-    public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
-            @NonNull final AllAppsList appsList) {
+    public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
+            @NonNull AllAppsList appsList) {
+        final LauncherAppState app = taskController.getApp();
         final Context context = app.getContext();
         final IconCache iconCache = app.getIconCache();
 
@@ -116,29 +117,39 @@
                 : ItemInfoMatcher.ofPackages(packageSet, mUser);
         final HashSet<ComponentName> removedComponents = new HashSet<>();
         final HashMap<String, List<LauncherActivityInfo>> activitiesLists = new HashMap<>();
-
+        if (DEBUG) {
+            Log.d(TAG, "Package updated: mOp=" + getOpString()
+                    + " packages=" + Arrays.toString(packages));
+        }
         switch (mOp) {
             case OP_ADD: {
                 for (int i = 0; i < N; i++) {
-                    if (DEBUG) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
                     iconCache.updateIconsForPkg(packages[i], mUser);
                     if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) {
+                        if (DEBUG) {
+                            Log.d(TAG, "OP_ADD: PROMISE_APPS_IN_ALL_APPS enabled:"
+                                    + " removing promise icon apps from package=" + packages[i]);
+                        }
                         appsList.removePackage(packages[i], mUser);
                     }
-                    activitiesLists.put(
-                            packages[i], appsList.addPackage(context, packages[i], mUser));
+                    activitiesLists.put(packages[i],
+                            appsList.addPackage(context, packages[i], mUser));
                 }
                 flagOp = FlagOp.NO_OP.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
                 break;
             }
             case OP_UPDATE:
-                try (SafeCloseable t =
-                             appsList.trackRemoves(a -> removedComponents.add(a.componentName))) {
+                try (SafeCloseable t = appsList.trackRemoves(a -> {
+                    Log.d(TAG, "OP_UPDATE - AllAppsList.trackRemoves callback:"
+                            + " removed component=" + a.componentName
+                            + " id=" + a.id
+                            + " Look for earlier AllAppsList logs to find more information.");
+                    removedComponents.add(a.componentName);
+                })) {
                     for (int i = 0; i < N; i++) {
-                        if (DEBUG) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);
                         iconCache.updateIconsForPkg(packages[i], mUser);
-                        activitiesLists.put(
-                                packages[i], appsList.updatePackage(context, packages[i], mUser));
+                        activitiesLists.put(packages[i],
+                                appsList.updatePackage(context, packages[i], mUser));
                     }
                 }
                 // Since package was just updated, the target must be available now.
@@ -146,14 +157,15 @@
                 break;
             case OP_REMOVE: {
                 for (int i = 0; i < N; i++) {
-                    FileLog.d(TAG, "Removing app icon: " + packages[i]);
                     iconCache.removeIconsForPkg(packages[i], mUser);
                 }
                 // Fall through
             }
             case OP_UNAVAILABLE:
                 for (int i = 0; i < N; i++) {
-                    if (DEBUG) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
+                    if (DEBUG) {
+                        Log.d(TAG, getOpString() + ": removing package=" + packages[i]);
+                    }
                     appsList.removePackage(packages[i], mUser);
                 }
                 flagOp = FlagOp.NO_OP.addFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
@@ -162,7 +174,6 @@
             case OP_UNSUSPEND:
                 flagOp = FlagOp.NO_OP.setFlag(
                         WorkspaceItemInfo.FLAG_DISABLED_SUSPENDED, mOp == OP_SUSPEND);
-                if (DEBUG) Log.d(TAG, "mAllAppsList.(un)suspend " + N);
                 appsList.updateDisabledFlags(matcher, flagOp);
                 break;
             case OP_USER_AVAILABILITY_CHANGE: {
@@ -192,7 +203,7 @@
                 break;
         }
 
-        bindApplicationsIfNeeded();
+        taskController.bindApplicationsIfNeeded();
 
         final IntSet removedShortcuts = new IntSet();
         // Shortcuts to keep even if the corresponding app was removed
@@ -233,7 +244,16 @@
                                                 .query(ShortcutRequest.PINNED);
                                 if (shortcut.isEmpty()) {
                                     isTargetValid = false;
+                                    if (DEBUG) {
+                                        Log.d(TAG, "Pinned Shortcut not found for updated"
+                                                + " package=" + si.getTargetPackage());
+                                    }
                                 } else {
+                                    if (DEBUG) {
+                                        Log.d(TAG, "Found pinned shortcut for updated"
+                                                + " package=" + si.getTargetPackage()
+                                                + ", isTargetValid=" + isTargetValid);
+                                    }
                                     si.updateFromDeepShortcutInfo(shortcut.get(0), context);
                                     infoUpdated = true;
                                 }
@@ -241,6 +261,7 @@
                                 isTargetValid = context.getSystemService(LauncherApps.class)
                                         .isActivityEnabled(cn, mUser);
                             }
+
                             if (!isTargetValid && (si.hasStatusFlag(
                                     FLAG_RESTORED_ICON | FLAG_AUTOINSTALL_ICON)
                                     || si.isArchived())) {
@@ -248,12 +269,25 @@
                                     infoUpdated = true;
                                 } else if (si.hasPromiseIconUi()) {
                                     removedShortcuts.add(si.id);
+                                    if (DEBUG) {
+                                        FileLog.w(TAG, "Removing restored shortcut promise icon"
+                                                + " that no longer points to valid component."
+                                                + " id=" + si.id
+                                                + ", package=" + si.getTargetPackage()
+                                                + ", status=" + si.status
+                                                + ", isArchived=" + si.isArchived());
+                                    }
                                     return;
                                 }
                             } else if (!isTargetValid) {
                                 removedShortcuts.add(si.id);
-                                FileLog.e(TAG, "Restored shortcut no longer valid "
-                                        + si.getIntent());
+                                if (DEBUG) {
+                                    FileLog.w(TAG, "Removing shortcut that no longer points to"
+                                            + " valid component."
+                                            + " id=" + si.id
+                                            + " package=" + si.getTargetPackage()
+                                            + " status=" + si.status);
+                                }
                                 return;
                             } else {
                                 si.status = WorkspaceItemInfo.DEFAULT;
@@ -268,6 +302,8 @@
                         if (isNewApkAvailable) {
                             List<LauncherActivityInfo> activities = activitiesLists.get(
                                     packageName);
+                            // TODO: See if we can migrate this to
+                            //  AppInfo#updateRuntimeFlagsForActivityTarget
                             si.setProgressLevel(
                                     activities == null || activities.isEmpty()
                                             ? 100
@@ -305,7 +341,7 @@
                         updatedWorkspaceItems.add(si);
                     }
                     if (infoUpdated && si.id != ItemInfo.NO_ID) {
-                        getModelWriter().updateItemInDatabase(si);
+                        taskController.getModelWriter().updateItemInDatabase(si);
                     }
                 });
 
@@ -324,20 +360,21 @@
                         widgetInfo.restoreStatus |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
 
                         widgets.add(widgetInfo);
-                        getModelWriter().updateItemInDatabase(widgetInfo);
+                        taskController.getModelWriter().updateItemInDatabase(widgetInfo);
                     }
                 }
             }
 
-            bindUpdatedWorkspaceItems(updatedWorkspaceItems);
+            taskController.bindUpdatedWorkspaceItems(updatedWorkspaceItems);
             if (!removedShortcuts.isEmpty()) {
-                deleteAndBindComponentsRemoved(
+                taskController.deleteAndBindComponentsRemoved(
                         ItemInfoMatcher.ofItemIds(removedShortcuts),
-                        "removed because the target component is invalid");
+                        "removing shortcuts with invalid target components."
+                                + " ids=" + removedShortcuts);
             }
 
             if (!widgets.isEmpty()) {
-                scheduleCallbackTask(c -> c.bindWidgetsRestored(widgets));
+                taskController.scheduleCallbackTask(c -> c.bindWidgetsRestored(widgets));
             }
         }
 
@@ -345,6 +382,9 @@
         if (mOp == OP_REMOVE) {
             // Mark all packages in the broadcast to be removed
             Collections.addAll(removedPackages, packages);
+            if (DEBUG) {
+                Log.d(TAG, "OP_REMOVE: removing packages=" + Arrays.toString(packages));
+            }
 
             // No need to update the removedComponents as
             // removedPackages is a super-set of removedComponents
@@ -353,6 +393,10 @@
             final LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
             for (int i=0; i<N; i++) {
                 if (!launcherApps.isPackageEnabled(packages[i], mUser)) {
+                    if (DEBUG) {
+                        Log.d(TAG, "OP_UPDATE:"
+                                + " package " + packages[i] + " is disabled, removing package.");
+                    }
                     removedPackages.add(packages[i]);
                 }
             }
@@ -363,7 +407,7 @@
                     ItemInfoMatcher.ofPackages(removedPackages, mUser)
                             .or(ItemInfoMatcher.ofComponents(removedComponents, mUser))
                             .and(ItemInfoMatcher.ofItemIds(forceKeepShortcuts).negate());
-            deleteAndBindComponentsRemoved(removeMatch,
+            taskController.deleteAndBindComponentsRemoved(removeMatch,
                     "removed because the corresponding package or component is removed. "
                             + "mOp=" + mOp + " removedPackages=" + removedPackages.stream().collect(
                                     Collectors.joining(",", "[", "]"))
@@ -382,7 +426,7 @@
             for (int i = 0; i < N; i++) {
                 dataModel.widgetsModel.update(app, new PackageUserKey(packages[i], mUser));
             }
-            bindUpdatedWidgets(dataModel);
+            taskController.bindUpdatedWidgets(dataModel);
         }
     }
 
@@ -398,7 +442,8 @@
             return false;
         }
         // Try to find the best match activity.
-        Intent intent = new PackageManagerHelper(context).getAppLaunchIntent(packageName, mUser);
+        Intent intent = PackageManagerHelper.INSTANCE.get(context)
+                .getAppLaunchIntent(packageName, mUser);
         if (intent != null) {
             si.intent = intent;
             si.status = WorkspaceItemInfo.DEFAULT;
@@ -406,4 +451,18 @@
         }
         return false;
     }
+
+    private String getOpString() {
+        return switch (mOp) {
+            case OP_NONE -> "NONE";
+            case OP_ADD -> "ADD";
+            case OP_UPDATE -> "UPDATE";
+            case OP_REMOVE -> "REMOVE";
+            case OP_UNAVAILABLE -> "UNAVAILABLE";
+            case OP_SUSPEND -> "SUSPEND";
+            case OP_UNSUSPEND -> "UNSUSPEND";
+            case OP_USER_AVAILABILITY_CHANGE -> "USER_AVAILABILITY_CHANGE";
+            default -> "UNKNOWN";
+        };
+    }
 }
diff --git a/src/com/android/launcher3/model/ReloadStringCacheTask.java b/src/com/android/launcher3/model/ReloadStringCacheTask.java
index 34f7057..3d974d6 100644
--- a/src/com/android/launcher3/model/ReloadStringCacheTask.java
+++ b/src/com/android/launcher3/model/ReloadStringCacheTask.java
@@ -17,13 +17,13 @@
 
 import androidx.annotation.NonNull;
 
-import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
 
 /**
  * Handles updates due to changes in Device Policy Management resources triggered by
  * {@link android.app.admin.DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED}.
  */
-public class ReloadStringCacheTask extends BaseModelUpdateTask {
+public class ReloadStringCacheTask implements ModelUpdateTask {
 
     @NonNull
     private ModelDelegate mModelDelegate;
@@ -33,12 +33,12 @@
     }
 
     @Override
-    public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
-            @NonNull final AllAppsList appsList) {
+    public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
+            @NonNull AllAppsList apps) {
         synchronized (dataModel) {
             mModelDelegate.loadStringCache(dataModel.stringCache);
             StringCache cloneSC = dataModel.stringCache.clone();
-            scheduleCallbackTask(c -> c.bindStringCache(cloneSC));
+            taskController.scheduleCallbackTask(c -> c.bindStringCache(cloneSC));
         }
     }
 }
diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java
index 1cb5215..1916d23 100644
--- a/src/com/android/launcher3/model/ShortcutsChangedTask.java
+++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java
@@ -22,6 +22,7 @@
 import androidx.annotation.NonNull;
 
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.shortcuts.ShortcutKey;
@@ -38,7 +39,7 @@
 /**
  * Handles changes due to shortcut manager updates (deep shortcut changes)
  */
-public class ShortcutsChangedTask extends BaseModelUpdateTask {
+public class ShortcutsChangedTask implements ModelUpdateTask {
 
     @NonNull
     private final String mPackageName;
@@ -61,8 +62,9 @@
     }
 
     @Override
-    public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
-            @NonNull final AllAppsList apps) {
+    public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
+            @NonNull AllAppsList apps) {
+        final LauncherAppState app = taskController.getApp();
         final Context context = app.getContext();
         // Find WorkspaceItemInfo's that have changed on the workspace.
         ArrayList<WorkspaceItemInfo> matchingWorkspaceItems = new ArrayList<>();
@@ -78,8 +80,8 @@
 
         if (!matchingWorkspaceItems.isEmpty()) {
             if (mShortcuts.isEmpty()) {
-                PackageManagerHelper packageManagerHelper = PackageManagerHelper.INSTANCE.get(
-                        app.getContext());
+                PackageManagerHelper packageManagerHelper =
+                        PackageManagerHelper.INSTANCE.get(context);
                 // Verify that the app is indeed installed.
                 if (!packageManagerHelper.isAppInstalled(mPackageName, mUser)
                         && !packageManagerHelper.isAppArchivedForUser(mPackageName, mUser)) {
@@ -115,9 +117,9 @@
                         });
             }
 
-            bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos);
+            taskController.bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos);
             if (!nonPinnedIds.isEmpty()) {
-                deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(
+                taskController.deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(
                         nonPinnedIds.stream()
                                 .map(id -> new ShortcutKey(mPackageName, mUser, id))
                                 .collect(Collectors.toSet())),
@@ -128,7 +130,7 @@
         if (mUpdateIdMap) {
             // Update the deep shortcut map if the list of ids has changed for an activity.
             dataModel.updateDeepShortcutCounts(mPackageName, mUser, mShortcuts);
-            bindDeepShortcuts(dataModel);
+            taskController.bindDeepShortcuts(dataModel);
         }
     }
 }
diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java
index 63ca35b..3dc5ff3 100644
--- a/src/com/android/launcher3/model/UserLockStateChangedTask.java
+++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java
@@ -24,6 +24,7 @@
 import androidx.annotation.NonNull;
 
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.shortcuts.ShortcutKey;
@@ -40,7 +41,7 @@
 /**
  * Task to handle changing of lock state of the user
  */
-public class UserLockStateChangedTask extends BaseModelUpdateTask {
+public class UserLockStateChangedTask implements ModelUpdateTask {
 
     @NonNull
     private final UserHandle mUser;
@@ -52,8 +53,9 @@
     }
 
     @Override
-    public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
-            @NonNull final AllAppsList apps) {
+    public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
+            @NonNull AllAppsList apps) {
+        LauncherAppState app = taskController.getApp();
         Context context = app.getContext();
 
         HashMap<ShortcutKey, ShortcutInfo> pinnedShortcuts = new HashMap<>();
@@ -98,9 +100,10 @@
                 }
             });
         }
-        bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos);
+        taskController.bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos);
         if (!removedKeys.isEmpty()) {
-            deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(removedKeys),
+            taskController.deleteAndBindComponentsRemoved(
+                    ItemInfoMatcher.ofShortcutKeys(removedKeys),
                     "removed during unlock because it's no longer available"
                             + " (possibly due to clear data)");
         }
@@ -118,6 +121,6 @@
                     null, mUser,
                     new ShortcutRequest(context, mUser).query(ShortcutRequest.ALL));
         }
-        bindDeepShortcuts(dataModel);
+        taskController.bindDeepShortcuts(dataModel);
     }
 }
diff --git a/src/com/android/launcher3/model/UserManagerState.java b/src/com/android/launcher3/model/UserManagerState.java
index 720f08e..ed32430 100644
--- a/src/com/android/launcher3/model/UserManagerState.java
+++ b/src/com/android/launcher3/model/UserManagerState.java
@@ -17,6 +17,7 @@
 
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.SparseBooleanArray;
 
@@ -27,6 +28,8 @@
  */
 public class UserManagerState {
 
+    private static final String TAG = "UserManagerState";
+
     public final LongSparseArray<UserHandle> allUsers = new LongSparseArray<>();
 
     private final LongSparseArray<Boolean> mQuietUsersSerialNoMap = new LongSparseArray<>();
@@ -39,6 +42,13 @@
         for (UserHandle user : userManager.getUserProfiles()) {
             long serialNo = userCache.getSerialNumberForUser(user);
             boolean isUserQuiet = userManager.isQuietModeEnabled(user);
+            // Mapping different UserHandles to the same serialNo in allUsers could lead to losing
+            // UserHandle and cause a series of problems, such as incorrectly marking app as
+            // disabled and deleting app icons from workspace.
+            if (allUsers.get(serialNo) != null) {
+                Log.w(TAG, String.format("Override allUsers[%d]=%s with %s",
+                        serialNo, allUsers.get(serialNo), user));
+            }
             allUsers.put(serialNo, user);
             mQuietUsersHashCodeMap.put(user.hashCode(), isUserQuiet);
             mQuietUsersSerialNoMap.put(serialNo, isUserQuiet);
diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
index cea4380..90e47d6 100644
--- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
+++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
@@ -336,7 +336,8 @@
                     info,
                     activityInfo,
                     userCache.getUserInfo(c.user),
-                    ApiWrapper.INSTANCE[app.context]
+                    ApiWrapper.INSTANCE[app.context],
+                    pmHelper
                 )
             }
             if (
diff --git a/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java b/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java
index 929f698..1a6d178 100644
--- a/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java
+++ b/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java
@@ -15,8 +15,8 @@
  */
 package com.android.launcher3.model;
 
+import static com.android.launcher3.Utilities.SHOULD_SHOW_FIRST_PAGE_WIDGET;
 import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
-import static com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget;
 
 import android.util.LongSparseArray;
 
@@ -68,7 +68,7 @@
         // First check the preferred screen.
         IntSet screensToExclude = new IntSet();
         if (FeatureFlags.QSB_ON_FIRST_SCREEN
-                && !shouldShowFirstPageWidget()) {
+                && !SHOULD_SHOW_FIRST_PAGE_WIDGET) {
             screensToExclude.add(FIRST_SCREEN_ID);
         }
 
diff --git a/src/com/android/launcher3/model/data/AppInfo.java b/src/com/android/launcher3/model/data/AppInfo.java
index 18aa6e7..a4281f8 100644
--- a/src/com/android/launcher3/model/data/AppInfo.java
+++ b/src/com/android/launcher3/model/data/AppInfo.java
@@ -90,12 +90,12 @@
      */
     public AppInfo(Context context, LauncherActivityInfo info, UserHandle user) {
         this(info, UserCache.INSTANCE.get(context).getUserInfo(user),
-                ApiWrapper.INSTANCE.get(context),
+                ApiWrapper.INSTANCE.get(context), PackageManagerHelper.INSTANCE.get(context),
                 context.getSystemService(UserManager.class).isQuietModeEnabled(user));
     }
 
     public AppInfo(LauncherActivityInfo info, UserIconInfo userIconInfo,
-            ApiWrapper apiWrapper, boolean quietModeEnabled) {
+            ApiWrapper apiWrapper, PackageManagerHelper pmHelper, boolean quietModeEnabled) {
         this.componentName = info.getComponentName();
         this.container = CONTAINER_ALL_APPS;
         this.user = userIconInfo.user;
@@ -105,7 +105,7 @@
             runtimeStatusFlags |= FLAG_DISABLED_QUIET_USER;
         }
         uid = info.getApplicationInfo().uid;
-        updateRuntimeFlagsForActivityTarget(this, info, userIconInfo, apiWrapper);
+        updateRuntimeFlagsForActivityTarget(this, info, userIconInfo, apiWrapper, pmHelper);
     }
 
     public AppInfo(AppInfo info) {
@@ -184,7 +184,7 @@
      */
     public static boolean updateRuntimeFlagsForActivityTarget(
             ItemInfoWithIcon info, LauncherActivityInfo lai, UserIconInfo userIconInfo,
-            ApiWrapper apiWrapper) {
+            ApiWrapper apiWrapper, PackageManagerHelper pmHelper) {
         final int oldProgressLevel = info.getProgressLevel();
         final int oldRuntimeStatusFlags = info.runtimeStatusFlags;
         ApplicationInfo appInfo = lai.getApplicationInfo();
@@ -216,6 +216,8 @@
                 PackageManagerHelper.getLoadingProgress(lai),
                 PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);
         info.setNonResizeable(apiWrapper.isNonResizeableActivity(lai));
+        info.setSupportsMultiInstance(
+                pmHelper.supportsMultiInstance(lai.getComponentName()));
         return (oldProgressLevel != info.getProgressLevel())
                 || (oldRuntimeStatusFlags != info.runtimeStatusFlags);
     }
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index 72e85c7..b82d0a0 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -73,6 +73,7 @@
  * Represents an item in the launcher.
  */
 public class ItemInfo {
+    private static final String TAG = "ItemInfo";
 
     public static final boolean DEBUG = false;
     public static final int NO_ID = -1;
@@ -285,7 +286,7 @@
     @Override
     @NonNull
     public final String toString() {
-        return getClass().getSimpleName() + "(" + dumpProperties() + ")";
+        return TAG + "(" + dumpProperties() + ")";
     }
 
     @NonNull
diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
index d4c25cb..6ac44ff 100644
--- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
@@ -127,6 +127,11 @@
     public static final int FLAG_NOT_RESIZEABLE = 1 << 15;
 
     /**
+     * Flag indicating whether the package related to the item & user supports multiple instances.
+     */
+    public static final int FLAG_SUPPORTS_MULTI_INSTANCE = 1 << 16;
+
+    /**
      * Status associated with the system state of the underlying item. This is calculated every
      * time a new info is created and not persisted on the disk.
      */
@@ -252,6 +257,24 @@
     }
 
     /**
+     * Sets whether this app info supports multi-instance.
+     */
+    protected void setSupportsMultiInstance(boolean supportsMultiInstance) {
+        if (supportsMultiInstance) {
+            runtimeStatusFlags |= FLAG_SUPPORTS_MULTI_INSTANCE;
+        } else {
+            runtimeStatusFlags &= ~FLAG_SUPPORTS_MULTI_INSTANCE;
+        }
+    }
+
+    /**
+     * Returns whether this app info supports multi-instance.
+     */
+    public boolean supportsMultiInstance() {
+        return (runtimeStatusFlags & FLAG_SUPPORTS_MULTI_INSTANCE) != 0;
+    }
+
+    /**
      * Sets whether this app info is non-resizeable.
      */
     public void setNonResizeable(boolean nonResizeable) {
@@ -301,4 +324,11 @@
         drawable.setIsDisabled(isDisabled());
         return drawable;
     }
+
+    @Override
+    protected String dumpProperties() {
+        return super.dumpProperties()
+                + " supportsMultiInstance=" + supportsMultiInstance()
+                + " nonResizeable=" + isNonResizeable();
+    }
 }
diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
index 2c533ac..40e3813 100644
--- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.pm.ShortcutInfo;
 import android.text.TextUtils;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
 
@@ -186,9 +187,12 @@
         if (shortcutInfo.isEnabled()) {
             runtimeStatusFlags &= ~FLAG_DISABLED_BY_PUBLISHER;
         } else {
+            Log.w(TAG, "updateFromDeepShortcutInfo: Updated shortcut has been disabled. "
+                    + " package=" + shortcutInfo.getPackage()
+                    + " disabledReason=" + shortcutInfo.getDisabledReason());
             runtimeStatusFlags |= FLAG_DISABLED_BY_PUBLISHER;
         }
-        disabledMessage = shortcutInfo.getDisabledMessage();
+
         if (shortcutInfo.getDisabledReason() == ShortcutInfo.DISABLED_REASON_VERSION_LOWER) {
             runtimeStatusFlags |= FLAG_DISABLED_VERSION_LOWER;
         } else {
diff --git a/src/com/android/launcher3/pm/PackageInstallInfo.java b/src/com/android/launcher3/pm/PackageInstallInfo.java
index 1797c1f..23d3b61 100644
--- a/src/com/android/launcher3/pm/PackageInstallInfo.java
+++ b/src/com/android/launcher3/pm/PackageInstallInfo.java
@@ -22,6 +22,7 @@
 import androidx.annotation.NonNull;
 
 public final class PackageInstallInfo {
+    private static final String TAG = "PackageInstallInfo";
 
     public static final int STATUS_INSTALLED = 0;
     public static final int STATUS_INSTALLING = 1;
@@ -61,7 +62,7 @@
 
     @Override
     public String toString() {
-        return getClass().getSimpleName() + "(" + dumpProperties() + ")";
+        return TAG + "(" + dumpProperties() + ")";
     }
 
     private String dumpProperties() {
diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java
index b7b557d..ed25186 100644
--- a/src/com/android/launcher3/pm/UserCache.java
+++ b/src/com/android/launcher3/pm/UserCache.java
@@ -101,6 +101,7 @@
         mUserChangeReceiver.register(mContext,
                 Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
                 Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
+                Intent.ACTION_MANAGED_PROFILE_REMOVED,
                 ACTION_PROFILE_ADDED,
                 ACTION_PROFILE_REMOVED,
                 ACTION_PROFILE_UNLOCKED,
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 6005573..83e9810 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -360,7 +360,8 @@
 
         UninstallApp(T target, ItemInfo itemInfo, @NonNull View originalView,
                 @NonNull ComponentName cn) {
-            super(R.drawable.ic_uninstall_no_shadow, R.string.uninstall_drop_target_label, target,
+            super(R.drawable.ic_uninstall_no_shadow,
+                    R.string.uninstall_private_system_shortcut_label, target,
                     itemInfo, originalView);
             mComponentName = cn;
 
diff --git a/src/com/android/launcher3/provider/LauncherDbUtils.java b/src/com/android/launcher3/provider/LauncherDbUtils.java
index b992a92..3ae643e 100644
--- a/src/com/android/launcher3/provider/LauncherDbUtils.java
+++ b/src/com/android/launcher3/provider/LauncherDbUtils.java
@@ -44,6 +44,7 @@
 import com.android.launcher3.shortcuts.ShortcutKey;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.IntSet;
+import com.android.launcher3.util.PackageManagerHelper;
 
 /**
  * A set of utility methods for Launcher DB used for DB updates and migration.
@@ -107,9 +108,11 @@
         Cursor c = db.query(
                 Favorites.TABLE_NAME, null, "itemType = 1", null, null, null, null);
         UserManagerState ums = new UserManagerState();
+        PackageManagerHelper pmHelper = PackageManagerHelper.INSTANCE.get(context);
         ums.init(UserCache.INSTANCE.get(context),
                 context.getSystemService(UserManager.class));
-        LoaderCursor lc = new LoaderCursor(c, LauncherAppState.getInstance(context), ums, null);
+        LoaderCursor lc = new LoaderCursor(c, LauncherAppState.getInstance(context), ums, pmHelper,
+                null);
         IntSet deletedShortcuts = new IntSet();
 
         while (lc.moveToNext()) {
diff --git a/src/com/android/launcher3/qsb/QsbContainerView.java b/src/com/android/launcher3/qsb/QsbContainerView.java
index f0f376f..8e53aff 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.config.FeatureFlags.shouldShowFirstPageWidget;
+import static com.android.launcher3.Utilities.SHOULD_SHOW_FIRST_PAGE_WIDGET;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -292,7 +292,8 @@
         }
 
         public boolean isQsbEnabled() {
-            return FeatureFlags.QSB_ON_FIRST_SCREEN && !shouldShowFirstPageWidget();
+            return FeatureFlags.QSB_ON_FIRST_SCREEN
+                    && !SHOULD_SHOW_FIRST_PAGE_WIDGET;
         }
 
         protected Bundle createBindOptions() {
diff --git a/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt b/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt
index 43027da..6d6b3b6 100644
--- a/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt
+++ b/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt
@@ -26,7 +26,9 @@
 import com.android.launcher3.util.CancellableTask
 import com.android.launcher3.util.Executors.MAIN_EXECUTOR
 import com.android.launcher3.util.Executors.VIEW_PREINFLATION_EXECUTOR
+import com.android.launcher3.util.Themes
 import com.android.launcher3.views.ActivityContext
+import com.android.launcher3.views.ActivityContext.ActivityContextDelegate
 
 const val PREINFLATE_ICONS_ROW_COUNT = 4
 const val EXTRA_ICONS_COUNT = 2
@@ -52,12 +54,28 @@
             return
         }
 
+        // Create a separate context dedicated for all apps preinflation thread. The goal is to
+        // create a separate AssetManager obj internally to avoid lock contention with
+        // AssetManager obj that is associated with the launcher context on the main thread.
+        val allAppsPreInflationContext =
+            ActivityContextDelegate(
+                context.createConfigurationContext(context.resources.configuration),
+                Themes.getActivityThemeRes(context),
+                context
+            )
+
         // Because we perform onCreateViewHolder() on worker thread, we need a separate
         // adapter/inflator object as they are not thread-safe. Note that the adapter
         // just need to perform onCreateViewHolder(parent, VIEW_TYPE_ICON) so it doesn't need
         // data source information.
         val adapter: RecyclerView.Adapter<BaseAllAppsAdapter.ViewHolder> =
-            object : BaseAllAppsAdapter<T>(context, context.appsView.layoutInflater, null, null) {
+            object :
+                BaseAllAppsAdapter<T>(
+                    context,
+                    context.appsView.layoutInflater.cloneInContext(allAppsPreInflationContext),
+                    null,
+                    null
+                ) {
                 override fun setAppsPerRow(appsPerRow: Int) = Unit
                 override fun getLayoutManager(): RecyclerView.LayoutManager? = null
             }
diff --git a/src/com/android/launcher3/responsive/HotseatSpecsProvider.kt b/src/com/android/launcher3/responsive/HotseatSpecsProvider.kt
index 7502a43..2c3035f 100644
--- a/src/com/android/launcher3/responsive/HotseatSpecsProvider.kt
+++ b/src/com/android/launcher3/responsive/HotseatSpecsProvider.kt
@@ -135,7 +135,7 @@
         hotseatQsbSpace.fixedSize + edgePadding.fixedSize <= maxAvailableSize
 
     private fun logError(message: String) {
-        Log.e(LOG_TAG, "${this::class.simpleName}#isValid - $message - $this")
+        Log.e(LOG_TAG, "$LOG_TAG #isValid - $message - $this")
     }
 
     companion object {
diff --git a/src/com/android/launcher3/responsive/ResponsiveCellSpecsProvider.kt b/src/com/android/launcher3/responsive/ResponsiveCellSpecsProvider.kt
index a4b25e5..ef9b7df 100644
--- a/src/com/android/launcher3/responsive/ResponsiveCellSpecsProvider.kt
+++ b/src/com/android/launcher3/responsive/ResponsiveCellSpecsProvider.kt
@@ -31,7 +31,7 @@
             groupOfSpecs
                 .onEach { group ->
                     check(group.widthSpecs.isEmpty() && group.heightSpecs.isNotEmpty()) {
-                        "${this::class.simpleName} is invalid, only heightSpecs are allowed - " +
+                        "$LOG_TAG is invalid, only heightSpecs are allowed - " +
                             "width list size = ${group.widthSpecs.size}; " +
                             "height list size = ${group.heightSpecs.size}."
                     }
@@ -65,6 +65,7 @@
     }
 
     companion object {
+        private const val LOG_TAG = "ResponsiveCellSpecsProvider"
         @JvmStatic
         fun create(resourceHelper: ResourceHelper): ResponsiveCellSpecsProvider {
             val parser = ResponsiveSpecsParser(resourceHelper)
@@ -137,11 +138,11 @@
     }
 
     private fun logError(message: String) {
-        Log.e(LOG_TAG, "${this::class.simpleName}#isValid - $message - $this")
+        Log.e(LOG_TAG, "$LOG_TAG#isValid - $message - $this")
     }
 
     companion object {
-        private const val LOG_TAG = "CellSpec"
+        const val LOG_TAG = "CellSpec"
     }
 }
 
@@ -182,6 +183,7 @@
     )
 
     companion object {
+        private const val LOG_TAG = "CalculatedCellSpec"
         private fun getCalculatedValue(
             availableSpace: Int,
             spec: SizeSpec,
@@ -191,10 +193,10 @@
     }
 
     override fun toString(): String {
-        return "${this::class.simpleName}(" +
+        return "$LOG_TAG(" +
             "availableSpace=$availableSpace, iconSize=$iconSize, " +
             "iconTextSize=$iconTextSize, iconDrawablePadding=$iconDrawablePadding, " +
-            "${spec::class.simpleName}.maxAvailableSize=${spec.maxAvailableSize}" +
+            "${CellSpec.LOG_TAG}.maxAvailableSize=${spec.maxAvailableSize}" +
             ")"
     }
 }
diff --git a/src/com/android/launcher3/responsive/ResponsiveSpec.kt b/src/com/android/launcher3/responsive/ResponsiveSpec.kt
index 65e0b32..e69324d 100644
--- a/src/com/android/launcher3/responsive/ResponsiveSpec.kt
+++ b/src/com/android/launcher3/responsive/ResponsiveSpec.kt
@@ -154,7 +154,7 @@
     }
 
     private fun logError(message: String) {
-        Log.e(LOG_TAG, "${this::class.simpleName}#isValid - $message - $this")
+        Log.e(LOG_TAG, "$LOG_TAG#isValid - $message - $this")
     }
 
     enum class DimensionType {
diff --git a/src/com/android/launcher3/responsive/ResponsiveSpecsProvider.kt b/src/com/android/launcher3/responsive/ResponsiveSpecsProvider.kt
index 67eaac0..654608d 100644
--- a/src/com/android/launcher3/responsive/ResponsiveSpecsProvider.kt
+++ b/src/com/android/launcher3/responsive/ResponsiveSpecsProvider.kt
@@ -40,7 +40,7 @@
             groupOfSpecs
                 .onEach { group ->
                     check(group.widthSpecs.isNotEmpty() && group.heightSpecs.isNotEmpty()) {
-                        "${this::class.simpleName} is incomplete - " +
+                        "$LOG_TAG is incomplete - " +
                             "width list size = ${group.widthSpecs.size}; " +
                             "height list size = ${group.heightSpecs.size}."
                     }
@@ -124,6 +124,7 @@
     }
 
     companion object {
+        private const val LOG_TAG = "ResponsiveSpecsProvider"
         @JvmStatic
         fun create(
             resourceHelper: ResourceHelper,
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 51bc339..eea1a7d 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -51,7 +51,7 @@
 public class StateManager<STATE_TYPE extends BaseState<STATE_TYPE>> {
 
     public static final String TAG = "StateManager";
-    // b/279059025
+    // b/279059025, b/325463989
     private static final boolean DEBUG = true;
 
     private final AnimationState mConfig = new AnimationState();
@@ -240,16 +240,8 @@
     private void goToState(
             STATE_TYPE state, boolean animated, long delay, AnimatorListener listener) {
         if (DEBUG) {
-            String stackTrace = Log.getStackTraceString(new Exception("tracing state transition"));
-            String truncatedTrace =
-                    Arrays.stream(stackTrace.split("\\n"))
-                            .limit(5)
-                            .skip(1) // Removes the line "java.lang.Exception: tracing state
-                            // transition"
-                            .filter(traceLine -> !traceLine.contains("StateManager.goToState"))
-                            .collect(Collectors.joining("\n"));
             Log.d(TAG, "goToState - fromState: " + mState + ", toState: " + state
-                    + ", partial trace:\n" + truncatedTrace);
+                    + ", partial trace:\n" + getTrimmedStackTrace("StateManager.goToState"));
         }
 
         animated &= areAnimatorsEnabled();
@@ -336,17 +328,9 @@
     public AnimatorSet createAtomicAnimation(
             STATE_TYPE fromState, STATE_TYPE toState, StateAnimationConfig config) {
         if (DEBUG) {
-            String stackTrace = Log.getStackTraceString(new Exception("tracing state transition"));
-            String truncatedTrace =
-                    Arrays.stream(stackTrace.split("\\n"))
-                            .limit(5)
-                            .skip(1) // Removes the line "java.lang.Exception: tracing state
-                            // transition"
-                            .filter(traceLine -> !traceLine.contains(
-                                    "StateManager.createAtomicAnimation"))
-                            .collect(Collectors.joining("\n"));
             Log.d(TAG, "createAtomicAnimation - fromState: " + fromState + ", toState: " + toState
-                    + ", partial trace:\n" + truncatedTrace);
+                    + ", partial trace:\n" + getTrimmedStackTrace(
+                            "StateManager.createAtomicAnimation"));
         }
 
         PendingAnimation builder = new PendingAnimation(config.duration);
@@ -481,7 +465,8 @@
      */
     public void cancelAnimation() {
         if (DEBUG && mConfig.currentAnimation != null) {
-            Log.d(TAG, "cancelAnimation - with ongoing animation");
+            Log.d(TAG, "cancelAnimation - with ongoing animation"
+                    + ", partial trace:\n" + getTrimmedStackTrace("StateManager.cancelAnimation"));
         }
         mConfig.reset();
         // It could happen that a new animation is set as a result of an endListener on the
@@ -579,6 +564,15 @@
         mConfig.playbackController = null;
     }
 
+    private String getTrimmedStackTrace(String callingMethodName) {
+        String stackTrace = Log.getStackTraceString(new Exception());
+        return Arrays.stream(stackTrace.split("\\n"))
+                .skip(2) // Removes the line "java.lang.Exception" and "getTrimmedStackTrace".
+                .filter(traceLine -> !traceLine.contains(callingMethodName))
+                .limit(3)
+                .collect(Collectors.joining("\n"));
+    }
+
     private class StartAnimRunnable implements Runnable {
 
         private final AnimatorSet mAnim;
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 50f98f2..3817563 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -411,17 +411,29 @@
         mLauncher.getStatsLogManager().logger()
                 .withSrcState(mStartState.statsLogOrdinal)
                 .withDstState(targetState.statsLogOrdinal)
-                .withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
-                        .setWorkspace(
-                                LauncherAtom.WorkspaceContainer.newBuilder()
-                                        .setPageIndex(mLauncher.getWorkspace().getCurrentPage()))
-                        .build())
+                .withContainerInfo(getContainerInfo(targetState))
                 .log(StatsLogManager.getLauncherAtomEvent(mStartState.statsLogOrdinal,
                             targetState.statsLogOrdinal, mToState.ordinal > mFromState.ordinal
                                     ? LAUNCHER_UNKNOWN_SWIPEUP
                                     : LAUNCHER_UNKNOWN_SWIPEDOWN));
     }
 
+    private LauncherAtom.ContainerInfo getContainerInfo(LauncherState targetState) {
+        if (targetState.isRecentsViewVisible) {
+            return LauncherAtom.ContainerInfo.newBuilder()
+                    .setTaskSwitcherContainer(
+                            LauncherAtom.TaskSwitcherContainer.getDefaultInstance()
+                    )
+                    .build();
+        }
+
+        return LauncherAtom.ContainerInfo.newBuilder()
+                .setWorkspace(
+                        LauncherAtom.WorkspaceContainer.newBuilder()
+                                .setPageIndex(mLauncher.getWorkspace().getCurrentPage()))
+                .build();
+    }
+
     protected void clearState() {
         cancelAnimationControllers();
         mGoingBetweenStates = true;
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 0ed6ea0..f46dcd3 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -84,7 +84,8 @@
  */
 public class ItemClickHandler {
 
-    private static final String TAG = ItemClickHandler.class.getSimpleName();
+    private static final String TAG = "ItemClickHandler";
+    private static final boolean DEBUG = true;
 
     /**
      * Instance used for click handling on items
@@ -110,7 +111,19 @@
             startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher);
         } else if (tag instanceof LauncherAppWidgetInfo) {
             if (v instanceof PendingAppWidgetHostView) {
+                if (DEBUG) {
+                    String targetPackage = ((LauncherAppWidgetInfo) tag).getTargetPackage();
+                    Log.d(TAG, "onClick: PendingAppWidgetHostView clicked for"
+                            + " package=" + targetPackage);
+                }
                 onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
+            } else {
+                if (DEBUG) {
+                    String targetPackage = ((LauncherAppWidgetInfo) tag).getTargetPackage();
+                    Log.d(TAG, "onClick: LauncherAppWidgetInfo clicked,"
+                            + " but not instance of PendingAppWidgetHostView. Returning."
+                            + " package=" + targetPackage);
+                }
             }
         } else if (tag instanceof ItemClickProxy) {
             ((ItemClickProxy) tag).onItemClicked(v);
@@ -120,6 +133,10 @@
                     launcher.getString(R.string.long_accessible_way_to_add_shortcut));
             Snackbar.show(launcher, msg, null);
         } else if (tag instanceof PendingAddWidgetInfo) {
+            if (DEBUG) {
+                String targetPackage = ((PendingAddWidgetInfo) tag).getTargetPackage();
+                Log.d(TAG, "onClick: PendingAddWidgetInfo clicked for package=" + targetPackage);
+            }
             CharSequence msg = Utilities.wrapForTts(
                     launcher.getText(R.string.long_press_widget_to_add),
                     launcher.getString(R.string.long_accessible_way_to_add));
@@ -199,6 +216,9 @@
             LauncherAppWidgetProviderInfo appWidgetInfo = new WidgetManagerHelper(launcher)
                     .findProvider(info.providerName, info.user);
             if (appWidgetInfo == null) {
+                Log.e(TAG, "onClickPendingWidget: Pending widget ready for click setup,"
+                        + " but LauncherAppWidgetProviderInfo was null. Returning."
+                        + " component=" + info.getTargetComponent());
                 return;
             }
             WidgetAddFlowHandler addFlowHandler = new WidgetAddFlowHandler(appWidgetInfo);
@@ -206,6 +226,10 @@
             if (info.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
                 if (!info.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_ALLOCATED)) {
                     // This should not happen, as we make sure that an Id is allocated during bind.
+                    Log.e(TAG, "onClickPendingWidget: Pending widget ready for click setup,"
+                            + " and LauncherAppWidgetProviderInfo was found. However,"
+                            + " no appWidgetId was allocated. Returning."
+                            + " component=" + info.getTargetComponent());
                     return;
                 }
                 addFlowHandler.startBindFlow(launcher, info.appWidgetId, info,
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 8806e27..21eee55 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -23,6 +23,8 @@
 import static com.android.launcher3.InvariantDeviceProfile.TYPE_PHONE;
 import static com.android.launcher3.InvariantDeviceProfile.TYPE_TABLET;
 import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING;
+import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING_DESKTOP_MODE_KEY;
+import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING_IN_DESKTOP_MODE;
 import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING_KEY;
 import static com.android.launcher3.Utilities.dpiFromPx;
 import static com.android.launcher3.config.FeatureFlags.enableTaskbarPinning;
@@ -88,10 +90,11 @@
     public static final int CHANGE_SUPPORTED_BOUNDS = 1 << 3;
     public static final int CHANGE_NAVIGATION_MODE = 1 << 4;
     public static final int CHANGE_TASKBAR_PINNING = 1 << 5;
+    public static final int CHANGE_DESKTOP_MODE = 1 << 6;
 
     public static final int CHANGE_ALL = CHANGE_ACTIVE_SCREEN | CHANGE_ROTATION
             | CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS | CHANGE_NAVIGATION_MODE
-            | CHANGE_TASKBAR_PINNING;
+            | CHANGE_TASKBAR_PINNING | CHANGE_DESKTOP_MODE;
 
     private static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
     private static final String TARGET_OVERLAY_PACKAGE = "android";
@@ -145,23 +148,29 @@
     private void attachTaskbarPinningSharedPreferenceChangeListener(Context context) {
         mTaskbarPinningPreferenceChangeListener =
                 (sharedPreferences, key) -> {
-                    if (TASKBAR_PINNING_KEY.equals(key)
-                            && mInfo.mIsTaskbarPinned != LauncherPrefs.get(mContext).get(
-                            TASKBAR_PINNING)
-                    ) {
+                    LauncherPrefs prefs = LauncherPrefs.get(mContext);
+                    boolean isTaskbarPinningChanged = TASKBAR_PINNING_KEY.equals(key)
+                            && mInfo.mIsTaskbarPinned != prefs.get(TASKBAR_PINNING);
+                    boolean isTaskbarPinningDesktopModeChanged =
+                            TASKBAR_PINNING_DESKTOP_MODE_KEY.equals(key)
+                                    && mInfo.mIsTaskbarPinnedInDesktopMode != prefs.get(
+                                    TASKBAR_PINNING_IN_DESKTOP_MODE);
+                    if (isTaskbarPinningChanged || isTaskbarPinningDesktopModeChanged) {
                         handleInfoChange(mWindowContext.getDisplay());
                     }
                 };
 
         LauncherPrefs.get(context).addListener(
                 mTaskbarPinningPreferenceChangeListener, TASKBAR_PINNING);
+        LauncherPrefs.get(context).addListener(
+                mTaskbarPinningPreferenceChangeListener, TASKBAR_PINNING_IN_DESKTOP_MODE);
     }
 
     /**
      * Returns the current navigation mode
      */
     public static NavigationMode getNavigationMode(Context context) {
-        return INSTANCE.get(context).getInfo().navigationMode;
+        return INSTANCE.get(context).getInfo().getNavigationMode();
     }
 
     /**
@@ -172,6 +181,13 @@
     }
 
     /**
+     * Handles info change for desktop mode.
+     */
+    public static void handleInfoChangeForDesktopMode(Context context) {
+        INSTANCE.get(context).handleInfoChange(context.getDisplay());
+    }
+
+    /**
      * Enables transient taskbar status for tests.
      */
     @VisibleForTesting
@@ -192,6 +208,8 @@
         if (enableTaskbarPinning()) {
             LauncherPrefs.get(mContext).removeListener(
                     mTaskbarPinningPreferenceChangeListener, TASKBAR_PINNING);
+            LauncherPrefs.get(mContext).removeListener(
+                    mTaskbarPinningPreferenceChangeListener, TASKBAR_PINNING_IN_DESKTOP_MODE);
         }
         if (mWindowContext != null) {
             mWindowContext.unregisterComponentCallbacks(this);
@@ -284,7 +302,7 @@
         Info newInfo = new Info(displayInfoContext, wmProxy, oldInfo.mPerDisplayBounds);
 
         if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale
-                || newInfo.navigationMode != oldInfo.navigationMode) {
+                || newInfo.getNavigationMode() != oldInfo.getNavigationMode()) {
             // Cache may not be valid anymore, recreate without cache
             newInfo = new Info(displayInfoContext, wmProxy,
                     wmProxy.estimateInternalDisplayBounds(displayInfoContext));
@@ -300,7 +318,7 @@
         if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale) {
             change |= CHANGE_DENSITY;
         }
-        if (newInfo.navigationMode != oldInfo.navigationMode) {
+        if (newInfo.getNavigationMode() != oldInfo.getNavigationMode()) {
             change |= CHANGE_NAVIGATION_MODE;
         }
         if (!newInfo.supportedBounds.equals(oldInfo.supportedBounds)
@@ -309,9 +327,15 @@
             FileLog.w(TAG,
                     "(CHANGE_SUPPORTED_BOUNDS) perDisplayBounds: " + newInfo.mPerDisplayBounds);
         }
-        if (newInfo.mIsTaskbarPinned != oldInfo.mIsTaskbarPinned) {
+        if ((newInfo.mIsTaskbarPinned != oldInfo.mIsTaskbarPinned)
+                || (newInfo.mIsTaskbarPinnedInDesktopMode
+                    != oldInfo.mIsTaskbarPinnedInDesktopMode)) {
             change |= CHANGE_TASKBAR_PINNING;
         }
+        if (newInfo.mIsInDesktopMode != oldInfo.mIsInDesktopMode) {
+            change |= CHANGE_DESKTOP_MODE;
+        }
+
         if (DEBUG) {
             Log.d(TAG, "handleInfoChange - change: " + getChangeFlagsString(change));
         }
@@ -345,7 +369,7 @@
         // Configuration property
         public final float fontScale;
         private final int densityDpi;
-        public final NavigationMode navigationMode;
+        private final NavigationMode navigationMode;
         private final PortraitSize mScreenSizeDp;
 
         // WindowBounds
@@ -355,6 +379,9 @@
                 new ArrayMap<>();
 
         private final boolean mIsTaskbarPinned;
+        private final boolean mIsTaskbarPinnedInDesktopMode;
+
+        private final boolean mIsInDesktopMode;
 
         public Info(Context displayInfoContext) {
             /* don't need system overrides for external displays */
@@ -414,6 +441,9 @@
             }
 
             mIsTaskbarPinned = LauncherPrefs.get(displayInfoContext).get(TASKBAR_PINNING);
+            mIsTaskbarPinnedInDesktopMode = LauncherPrefs.get(displayInfoContext).get(
+                    TASKBAR_PINNING_IN_DESKTOP_MODE);
+            mIsInDesktopMode = wmProxy.isInDesktopMode();
         }
 
         /**
@@ -430,10 +460,14 @@
                 return sTransientTaskbarStatusForTests;
             }
             if (enableTaskbarPinning()) {
+                if (mIsInDesktopMode) {
+                    return !mIsTaskbarPinnedInDesktopMode;
+                }
                 return !mIsTaskbarPinned;
             }
             return true;
         }
+
         /**
          * Returns whether the taskbar is pinned in gesture navigation mode.
          */
@@ -441,6 +475,10 @@
             return navigationMode == NavigationMode.NO_BUTTON && !isTransientTaskbar();
         }
 
+        public boolean isInDesktopMode() {
+            return mIsInDesktopMode;
+        }
+
         /**
          * Returns {@code true} if the bounds represent a tablet.
          */
@@ -501,6 +539,7 @@
         appendFlag(result, change, CHANGE_SUPPORTED_BOUNDS, "CHANGE_SUPPORTED_BOUNDS");
         appendFlag(result, change, CHANGE_NAVIGATION_MODE, "CHANGE_NAVIGATION_MODE");
         appendFlag(result, change, CHANGE_TASKBAR_PINNING, "CHANGE_TASKBAR_VARIANT");
+        appendFlag(result, change, CHANGE_DESKTOP_MODE, "CHANGE_DESKTOP_MODE");
         return result.toString();
     }
 
@@ -514,8 +553,10 @@
         pw.println("  rotation=" + info.rotation);
         pw.println("  fontScale=" + info.fontScale);
         pw.println("  densityDpi=" + info.densityDpi);
-        pw.println("  navigationMode=" + info.navigationMode.name());
+        pw.println("  navigationMode=" + info.getNavigationMode().name());
         pw.println("  isTaskbarPinned=" + info.mIsTaskbarPinned);
+        pw.println("  isTaskbarPinnedInDesktopMode=" + info.mIsTaskbarPinnedInDesktopMode);
+        pw.println("  isInDesktopMode=" + info.mIsInDesktopMode);
         pw.println("  currentSize=" + info.currentSize);
         info.mPerDisplayBounds.forEach((key, value) -> pw.println(
                 "  perDisplayBounds - " + key + ": " + value));
diff --git a/src/com/android/launcher3/util/FlagDebugUtils.kt b/src/com/android/launcher3/util/FlagDebugUtils.kt
index f281943..33b8330 100644
--- a/src/com/android/launcher3/util/FlagDebugUtils.kt
+++ b/src/com/android/launcher3/util/FlagDebugUtils.kt
@@ -2,6 +2,7 @@
 
 import java.util.StringJoiner
 import java.util.function.IntFunction
+import java.util.function.LongFunction
 
 object FlagDebugUtils {
 
@@ -12,6 +13,13 @@
             str.add(flagName)
         }
     }
+    /** Appends the [flagName] to [str] when the [flag] is set in [flags]. */
+    @JvmStatic
+    fun appendFlag(str: StringJoiner, flags: Long, flag: Long, flagName: String) {
+        if (flags and flag != 0L) {
+            str.add(flagName)
+        }
+    }
 
     /**
      * Produces a human-readable representation of the [current] flags, followed by a diff from from
@@ -34,4 +42,30 @@
         }
         return result.toString()
     }
+
+    /**
+     * Produces a human-readable representation of the [current] flags, followed by a diff from from
+     * [previous].
+     *
+     * The resulting string is intented for logging and debugging.
+     */
+    @JvmStatic
+    fun formatFlagChange(
+        current: Long,
+        previous: Long,
+        flagSerializer: LongFunction<String>
+    ): String {
+        val result = StringJoiner(" ")
+        result.add("[" + flagSerializer.apply(current) + "]")
+        val changed = current xor previous
+        val added = current and changed
+        if (added != 0L) {
+            result.add("+[" + flagSerializer.apply(added) + "]")
+        }
+        val removed = previous and changed
+        if (removed != 0L) {
+            result.add("-[" + flagSerializer.apply(removed) + "]")
+        }
+        return result.toString()
+    }
 }
diff --git a/src/com/android/launcher3/util/LauncherLayoutBuilder.kt b/src/com/android/launcher3/util/LauncherLayoutBuilder.kt
new file mode 100644
index 0000000..ecc9953
--- /dev/null
+++ b/src/com/android/launcher3/util/LauncherLayoutBuilder.kt
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util
+
+import android.util.Xml
+import com.android.launcher3.AutoInstallsLayout.ATTR_CLASS_NAME
+import com.android.launcher3.AutoInstallsLayout.ATTR_CONTAINER
+import com.android.launcher3.AutoInstallsLayout.ATTR_PACKAGE_NAME
+import com.android.launcher3.AutoInstallsLayout.ATTR_RANK
+import com.android.launcher3.AutoInstallsLayout.ATTR_SCREEN
+import com.android.launcher3.AutoInstallsLayout.ATTR_SHORTCUT_ID
+import com.android.launcher3.AutoInstallsLayout.ATTR_SPAN_X
+import com.android.launcher3.AutoInstallsLayout.ATTR_SPAN_Y
+import com.android.launcher3.AutoInstallsLayout.ATTR_TITLE
+import com.android.launcher3.AutoInstallsLayout.ATTR_TITLE_TEXT
+import com.android.launcher3.AutoInstallsLayout.ATTR_USER_TYPE
+import com.android.launcher3.AutoInstallsLayout.ATTR_X
+import com.android.launcher3.AutoInstallsLayout.ATTR_Y
+import com.android.launcher3.AutoInstallsLayout.TAG_APPWIDGET
+import com.android.launcher3.AutoInstallsLayout.TAG_AUTO_INSTALL
+import com.android.launcher3.AutoInstallsLayout.TAG_FOLDER
+import com.android.launcher3.AutoInstallsLayout.TAG_SHORTCUT
+import com.android.launcher3.AutoInstallsLayout.TAG_WORKSPACE
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT
+import com.android.launcher3.LauncherSettings.Favorites.containerToString
+import java.io.IOException
+import java.io.StringWriter
+import java.io.Writer
+import org.xmlpull.v1.XmlSerializer
+
+/** Helper class to build xml for Launcher Layout */
+class LauncherLayoutBuilder {
+    private val nodes = ArrayList<Node>()
+
+    fun atHotseat(rank: Int) =
+        ItemTarget(
+            mapOf(
+                ATTR_CONTAINER to containerToString(CONTAINER_HOTSEAT),
+                ATTR_RANK to rank.toString()
+            )
+        )
+
+    fun atWorkspace(x: Int, y: Int, screen: Int) =
+        ItemTarget(
+            mapOf(
+                ATTR_CONTAINER to containerToString(CONTAINER_DESKTOP),
+                ATTR_X to x.toString(),
+                ATTR_Y to y.toString(),
+                ATTR_SCREEN to screen.toString()
+            )
+        )
+
+    @Throws(IOException::class) fun build() = StringWriter().apply { build(this) }.toString()
+
+    @Throws(IOException::class)
+    fun build(writer: Writer) {
+        Xml.newSerializer().apply {
+            setOutput(writer)
+            setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true)
+            startDocument("UTF-8", true)
+            startTag(null, TAG_WORKSPACE)
+            writeNodes(nodes)
+            endTag(null, TAG_WORKSPACE)
+            endDocument()
+            flush()
+        }
+    }
+
+    open inner class ItemTarget(private val baseValues: Map<String, String>) {
+        @JvmOverloads
+        fun putApp(packageName: String, className: String?, userType: String? = null) =
+            addItem(
+                TAG_AUTO_INSTALL,
+                userType,
+                mapOf(
+                    ATTR_PACKAGE_NAME to packageName,
+                    ATTR_CLASS_NAME to (className ?: packageName)
+                )
+            )
+
+        @JvmOverloads
+        fun putShortcut(packageName: String, shortcutId: String, userType: String? = null) =
+            addItem(
+                TAG_SHORTCUT,
+                userType,
+                mapOf(ATTR_PACKAGE_NAME to packageName, ATTR_SHORTCUT_ID to shortcutId)
+            )
+
+        @JvmOverloads
+        fun putWidget(
+            packageName: String,
+            className: String,
+            spanX: Int,
+            spanY: Int,
+            userType: String? = null
+        ) =
+            addItem(
+                TAG_APPWIDGET,
+                userType,
+                mapOf(
+                    ATTR_PACKAGE_NAME to packageName,
+                    ATTR_CLASS_NAME to className,
+                    ATTR_SPAN_X to spanX.toString(),
+                    ATTR_SPAN_Y to spanY.toString()
+                )
+            )
+
+        fun putFolder(titleResId: Int) = putFolder(ATTR_TITLE, titleResId.toString())
+
+        fun putFolder(title: String?) = putFolder(ATTR_TITLE_TEXT, title)
+
+        protected open fun addItem(
+            tag: String,
+            userType: String?,
+            props: Map<String, String>,
+            children: List<Node>? = null
+        ): LauncherLayoutBuilder {
+            nodes.add(
+                Node(
+                    tag,
+                    HashMap(baseValues).apply {
+                        putAll(props)
+                        userType?.let { put(ATTR_USER_TYPE, it) }
+                    },
+                    children
+                )
+            )
+            return this@LauncherLayoutBuilder
+        }
+
+        protected open fun putFolder(titleKey: String, titleValue: String?): FolderBuilder {
+            val folderBuilder = FolderBuilder()
+            addItem(TAG_FOLDER, null, mapOf(titleKey to (titleValue ?: "")), folderBuilder.children)
+            return folderBuilder
+        }
+    }
+
+    inner class FolderBuilder : ItemTarget(mapOf()) {
+
+        val children = ArrayList<Node>()
+
+        fun addApp(packageName: String, className: String?): FolderBuilder {
+            putApp(packageName, className)
+            return this
+        }
+
+        fun addShortcut(packageName: String, shortcutId: String): FolderBuilder {
+            putShortcut(packageName, shortcutId)
+            return this
+        }
+
+        override fun addItem(
+            tag: String,
+            userType: String?,
+            props: Map<String, String>,
+            childrenIgnored: List<Node>?
+        ): LauncherLayoutBuilder {
+            children.add(
+                Node(tag, HashMap(props).apply { userType?.let { put(ATTR_USER_TYPE, it) } })
+            )
+            return this@LauncherLayoutBuilder
+        }
+
+        override fun putFolder(titleKey: String, titleValue: String?): FolderBuilder {
+            throw IllegalArgumentException("Can't have folder inside a folder")
+        }
+
+        fun build() = this@LauncherLayoutBuilder
+    }
+
+    @Throws(IOException::class)
+    private fun XmlSerializer.writeNodes(nodes: List<Node>) {
+        nodes.forEach { node ->
+            startTag(null, node.name)
+            node.attrs.forEach { (key, value) -> attribute(null, key, value) }
+            node.children?.let { writeNodes(it) }
+            endTag(null, node.name)
+        }
+    }
+
+    data class Node(
+        val name: String,
+        val attrs: Map<String, String>,
+        val children: List<Node>? = null
+    )
+}
diff --git a/src/com/android/launcher3/util/LogConfig.java b/src/com/android/launcher3/util/LogConfig.java
index d59c339..3d4b409 100644
--- a/src/com/android/launcher3/util/LogConfig.java
+++ b/src/com/android/launcher3/util/LogConfig.java
@@ -70,4 +70,10 @@
      * When turned on, we enable long press nav handle related logging.
      */
     public static final String NAV_HANDLE_LONG_PRESS = "NavHandleLongPress";
+
+
+    /**
+     * When turned on, we enable zero state web data loader related logging.
+     */
+    public static final String ZERO_WEB_DATA_LOADER = "ZeroStateWebDataLoaderLog";
 }
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 3684f56..f7c4df4 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -17,6 +17,7 @@
 package com.android.launcher3.util;
 
 import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
+import static android.view.WindowManager.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI;
 
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
@@ -73,10 +74,14 @@
     @NonNull
     private final LauncherApps mLauncherApps;
 
+    private final String[] mLegacyMultiInstanceSupportedApps;
+
     public PackageManagerHelper(@NonNull final Context context) {
         mContext = context;
         mPm = context.getPackageManager();
         mLauncherApps = Objects.requireNonNull(context.getSystemService(LauncherApps.class));
+        mLegacyMultiInstanceSupportedApps = mContext.getResources().getStringArray(
+                R.array.config_appsSupportMultiInstancesSplit);
     }
 
     @Override
@@ -159,11 +164,23 @@
         }
     }
 
+    /**
+     * Returns the preferred launch activity intent for a given package.
+     */
     @Nullable
     public Intent getAppLaunchIntent(@Nullable final String pkg, @NonNull final UserHandle user) {
+        LauncherActivityInfo info = getAppLaunchInfo(pkg, user);
+        return info != null ? AppInfo.makeLaunchIntent(info) : null;
+    }
+
+    /**
+     * Returns the preferred launch activity for a given package.
+     */
+    @Nullable
+    public LauncherActivityInfo getAppLaunchInfo(@Nullable final String pkg,
+            @NonNull final UserHandle user) {
         List<LauncherActivityInfo> activities = mLauncherApps.getActivityList(pkg, user);
-        return activities.isEmpty() ? null :
-                AppInfo.makeLaunchIntent(activities.get(0));
+        return activities.isEmpty() ? null : activities.get(0);
     }
 
     /**
@@ -285,4 +302,47 @@
         return (info.flags & ApplicationInfo.FLAG_INSTALLED) != 0 || (
                 Flags.enableSupportForArchiving() && info.isArchived);
     }
+
+    /**
+     * Returns whether the given component or its application has the multi-instance property set.
+     */
+    public boolean supportsMultiInstance(@NonNull ComponentName component) {
+        // Check the legacy hardcoded allowlist first
+        for (String pkg : mLegacyMultiInstanceSupportedApps) {
+            if (pkg.equals(component.getPackageName())) {
+                return true;
+            }
+        }
+
+        // Check app multi-instance properties after V
+        if (!Utilities.ATLEAST_V) {
+            return false;
+        }
+
+        try {
+            // Check if the component has the multi-instance property
+            return mPm.getProperty(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, component)
+                    .getBoolean();
+        } catch (PackageManager.NameNotFoundException e1) {
+            try {
+                // Check if the application has the multi-instance property
+                return mPm.getProperty(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI,
+                                component.getPackageName())
+                    .getBoolean();
+            } catch (PackageManager.NameNotFoundException e2) {
+                // Fall through
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns whether two apps should be considered the same for multi-instance purposes, which
+     * requires additional checks to ensure they can be started as multiple instances.
+     */
+    public static boolean isSameAppForMultiInstance(@NonNull ItemInfo app1,
+            @NonNull ItemInfo app2) {
+        return app1.getTargetPackage().equals(app2.getTargetPackage())
+                && app1.user.equals(app2.user);
+    }
 }
diff --git a/src/com/android/launcher3/util/rects/Rects.kt b/src/com/android/launcher3/util/rects/Rects.kt
new file mode 100644
index 0000000..1e6d717
--- /dev/null
+++ b/src/com/android/launcher3/util/rects/Rects.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 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.rects
+
+import android.graphics.Rect
+import android.view.View
+
+/** Copy the coordinates of the [view] relative to its parent into this rectangle. */
+fun Rect.set(view: View) {
+    set(0, 0, view.width, view.height)
+    offset(view.x.toInt(), view.y.toInt())
+}
diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java
index 4b004f3..0817c0a 100644
--- a/src/com/android/launcher3/util/window/WindowManagerProxy.java
+++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java
@@ -115,6 +115,13 @@
     }
 
     /**
+     * Returns if we are in desktop mode or not.
+     */
+    public boolean isInDesktopMode() {
+        return false;
+    }
+
+    /**
      * Returns the real bounds for the provided display after applying any insets normalization
      */
     public WindowBounds getRealBounds(Context displayInfoContext, CachedDisplayInfo info) {
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index 5ce455a..85aad89 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -92,7 +92,7 @@
     protected @NonNull AnimatorPlaybackController mOpenCloseAnimation;
 
     protected ViewGroup mContent;
-    protected final View mColorScrim;
+    protected final @Nullable View mColorScrim;
 
     /**
      * Interpolator for {@link #mOpenCloseAnimation} when we are closing due to dragging downwards.
@@ -216,6 +216,9 @@
 
         animation.addFloat(
                 this, TRANSLATION_SHIFT, fromTranslationShift, toTranslationShift, LINEAR);
+        if (mColorScrim != null) {
+            animation.setViewAlpha(mColorScrim, 1 - toTranslationShift, getScrimInterpolator());
+        }
         onOpenCloseAnimationPending(animation);
 
         mOpenCloseAnimation = animation.createPlaybackController();
@@ -254,9 +257,6 @@
     protected void setTranslationShift(float translationShift) {
         mTranslationShift = translationShift;
         mContent.setTranslationY(mTranslationShift * getShiftRange());
-        if (mColorScrim != null) {
-            mColorScrim.setAlpha(1 - mTranslationShift);
-        }
         invalidate();
     }
 
@@ -500,6 +500,10 @@
         return Interpolators.ACCELERATE;
     }
 
+    protected Interpolator getScrimInterpolator() {
+        return LINEAR;
+    }
+
     protected void onCloseComplete() {
         mIsOpen = false;
         getPopupContainer().removeView(this);
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index bf43a22..cfac91a 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -41,6 +41,7 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.util.Log;
+import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -515,10 +516,21 @@
     static <T extends Context & ActivityContext> T lookupContextNoThrow(Context context) {
         if (context instanceof ActivityContext) {
             return (T) context;
+        } else if (context instanceof ActivityContextDelegate acd) {
+            return (T) acd.mDelegate;
         } else if (context instanceof ContextWrapper) {
             return lookupContextNoThrow(((ContextWrapper) context).getBaseContext());
         } else {
             return null;
         }
     }
+
+    class ActivityContextDelegate extends ContextThemeWrapper {
+        public final ActivityContext mDelegate;
+
+        public ActivityContextDelegate(Context base, int themeResId, ActivityContext delegate) {
+            super(base, themeResId);
+            mDelegate = delegate;
+        }
+    }
 }
diff --git a/src/com/android/launcher3/views/ArrowTipView.java b/src/com/android/launcher3/views/ArrowTipView.java
index 2f0da03..bb4f040 100644
--- a/src/com/android/launcher3/views/ArrowTipView.java
+++ b/src/com/android/launcher3/views/ArrowTipView.java
@@ -54,7 +54,7 @@
  */
 public class ArrowTipView extends AbstractFloatingView {
 
-    private static final String TAG = ArrowTipView.class.getSimpleName();
+    private static final String TAG = "ArrowTipView";
     private static final long AUTO_CLOSE_TIMEOUT_MILLIS = 10 * 1000;
     private static final long SHOW_DELAY_MS = 200;
     private static final long SHOW_DURATION_MS = 300;
diff --git a/src/com/android/launcher3/views/ClipIconView.java b/src/com/android/launcher3/views/ClipIconView.java
index 172f968..325c1cd 100644
--- a/src/com/android/launcher3/views/ClipIconView.java
+++ b/src/com/android/launcher3/views/ClipIconView.java
@@ -40,6 +40,7 @@
 import android.view.ViewOutlineProvider;
 
 import androidx.annotation.Nullable;
+import androidx.core.util.Consumer;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
@@ -74,6 +75,8 @@
     private final Rect mOutline = new Rect();
     private final Rect mFinalDrawableBounds = new Rect();
 
+    @Nullable private TaskViewArtist mTaskViewArtist;
+
     public ClipIconView(Context context) {
         this(context, null);
     }
@@ -90,10 +93,28 @@
     }
 
     /**
+     * Sets a {@link TaskViewArtist} that will draw a {@link com.android.quickstep.views.TaskView}
+     * within the clip bounds of this view.
+     */
+    public void setTaskViewArtist(TaskViewArtist taskViewArtist) {
+        mTaskViewArtist = taskViewArtist;
+        invalidate();
+    }
+
+    /**
      * Update the icon UI to match the provided parameters during an animation frame
      */
     public void update(RectF rect, float progress, float shapeProgressStart, float cornerRadius,
             boolean isOpening, View container, DeviceProfile dp) {
+        update(rect, progress, shapeProgressStart, cornerRadius, isOpening, container, dp, 255);
+    }
+
+    /**
+     * Update the icon UI to match the provided parameters during an animation frame, optionally
+     * varying the alpha of the {@link TaskViewArtist}
+     */
+    public void update(RectF rect, float progress, float shapeProgressStart, float cornerRadius,
+            boolean isOpening, View container, DeviceProfile dp, int taskViewDrawAlpha) {
         MarginLayoutParams lp = (MarginLayoutParams) container.getLayoutParams();
 
         float dX = mIsRtl
@@ -107,6 +128,14 @@
         float scaleX = rect.width() / minSize;
         float scaleY = rect.height() / minSize;
         float scale = Math.max(1f, Math.min(scaleX, scaleY));
+        if (mTaskViewArtist != null) {
+            mTaskViewArtist.taskViewDrawWidth = lp.width;
+            mTaskViewArtist.taskViewDrawHeight = lp.height;
+            mTaskViewArtist.taskViewDrawAlpha = taskViewDrawAlpha;
+            mTaskViewArtist.taskViewDrawScale = (mTaskViewArtist.drawForPortraitLayout
+                    ? Math.min(lp.height, lp.width) : Math.max(lp.height, lp.width))
+                    / mTaskViewArtist.taskViewMinSize;
+        }
 
         if (Float.isNaN(scale) || Float.isInfinite(scale)) {
             // Views are no longer laid out, do not update.
@@ -287,6 +316,19 @@
         if (mForeground != null) {
             mForeground.draw(canvas);
         }
+        if (mTaskViewArtist != null) {
+            canvas.saveLayerAlpha(
+                    0,
+                    0,
+                    mTaskViewArtist.taskViewDrawWidth,
+                    mTaskViewArtist.taskViewDrawHeight,
+                    mTaskViewArtist.taskViewDrawAlpha);
+            float drawScale = mTaskViewArtist.taskViewDrawScale;
+            canvas.translate(drawScale * mTaskViewArtist.taskViewTranslationX,
+                    drawScale * mTaskViewArtist.taskViewTranslationY);
+            canvas.scale(drawScale, drawScale);
+            mTaskViewArtist.taskViewDrawCallback.accept(canvas);
+        }
         canvas.restoreToCount(count);
     }
 
@@ -303,5 +345,37 @@
         mRevealAnimator = null;
         mTaskCornerRadius = 0;
         mOutline.setEmpty();
+        mTaskViewArtist = null;
+    }
+
+    /**
+     * Utility class to help draw a {@link com.android.quickstep.views.TaskView} within
+     * a {@link ClipIconView} bounds.
+     */
+    public static class TaskViewArtist {
+
+        public final Consumer<Canvas> taskViewDrawCallback;
+        public final float taskViewTranslationX;
+        public final float taskViewTranslationY;
+        public final float taskViewMinSize;
+        public final boolean drawForPortraitLayout;
+
+        public int taskViewDrawAlpha;
+        public float taskViewDrawScale;
+        public int taskViewDrawWidth;
+        public int taskViewDrawHeight;
+
+        public TaskViewArtist(
+                Consumer<Canvas> taskViewDrawCallback,
+                float taskViewTranslationX,
+                float taskViewTranslationY,
+                float taskViewMinSize,
+                boolean drawForPortraitLayout) {
+            this.taskViewDrawCallback = taskViewDrawCallback;
+            this.taskViewTranslationX = taskViewTranslationX;
+            this.taskViewTranslationY = taskViewTranslationY;
+            this.taskViewMinSize = taskViewMinSize;
+            this.drawForPortraitLayout = drawForPortraitLayout;
+        }
     }
 }
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index f560311..1d5a9dc 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -55,7 +55,6 @@
 import com.android.launcher3.graphics.PreloadIconDrawable;
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.launcher3.icons.LauncherIcons;
-import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.popup.SystemShortcut;
@@ -69,7 +68,7 @@
 public class FloatingIconView extends FrameLayout implements
         Animator.AnimatorListener, OnGlobalLayoutListener, FloatingView {
 
-    private static final String TAG = FloatingIconView.class.getSimpleName();
+    private static final String TAG = "FloatingIconView";
 
     // Manages loading the icon on a worker thread
     private static @Nullable IconLoadResult sIconLoadResult;
@@ -146,18 +145,28 @@
     }
 
     /**
-     * Positions this view to match the size and location of {@param rect}.
-     * @param alpha The alpha[0, 1] of the entire floating view.
-     * @param progress A value from [0, 1] that represents the animation progress.
-     * @param shapeProgressStart The progress value at which to start the shape reveal.
-     * @param cornerRadius The corner radius of {@param rect}.
-     * @param isOpening True if view is used for app open animation, false for app close animation.
+     * Positions this view to match the size and location of {@code rect}.
      */
     public void update(float alpha, RectF rect, float progress, float shapeProgressStart,
             float cornerRadius, boolean isOpening) {
-        setAlpha(alpha);
+        update(alpha, rect, progress, shapeProgressStart, cornerRadius, isOpening, 0);
+    }
+
+    /**
+     * Positions this view to match the size and location of {@code rect}.
+     * <p>
+     * @param alpha The alpha[0, 1] of the entire floating view.
+     * @param progress A value from [0, 1] that represents the animation progress.
+     * @param shapeProgressStart The progress value at which to start the shape reveal.
+     * @param cornerRadius The corner radius of {@code rect}.
+     * @param isOpening True if view is used for app open animation, false for app close animation.
+     * @param taskViewDrawAlpha the drawn {@link com.android.quickstep.views.TaskView} alpha
+     */
+    public void update(float alpha, RectF rect, float progress, float shapeProgressStart,
+            float cornerRadius, boolean isOpening, int taskViewDrawAlpha) {
+        setAlpha(isLaidOut() ? alpha : 0f);
         mClipIconView.update(rect, progress, shapeProgressStart, cornerRadius, isOpening, this,
-                mLauncher.getDeviceProfile());
+                mLauncher.getDeviceProfile(), taskViewDrawAlpha);
 
         if (mFadeOutView != null) {
             // The alpha goes from 1 to 0 when progress is 0 and 0.33 respectively.
@@ -165,6 +174,14 @@
         }
     }
 
+    /**
+     * Sets a {@link com.android.quickstep.views.TaskView} that will draw a
+     * {@link com.android.quickstep.views.TaskView} within the {@code mClipIconView} clip bounds
+     */
+    public void setOverlayArtist(ClipIconView.TaskViewArtist taskViewArtist) {
+        mClipIconView.setTaskViewArtist(taskViewArtist);
+    }
+
     @Override
     public void onAnimationEnd(Animator animator) {
         if (mLoadIconSignal != null) {
@@ -179,8 +196,8 @@
     }
 
     /**
-     * Sets the size and position of this view to match {@param v}.
-     *
+     * Sets the size and position of this view to match {@code v}.
+     * <p>
      * @param v The view to copy
      * @param positionOut Rect that will hold the size and position of v.
      */
@@ -254,10 +271,11 @@
 
     /**
      * Loads the icon and saves the results to {@link #sIconLoadResult}.
+     * <p>
      * Runs onIconLoaded callback (if any), which signifies that the FloatingIconView is
      * ready to display the icon. Otherwise, the FloatingIconView will grab the results when its
      * initialized.
-     *
+     * <p>
      * @param originalView The View that the FloatingIconView will replace.
      * @param info ItemInfo of the originalView
      * @param pos The position of the view.
@@ -324,8 +342,8 @@
     }
 
     /**
-     * Sets the drawables of the {@param originalView} onto this view.
-     *
+     * Sets the drawables of the {@code originalView} onto this view.
+     * <p>
      * @param drawable The drawable of the original view.
      * @param badge The badge of the original view.
      * @param iconOffset The amount of offset needed to match this view with the original view.
@@ -368,11 +386,11 @@
 
     /**
      * Draws the drawable of the BubbleTextView behind ClipIconView
-     *
+     * <p>
      * This is used to:
      * - Have icon displayed while Adaptive Icon is loading
      * - Displays the built in shadow to ensure a clean handoff
-     *
+     * <p>
      * Allows nullable as this may be cleared when drawing is deferred to ClipIconView.
      */
     private void setOriginalDrawableBackground(@Nullable Supplier<Drawable> btvIcon) {
@@ -573,11 +591,12 @@
     }
 
     /**
-     * Creates a floating icon view for {@param originalView}.
+     * Creates a floating icon view for {@code originalView}.
+     * <p>
      * @param originalView The view to copy
      * @param visibilitySyncView A view whose visibility should update in sync with originalView.
      * @param fadeOutView A view that will fade out as the animation progresses.
-     * @param hideOriginal If true, it will hide {@param originalView} while this view is visible.
+     * @param hideOriginal If true, it will hide {@code originalView} while this view is visible.
      *                     Else, we will not draw anything in this view.
      * @param positionOut Rect that will hold the size and position of v.
      * @param isOpening True if this view replaces the icon for app open animation.
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index df8f635..cdbd0c0 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -109,6 +109,13 @@
 
     private float mLastTouchY;
     private boolean mIsDragging;
+    /**
+     * Tracks whether a keyboard hide request has been sent due to downward scrolling.
+     * <p>
+     * Set to true when scrolling down and reset when scrolling up to prevents redundant hide
+     * requests during continuous downward scrolls.
+     */
+    private boolean mRequestedHideKeyboard;
     private boolean mIsThumbDetached;
     private final boolean mCanThumbDetach;
     private boolean mIgnoreDragGesture;
@@ -241,6 +248,7 @@
     public boolean handleTouchEvent(MotionEvent ev, Point offset) {
         int x = (int) ev.getX() - offset.x;
         int y = (int) ev.getY() - offset.y;
+        ActivityContext activityContext = ActivityContext.lookupContext(getContext());
 
         switch (ev.getAction()) {
             case MotionEvent.ACTION_DOWN:
@@ -248,6 +256,7 @@
                 mDownX = x;
                 mDownY = mLastY = y;
                 mDownTimeStampMillis = ev.getDownTime();
+                mRequestedHideKeyboard = false;
 
                 if ((Math.abs(mDy) < mDeltaThreshold &&
                         mRv.getScrollState() != SCROLL_STATE_IDLE)) {
@@ -260,6 +269,15 @@
                 }
                 break;
             case MotionEvent.ACTION_MOVE:
+                if (y > mLastY) {
+                    if (!mRequestedHideKeyboard) {
+                        activityContext.hideKeyboard();
+                    }
+                    mRequestedHideKeyboard = true;
+                } else {
+                    mRequestedHideKeyboard = false;
+                }
+
                 mLastY = y;
                 int absDeltaY = Math.abs(y - mDownY);
                 int absDeltaX = Math.abs(x - mDownX);
@@ -294,7 +312,6 @@
     }
 
     private void calcTouchOffsetAndPrepToFastScroll(int downY, int lastY) {
-        ActivityContext.lookupContext(getContext()).hideKeyboard();
         mIsDragging = true;
         if (mCanThumbDetach) {
             mIsThumbDetached = true;
diff --git a/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java b/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
index 4f5d311..5e702aa 100644
--- a/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
@@ -145,7 +145,10 @@
 
     @Override
     protected int getScrimColor(Context context) {
-        return context.getResources().getColor(R.color.widgets_picker_scrim);
+        // Don't add a scrim when using the standalone picker activity. The background dimming is
+        // handled by applying dimBackground in the activity theme, so the scrim doesn't slide in
+        // with the window.
+        return -1;
     }
 
     @SuppressLint("NewApi") // Already added API check.
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 8892a18..1368084 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -17,6 +17,8 @@
 
 import static com.android.app.animation.Interpolators.EMPHASIZED;
 import static com.android.launcher3.Flags.enableWidgetTapToAdd;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_ADD_BUTTON_TAP;
 
 import android.content.Context;
@@ -42,6 +44,7 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.PendingAddItemInfo;
 import com.android.launcher3.R;
+import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.popup.PopupDataProvider;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
@@ -74,6 +77,7 @@
     private boolean mDisableNavBarScrim = false;
 
     @Nullable private WidgetCell mWidgetCellWithAddButton = null;
+    @Nullable private WidgetItem mLastSelectedWidgetItem = null;
 
     public BaseWidgetSheet(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
@@ -161,13 +165,26 @@
             }
 
             mWidgetCellWithAddButton = mWidgetCellWithAddButton != wc ? wc : null;
+            if (mWidgetCellWithAddButton != null) {
+                mLastSelectedWidgetItem = mWidgetCellWithAddButton.getWidgetItem();
+            } else {
+                mLastSelectedWidgetItem = null;
+            }
         } else {
             mActivityContext.getItemOnClickListener().onClick(wc);
         }
     }
 
+    @Override
+    protected float getShiftRange() {
+        // We add the extra height added during predictive back / swipe up to the shift range, so
+        // that the idle interpolator knows to animate the view off fully.
+        return mContent.getHeight() + getBottomOffsetPx();
+    }
+
     /**
-     * Click handler for tap to add button.
+     * Click handler for tap to add button. This handler assumes we are in the Launcher activity and
+     * should not be used when the widget sheet is displayed elsewhere.
      */
     private void addWidget(@NonNull PendingAddItemInfo info) {
         // Using a boolean flag here to make sure the callback is only run once. This should never
@@ -175,19 +192,23 @@
         // needed.
         final AtomicBoolean hasRun = new AtomicBoolean(false);
         addOnCloseListener(() -> {
-            if (!hasRun.get()) {
-                Launcher.getLauncher(mActivityContext).getAccessibilityDelegate().addToWorkspace(
-                        info, /*accessibility=*/ false,
+            if (hasRun.get()) return;
+            hasRun.set(true);
+
+            // Going to NORMAL state will also dismiss the All Apps view if it is showing.
+            Launcher launcher = Launcher.getLauncher(mActivityContext);
+            launcher.getStateManager().goToState(NORMAL, forSuccessCallback(() -> {
+                launcher.getAccessibilityDelegate().addToWorkspace(info,
+                        /*accessibility=*/ false,
                         /*finishCallback=*/ (success) -> {
                             mActivityContext.getStatsLogManager()
                                     .logger()
                                     .withItemInfo(info)
                                     .log(LAUNCHER_WIDGET_ADD_BUTTON_TAP);
                         });
-                hasRun.set(true);
-            }
+            }));
         });
-        handleClose(true);
+        close(/* animate= */ true);
     }
 
     /**
@@ -236,6 +257,14 @@
         return 0;
     }
 
+    /**
+     * Returns the component of the widget that is currently showing an add button, if any.
+     */
+    @Nullable
+    protected WidgetItem getLastSelectedWidgetItem() {
+        return mLastSelectedWidgetItem;
+    }
+
     @Override
     public boolean onLongClick(View v) {
         TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "Widgets.onLongClick");
diff --git a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
index aab78bd..2817299 100644
--- a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
+++ b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
@@ -27,12 +27,12 @@
 import android.graphics.PorterDuffXfermode;
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
 import android.os.Handler;
 import android.util.Log;
 import android.util.Size;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherAppState;
@@ -45,6 +45,7 @@
 import com.android.launcher3.pm.ShortcutConfigActivityInfo;
 import com.android.launcher3.util.CancellableTask;
 import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.LooperExecutor;
 import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.widget.util.WidgetSizes;
 
@@ -68,8 +69,7 @@
     }
 
     /**
-     * Generates the widget preview on {@link AsyncTask#THREAD_POOL_EXECUTOR}. Must be
-     * called on UI thread.
+     * Generates the widget preview on {@link Executors#UI_HELPER_EXECUTOR}.
      *
      * @return a request id which can be used to cancel the request.
      */
@@ -78,7 +78,7 @@
             @NonNull WidgetItem item,
             @NonNull Size previewSize,
             @NonNull Consumer<Bitmap> callback) {
-        Handler handler = Executors.UI_HELPER_EXECUTOR.getHandler();
+        Handler handler = getLoaderExecutor().getHandler();
         CancellableTask<Bitmap> request = new CancellableTask<>(
                 () -> generatePreview(item, previewSize.getWidth(), previewSize.getHeight()),
                 MAIN_EXECUTOR,
@@ -87,6 +87,12 @@
         return request;
     }
 
+    @VisibleForTesting
+    @NonNull
+    public static LooperExecutor getLoaderExecutor() {
+        return Executors.UI_HELPER_EXECUTOR;
+    }
+
     /**
      * Returns a generated preview for a widget and if the preview should be saved in persistent
      * storage.
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index c3e9ad6..44ab966 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -42,7 +42,6 @@
 import com.android.launcher3.Flags;
 import com.android.launcher3.R;
 import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.views.BaseDragLayer;
@@ -52,8 +51,7 @@
  * {@inheritDoc}
  */
 public class LauncherAppWidgetHostView extends BaseLauncherAppWidgetHostView
-        implements TouchCompleteListener, View.OnLongClickListener,
-        LocalColorExtractor.Listener {
+        implements TouchCompleteListener, View.OnLongClickListener {
 
     private static final String TAG = "LauncherAppWidgetHostView";
 
@@ -70,13 +68,9 @@
 
     private static final String TRACE_METHOD_NAME = "appwidget load-widget ";
 
-    private final Rect mTempRect = new Rect();
     private final CheckLongPressHelper mLongPressHelper;
     protected final ActivityContext mActivityContext;
 
-    // Maintain the color manager.
-    private final LocalColorExtractor mColorExtractor;
-
     private boolean mIsScrollable;
     private boolean mIsAttachedToWindow;
     private boolean mIsAutoAdvanceRegistered;
@@ -84,11 +78,6 @@
 
     private long mDeferUpdatesUntilMillis = 0;
     RemoteViews mLastRemoteViews;
-    private boolean mHasDeferredColorChange = false;
-    private @Nullable SparseIntArray mDeferredColorChange = null;
-
-    // The following member variables are only used during drag-n-drop.
-    private boolean mIsInDragMode = false;
 
     private boolean mTrackingWidgetUpdate = false;
 
@@ -109,7 +98,6 @@
         if (Themes.getAttrBoolean(context, R.attr.isWorkspaceDarkText)) {
             setOnLightBackground(true);
         }
-        mColorExtractor = new LocalColorExtractor(); // no-op
     }
 
     @Override
@@ -177,8 +165,8 @@
     }
 
     /**
-     * Returns true if the application of {@link RemoteViews} through {@link #updateAppWidget} and
-     * colors through {@link #onColorsChanged} are currently being deferred.
+     * Returns true if the application of {@link RemoteViews} through {@link #updateAppWidget} are
+     * currently being deferred.
      * @see #beginDeferringUpdates()
      */
     private boolean isDeferringUpdates() {
@@ -187,9 +175,8 @@
 
     /**
      * Begin deferring the application of any {@link RemoteViews} updates made through
-     * {@link #updateAppWidget} and color changes through {@link #onColorsChanged} until
-     * {@link #endDeferringUpdates()} has been called or the next {@link #updateAppWidget} or
-     * {@link #onColorsChanged} call after {@link #UPDATE_LOCK_TIMEOUT_MILLIS} have elapsed.
+     * {@link #updateAppWidget} until {@link #endDeferringUpdates()} has been called or the next
+     * {@link #updateAppWidget} call after {@link #UPDATE_LOCK_TIMEOUT_MILLIS} have elapsed.
      */
     public void beginDeferringUpdates() {
         mDeferUpdatesUntilMillis = SystemClock.uptimeMillis() + UPDATE_LOCK_TIMEOUT_MILLIS;
@@ -197,26 +184,16 @@
 
     /**
      * Stop deferring the application of {@link RemoteViews} updates made through
-     * {@link #updateAppWidget} and color changes made through {@link #onColorsChanged} and apply
-     * any deferred updates.
+     * {@link #updateAppWidget} and apply any deferred updates.
      */
     public void endDeferringUpdates() {
         RemoteViews remoteViews;
-        SparseIntArray deferredColors;
-        boolean hasDeferredColors;
         mDeferUpdatesUntilMillis = 0;
         remoteViews = mLastRemoteViews;
-        deferredColors = mDeferredColorChange;
-        hasDeferredColors = mHasDeferredColorChange;
-        mDeferredColorChange = null;
-        mHasDeferredColorChange = false;
 
         if (remoteViews != null) {
             updateAppWidget(remoteViews);
         }
-        if (hasDeferredColors) {
-            onColorsChanged(deferredColors);
-        }
     }
 
     public boolean onInterceptTouchEvent(MotionEvent ev) {
@@ -242,7 +219,6 @@
         super.onAttachedToWindow();
         mIsAttachedToWindow = true;
         checkIfAutoAdvance();
-        mColorExtractor.setListener(this);
     }
 
     @Override
@@ -253,7 +229,6 @@
         // state is updated. So isAttachedToWindow() will return true until next frame.
         mIsAttachedToWindow = false;
         checkIfAutoAdvance();
-        mColorExtractor.setListener(null);
     }
 
     @Override
@@ -292,29 +267,6 @@
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
         mIsScrollable = checkScrollableRecursively(this);
-
-        if (!mIsInDragMode && getTag() instanceof LauncherAppWidgetInfo info) {
-            mTempRect.set(left, top, right, bottom);
-            mColorExtractor.setWorkspaceLocation(mTempRect, (View) getParent(), info.screenId);
-        }
-    }
-
-    /** Starts the drag mode. */
-    public void startDrag() {
-        mIsInDragMode = true;
-    }
-
-    /** Handles a drag event occurred on a workspace page corresponding to the {@code screenId}. */
-    public void handleDrag(Rect rectInView, View view, int screenId) {
-        if (mIsInDragMode) {
-            mColorExtractor.setWorkspaceLocation(rectInView, view, screenId);
-        }
-    }
-
-    /** Ends the drag mode. */
-    public void endDrag() {
-        mIsInDragMode = false;
-        requestLayout();
     }
 
     /**
@@ -338,20 +290,6 @@
     }
 
     @Override
-    public void onColorsChanged(SparseIntArray colors) {
-        if (isDeferringUpdates()) {
-            mDeferredColorChange = colors;
-            mHasDeferredColorChange = true;
-            return;
-        }
-        mDeferredColorChange = null;
-        mHasDeferredColorChange = false;
-
-        // setColorResources will reapply the view, which must happen in the UI thread.
-        post(() -> setColorResources(colors));
-    }
-
-    @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(getClass().getName());
diff --git a/src/com/android/launcher3/widget/LocalColorExtractor.java b/src/com/android/launcher3/widget/LocalColorExtractor.java
index 96e7531..7b500c7 100644
--- a/src/com/android/launcher3/widget/LocalColorExtractor.java
+++ b/src/com/android/launcher3/widget/LocalColorExtractor.java
@@ -17,11 +17,8 @@
 package com.android.launcher3.widget;
 
 import android.app.WallpaperColors;
-import android.appwidget.AppWidgetHostView;
 import android.content.Context;
-import android.graphics.Rect;
 import android.util.SparseIntArray;
-import android.view.View;
 
 import androidx.annotation.Nullable;
 
@@ -31,18 +28,6 @@
 /** Extracts the colors we need from the wallpaper at given locations. */
 public class LocalColorExtractor implements ResourceBasedOverride {
 
-    /** Listener for color changes on a screen location. */
-    public interface Listener {
-        /**
-         * Method called when the colors on a registered location has changed.
-         *
-         * {@code extractedColors} maps the color resources {@code android.R.colors.system_*} to
-         * their value, in a format that can be passed directly to
-         * {@link AppWidgetHostView#setColorResources(SparseIntArray)}.
-         */
-        void onColorsChanged(SparseIntArray extractedColors);
-    }
-
     /**
      * Creates a new instance of LocalColorExtractor
      */
@@ -51,19 +36,6 @@
                 R.string.local_colors_extraction_class);
     }
 
-    /** Sets the object that will receive the color changes. */
-    public void setListener(@Nullable Listener listener) {
-        // no-op
-    }
-
-    /**
-     * Sets the location used for color extraction
-     * @param pos position to use for color extraction
-     * @param child view whose coordinate space is used for {@code pos}
-     * @param screenId the workspace screenId
-     */
-    public void setWorkspaceLocation(Rect pos, View child, int screenId) { }
-
     /**
      * Updates the base context to contain the colors override
      */
@@ -76,5 +48,4 @@
     public SparseIntArray generateColorsOverride(WallpaperColors colors) {
         return null;
     }
-
 }
diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java
index faad307..8857774 100644
--- a/src/com/android/launcher3/widget/PendingItemDragHelper.java
+++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java
@@ -44,7 +44,6 @@
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.icons.RoundDrawableWrapper;
-import com.android.launcher3.widget.dragndrop.AppWidgetHostViewDragListener;
 
 /**
  * Extension of {@link DragPreviewProvider} with logic specific to pending widgets/shortcuts
@@ -132,8 +131,6 @@
             }
             if (mAppWidgetHostViewPreview != null) {
                 previewSizeBeforeScale[0] = mAppWidgetHostViewPreview.getMeasuredWidth();
-                launcher.getDragController()
-                        .addDragListener(new AppWidgetHostViewDragListener(launcher));
             }
             if (preview == null && mAppWidgetHostViewPreview == null) {
                 Drawable p = new FastBitmapDrawable(new DatabaseWidgetPreviewLoader(launcher)
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index 6dcaf75..eac2ce7 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -29,6 +29,7 @@
 import android.animation.TimeInterpolator;
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -502,6 +503,15 @@
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }
 
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+
+        if (changed && isShowingAddButton()) {
+            post(this::setupIconOrTextButton);
+        }
+    }
+
     /**
      * Loads a high resolution package icon to show next to the widget title.
      */
@@ -544,12 +554,47 @@
         if (mIsShowingAddButton) return;
         mIsShowingAddButton = true;
 
+        setupIconOrTextButton();
         mWidgetAddButton.setOnClickListener(callback);
         fadeThrough(/* hide= */ mWidgetTextContainer, /* show= */ mWidgetAddButton,
                 ADD_BUTTON_FADE_DURATION_MS, Interpolators.LINEAR);
     }
 
     /**
+     * Depending on the width of the cell, set up the add button to be icon-only or icon+text.
+     */
+    private void setupIconOrTextButton() {
+        String addText = getResources().getString(R.string.widget_add_button_label);
+        Rect textSize = new Rect();
+        mWidgetAddButton.getPaint().getTextBounds(addText, 0, addText.length(), textSize);
+        int startPadding = getResources()
+                .getDimensionPixelSize(R.dimen.widget_cell_add_button_start_padding);
+        int endPadding = getResources()
+                .getDimensionPixelSize(R.dimen.widget_cell_add_button_end_padding);
+        int drawableWidth = getResources()
+                .getDimensionPixelSize(R.dimen.widget_cell_add_button_drawable_width);
+        int drawablePadding = getResources()
+                .getDimensionPixelSize(R.dimen.widget_cell_add_button_drawable_padding);
+        int textButtonWidth = textSize.width() + startPadding + endPadding + drawableWidth
+                + drawablePadding;
+        if (textButtonWidth > getMeasuredWidth()) {
+            // Setup icon-only button
+            mWidgetAddButton.setText(null);
+            int startIconPadding = getResources()
+                    .getDimensionPixelSize(R.dimen.widget_cell_add_icon_button_start_padding);
+            mWidgetAddButton.setPaddingRelative(/* start= */ startIconPadding, /* top= */ 0,
+                    /* end= */ endPadding, /* bottom= */ 0);
+            mWidgetAddButton.setCompoundDrawablePadding(0);
+        } else {
+            // Setup icon + text button
+            mWidgetAddButton.setText(addText);
+            mWidgetAddButton.setPaddingRelative(/* start= */ startPadding, /* top= */ 0,
+                    /* end= */ endPadding, /* bottom= */ 0);
+            mWidgetAddButton.setCompoundDrawablePadding(drawablePadding);
+        }
+    }
+
+    /**
      * Hide tap to add button.
      */
     public void hideAddButton(boolean animate) {
@@ -591,4 +636,19 @@
         set.playSequentially(hideAnim, showAnim);
         set.start();
     }
+
+    /**
+     * Returns true if this WidgetCell is displaying the same item as info.
+     */
+    public boolean matchesItem(WidgetItem info) {
+        if (info == null || mItem == null) return false;
+        if (info.widgetInfo != null && mItem.widgetInfo != null) {
+            return info.widgetInfo.getUser().equals(mItem.widgetInfo.getUser())
+                    && info.widgetInfo.getComponent().equals(mItem.widgetInfo.getComponent());
+        } else if (info.activityInfo != null && mItem.activityInfo != null) {
+            return info.activityInfo.getUser().equals(mItem.activityInfo.getUser())
+                    && info.activityInfo.getComponent().equals(mItem.activityInfo.getComponent());
+        }
+        return false;
+    }
 }
diff --git a/src/com/android/launcher3/widget/WidgetManagerHelper.java b/src/com/android/launcher3/widget/WidgetManagerHelper.java
index d293d15..9132b4f 100644
--- a/src/com/android/launcher3/widget/WidgetManagerHelper.java
+++ b/src/com/android/launcher3/widget/WidgetManagerHelper.java
@@ -26,6 +26,7 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.util.Log;
 import android.widget.RemoteViews;
 
 import androidx.annotation.NonNull;
@@ -104,6 +105,8 @@
             // If exception is thrown because of device is locked, it means a race condition occurs
             // that the user got locked again while launcher is processing the event. In this case
             // we should return empty list.
+            Log.e(TAG, "getAllProviders: Error getting installed providers for"
+                    + " package=" + packageUser.mPackageName, e);
             return Collections.emptyList();
         }
     }
@@ -133,6 +136,8 @@
                 return LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
             }
         }
+        Log.w(TAG, "findProvider: No App Widget Provider found for component=" + provider
+                + " user=" + user);
         return null;
     }
 
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index b4c4623..4ea2426 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -142,6 +142,9 @@
                     row.forEach(widgetItem -> {
                         WidgetCell widget = addItemCell(tableRow);
                         widget.applyFromCellItem(widgetItem);
+                        if (widget.matchesItem(getLastSelectedWidgetItem())) {
+                            widget.callOnClick();
+                        }
                     });
                     widgetsTable.addView(tableRow);
                 });
diff --git a/src/com/android/launcher3/widget/custom/CustomWidgetManager.java b/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
index 05fe8e3..50012b3 100644
--- a/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
+++ b/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher3.widget.custom;
 
-import static com.android.launcher3.config.FeatureFlags.SMARTSPACE_AS_A_WIDGET;
+import static com.android.launcher3.Flags.enableSmartspaceAsAWidget;
 import static com.android.launcher3.model.data.LauncherAppWidgetInfo.CUSTOM_WIDGET_ID;
 import static com.android.launcher3.widget.LauncherAppWidgetProviderInfo.CLS_CUSTOM_WIDGET_PREFIX;
 
@@ -70,7 +70,7 @@
         PluginManagerWrapper.INSTANCE.get(context)
                 .addPluginListener(this, CustomWidgetPlugin.class, true);
 
-        if (SMARTSPACE_AS_A_WIDGET.get()) {
+        if (enableSmartspaceAsAWidget()) {
             for (String s: context.getResources()
                     .getStringArray(R.array.custom_widget_providers)) {
                 try {
diff --git a/src/com/android/launcher3/widget/dragndrop/AppWidgetHostViewDragListener.java b/src/com/android/launcher3/widget/dragndrop/AppWidgetHostViewDragListener.java
deleted file mode 100644
index 3e54b33..0000000
--- a/src/com/android/launcher3/widget/dragndrop/AppWidgetHostViewDragListener.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.widget.dragndrop;
-
-import com.android.launcher3.DropTarget;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.dragndrop.DragController;
-import com.android.launcher3.dragndrop.DragOptions;
-import com.android.launcher3.widget.LauncherAppWidgetHostView;
-
-/** A drag listener of {@link LauncherAppWidgetHostView}. */
-public final class AppWidgetHostViewDragListener implements DragController.DragListener {
-    private final Launcher mLauncher;
-    private LauncherAppWidgetHostView mAppWidgetHostView;
-
-    public AppWidgetHostViewDragListener(Launcher launcher) {
-        mLauncher = launcher;
-    }
-
-    @Override
-    public void onDragStart(DropTarget.DragObject dragObject, DragOptions unused) {
-        if (dragObject.dragView.getContentView() instanceof LauncherAppWidgetHostView) {
-            mAppWidgetHostView = (LauncherAppWidgetHostView) dragObject.dragView.getContentView();
-            mAppWidgetHostView.startDrag();
-        } else {
-            mLauncher.getDragController().removeDragListener(this);
-        }
-    }
-
-    @Override
-    public void onDragEnd() {
-        mAppWidgetHostView.endDrag();
-        mLauncher.getDragController().removeDragListener(this);
-    }
-}
diff --git a/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java b/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java
index 80bda22..9253b37 100644
--- a/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java
+++ b/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java
@@ -64,14 +64,11 @@
         Preconditions.assertWorkerThread();
         try (PackageManagerHelper pmHelper = new PackageManagerHelper(context)) {
             if (item.widgetInfo != null && item.widgetInfo.getComponent() != null) {
-                String widgetComponentName = item.widgetInfo.getComponent().getClassName();
                 ApplicationInfo applicationInfo = pmHelper.getApplicationInfo(
                         item.widgetInfo.getComponent().getPackageName(), item.widgetInfo.getUser(),
                         0 /* flags */);
                 if (applicationInfo != null) {
-                    int predictionCategory = applicationInfo.category;
-                    return getCategoryFromApplicationCategory(context, predictionCategory,
-                            widgetComponentName);
+                    return getCategoryFromApplicationCategory(applicationInfo.category);
                 }
             }
         }
@@ -80,29 +77,7 @@
 
     /** Maps application category to an appropriate displayable category. */
     private static WidgetRecommendationCategory getCategoryFromApplicationCategory(
-            Context context, int applicationCategory, String componentName) {
-        // Weather categories don't map to a specific application category, so, we maintain an
-        // allowlist.
-        String[] weatherRecommendationAllowlist =
-                context.getResources().getStringArray(R.array.weather_recommendations);
-        for (String allowedWeatherComponentName : weatherRecommendationAllowlist) {
-            if (componentName.equalsIgnoreCase(allowedWeatherComponentName)) {
-                return new WidgetRecommendationCategory(
-                        R.string.weather_widget_recommendation_category_label, /*order=*/3);
-            }
-        }
-
-        // Fitness categories don't map to a specific application category, so, we maintain an
-        // allowlist.
-        String[] fitnessRecommendationAllowlist =
-                context.getResources().getStringArray(R.array.fitness_recommendations);
-        for (String allowedFitnessComponentName : fitnessRecommendationAllowlist) {
-            if (componentName.equalsIgnoreCase(allowedFitnessComponentName)) {
-                return new WidgetRecommendationCategory(
-                        R.string.fitness_widget_recommendation_category_label, /*order=*/2);
-            }
-        }
-
+            int applicationCategory) {
         if (applicationCategory == ApplicationInfo.CATEGORY_PRODUCTIVITY) {
             return new WidgetRecommendationCategory(
                     R.string.productivity_widget_recommendation_category_label, /*order=*/0);
@@ -116,7 +91,7 @@
         if (applicationCategory == ApplicationInfo.CATEGORY_SOCIAL) {
             return new WidgetRecommendationCategory(
                     R.string.social_widget_recommendation_category_label,
-                    /*order=*/5);
+                    /*order=*/3);
         }
 
         if (applicationCategory == ApplicationInfo.CATEGORY_AUDIO
@@ -124,11 +99,10 @@
                 || applicationCategory == ApplicationInfo.CATEGORY_IMAGE) {
             return new WidgetRecommendationCategory(
                     R.string.entertainment_widget_recommendation_category_label,
-                    /*order=*/6);
+                    /*order=*/4);
         }
 
         return new WidgetRecommendationCategory(
-                R.string.others_widget_recommendation_category_label, /*order=*/4);
+                R.string.others_widget_recommendation_category_label, /*order=*/2);
     }
-
 }
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
index 03af0cb..6dbad5c 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
@@ -58,12 +58,13 @@
 
     public WidgetsRecommendationTableLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
-        // There are 1 row for title, 1 row for dimension and 2 rows for description.
+        // There are 1 row for title, 1 row for dimension and max 3 rows for description.
         mWidgetsRecommendationTableVerticalPadding = 2 * getResources()
                 .getDimensionPixelSize(R.dimen.widget_recommendations_table_vertical_padding);
         mWidgetCellVerticalPadding = 2 * getResources()
                 .getDimensionPixelSize(R.dimen.widget_cell_vertical_padding);
-        mWidgetCellTextViewsHeight = 4 * getResources().getDimension(R.dimen.widget_cell_font_size);
+        mWidgetCellTextViewsHeight =
+                getResources().getDimension(R.dimen.widget_cell_title_line_height);
     }
 
     /** Sets a {@link android.view.View.OnLongClickListener} for all widget cells in this table. */
diff --git a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
index 79ddadc..f835e18 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
@@ -29,17 +29,20 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.Px;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.model.data.PackageItemInfo;
 import com.android.launcher3.recyclerview.ViewHolderBinder;
 import com.android.launcher3.util.PackageUserKey;
@@ -64,7 +67,7 @@
 
     // This ratio defines the max percentage of content area that the recommendations can display
     // with respect to the bottom sheet's height.
-    private static final float RECOMMENDATION_SECTION_HEIGHT_RATIO_TWO_PANE = 0.75f;
+    private static final float RECOMMENDATION_SECTION_HEIGHT_RATIO_TWO_PANE = 0.60f;
     private FrameLayout mSuggestedWidgetsContainer;
     private WidgetsListHeader mSuggestedWidgetsHeader;
     private PackageUserKey mSuggestedWidgetsPackageUserKey;
@@ -76,6 +79,7 @@
 
     private boolean mOldIsSwipeToDismissInProgress;
     private int mActivePage = -1;
+    @Nullable
     private PackageUserKey mSelectedHeader;
 
     public WidgetsTwoPaneSheet(Context context, AttributeSet attrs, int defStyleAttr) {
@@ -194,15 +198,21 @@
                 layoutParams.width = 0;
             }
             layoutParams.weight = layoutParams.width == 0 ? 0.33F : 0;
-            leftPane.setLayoutParams(layoutParams);
-            requestApplyInsets();
-            if (mSelectedHeader != null) {
-                if (mSelectedHeader.equals(mSuggestedWidgetsPackageUserKey)) {
-                    mSuggestedWidgetsHeader.callOnClick();
-                } else {
-                    getHeaderChangeListener().onHeaderChanged(mSelectedHeader);
+
+            post(() -> {
+                // The following calls all trigger requestLayout, so we post them to avoid
+                // calling requestLayout during a layout pass. This also fixes the related warnings
+                // in logcat.
+                leftPane.setLayoutParams(layoutParams);
+                requestApplyInsets();
+                if (mSelectedHeader != null) {
+                    if (mSelectedHeader.equals(mSuggestedWidgetsPackageUserKey)) {
+                        mSuggestedWidgetsHeader.callOnClick();
+                    } else {
+                        getHeaderChangeListener().onHeaderChanged(mSelectedHeader);
+                    }
                 }
-            }
+            });
         }
     }
 
@@ -222,6 +232,10 @@
         if (mSuggestedWidgetsContainer == null && mRecommendedWidgetsCount > 0) {
             setupSuggestedWidgets(LayoutInflater.from(getContext()));
             mSuggestedWidgetsHeader.callOnClick();
+        } else if (mSelectedHeader != null
+                && mSelectedHeader.equals(mSuggestedWidgetsPackageUserKey)) {
+            // Reselect widget if we are reloading recommendations while it is currently showing.
+            selectWidgetCell(mWidgetRecommendationsContainer, getLastSelectedWidgetItem());
         }
     }
 
@@ -269,6 +283,16 @@
             mRightPaneScrollView.setScrollY(0);
             mRightPane.setAccessibilityPaneTitle(suggestionsRightPaneTitle);
             mSuggestedWidgetsPackageUserKey = PackageUserKey.fromPackageItemInfo(packageItemInfo);
+            final boolean isChangingHeaders = mSelectedHeader == null
+                    || !mSelectedHeader.equals(mSuggestedWidgetsPackageUserKey);
+            if (isChangingHeaders)  {
+                // If switching from another header, unselect any WidgetCells. This is necessary
+                // because we do not clear/recycle the WidgetCells in the recommendations container
+                // when the header is clicked, only when onRecommendationsBound is called. That
+                // means a WidgetCell in the recommendations container may still be selected from
+                // the last time the recommendations were shown.
+                unselectWidgetCell(mWidgetRecommendationsContainer, getLastSelectedWidgetItem());
+            }
             mSelectedHeader = mSuggestedWidgetsPackageUserKey;
         });
         mSuggestedWidgetsContainer.addView(mSuggestedWidgetsHeader);
@@ -357,6 +381,8 @@
         return new HeaderChangeListener() {
             @Override
             public void onHeaderChanged(@NonNull PackageUserKey selectedHeader) {
+                final boolean isSameHeader = mSelectedHeader != null
+                        && mSelectedHeader.equals(selectedHeader);
                 mSelectedHeader = selectedHeader;
                 WidgetsListContentEntry contentEntry = mActivityContext.getPopupDataProvider()
                         .getSelectedAppWidgets(selectedHeader);
@@ -384,11 +410,20 @@
                         contentEntryToBind,
                         ViewHolderBinder.POSITION_FIRST | ViewHolderBinder.POSITION_LAST,
                         Collections.EMPTY_LIST);
+                if (isSameHeader) {
+                    // Reselect the last selected widget if we are reloading the same header.
+                    selectWidgetCell(widgetsRowViewHolder.tableContainer,
+                            getLastSelectedWidgetItem());
+                }
                 widgetsRowViewHolder.mDataCallback = data -> {
                     mWidgetsListTableViewHolderBinder.bindViewHolder(widgetsRowViewHolder,
                             contentEntryToBind,
                             ViewHolderBinder.POSITION_FIRST | ViewHolderBinder.POSITION_LAST,
                             Collections.singletonList(data));
+                    if (isSameHeader) {
+                        selectWidgetCell(widgetsRowViewHolder.tableContainer,
+                                getLastSelectedWidgetItem());
+                    }
                 };
                 mRightPane.removeAllViews();
                 mRightPane.addView(widgetsRowViewHolder.itemView);
@@ -401,6 +436,24 @@
         };
     }
 
+    private static void selectWidgetCell(ViewGroup parent, WidgetItem item) {
+        if (parent == null || item == null) return;
+        WidgetCell cell = Utilities.findViewByPredicate(parent, v -> v instanceof WidgetCell wc
+                && wc.matchesItem(item));
+        if (cell != null && !cell.isShowingAddButton()) {
+            cell.callOnClick();
+        }
+    }
+
+    private static void unselectWidgetCell(ViewGroup parent, WidgetItem item) {
+        if (parent == null || item == null) return;
+        WidgetCell cell = Utilities.findViewByPredicate(parent, v -> v instanceof WidgetCell wc
+                && wc.matchesItem(item));
+        if (cell != null && cell.isShowingAddButton()) {
+            cell.hideAddButton(/* animate= */ false);
+        }
+    }
+
     @Override
     public void setInsets(Rect insets) {
         super.setInsets(insets);
diff --git a/tests/Android.bp b/tests/Android.bp
index ef98794..a8fba85 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -23,7 +23,8 @@
     srcs: [
         "src/**/*.java",
         "src/**/*.kt",
-        ":launcher3-robo-src",
+        "multivalentTests/src/**/*.java",
+        "multivalentTests/src/**/*.kt",
     ],
     exclude_srcs: [
         ":launcher-non-quickstep-tests-src",
@@ -37,6 +38,8 @@
     srcs: [
         "multivalentTests/src/**/*.java",
         "multivalentTests/src/**/*.kt",
+        "src_deviceless/**/*.java",
+        "src_deviceless/**/*.kt",
     ],
 }
 
@@ -102,6 +105,7 @@
 android_library {
     name: "Launcher3TestResources",
     resource_dirs: ["res"],
+    asset_dirs: ["assets"],
     // TODO(b/319712088): re-enable use_resource_processor
     use_resource_processor: false,
 }
@@ -188,6 +192,7 @@
     java_resource_dirs: ["config"],
     static_libs: [
         "flag-junit-base",
+        "flag-junit",
         "com_android_launcher3_flags_lib",
         "com_android_wm_shell_flags_lib",
         "androidx.test.uiautomator_uiautomator",
@@ -195,9 +200,10 @@
         "androidx.test.ext.junit",
         "androidx.test.rules",
         "uiautomator-helpers",
-        "mockito-robolectric-prebuilt",
-        "mockito-kotlin2",
+        "inline-mockito-robolectric-prebuilt",
+        "mockito-kotlin-nodeps",
         "platform-parametric-runner-lib",
+        "platform-test-rules-deviceless",
         "testables",
         "Launcher3TestResources",
         "SystemUISharedLib",
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index a9b75ea..4b926a8 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -407,10 +407,14 @@
             </intent-filter>
         </activity>
 
-        <!-- [b/197780098] Disable eager initialization of Jetpack libraries. -->
+        <!-- Disable eager initialization of Jetpack libraries. See bug 197780098. -->
         <provider
             android:name="androidx.startup.InitializationProvider"
             android:authorities="${applicationId}.androidx-startup"
             tools:node="remove" />
+
+        <property
+            android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI"
+            android:value="true"/>
     </application>
 </manifest>
diff --git a/tests/Launcher3Tests.xml b/tests/Launcher3Tests.xml
index 29c34be..270a610 100644
--- a/tests/Launcher3Tests.xml
+++ b/tests/Launcher3Tests.xml
@@ -44,6 +44,8 @@
         <option name="run-command" value="settings put global airplane_mode_on 1" />
         <option name="run-command" value="am broadcast -a android.intent.action.AIRPLANE_MODE" />
 
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
+
         <option name="run-command" value="settings put system pointer_location 1" />
         <option name="run-command" value="settings put system show_touches 1" />
     </target_preparer>
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button_decoupleDepth.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button_decoupleDepth.txt
new file mode 100644
index 0000000..46cce24
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button_decoupleDepth.txt
@@ -0,0 +1,130 @@
+DeviceProfile:
+	1 dp = 2.625 px
+	isTablet:true
+	isPhone:false
+	transposeLayoutWithOrientation:false
+	isGestureMode:false
+	isLandscape:true
+	isMultiWindowMode:false
+	isTwoPanels:true
+	isLeftRightSplit:true
+	windowX: 0.0px (0.0dp)
+	windowY: 0.0px (0.0dp)
+	widthPx: 2208.0px (841.1429dp)
+	heightPx: 1840.0px (700.9524dp)
+	availableWidthPx: 2208.0px (841.1429dp)
+	availableHeightPx: 1730.0px (659.0476dp)
+	mInsets.left: 0.0px (0.0dp)
+	mInsets.top: 110.0px (41.904762dp)
+	mInsets.right: 0.0px (0.0dp)
+	mInsets.bottom: 0.0px (0.0dp)
+	aspectRatio:1.2
+	isResponsiveGrid:false
+	isScalableGrid:false
+	inv.numRows: 4
+	inv.numColumns: 4
+	inv.numSearchContainerColumns: 4
+	minCellSize: PointF(0.0, 0.0)dp
+	cellWidthPx: 154.0px (58.666668dp)
+	cellHeightPx: 218.0px (83.04762dp)
+	getCellSize().x: 270.0px (102.85714dp)
+	getCellSize().y: 342.0px (130.28572dp)
+	cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+	cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+	cellLayoutPaddingPx.left: 0.0px (0.0dp)
+	cellLayoutPaddingPx.top: 0.0px (0.0dp)
+	cellLayoutPaddingPx.right: 0.0px (0.0dp)
+	cellLayoutPaddingPx.bottom: 0.0px (0.0dp)
+	iconSizePx: 141.0px (53.714287dp)
+	iconTextSizePx: 34.0px (12.952381dp)
+	iconDrawablePaddingPx: 13.0px (4.952381dp)
+	numFolderRows: 3
+	numFolderColumns: 4
+	folderCellWidthPx: 189.0px (72.0dp)
+	folderCellHeightPx: 219.0px (83.42857dp)
+	folderChildIconSizePx: 141.0px (53.714287dp)
+	folderChildTextSizePx: 34.0px (12.952381dp)
+	folderChildDrawablePaddingPx: 5.0px (1.9047619dp)
+	folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+	folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+	folderContentPaddingLeftRight: 21.0px (8.0dp)
+	folderTopPadding: 63.0px (24.0dp)
+	folderFooterHeight: 147.0px (56.0dp)
+	bottomSheetTopPadding: 110.0px (41.904762dp)
+	bottomSheetOpenDuration: 500
+	bottomSheetCloseDuration: 500
+	bottomSheetWorkspaceScale: 0.97
+	bottomSheetDepth: 0.3
+	allAppsShiftRange: 1840.0px (700.9524dp)
+	allAppsOpenDuration: 500
+	allAppsCloseDuration: 500
+	allAppsIconSizePx: 141.0px (53.714287dp)
+	allAppsIconTextSizePx: 34.0px (12.952381dp)
+	allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+	allAppsCellHeightPx: 361.0px (137.5238dp)
+	allAppsCellWidthPx: 183.0px (69.71429dp)
+	allAppsBorderSpacePxX: 42.0px (16.0dp)
+	allAppsBorderSpacePxY: 42.0px (16.0dp)
+	numShownAllAppsColumns: 8
+	allAppsPadding.top: 110.0px (41.904762dp)
+	allAppsPadding.left: 42.0px (16.0dp)
+	allAppsPadding.right: 42.0px (16.0dp)
+	allAppsLeftRightMargin: 183.0px (69.71429dp)
+	hotseatBarSizePx: 267.0px (101.71429dp)
+	mHotseatColumnSpan: 4
+	mHotseatWidthPx: 0.0px (0.0dp)
+	hotseatCellHeightPx: 159.0px (60.57143dp)
+	hotseatBarBottomSpacePx: 126.0px (48.0dp)
+	mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+	mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+	hotseatBarEndOffset: 0.0px (0.0dp)
+	hotseatQsbSpace: 0.0px (0.0dp)
+	hotseatQsbHeight: 0.0px (0.0dp)
+	springLoadedHotseatBarTopMarginPx: 116.0px (44.190475dp)
+	getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+	getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
+	getHotseatLayoutPadding(context).left: 113.0px (43.04762dp)
+	getHotseatLayoutPadding(context).right: 113.0px (43.04762dp)
+	numShownHotseatIcons: 6
+	hotseatBorderSpace: 0.0px (0.0dp)
+	isQsbInline: false
+	hotseatQsbWidth: 0.0px (0.0dp)
+	isTaskbarPresent:false
+	isTaskbarPresentInApps:true
+	taskbarHeight: 0.0px (0.0dp)
+	stashedTaskbarHeight: 0.0px (0.0dp)
+	taskbarBottomMargin: 0.0px (0.0dp)
+	taskbarIconSize: 0.0px (0.0dp)
+	desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+	workspacePadding.left: 21.0px (8.0dp)
+	workspacePadding.top: 30.0px (11.428572dp)
+	workspacePadding.right: 21.0px (8.0dp)
+	workspacePadding.bottom: 330.0px (125.71429dp)
+	iconScale: 1.0px (0.3809524dp)
+	cellScaleToFit : 1.0px (0.3809524dp)
+	extraSpace: 498.0px (189.71428dp)
+	unscaled extraSpace: 498.0px (189.71428dp)
+	maxEmptySpace: 0.0px (0.0dp)
+	workspaceTopPadding: 0.0px (0.0dp)
+	workspaceBottomPadding: 0.0px (0.0dp)
+	overviewTaskMarginPx: 0.0px (0.0dp)
+	overviewTaskIconSizePx: 0.0px (0.0dp)
+	overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+	overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+	overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+	overviewActionsTopMarginPx: 0.0px (0.0dp)
+	overviewActionsHeight: 0.0px (0.0dp)
+	overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+	overviewActionsButtonSpacing: 0.0px (0.0dp)
+	overviewPageSpacing: 0.0px (0.0dp)
+	overviewRowSpacing: 0.0px (0.0dp)
+	overviewGridSideMargin: 0.0px (0.0dp)
+	dropTargetBarTopMarginPx: 0.0px (0.0dp)
+	dropTargetBarSizePx: 147.0px (56.0dp)
+	dropTargetBarBottomMarginPx: 42.0px (16.0dp)
+	getCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)
+	getCellLayoutSpringLoadShrunkBottom(): 1457.0px (555.0476dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
+	getWorkspaceSpringLoadScale(): 0.8452555px (0.32200208dp)
+	getCellLayoutHeight(): 1370.0px (521.9048dp)
+	getCellLayoutWidth(): 1083.0px (412.57144dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape_decoupleDepth.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape_decoupleDepth.txt
new file mode 100644
index 0000000..44b99e9
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape_decoupleDepth.txt
@@ -0,0 +1,130 @@
+DeviceProfile:
+	1 dp = 2.625 px
+	isTablet:true
+	isPhone:false
+	transposeLayoutWithOrientation:false
+	isGestureMode:true
+	isLandscape:true
+	isMultiWindowMode:false
+	isTwoPanels:true
+	isLeftRightSplit:true
+	windowX: 0.0px (0.0dp)
+	windowY: 0.0px (0.0dp)
+	widthPx: 2208.0px (841.1429dp)
+	heightPx: 1840.0px (700.9524dp)
+	availableWidthPx: 2208.0px (841.1429dp)
+	availableHeightPx: 1730.0px (659.0476dp)
+	mInsets.left: 0.0px (0.0dp)
+	mInsets.top: 110.0px (41.904762dp)
+	mInsets.right: 0.0px (0.0dp)
+	mInsets.bottom: 0.0px (0.0dp)
+	aspectRatio:1.2
+	isResponsiveGrid:false
+	isScalableGrid:false
+	inv.numRows: 4
+	inv.numColumns: 4
+	inv.numSearchContainerColumns: 4
+	minCellSize: PointF(0.0, 0.0)dp
+	cellWidthPx: 154.0px (58.666668dp)
+	cellHeightPx: 218.0px (83.04762dp)
+	getCellSize().x: 270.0px (102.85714dp)
+	getCellSize().y: 342.0px (130.28572dp)
+	cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+	cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+	cellLayoutPaddingPx.left: 0.0px (0.0dp)
+	cellLayoutPaddingPx.top: 0.0px (0.0dp)
+	cellLayoutPaddingPx.right: 0.0px (0.0dp)
+	cellLayoutPaddingPx.bottom: 0.0px (0.0dp)
+	iconSizePx: 141.0px (53.714287dp)
+	iconTextSizePx: 34.0px (12.952381dp)
+	iconDrawablePaddingPx: 13.0px (4.952381dp)
+	numFolderRows: 3
+	numFolderColumns: 4
+	folderCellWidthPx: 189.0px (72.0dp)
+	folderCellHeightPx: 219.0px (83.42857dp)
+	folderChildIconSizePx: 141.0px (53.714287dp)
+	folderChildTextSizePx: 34.0px (12.952381dp)
+	folderChildDrawablePaddingPx: 5.0px (1.9047619dp)
+	folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+	folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+	folderContentPaddingLeftRight: 21.0px (8.0dp)
+	folderTopPadding: 63.0px (24.0dp)
+	folderFooterHeight: 147.0px (56.0dp)
+	bottomSheetTopPadding: 110.0px (41.904762dp)
+	bottomSheetOpenDuration: 500
+	bottomSheetCloseDuration: 500
+	bottomSheetWorkspaceScale: 0.97
+	bottomSheetDepth: 0.3
+	allAppsShiftRange: 1840.0px (700.9524dp)
+	allAppsOpenDuration: 500
+	allAppsCloseDuration: 500
+	allAppsIconSizePx: 141.0px (53.714287dp)
+	allAppsIconTextSizePx: 34.0px (12.952381dp)
+	allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+	allAppsCellHeightPx: 361.0px (137.5238dp)
+	allAppsCellWidthPx: 183.0px (69.71429dp)
+	allAppsBorderSpacePxX: 42.0px (16.0dp)
+	allAppsBorderSpacePxY: 42.0px (16.0dp)
+	numShownAllAppsColumns: 8
+	allAppsPadding.top: 110.0px (41.904762dp)
+	allAppsPadding.left: 42.0px (16.0dp)
+	allAppsPadding.right: 42.0px (16.0dp)
+	allAppsLeftRightMargin: 183.0px (69.71429dp)
+	hotseatBarSizePx: 267.0px (101.71429dp)
+	mHotseatColumnSpan: 4
+	mHotseatWidthPx: 0.0px (0.0dp)
+	hotseatCellHeightPx: 159.0px (60.57143dp)
+	hotseatBarBottomSpacePx: 126.0px (48.0dp)
+	mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+	mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+	hotseatBarEndOffset: 0.0px (0.0dp)
+	hotseatQsbSpace: 0.0px (0.0dp)
+	hotseatQsbHeight: 0.0px (0.0dp)
+	springLoadedHotseatBarTopMarginPx: 116.0px (44.190475dp)
+	getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+	getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
+	getHotseatLayoutPadding(context).left: 113.0px (43.04762dp)
+	getHotseatLayoutPadding(context).right: 113.0px (43.04762dp)
+	numShownHotseatIcons: 6
+	hotseatBorderSpace: 0.0px (0.0dp)
+	isQsbInline: false
+	hotseatQsbWidth: 0.0px (0.0dp)
+	isTaskbarPresent:false
+	isTaskbarPresentInApps:true
+	taskbarHeight: 0.0px (0.0dp)
+	stashedTaskbarHeight: 0.0px (0.0dp)
+	taskbarBottomMargin: 0.0px (0.0dp)
+	taskbarIconSize: 0.0px (0.0dp)
+	desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+	workspacePadding.left: 21.0px (8.0dp)
+	workspacePadding.top: 30.0px (11.428572dp)
+	workspacePadding.right: 21.0px (8.0dp)
+	workspacePadding.bottom: 330.0px (125.71429dp)
+	iconScale: 1.0px (0.3809524dp)
+	cellScaleToFit : 1.0px (0.3809524dp)
+	extraSpace: 498.0px (189.71428dp)
+	unscaled extraSpace: 498.0px (189.71428dp)
+	maxEmptySpace: 0.0px (0.0dp)
+	workspaceTopPadding: 0.0px (0.0dp)
+	workspaceBottomPadding: 0.0px (0.0dp)
+	overviewTaskMarginPx: 0.0px (0.0dp)
+	overviewTaskIconSizePx: 0.0px (0.0dp)
+	overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+	overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+	overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+	overviewActionsTopMarginPx: 0.0px (0.0dp)
+	overviewActionsHeight: 0.0px (0.0dp)
+	overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+	overviewActionsButtonSpacing: 0.0px (0.0dp)
+	overviewPageSpacing: 0.0px (0.0dp)
+	overviewRowSpacing: 0.0px (0.0dp)
+	overviewGridSideMargin: 0.0px (0.0dp)
+	dropTargetBarTopMarginPx: 0.0px (0.0dp)
+	dropTargetBarSizePx: 147.0px (56.0dp)
+	dropTargetBarBottomMarginPx: 42.0px (16.0dp)
+	getCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)
+	getCellLayoutSpringLoadShrunkBottom(): 1457.0px (555.0476dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
+	getWorkspaceSpringLoadScale(): 0.8452555px (0.32200208dp)
+	getCellLayoutHeight(): 1370.0px (521.9048dp)
+	getCellLayoutWidth(): 1083.0px (412.57144dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button_decoupleDepth.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button_decoupleDepth.txt
new file mode 100644
index 0000000..e7b72f2
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button_decoupleDepth.txt
@@ -0,0 +1,130 @@
+DeviceProfile:
+	1 dp = 2.625 px
+	isTablet:true
+	isPhone:false
+	transposeLayoutWithOrientation:false
+	isGestureMode:false
+	isLandscape:false
+	isMultiWindowMode:false
+	isTwoPanels:true
+	isLeftRightSplit:false
+	windowX: 0.0px (0.0dp)
+	windowY: 0.0px (0.0dp)
+	widthPx: 1840.0px (700.9524dp)
+	heightPx: 2208.0px (841.1429dp)
+	availableWidthPx: 1840.0px (700.9524dp)
+	availableHeightPx: 2075.0px (790.4762dp)
+	mInsets.left: 0.0px (0.0dp)
+	mInsets.top: 133.0px (50.666668dp)
+	mInsets.right: 0.0px (0.0dp)
+	mInsets.bottom: 0.0px (0.0dp)
+	aspectRatio:1.2
+	isResponsiveGrid:false
+	isScalableGrid:false
+	inv.numRows: 4
+	inv.numColumns: 4
+	inv.numSearchContainerColumns: 4
+	minCellSize: PointF(0.0, 0.0)dp
+	cellWidthPx: 154.0px (58.666668dp)
+	cellHeightPx: 218.0px (83.04762dp)
+	getCellSize().x: 224.0px (85.333336dp)
+	getCellSize().y: 430.0px (163.80952dp)
+	cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+	cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+	cellLayoutPaddingPx.left: 0.0px (0.0dp)
+	cellLayoutPaddingPx.top: 0.0px (0.0dp)
+	cellLayoutPaddingPx.right: 0.0px (0.0dp)
+	cellLayoutPaddingPx.bottom: 0.0px (0.0dp)
+	iconSizePx: 141.0px (53.714287dp)
+	iconTextSizePx: 34.0px (12.952381dp)
+	iconDrawablePaddingPx: 13.0px (4.952381dp)
+	numFolderRows: 3
+	numFolderColumns: 4
+	folderCellWidthPx: 189.0px (72.0dp)
+	folderCellHeightPx: 219.0px (83.42857dp)
+	folderChildIconSizePx: 141.0px (53.714287dp)
+	folderChildTextSizePx: 34.0px (12.952381dp)
+	folderChildDrawablePaddingPx: 5.0px (1.9047619dp)
+	folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+	folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+	folderContentPaddingLeftRight: 21.0px (8.0dp)
+	folderTopPadding: 63.0px (24.0dp)
+	folderFooterHeight: 147.0px (56.0dp)
+	bottomSheetTopPadding: 133.0px (50.666668dp)
+	bottomSheetOpenDuration: 500
+	bottomSheetCloseDuration: 500
+	bottomSheetWorkspaceScale: 0.97
+	bottomSheetDepth: 0.3
+	allAppsShiftRange: 2208.0px (841.1429dp)
+	allAppsOpenDuration: 500
+	allAppsCloseDuration: 500
+	allAppsIconSizePx: 141.0px (53.714287dp)
+	allAppsIconTextSizePx: 34.0px (12.952381dp)
+	allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+	allAppsCellHeightPx: 361.0px (137.5238dp)
+	allAppsCellWidthPx: 183.0px (69.71429dp)
+	allAppsBorderSpacePxX: 42.0px (16.0dp)
+	allAppsBorderSpacePxY: 42.0px (16.0dp)
+	numShownAllAppsColumns: 8
+	allAppsPadding.top: 133.0px (50.666668dp)
+	allAppsPadding.left: 42.0px (16.0dp)
+	allAppsPadding.right: 42.0px (16.0dp)
+	allAppsLeftRightMargin: 1.0px (0.3809524dp)
+	hotseatBarSizePx: 267.0px (101.71429dp)
+	mHotseatColumnSpan: 4
+	mHotseatWidthPx: 0.0px (0.0dp)
+	hotseatCellHeightPx: 159.0px (60.57143dp)
+	hotseatBarBottomSpacePx: 126.0px (48.0dp)
+	mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+	mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+	hotseatBarEndOffset: 0.0px (0.0dp)
+	hotseatQsbSpace: 0.0px (0.0dp)
+	hotseatQsbHeight: 0.0px (0.0dp)
+	springLoadedHotseatBarTopMarginPx: 168.0px (64.0dp)
+	getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+	getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
+	getHotseatLayoutPadding(context).left: 98.0px (37.333332dp)
+	getHotseatLayoutPadding(context).right: 98.0px (37.333332dp)
+	numShownHotseatIcons: 6
+	hotseatBorderSpace: 0.0px (0.0dp)
+	isQsbInline: false
+	hotseatQsbWidth: 0.0px (0.0dp)
+	isTaskbarPresent:false
+	isTaskbarPresentInApps:true
+	taskbarHeight: 0.0px (0.0dp)
+	stashedTaskbarHeight: 0.0px (0.0dp)
+	taskbarBottomMargin: 0.0px (0.0dp)
+	taskbarIconSize: 0.0px (0.0dp)
+	desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+	workspacePadding.left: 21.0px (8.0dp)
+	workspacePadding.top: 24.0px (9.142858dp)
+	workspacePadding.right: 21.0px (8.0dp)
+	workspacePadding.bottom: 330.0px (125.71429dp)
+	iconScale: 1.0px (0.3809524dp)
+	cellScaleToFit : 1.0px (0.3809524dp)
+	extraSpace: 849.0px (323.42856dp)
+	unscaled extraSpace: 849.0px (323.42856dp)
+	maxEmptySpace: 0.0px (0.0dp)
+	workspaceTopPadding: 0.0px (0.0dp)
+	workspaceBottomPadding: 0.0px (0.0dp)
+	overviewTaskMarginPx: 0.0px (0.0dp)
+	overviewTaskIconSizePx: 0.0px (0.0dp)
+	overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+	overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+	overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+	overviewActionsTopMarginPx: 0.0px (0.0dp)
+	overviewActionsHeight: 0.0px (0.0dp)
+	overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+	overviewActionsButtonSpacing: 0.0px (0.0dp)
+	overviewPageSpacing: 0.0px (0.0dp)
+	overviewRowSpacing: 0.0px (0.0dp)
+	overviewGridSideMargin: 0.0px (0.0dp)
+	dropTargetBarTopMarginPx: 0.0px (0.0dp)
+	dropTargetBarSizePx: 147.0px (56.0dp)
+	dropTargetBarBottomMarginPx: 84.0px (32.0dp)
+	getCellLayoutSpringLoadShrunkTop(): 364.0px (138.66667dp)
+	getCellLayoutSpringLoadShrunkBottom(): 1773.0px (675.4286dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
+	getWorkspaceSpringLoadScale(): 0.81871px (0.31188953dp)
+	getCellLayoutHeight(): 1721.0px (655.619dp)
+	getCellLayoutWidth(): 899.0px (342.4762dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait_decoupleDepth.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait_decoupleDepth.txt
new file mode 100644
index 0000000..eae50f1
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait_decoupleDepth.txt
@@ -0,0 +1,130 @@
+DeviceProfile:
+	1 dp = 2.625 px
+	isTablet:true
+	isPhone:false
+	transposeLayoutWithOrientation:false
+	isGestureMode:true
+	isLandscape:false
+	isMultiWindowMode:false
+	isTwoPanels:true
+	isLeftRightSplit:false
+	windowX: 0.0px (0.0dp)
+	windowY: 0.0px (0.0dp)
+	widthPx: 1840.0px (700.9524dp)
+	heightPx: 2208.0px (841.1429dp)
+	availableWidthPx: 1840.0px (700.9524dp)
+	availableHeightPx: 2075.0px (790.4762dp)
+	mInsets.left: 0.0px (0.0dp)
+	mInsets.top: 133.0px (50.666668dp)
+	mInsets.right: 0.0px (0.0dp)
+	mInsets.bottom: 0.0px (0.0dp)
+	aspectRatio:1.2
+	isResponsiveGrid:false
+	isScalableGrid:false
+	inv.numRows: 4
+	inv.numColumns: 4
+	inv.numSearchContainerColumns: 4
+	minCellSize: PointF(0.0, 0.0)dp
+	cellWidthPx: 154.0px (58.666668dp)
+	cellHeightPx: 218.0px (83.04762dp)
+	getCellSize().x: 224.0px (85.333336dp)
+	getCellSize().y: 430.0px (163.80952dp)
+	cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+	cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+	cellLayoutPaddingPx.left: 0.0px (0.0dp)
+	cellLayoutPaddingPx.top: 0.0px (0.0dp)
+	cellLayoutPaddingPx.right: 0.0px (0.0dp)
+	cellLayoutPaddingPx.bottom: 0.0px (0.0dp)
+	iconSizePx: 141.0px (53.714287dp)
+	iconTextSizePx: 34.0px (12.952381dp)
+	iconDrawablePaddingPx: 13.0px (4.952381dp)
+	numFolderRows: 3
+	numFolderColumns: 4
+	folderCellWidthPx: 189.0px (72.0dp)
+	folderCellHeightPx: 219.0px (83.42857dp)
+	folderChildIconSizePx: 141.0px (53.714287dp)
+	folderChildTextSizePx: 34.0px (12.952381dp)
+	folderChildDrawablePaddingPx: 5.0px (1.9047619dp)
+	folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+	folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+	folderContentPaddingLeftRight: 21.0px (8.0dp)
+	folderTopPadding: 63.0px (24.0dp)
+	folderFooterHeight: 147.0px (56.0dp)
+	bottomSheetTopPadding: 133.0px (50.666668dp)
+	bottomSheetOpenDuration: 500
+	bottomSheetCloseDuration: 500
+	bottomSheetWorkspaceScale: 0.97
+	bottomSheetDepth: 0.3
+	allAppsShiftRange: 2208.0px (841.1429dp)
+	allAppsOpenDuration: 500
+	allAppsCloseDuration: 500
+	allAppsIconSizePx: 141.0px (53.714287dp)
+	allAppsIconTextSizePx: 34.0px (12.952381dp)
+	allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+	allAppsCellHeightPx: 361.0px (137.5238dp)
+	allAppsCellWidthPx: 183.0px (69.71429dp)
+	allAppsBorderSpacePxX: 42.0px (16.0dp)
+	allAppsBorderSpacePxY: 42.0px (16.0dp)
+	numShownAllAppsColumns: 8
+	allAppsPadding.top: 133.0px (50.666668dp)
+	allAppsPadding.left: 42.0px (16.0dp)
+	allAppsPadding.right: 42.0px (16.0dp)
+	allAppsLeftRightMargin: 1.0px (0.3809524dp)
+	hotseatBarSizePx: 267.0px (101.71429dp)
+	mHotseatColumnSpan: 4
+	mHotseatWidthPx: 0.0px (0.0dp)
+	hotseatCellHeightPx: 159.0px (60.57143dp)
+	hotseatBarBottomSpacePx: 126.0px (48.0dp)
+	mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+	mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+	hotseatBarEndOffset: 0.0px (0.0dp)
+	hotseatQsbSpace: 0.0px (0.0dp)
+	hotseatQsbHeight: 0.0px (0.0dp)
+	springLoadedHotseatBarTopMarginPx: 168.0px (64.0dp)
+	getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+	getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
+	getHotseatLayoutPadding(context).left: 98.0px (37.333332dp)
+	getHotseatLayoutPadding(context).right: 98.0px (37.333332dp)
+	numShownHotseatIcons: 6
+	hotseatBorderSpace: 0.0px (0.0dp)
+	isQsbInline: false
+	hotseatQsbWidth: 0.0px (0.0dp)
+	isTaskbarPresent:false
+	isTaskbarPresentInApps:true
+	taskbarHeight: 0.0px (0.0dp)
+	stashedTaskbarHeight: 0.0px (0.0dp)
+	taskbarBottomMargin: 0.0px (0.0dp)
+	taskbarIconSize: 0.0px (0.0dp)
+	desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+	workspacePadding.left: 21.0px (8.0dp)
+	workspacePadding.top: 24.0px (9.142858dp)
+	workspacePadding.right: 21.0px (8.0dp)
+	workspacePadding.bottom: 330.0px (125.71429dp)
+	iconScale: 1.0px (0.3809524dp)
+	cellScaleToFit : 1.0px (0.3809524dp)
+	extraSpace: 849.0px (323.42856dp)
+	unscaled extraSpace: 849.0px (323.42856dp)
+	maxEmptySpace: 0.0px (0.0dp)
+	workspaceTopPadding: 0.0px (0.0dp)
+	workspaceBottomPadding: 0.0px (0.0dp)
+	overviewTaskMarginPx: 0.0px (0.0dp)
+	overviewTaskIconSizePx: 0.0px (0.0dp)
+	overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+	overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+	overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+	overviewActionsTopMarginPx: 0.0px (0.0dp)
+	overviewActionsHeight: 0.0px (0.0dp)
+	overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+	overviewActionsButtonSpacing: 0.0px (0.0dp)
+	overviewPageSpacing: 0.0px (0.0dp)
+	overviewRowSpacing: 0.0px (0.0dp)
+	overviewGridSideMargin: 0.0px (0.0dp)
+	dropTargetBarTopMarginPx: 0.0px (0.0dp)
+	dropTargetBarSizePx: 147.0px (56.0dp)
+	dropTargetBarBottomMarginPx: 84.0px (32.0dp)
+	getCellLayoutSpringLoadShrunkTop(): 364.0px (138.66667dp)
+	getCellLayoutSpringLoadShrunkBottom(): 1773.0px (675.4286dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
+	getWorkspaceSpringLoadScale(): 0.81871px (0.31188953dp)
+	getCellLayoutHeight(): 1721.0px (655.619dp)
+	getCellLayoutWidth(): 899.0px (342.4762dp)
diff --git a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index 108db6c..c3b7a2a 100644
--- a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -170,20 +170,12 @@
 
     public static final String PERMANENT_DIAG_TAG = "TaplTarget";
     public static final String TWO_NEXUS_LAUNCHER_ACTIVITY_WHILE_UNLOCKING = "b/273347463";
-    public static final String TWO_TASKBAR_LONG_CLICKS = "b/262282528";
     public static final String ICON_MISSING = "b/282963545";
-    public static final String OVERVIEW_OVER_HOME = "b/279059025";
     public static final String UIOBJECT_STALE_ELEMENT = "b/319501259";
     public static final String TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE = "b/326908466";
-    public static final String TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE = "b/326073471";
     public static final String WIDGET_CONFIG_NULL_EXTRA_INTENT = "b/324419890";
-    public static final String ACTIVITY_NOT_RESUMED_AFTER_BACK = "b/322823209";
     public static final String OVERVIEW_SELECT_TOOLTIP_MISALIGNED = "b/332485341";
-
-    public static final String REQUEST_EMULATE_DISPLAY = "emulate-display";
-    public static final String REQUEST_STOP_EMULATE_DISPLAY = "stop-emulate-display";
-    public static final String REQUEST_IS_EMULATE_DISPLAY_RUNNING = "is-emulate-display-running";
-    public static final String REQUEST_EMULATE_PRINT_DEVICE = "emulate-print-device";
+    public static final String CLOCK_ICON_DRAWABLE_LEAKING = "b/319168409";
 
     public static final String REQUEST_FLAG_ENABLE_GRID_ONLY_OVERVIEW = "enable-grid-only-overview";
     public static final String REQUEST_FLAG_ENABLE_APP_PAIRS = "enable-app-pairs";
diff --git a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
similarity index 98%
rename from tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
index aefc2db..e378733 100644
--- a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
@@ -306,6 +306,7 @@
         context.putObject(LauncherPrefs.INSTANCE, launcherPrefs)
 
         whenever(launcherPrefs.get(LauncherPrefs.TASKBAR_PINNING)).thenReturn(false)
+        whenever(launcherPrefs.get(LauncherPrefs.TASKBAR_PINNING_IN_DESKTOP_MODE)).thenReturn(true)
         val info = spy(DisplayController.Info(context, windowManagerProxy, perDisplayBoundsCache))
         whenever(displayController.info).thenReturn(info)
         whenever(info.isTransientTaskbar).thenReturn(isGestureMode)
diff --git a/tests/multivalentTests/src/com/android/launcher3/AutoInstallsLayoutTest.kt b/tests/multivalentTests/src/com/android/launcher3/AutoInstallsLayoutTest.kt
new file mode 100644
index 0000000..b04bcca
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/AutoInstallsLayoutTest.kt
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2024 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
+
+import android.content.ComponentName
+import android.content.ContentValues
+import android.database.sqlite.SQLiteDatabase
+import android.os.Process.myUserHandle
+import android.os.UserHandle
+import android.util.Xml
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback
+import com.android.launcher3.AutoInstallsLayout.SourceResources
+import com.android.launcher3.AutoInstallsLayout.TAG_WORKSPACE
+import com.android.launcher3.AutoInstallsLayout.USER_TYPE_WORK
+import com.android.launcher3.LauncherSettings.Favorites.APPWIDGET_PROVIDER
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT
+import com.android.launcher3.LauncherSettings.Favorites.INTENT
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER
+import com.android.launcher3.LauncherSettings.Favorites.PROFILE_ID
+import com.android.launcher3.LauncherSettings.Favorites.SPANX
+import com.android.launcher3.LauncherSettings.Favorites.SPANY
+import com.android.launcher3.LauncherSettings.Favorites._ID
+import com.android.launcher3.model.data.AppInfo
+import com.android.launcher3.pm.UserCache
+import com.android.launcher3.util.ApiWrapper
+import com.android.launcher3.util.Executors
+import com.android.launcher3.util.LauncherLayoutBuilder
+import com.android.launcher3.util.LauncherModelHelper
+import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext
+import com.android.launcher3.util.TestUtil
+import com.android.launcher3.util.UserIconInfo
+import com.android.launcher3.util.UserIconInfo.TYPE_MAIN
+import com.android.launcher3.util.UserIconInfo.TYPE_WORK
+import com.android.launcher3.widget.LauncherWidgetHolder
+import com.google.common.truth.Truth.assertThat
+import java.io.StringReader
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.whenever
+
+/** Tests for [AutoInstallsLayout] */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AutoInstallsLayoutTest {
+
+    lateinit var modelHelper: LauncherModelHelper
+    lateinit var targetContext: SandboxModelContext
+
+    lateinit var callback: MyCallback
+
+    @Mock lateinit var widgetHolder: LauncherWidgetHolder
+    @Mock lateinit var db: SQLiteDatabase
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        modelHelper = LauncherModelHelper()
+        targetContext = modelHelper.sandboxContext
+        callback = MyCallback()
+    }
+
+    @After
+    fun tearDown() {
+        modelHelper.destroy()
+    }
+
+    @Test
+    fun pending_icon_added_on_home() {
+        LauncherLayoutBuilder()
+            .atWorkspace(1, 1, 0)
+            .putApp("p1", "c1")
+            .toAutoInstallsLayout()
+            .loadLayout(db)
+
+        assertThat(callback.items.size).isEqualTo(1)
+        assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_APPLICATION)
+        assertThat(callback.items[0][INTENT])
+            .isEqualTo(AppInfo.makeLaunchIntent(ComponentName("p1", "c1")).toUri(0))
+        assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_DESKTOP)
+        assertThat(callback.items[0].containsKey(PROFILE_ID)).isFalse()
+    }
+
+    @Test
+    fun pending_icon_added_on_hotseat() {
+        LauncherLayoutBuilder()
+            .atHotseat(1)
+            .putApp("p1", "c1")
+            .toAutoInstallsLayout()
+            .loadLayout(db)
+
+        assertThat(callback.items.size).isEqualTo(1)
+        assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_APPLICATION)
+        assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_HOTSEAT)
+    }
+
+    @Test
+    fun widget_added_to_home() {
+        LauncherLayoutBuilder()
+            .atWorkspace(1, 1, 0)
+            .putWidget("p1", "c1", 2, 3)
+            .toAutoInstallsLayout()
+            .loadLayout(db)
+
+        assertThat(callback.items.size).isEqualTo(1)
+        assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_APPWIDGET)
+        assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_DESKTOP)
+        assertThat(callback.items[0][APPWIDGET_PROVIDER])
+            .isEqualTo(ComponentName("p1", "c1").flattenToString())
+        assertThat(callback.items[0][SPANX]).isEqualTo(2.toString())
+        assertThat(callback.items[0][SPANY]).isEqualTo(3.toString())
+    }
+
+    @Test
+    fun items_added_to_folder() {
+        LauncherLayoutBuilder()
+            .atHotseat(1)
+            .putFolder("Test")
+            .addApp("p1", "c")
+            .addApp("p2", "c")
+            .addApp("p3", "c")
+            .build()
+            .toAutoInstallsLayout()
+            .loadLayout(db)
+
+        assertThat(callback.items.size).isEqualTo(4)
+        assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_FOLDER)
+        assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_HOTSEAT)
+
+        val folderId = callback.items[0][_ID]
+        assertThat(callback.items[1][CONTAINER]).isEqualTo(folderId)
+        assertThat(callback.items[2][CONTAINER]).isEqualTo(folderId)
+        assertThat(callback.items[3][CONTAINER]).isEqualTo(folderId)
+    }
+
+    @Test
+    fun work_item_added_to_home() {
+        val apiWrapperMock = spy(ApiWrapper.INSTANCE[targetContext])
+        targetContext.putObject(ApiWrapper.INSTANCE, apiWrapperMock)
+        doReturn(
+                mapOf(
+                    myUserHandle() to UserIconInfo(myUserHandle(), TYPE_MAIN, 0),
+                    UserHandle.of(20) to UserIconInfo(UserHandle.of(20), TYPE_WORK, 20),
+                )
+            )
+            .whenever(apiWrapperMock)
+            .queryAllUsers()
+
+        val cache = UserCache.getInstance(targetContext)
+        TestUtil.runOnExecutorSync(Executors.MODEL_EXECUTOR) {
+            assertThat(cache.userProfiles.size).isEqualTo(2)
+        }
+
+        LauncherLayoutBuilder()
+            .atWorkspace(1, 1, 0)
+            .putApp("p1", "c1", USER_TYPE_WORK)
+            .toAutoInstallsLayout()
+            .loadLayout(db)
+
+        assertThat(callback.items.size).isEqualTo(1)
+        assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_APPLICATION)
+        assertThat(callback.items[0][INTENT])
+            .isEqualTo(AppInfo.makeLaunchIntent(ComponentName("p1", "c1")).toUri(0))
+        assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_DESKTOP)
+        assertThat(callback.items[0][PROFILE_ID]).isEqualTo(20)
+    }
+
+    private fun LauncherLayoutBuilder.toAutoInstallsLayout() =
+        AutoInstallsLayout(
+            targetContext,
+            widgetHolder,
+            callback,
+            SourceResources.wrap(targetContext.resources),
+            { Xml.newPullParser().also { it.setInput(StringReader(build())) } },
+            TAG_WORKSPACE
+        )
+
+    class MyCallback : LayoutParserCallback {
+
+        val items = ArrayList<ContentValues>()
+
+        override fun generateNewItemId() = items.size
+
+        override fun insertAndCheck(db: SQLiteDatabase?, values: ContentValues): Int {
+            val id = values[_ID]
+            items.add(ContentValues(values))
+            return if (id is Int) id else 0
+        }
+    }
+}
diff --git a/tests/src/com/android/launcher3/DeleteDropTargetTest.kt b/tests/multivalentTests/src/com/android/launcher3/DeleteDropTargetTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/DeleteDropTargetTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/DeleteDropTargetTest.kt
diff --git a/tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt b/tests/multivalentTests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
similarity index 98%
rename from tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
index 13d7499..0538870 100644
--- a/tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
@@ -46,7 +46,7 @@
 @IgnoreLimit(ignoreLimit = BuildConfig.IS_STUDIO_BUILD)
 abstract class FakeInvariantDeviceProfileTest {
 
-    protected var context: Context? = null
+    protected lateinit var context: Context
     protected var inv: InvariantDeviceProfile? = null
     protected val info: Info = mock()
     protected var windowBounds: WindowBounds? = null
@@ -257,10 +257,10 @@
     }
 
     protected fun initializeVarsForTwoPanel(
-            isLandscape: Boolean = false,
-            isGestureMode: Boolean = true,
-            rows: Int = 4,
-            cols: Int = 4,
+        isLandscape: Boolean = false,
+        isGestureMode: Boolean = true,
+        rows: Int = 4,
+        cols: Int = 4,
     ) {
         val (x, y) = if (isLandscape) Pair(2208, 1840) else Pair(1840, 2208)
 
diff --git a/tests/src/com/android/launcher3/LauncherPrefsTest.kt b/tests/multivalentTests/src/com/android/launcher3/LauncherPrefsTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/LauncherPrefsTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/LauncherPrefsTest.kt
diff --git a/tests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java b/tests/multivalentTests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java
rename to tests/multivalentTests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java
diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutTestCaseReader.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/CellLayoutTestCaseReader.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/CellLayoutTestCaseReader.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/CellLayoutTestCaseReader.java
diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java
diff --git a/tests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt
similarity index 97%
rename from tests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt
index 13dfd5e..c32461e 100644
--- a/tests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt
@@ -22,6 +22,8 @@
 import android.view.View
 import androidx.core.view.get
 import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
 import com.android.launcher3.CellLayout
 import com.android.launcher3.celllayout.board.CellLayoutBoard
 import com.android.launcher3.celllayout.board.IconPoint
@@ -34,6 +36,7 @@
 import org.junit.Assert
 import org.junit.Rule
 import org.junit.Test
+import org.junit.runner.RunWith
 
 private class HotseatReorderTestCase(
     val startBoard: CellLayoutBoard,
@@ -44,6 +47,8 @@
     }
 }
 
+@SmallTest
+@RunWith(AndroidJUnit4::class)
 class HotseatReorderUnitTest {
 
     private val applicationContext: Context =
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
similarity index 98%
rename from tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
index 0ff7c20..8a9711d 100644
--- a/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
@@ -215,9 +215,11 @@
                 testCase.spanX, testCase.spanY, testCase.minSpanX, testCase.minSpanY,
                 isMultiCellLayout);
         assertEquals("should be a valid solution", solution.isSolution, testCase.isValidSolution);
+        Log.d(TAG, "test case:" + testCase);
         if (testCase.isValidSolution) {
             CellLayoutBoard finishBoard = boardFromSolution(solution,
                     testCase.startBoard.getWidth(), testCase.startBoard.getHeight());
+            Log.d(TAG, "finishBoard case:" + finishBoard);
             assertTrue("End result and test case result board doesn't match ",
                     finishBoard.compareTo(testCase.endBoard) == 0);
         }
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTestCase.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTestCase.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTestCase.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTestCase.java
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderPreviewAnimationTest.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderPreviewAnimationTest.kt
similarity index 95%
rename from tests/src/com/android/launcher3/celllayout/ReorderPreviewAnimationTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderPreviewAnimationTest.kt
index 0bec1b2..a9355ec 100644
--- a/tests/src/com/android/launcher3/celllayout/ReorderPreviewAnimationTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderPreviewAnimationTest.kt
@@ -141,11 +141,14 @@
             ReorderPreviewAnimation.MODE_PREVIEW,
             AnimationValues(dx = 0, dy = 0, scale = 100)
         )
-        testAnimationAtGivenProgress(
-            PREVIEW_DURATION * 99,
-            ReorderPreviewAnimation.MODE_PREVIEW,
-            AnimationValues(dx = 5, dy = -10, scale = 96)
-        )
+        // (b/339313407) Temporarily disable this test as the behavior is
+        // inconsistent between Soong & Gradle builds.
+        //
+        // testAnimationAtGivenProgress(
+        //     PREVIEW_DURATION * 99,
+        //     ReorderPreviewAnimation.MODE_PREVIEW,
+        //     AnimationValues(dx = 5, dy = -10, scale = 96)
+        // )
         testAnimationAtGivenProgress(
             PREVIEW_DURATION * 98,
             ReorderPreviewAnimation.MODE_PREVIEW,
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderTestCase.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderTestCase.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/ReorderTestCase.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderTestCase.java
diff --git a/tests/src/com/android/launcher3/celllayout/UnitTestCellLayoutBuilderRule.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/UnitTestCellLayoutBuilderRule.kt
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/UnitTestCellLayoutBuilderRule.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/UnitTestCellLayoutBuilderRule.kt
diff --git a/tests/src/com/android/launcher3/celllayout/testgenerator/DeterministicRandomGenerator.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/testgenerator/DeterministicRandomGenerator.kt
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/testgenerator/DeterministicRandomGenerator.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/testgenerator/DeterministicRandomGenerator.kt
diff --git a/tests/src/com/android/launcher3/celllayout/testgenerator/RandomBoardGenerator.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/testgenerator/RandomBoardGenerator.kt
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/testgenerator/RandomBoardGenerator.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/testgenerator/RandomBoardGenerator.kt
diff --git a/tests/src/com/android/launcher3/celllayout/testgenerator/RandomMultiBoardGenerator.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/testgenerator/RandomMultiBoardGenerator.kt
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/testgenerator/RandomMultiBoardGenerator.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/testgenerator/RandomMultiBoardGenerator.kt
diff --git a/tests/src/com/android/launcher3/folder/FolderNameProviderTest.java b/tests/multivalentTests/src/com/android/launcher3/folder/FolderNameProviderTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/folder/FolderNameProviderTest.java
rename to tests/multivalentTests/src/com/android/launcher3/folder/FolderNameProviderTest.java
diff --git a/tests/multivalentTests/src/com/android/launcher3/icons/FastBitmapDrawableTest.java b/tests/multivalentTests/src/com/android/launcher3/icons/FastBitmapDrawableTest.java
index 7e9b68d..58dce0b 100644
--- a/tests/multivalentTests/src/com/android/launcher3/icons/FastBitmapDrawableTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/icons/FastBitmapDrawableTest.java
@@ -37,15 +37,12 @@
 import android.view.animation.PathInterpolator;
 
 import androidx.test.annotation.UiThreadTest;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
-import com.android.launcher3.util.rule.RobolectricUiThreadRule;
+import com.android.launcher3.util.LauncherMultivalentJUnit;
 
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
@@ -55,14 +52,11 @@
  * Tests for FastBitmapDrawable.
  */
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(LauncherMultivalentJUnit.class)
 @UiThreadTest
 public class FastBitmapDrawableTest {
     private static final float EPSILON = 0.00001f;
 
-    @Rule
-    public final TestRule roboUiThreadRule = new RobolectricUiThreadRule();
-
     @Spy
     FastBitmapDrawable mFastBitmapDrawable =
             spy(new FastBitmapDrawable(Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)));
diff --git a/tests/src/com/android/launcher3/icons/IconCacheTest.java b/tests/multivalentTests/src/com/android/launcher3/icons/IconCacheTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/icons/IconCacheTest.java
rename to tests/multivalentTests/src/com/android/launcher3/icons/IconCacheTest.java
diff --git a/tests/multivalentTests/src/com/android/launcher3/logging/StartupLatencyLoggerTest.kt b/tests/multivalentTests/src/com/android/launcher3/logging/StartupLatencyLoggerTest.kt
index 12f6c8c..713d4d5 100644
--- a/tests/multivalentTests/src/com/android/launcher3/logging/StartupLatencyLoggerTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/logging/StartupLatencyLoggerTest.kt
@@ -2,22 +2,18 @@
 
 import androidx.core.util.isEmpty
 import androidx.test.annotation.UiThreadTest
-import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import com.android.launcher3.util.rule.RobolectricUiThreadRule
+import com.android.launcher3.util.LauncherMultivalentJUnit
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
-import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 
 /** Unit test for [ColdRebootStartupLatencyLogger]. */
 @SmallTest
-@RunWith(AndroidJUnit4::class)
+@RunWith(LauncherMultivalentJUnit::class)
 class StartupLatencyLoggerTest {
 
-    @get:Rule val roboUiThreadRule = RobolectricUiThreadRule()
-
     private val underTest = ColdRebootStartupLatencyLogger()
 
     @Before
diff --git a/tests/src/com/android/launcher3/model/DatabaseHelperTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/DatabaseHelperTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/model/DatabaseHelperTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/model/DatabaseHelperTest.kt
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
diff --git a/tests/src/com/android/launcher3/responsive/SizeSpecTest.kt b/tests/multivalentTests/src/com/android/launcher3/responsive/SizeSpecTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/responsive/SizeSpecTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/responsive/SizeSpecTest.kt
diff --git a/tests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java b/tests/multivalentTests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java
rename to tests/multivalentTests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java
diff --git a/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java b/tests/multivalentTests/src/com/android/launcher3/ui/BubbleTextViewTest.java
similarity index 98%
rename from tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
rename to tests/multivalentTests/src/com/android/launcher3/ui/BubbleTextViewTest.java
index 90ded10..b83349e 100644
--- a/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/ui/BubbleTextViewTest.java
@@ -37,6 +37,9 @@
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.view.ViewGroup;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.Flags;
 import com.android.launcher3.LauncherPrefs;
@@ -52,6 +55,7 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
 
 /**
@@ -61,6 +65,8 @@
  * two lines, and this is enough to ensure whether the string should be specifically wrapped onto
  * the second line and to ensure truncation.
  */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
 public class BubbleTextViewTest {
 
     @Rule public final SetFlagsRule mSetFlagsRule =
diff --git a/tests/src/com/android/launcher3/util/CellContentDimensionsTest.kt b/tests/multivalentTests/src/com/android/launcher3/util/CellContentDimensionsTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/util/CellContentDimensionsTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/util/CellContentDimensionsTest.kt
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/LauncherLayoutBuilder.java b/tests/multivalentTests/src/com/android/launcher3/util/LauncherLayoutBuilder.java
deleted file mode 100644
index ba01b04..0000000
--- a/tests/multivalentTests/src/com/android/launcher3/util/LauncherLayoutBuilder.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.android.launcher3.util;
-
-
-import android.text.TextUtils;
-import android.util.Pair;
-import android.util.Xml;
-
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Helper class to build xml for Launcher Layout
- */
-public class LauncherLayoutBuilder {
-
-    // Object Tags
-    private static final String TAG_WORKSPACE = "workspace";
-    private static final String TAG_AUTO_INSTALL = "autoinstall";
-    private static final String TAG_FOLDER = "folder";
-    private static final String TAG_APPWIDGET = "appwidget";
-    private static final String TAG_SHORTCUT = "shortcut";
-    private static final String TAG_EXTRA = "extra";
-
-    private static final String ATTR_CONTAINER = "container";
-    private static final String ATTR_RANK = "rank";
-
-    private static final String ATTR_PACKAGE_NAME = "packageName";
-    private static final String ATTR_CLASS_NAME = "className";
-    private static final String ATTR_TITLE = "title";
-    private static final String ATTR_TITLE_TEXT = "titleText";
-    private static final String ATTR_SCREEN = "screen";
-    private static final String ATTR_SHORTCUT_ID = "shortcutId";
-
-    // x and y can be specified as negative integers, in which case -1 represents the
-    // last row / column, -2 represents the second last, and so on.
-    private static final String ATTR_X = "x";
-    private static final String ATTR_Y = "y";
-    private static final String ATTR_SPAN_X = "spanX";
-    private static final String ATTR_SPAN_Y = "spanY";
-
-    private static final String ATTR_CHILDREN = "children";
-
-
-    // Style attrs -- "Extra"
-    private static final String ATTR_KEY = "key";
-    private static final String ATTR_VALUE = "value";
-
-    private static final String CONTAINER_DESKTOP = "desktop";
-    private static final String CONTAINER_HOTSEAT = "hotseat";
-
-    private final ArrayList<Pair<String, HashMap<String, Object>>> mNodes = new ArrayList<>();
-
-    public Location atHotseat(int rank) {
-        Location l = new Location();
-        l.items.put(ATTR_CONTAINER, CONTAINER_HOTSEAT);
-        l.items.put(ATTR_RANK, Integer.toString(rank));
-        return l;
-    }
-
-    public Location atWorkspace(int x, int y, int screen) {
-        Location l = new Location();
-        l.items.put(ATTR_CONTAINER, CONTAINER_DESKTOP);
-        l.items.put(ATTR_X, Integer.toString(x));
-        l.items.put(ATTR_Y, Integer.toString(y));
-        l.items.put(ATTR_SCREEN, Integer.toString(screen));
-        return l;
-    }
-
-    public String build() throws IOException {
-        StringWriter writer = new StringWriter();
-        build(writer);
-        return writer.toString();
-    }
-
-    public void build(Writer writer) throws IOException {
-        XmlSerializer serializer = Xml.newSerializer();
-        serializer.setOutput(writer);
-
-        serializer.startDocument("UTF-8", true);
-        serializer.startTag(null, TAG_WORKSPACE);
-        writeNodes(serializer, mNodes);
-        serializer.endTag(null, TAG_WORKSPACE);
-        serializer.endDocument();
-        serializer.flush();
-    }
-
-    private static void writeNodes(XmlSerializer serializer,
-            ArrayList<Pair<String, HashMap<String, Object>>> nodes) throws IOException {
-        for (Pair<String, HashMap<String, Object>> node : nodes) {
-            ArrayList<Pair<String, HashMap<String, Object>>> children = null;
-
-            serializer.startTag(null, node.first);
-            for (Map.Entry<String, Object> attr : node.second.entrySet()) {
-                if (ATTR_CHILDREN.equals(attr.getKey())) {
-                    children = (ArrayList<Pair<String, HashMap<String, Object>>>) attr.getValue();
-                } else {
-                    serializer.attribute(null, attr.getKey(), (String) attr.getValue());
-                }
-            }
-
-            if (children != null) {
-                writeNodes(serializer, children);
-            }
-            serializer.endTag(null, node.first);
-        }
-    }
-
-    public class Location {
-
-        final HashMap<String, Object> items = new HashMap<>();
-
-        public LauncherLayoutBuilder putApp(String packageName, String className) {
-            items.put(ATTR_PACKAGE_NAME, packageName);
-            items.put(ATTR_CLASS_NAME, TextUtils.isEmpty(className) ? packageName : className);
-            mNodes.add(Pair.create(TAG_AUTO_INSTALL, items));
-            return LauncherLayoutBuilder.this;
-        }
-
-        public LauncherLayoutBuilder putShortcut(String packageName, String shortcutId) {
-            items.put(ATTR_PACKAGE_NAME, packageName);
-            items.put(ATTR_SHORTCUT_ID, shortcutId);
-            mNodes.add(Pair.create(TAG_SHORTCUT, items));
-            return LauncherLayoutBuilder.this;
-        }
-
-        public LauncherLayoutBuilder putWidget(String packageName, String className,
-                int spanX, int spanY) {
-            items.put(ATTR_PACKAGE_NAME, packageName);
-            items.put(ATTR_CLASS_NAME, className);
-            items.put(ATTR_SPAN_X, Integer.toString(spanX));
-            items.put(ATTR_SPAN_Y, Integer.toString(spanY));
-            mNodes.add(Pair.create(TAG_APPWIDGET, items));
-            return LauncherLayoutBuilder.this;
-        }
-
-        public FolderBuilder putFolder(int titleResId) {
-            items.put(ATTR_TITLE, Integer.toString(titleResId));
-            return putFolder();
-        }
-
-        public FolderBuilder putFolder(String title) {
-            items.put(ATTR_TITLE_TEXT, title);
-            return putFolder();
-        }
-
-        private FolderBuilder putFolder() {
-            FolderBuilder folderBuilder = new FolderBuilder();
-            items.put(ATTR_CHILDREN, folderBuilder.mChildren);
-            mNodes.add(Pair.create(TAG_FOLDER, items));
-            return folderBuilder;
-        }
-    }
-
-    public class FolderBuilder {
-
-        final ArrayList<Pair<String, HashMap<String, Object>>> mChildren = new ArrayList<>();
-
-        public FolderBuilder addApp(String packageName, String className) {
-            HashMap<String, Object> items = new HashMap<>();
-            items.put(ATTR_PACKAGE_NAME, packageName);
-            items.put(ATTR_CLASS_NAME, TextUtils.isEmpty(className) ? packageName : className);
-            mChildren.add(Pair.create(TAG_AUTO_INSTALL, items));
-            return this;
-        }
-
-        public FolderBuilder addShortcut(String packageName, String shortcutId) {
-            HashMap<String, Object> items = new HashMap<>();
-            items.put(ATTR_PACKAGE_NAME, packageName);
-            items.put(ATTR_SHORTCUT_ID, shortcutId);
-            mChildren.add(Pair.create(TAG_SHORTCUT, items));
-            return this;
-        }
-
-        public LauncherLayoutBuilder build() {
-            return LauncherLayoutBuilder.this;
-        }
-    }
-}
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/multivalentTests/src/com/android/launcher3/util/LauncherModelHelper.java
index 002f496..f18c02b 100644
--- a/tests/multivalentTests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/tests/multivalentTests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -44,15 +44,12 @@
 import android.test.mock.MockContentResolver;
 import android.util.ArrayMap;
 
-import androidx.annotation.NonNull;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.uiautomator.UiDevice;
 
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherModel;
-import com.android.launcher3.LauncherModel.ModelUpdateTask;
-import com.android.launcher3.model.AllAppsList;
 import com.android.launcher3.model.BgDataModel;
 import com.android.launcher3.model.BgDataModel.Callbacks;
 import com.android.launcher3.testing.TestInformationProvider;
@@ -66,7 +63,6 @@
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
 
 /**
  * Utility class to help manage Launcher Model and related objects for test.
@@ -115,17 +111,9 @@
 
     public synchronized BgDataModel getBgDataModel() {
         if (mDataModel == null) {
-            getModel().enqueueModelUpdateTask(new ModelUpdateTask() {
-                @Override
-                public void init(@NonNull LauncherAppState app, @NonNull LauncherModel model,
-                        @NonNull BgDataModel dataModel, @NonNull AllAppsList allAppsList,
-                        @NonNull Executor uiExecutor) {
-                    mDataModel = dataModel;
-                }
-
-                @Override
-                public void run() { }
-            });
+            getModel().enqueueModelUpdateTask((taskController, dataModel, apps) ->
+                    mDataModel = dataModel);
+            runOnExecutorSync(Executors.MODEL_EXECUTOR, () -> { });
         }
         return mDataModel;
     }
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/LauncherMultivalentJUnit.kt b/tests/multivalentTests/src/com/android/launcher3/util/LauncherMultivalentJUnit.kt
new file mode 100644
index 0000000..e8560af
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/util/LauncherMultivalentJUnit.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 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 androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.collect.ImmutableList
+import java.util.Locale
+import kotlin.annotation.AnnotationRetention.RUNTIME
+import kotlin.annotation.AnnotationTarget.CLASS
+import org.junit.runner.Runner
+import org.junit.runners.Suite
+
+/**
+ * A custom runner for multivalent tests with launcher specific features
+ * 1) Adds support for @UiThread annotations in deviceless tests
+ * 2) Allows emulating multiple devices when running in deviceless mode
+ */
+class LauncherMultivalentJUnit(klass: Class<*>?) : Suite(klass, ImmutableList.of()) {
+
+    val runners: List<Runner> =
+        (testClass.getAnnotation(EmulatedDevices::class.java)?.value ?: emptyArray()).let { devices
+            ->
+            if (!isRunningInRobolectric) {
+                return@let null
+            }
+            try {
+                (testClass.javaClass.classLoader.loadClass(ROBOLECTRIC_RUNNER) as Class<Runner>)
+                    .getConstructor(Class::class.java, String::class.java)
+                    .let { ctor ->
+                        if (devices.isEmpty()) listOf(ctor.newInstance(testClass.javaClass, null))
+                        else devices.map { ctor.newInstance(testClass.javaClass, it) }
+                    }
+            } catch (e: Exception) {
+                null
+            }
+        }
+            ?: listOf(AndroidJUnit4(testClass.javaClass))
+
+    override fun getChildren() = runners
+
+    /**
+     * Annotation to be added to a test so run it on a list of emulated devices for deviceless test
+     */
+    @Retention(RUNTIME) @Target(CLASS) annotation class EmulatedDevices(val value: Array<String>)
+
+    companion object {
+        private const val ROBOLECTRIC_RUNNER = "com.android.launcher3.util.RobolectricDeviceRunner"
+
+        val isRunningInRobolectric: Boolean
+            get() =
+                if (
+                    System.getProperty("java.runtime.name")
+                        .lowercase(Locale.getDefault())
+                        .contains("android")
+                ) {
+                    false
+                } else {
+                    try {
+                        // Check if robolectric runner exists
+                        Class.forName("org.robolectric.RobolectricTestRunner") != null
+                    } catch (e: ClassNotFoundException) {
+                        false
+                    }
+                }
+    }
+}
diff --git a/tests/src/com/android/launcher3/util/PackageManagerHelperTest.java b/tests/multivalentTests/src/com/android/launcher3/util/PackageManagerHelperTest.java
similarity index 93%
rename from tests/src/com/android/launcher3/util/PackageManagerHelperTest.java
rename to tests/multivalentTests/src/com/android/launcher3/util/PackageManagerHelperTest.java
index d1da5f4..b5e797e 100644
--- a/tests/src/com/android/launcher3/util/PackageManagerHelperTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/util/PackageManagerHelperTest.java
@@ -34,6 +34,7 @@
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -63,6 +64,8 @@
         mContext = mock(Context.class);
         mLauncherApps = mock(LauncherApps.class);
         when(mContext.getSystemService(eq(LauncherApps.class))).thenReturn(mLauncherApps);
+        when(mContext.getResources()).thenReturn(
+                InstrumentationRegistry.getInstrumentation().getTargetContext().getResources());
         mPackageManagerHelper = new PackageManagerHelper(mContext);
     }
 
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/WidgetUtils.java b/tests/multivalentTests/src/com/android/launcher3/util/WidgetUtils.java
index 027a31a..deb0ef3 100644
--- a/tests/multivalentTests/src/com/android/launcher3/util/WidgetUtils.java
+++ b/tests/multivalentTests/src/com/android/launcher3/util/WidgetUtils.java
@@ -15,15 +15,12 @@
  */
 package com.android.launcher3.util;
 
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.os.Bundle;
-import android.os.Process;
 
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@@ -87,10 +84,10 @@
      * Creates a {@link AppWidgetProviderInfo} for the provided component name
      */
     public static AppWidgetProviderInfo createAppWidgetProviderInfo(ComponentName cn) {
-        AppWidgetProviderInfo info = AppWidgetManager.getInstance(getApplicationContext())
-                .getInstalledProvidersForPackage(
-                        getInstrumentation().getContext().getPackageName(), Process.myUserHandle())
-                .get(0);
+        ActivityInfo activityInfo = new ActivityInfo();
+        activityInfo.applicationInfo = new ApplicationInfo();
+        AppWidgetProviderInfo info = new AppWidgetProviderInfo();
+        info.providerInfo = activityInfo;
         info.provider = cn;
         return info;
     }
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/rule/RobolectricUiThreadRule.kt b/tests/multivalentTests/src/com/android/launcher3/util/rule/RobolectricUiThreadRule.kt
deleted file mode 100644
index 18cd1e4..0000000
--- a/tests/multivalentTests/src/com/android/launcher3/util/rule/RobolectricUiThreadRule.kt
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2024 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.rule
-
-import androidx.test.annotation.UiThreadTest
-import androidx.test.platform.app.InstrumentationRegistry
-import java.util.Locale
-import java.util.concurrent.atomic.AtomicReference
-import org.junit.rules.TestRule
-import org.junit.runner.Description
-import org.junit.runners.model.Statement
-
-/**
- * A test rule to add support for @UiThreadTest annotations when running in robolectric until is it
- * natively supported by the robolectric runner:
- * https://github.com/robolectric/robolectric/issues/9026
- */
-class RobolectricUiThreadRule : TestRule {
-
-    override fun apply(base: Statement, description: Description): Statement =
-        if (!shouldRunOnUiThread(description)) base else UiThreadStatement(base)
-
-    private fun shouldRunOnUiThread(description: Description): Boolean {
-        if (!isRunningInRobolectric()) {
-            // If not running in robolectric, let the default runner handle this
-            return false
-        }
-        var clazz = description.testClass
-        try {
-            if (
-                clazz
-                    .getDeclaredMethod(description.methodName)
-                    .getAnnotation(UiThreadTest::class.java) != null
-            ) {
-                return true
-            }
-        } catch (_: Exception) {
-            // Ignore
-        }
-
-        while (!clazz.isAnnotationPresent(UiThreadTest::class.java)) {
-            clazz = clazz.superclass ?: return false
-        }
-        return true
-    }
-
-    private fun isRunningInRobolectric(): Boolean {
-        if (
-            System.getProperty("java.runtime.name")
-                .lowercase(Locale.getDefault())
-                .contains("android")
-        )
-            return false
-        return try {
-            // Check if robolectric runner exists
-            Class.forName("org.robolectric.RobolectricTestRunner") != null
-        } catch (e: ClassNotFoundException) {
-            false
-        }
-    }
-
-    private class UiThreadStatement(val base: Statement) : Statement() {
-
-        override fun evaluate() {
-            val exceptionRef = AtomicReference<Throwable>()
-            InstrumentationRegistry.getInstrumentation().runOnMainSync {
-                try {
-                    base.evaluate()
-                } catch (throwable: Throwable) {
-                    exceptionRef.set(throwable)
-                }
-            }
-            exceptionRef.get()?.let { throw it }
-        }
-    }
-}
diff --git a/tests/src/com/android/launcher3/util/rule/SetFlagsRuleExt.kt b/tests/multivalentTests/src/com/android/launcher3/util/rule/SetFlagsRuleExt.kt
similarity index 100%
rename from tests/src/com/android/launcher3/util/rule/SetFlagsRuleExt.kt
rename to tests/multivalentTests/src/com/android/launcher3/util/rule/SetFlagsRuleExt.kt
diff --git a/tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetImageViewTest.kt b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetImageViewTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/widget/picker/WidgetImageViewTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetImageViewTest.kt
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java
similarity index 91%
rename from tests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java
index 60a4cd3..3024d26 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java
@@ -25,7 +25,6 @@
 import static android.content.pm.ApplicationInfo.CATEGORY_VIDEO;
 import static android.content.pm.ApplicationInfo.FLAG_INSTALLED;
 
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -35,7 +34,6 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.when;
 
-import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
 import android.content.Context;
@@ -53,6 +51,7 @@
 import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.WidgetUtils;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
 
 import com.google.common.collect.ImmutableMap;
@@ -79,15 +78,15 @@
                     R.string.news_widget_recommendation_category_label, /*order=*/1);
     private static final WidgetRecommendationCategory SUGGESTED_FOR_YOU =
             new WidgetRecommendationCategory(
-                    R.string.others_widget_recommendation_category_label, /*order=*/4);
+                    R.string.others_widget_recommendation_category_label, /*order=*/2);
     private static final WidgetRecommendationCategory SOCIAL =
             new WidgetRecommendationCategory(
                     R.string.social_widget_recommendation_category_label,
-                    /*order=*/5);
+                    /*order=*/3);
     private static final WidgetRecommendationCategory ENTERTAINMENT =
             new WidgetRecommendationCategory(
                     R.string.entertainment_widget_recommendation_category_label,
-                    /*order=*/6);
+                    /*order=*/4);
 
     private final ApplicationInfo mTestAppInfo = ApplicationInfoBuilder.newBuilder().setPackageName(
             TEST_PACKAGE).setName(TEST_APP_NAME).build();
@@ -152,11 +151,8 @@
 
         doAnswer(invocation -> widgetLabel).when(mIconCache).getTitleNoCache(any());
 
-        AppWidgetProviderInfo providerInfo = AppWidgetManager.getInstance(getApplicationContext())
-                .getInstalledProvidersForPackage(
-                        getInstrumentation().getContext().getPackageName(), Process.myUserHandle())
-                .get(0);
-        providerInfo.provider = ComponentName.createRelative(TEST_PACKAGE, widgetClassName);
+        AppWidgetProviderInfo providerInfo = WidgetUtils.createAppWidgetProviderInfo(ComponentName
+                .createRelative(TEST_PACKAGE, widgetClassName));
 
         LauncherAppWidgetProviderInfo launcherAppWidgetProviderInfo =
                 LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, providerInfo);
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderAccessibilityTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListHeaderAccessibilityTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderAccessibilityTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListHeaderAccessibilityTest.java
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
similarity index 96%
rename from tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
index 8fc4481..d4e061a 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
@@ -31,6 +31,7 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.os.UserHandle;
+import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.widget.FrameLayout;
 import android.widget.TextView;
@@ -79,7 +80,8 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
-        mContext = new ActivityContextWrapper(getApplicationContext());
+        mContext = new ActivityContextWrapper(new ContextThemeWrapper(getApplicationContext(),
+                R.style.WidgetContainerTheme));
         mTestProfile = new InvariantDeviceProfile();
         mTestProfile.numRows = 5;
         mTestProfile.numColumns = 5;
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
similarity index 94%
rename from tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
index 85fb380..e1cc010 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
@@ -16,6 +16,7 @@
 package com.android.launcher3.widget.picker;
 
 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -49,8 +50,8 @@
 import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.model.data.PackageItemInfo;
 import com.android.launcher3.util.ActivityContextWrapper;
-import com.android.launcher3.util.Executors;
 import com.android.launcher3.util.WidgetUtils;
+import com.android.launcher3.widget.DatabaseWidgetPreviewLoader;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
 import com.android.launcher3.widget.WidgetCell;
 import com.android.launcher3.widget.WidgetManagerHelper;
@@ -112,7 +113,9 @@
                 TEST_PACKAGE,
                 /* numOfWidgets= */ 3);
         mViewHolderBinder.bindViewHolder(viewHolder, entry, /* position= */ 0, EMPTY_LIST);
-        Executors.MAIN_EXECUTOR.submit(() -> { }).get();
+        // Wait for the loader to complete the preview loading
+        DatabaseWidgetPreviewLoader.getLoaderExecutor().submit(() -> { }).get();
+        getInstrumentation().waitForIdleSync();
 
         // THEN the table container has one row, which contains 3 widgets.
         // View:  .SampleWidget0 | .SampleWidget1 | .SampleWidget2
diff --git a/tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
diff --git a/tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
similarity index 98%
rename from tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
index 9c03ccf..0370a6b 100644
--- a/tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
@@ -17,6 +17,7 @@
 package com.android.launcher3.widget.picker.search;
 
 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.WidgetUtils.createAppWidgetProviderInfo;
@@ -163,7 +164,7 @@
                 .when(mDataProvider)
                 .getAllWidgets();
         mSimpleWidgetsSearchAlgorithm.doSearch("Ca", mSearchCallback);
-        MAIN_EXECUTOR.submit(() -> { }).get();
+        getInstrumentation().waitForIdleSync();
         verify(mSearchCallback).onSearchResult(
                 matches("Ca"), argThat(a -> a != null && !a.isEmpty()));
     }
diff --git a/tests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt b/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt
similarity index 93%
rename from tests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt
index 040fbf5..7b629bf 100644
--- a/tests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt
@@ -43,6 +43,7 @@
     private lateinit var context: Context
     private lateinit var deviceProfile: DeviceProfile
     private lateinit var testInvariantProfile: InvariantDeviceProfile
+    private lateinit var widgetItemInvariantProfile: InvariantDeviceProfile
 
     @Mock private lateinit var iconCache: IconCache
 
@@ -51,6 +52,11 @@
         MockitoAnnotations.initMocks(this)
         context = ActivityContextWrapper(ApplicationProvider.getApplicationContext())
         testInvariantProfile = LauncherAppState.getIDP(context)
+        widgetItemInvariantProfile =
+            InvariantDeviceProfile().apply {
+                numRows = TEST_GRID_SIZE
+                numColumns = TEST_GRID_SIZE
+            }
         deviceProfile = testInvariantProfile.getDeviceProfile(context).copy(context)
     }
 
@@ -60,7 +66,8 @@
         val expectedPreviewContainers = testSizes.values.toList()
 
         for ((index, widgetSize) in testSizes.keys.withIndex()) {
-            val widgetItem = createWidgetItem(widgetSize, context, testInvariantProfile, iconCache)
+            val widgetItem =
+                createWidgetItem(widgetSize, context, widgetItemInvariantProfile, iconCache)
 
             assertWithMessage("size for $widgetSize should be: ${expectedPreviewContainers[index]}")
                 .that(WidgetPreviewContainerSize.forItem(widgetItem, deviceProfile))
@@ -70,6 +77,7 @@
 
     companion object {
         private const val TEST_PACKAGE = "com.google.test"
+        private const val TEST_GRID_SIZE = 6
 
         private val HANDHELD_TEST_SIZES: Map<Point, WidgetPreviewContainerSize> =
             mapOf(
diff --git a/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
diff --git a/tests/multivalentTestsForDeviceless b/tests/multivalentTestsForDeviceless
deleted file mode 120000
index 20ee34a..0000000
--- a/tests/multivalentTestsForDeviceless
+++ /dev/null
@@ -1 +0,0 @@
-multivalentTests
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/AppFilterTest.kt b/tests/src/com/android/launcher3/AppFilterTest.kt
new file mode 100644
index 0000000..f2150a2
--- /dev/null
+++ b/tests/src/com/android/launcher3/AppFilterTest.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 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
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.res.Resources
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnitRunner
+
+@RunWith(MockitoJUnitRunner::class)
+class AppFilterTest {
+
+    @Mock private lateinit var mockContext: Context
+
+    @Mock // Mock the Resources object as well
+    private lateinit var mockResources: Resources
+
+    private lateinit var appFilter: AppFilter
+
+    @Before
+    fun setUp() {
+        `when`(mockContext.resources).thenReturn(mockResources) // Link the context and resources
+        `when`(mockResources.getStringArray(R.array.filtered_components))
+            .thenReturn(arrayOf("com.example.app1/Activity1"))
+        appFilter = AppFilter(mockContext)
+    }
+
+    @Test
+    fun shouldShowApp_notFiltered_returnsTrue() {
+        val appToShow = ComponentName("com.example.app2", "Activity2")
+        assertThat(appFilter.shouldShowApp(appToShow)).isTrue()
+    }
+
+    @Test
+    fun shouldShowApp_filtered_returnsFalse() {
+        val appToHide = ComponentName("com.example.app1", "Activity1")
+        assertThat(appFilter.shouldShowApp(appToHide)).isFalse()
+    }
+}
diff --git a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
index b6b2261..4cd2a07 100644
--- a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
+++ b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
@@ -202,6 +202,7 @@
     }
 
     @Test
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/339109319
     public void openPrivateSpaceSettings_triggersCorrectIntent() {
         Intent expectedIntent = ApiWrapper.INSTANCE.get(mContext).getPrivateSpaceSettingsIntent();
         ArgumentCaptor<Intent> acIntent = ArgumentCaptor.forClass(Intent.class);
diff --git a/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java b/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java
index 20684eb..4e627a9 100644
--- a/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java
+++ b/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java
@@ -75,7 +75,6 @@
     }
 
     @Test
-    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/311410127
     public void testAllAppsExitSearchAndFocusSearchResults() {
         final HomeAllApps allApps = mLauncher.goHome().switchToAllApps();
         assertTrue("Launcher internal state is not All Apps",
diff --git a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
index 70c0333..362596c 100644
--- a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
+++ b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
@@ -177,6 +177,8 @@
      */
     @Test
     @PortraitLandscape
+    @ScreenRecordRule.ScreenRecord // b/338869019
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/338869019
     public void testAddDeleteShortcutOnHotseat() {
         mLauncher.getWorkspace()
                 .deleteAppIcon(mLauncher.getWorkspace().getHotseatAppIcon(0))
diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
index 56ac960..b4945d7 100644
--- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java
+++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
@@ -79,6 +79,7 @@
 
     private LauncherModelHelper mModelHelper;
     private LauncherAppState mApp;
+    private PackageManagerHelper mPmHelper;
 
     private MatrixCursor mCursor;
     private InvariantDeviceProfile mIDP;
@@ -92,6 +93,7 @@
         mContext = mModelHelper.sandboxContext;
         mIDP = InvariantDeviceProfile.INSTANCE.get(mContext);
         mApp = LauncherAppState.getInstance(mContext);
+        mPmHelper = PackageManagerHelper.INSTANCE.get(mContext);
 
         mCursor = new MatrixCursor(new String[] {
                 ICON, TITLE, _ID, CONTAINER, ITEM_TYPE,
@@ -101,7 +103,7 @@
         });
 
         UserManagerState ums = new UserManagerState();
-        mLoaderCursor = new LoaderCursor(mCursor, mApp, ums, null);
+        mLoaderCursor = new LoaderCursor(mCursor, mApp, ums, mPmHelper, null);
         ums.allUsers.put(0, Process.myUserHandle());
     }
 
diff --git a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
index 6bbcf85..6cf3b19 100644
--- a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
+++ b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
@@ -23,6 +23,7 @@
 import android.content.pm.LauncherApps
 import android.content.pm.PackageInstaller
 import android.content.pm.ShortcutInfo
+import android.os.Process
 import android.os.UserHandle
 import android.platform.test.annotations.EnableFlags
 import android.util.LongSparseArray
@@ -429,6 +430,7 @@
                 whenever(disabledMessage).thenReturn("")
                 whenever(disabledReason).thenReturn(0)
                 whenever(persons).thenReturn(EMPTY_PERSON_ARRAY)
+                whenever(userHandle).thenReturn(Process.myUserHandle())
             }
         mIconRequestInfos = mutableListOf()
         // Make sure shortcuts map has expected key from expected package
diff --git a/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt b/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
index 9409ac1..60385a7 100644
--- a/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
+++ b/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
@@ -15,137 +15,105 @@
  */
 package com.android.launcher3.nonquickstep
 
-import android.content.Context
-import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry
 import com.android.launcher3.AbstractDeviceProfileTest
 import com.android.launcher3.DeviceProfile
+import com.android.launcher3.Flags
 import com.android.launcher3.InvariantDeviceProfile
-import com.google.common.truth.Truth.assertThat
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
 
 /** Tests for DeviceProfile. */
 @SmallTest
-@RunWith(AndroidJUnit4::class)
+@RunWith(Parameterized::class)
 class DeviceProfileDumpTest : AbstractDeviceProfileTest() {
     private val folderName: String = "DeviceProfileDumpTest"
-    @Test
-    fun phonePortrait3Button() {
-        initializeVarsForPhone(deviceSpecs["phone"]!!, isGestureMode = false)
-        val dp = getDeviceProfileForGrid("5_by_5")
 
-        assertDump(dp, "phonePortrait3Button")
+    @Parameterized.Parameter lateinit var instance: TestCase
+
+    @Before
+    fun setUp() {
+        if (instance.decoupleDepth) {
+            setFlagsRule.enableFlags(Flags.FLAG_ENABLE_SCALING_REVEAL_HOME_ANIMATION)
+        } else {
+            setFlagsRule.disableFlags(Flags.FLAG_ENABLE_SCALING_REVEAL_HOME_ANIMATION)
+        }
     }
 
     @Test
-    fun phonePortrait() {
-        initializeVarsForPhone(deviceSpecs["phone"]!!)
-        val dp = getDeviceProfileForGrid("5_by_5")
+    fun dumpPortraitGesture() {
+        initializeDevice(instance.deviceName, isGestureMode = true, isLandscape = false)
+        val dp = getDeviceProfileForGrid(instance.gridName)
+        dp.isTaskbarPresentInApps = instance.isTaskbarPresentInApps
 
-        assertDump(dp, "phonePortrait")
+        assertDump(dp, instance.filename("Portrait"))
     }
 
     @Test
-    fun phoneVerticalBar3Button() {
-        initializeVarsForPhone(deviceSpecs["phone"]!!, isVerticalBar = true, isGestureMode = false)
-        val dp = getDeviceProfileForGrid("5_by_5")
+    fun dumpPortrait3Button() {
+        initializeDevice(instance.deviceName, isGestureMode = false, isLandscape = false)
+        val dp = getDeviceProfileForGrid(instance.gridName)
+        dp.isTaskbarPresentInApps = instance.isTaskbarPresentInApps
 
-        assertDump(dp, "phoneVerticalBar3Button")
+        assertDump(dp, instance.filename("Portrait3Button"))
     }
 
     @Test
-    fun phoneVerticalBar() {
-        initializeVarsForPhone(deviceSpecs["phone"]!!, isVerticalBar = true)
-        val dp = getDeviceProfileForGrid("5_by_5")
+    fun dumpLandscapeGesture() {
+        initializeDevice(instance.deviceName, isGestureMode = true, isLandscape = true)
+        val dp = getDeviceProfileForGrid(instance.gridName)
+        dp.isTaskbarPresentInApps = instance.isTaskbarPresentInApps
 
-        assertDump(dp, "phoneVerticalBar")
+        val testName =
+            if (instance.deviceName == "phone") {
+                "VerticalBar"
+            } else {
+                "Landscape"
+            }
+        assertDump(dp, instance.filename(testName))
     }
 
     @Test
-    fun tabletLandscape3Button() {
-        initializeVarsForTablet(deviceSpecs["tablet"]!!, isLandscape = true, isGestureMode = false)
-        val dp = getDeviceProfileForGrid("6_by_5")
-        dp.isTaskbarPresentInApps = true
+    fun dumpLandscape3Button() {
+        initializeDevice(instance.deviceName, isGestureMode = false, isLandscape = true)
+        val dp = getDeviceProfileForGrid(instance.gridName)
+        dp.isTaskbarPresentInApps = instance.isTaskbarPresentInApps
 
-        assertDump(dp, "tabletLandscape3Button")
+        val testName =
+            if (instance.deviceName == "phone") {
+                "VerticalBar3Button"
+            } else {
+                "Landscape3Button"
+            }
+        assertDump(dp, instance.filename(testName))
     }
 
-    @Test
-    fun tabletLandscape() {
-        initializeVarsForTablet(deviceSpecs["tablet"]!!, isLandscape = true)
-        val dp = getDeviceProfileForGrid("6_by_5")
-        dp.isTaskbarPresentInApps = true
-
-        assertDump(dp, "tabletLandscape")
-    }
-
-    @Test
-    fun tabletPortrait3Button() {
-        initializeVarsForTablet(deviceSpecs["tablet"]!!, isGestureMode = false)
-        val dp = getDeviceProfileForGrid("6_by_5")
-        dp.isTaskbarPresentInApps = true
-
-        assertDump(dp, "tabletPortrait3Button")
-    }
-
-    @Test
-    fun tabletPortrait() {
-        initializeVarsForTablet(deviceSpecs["tablet"]!!)
-        val dp = getDeviceProfileForGrid("6_by_5")
-        dp.isTaskbarPresentInApps = true
-
-        assertDump(dp, "tabletPortrait")
-    }
-
-    @Test
-    fun twoPanelLandscape3Button() {
-        initializeVarsForTwoPanel(
-            deviceSpecs["twopanel-tablet"]!!,
-            deviceSpecs["twopanel-phone"]!!,
-            isLandscape = true,
-            isGestureMode = false
-        )
-        val dp = getDeviceProfileForGrid("4_by_4")
-        dp.isTaskbarPresentInApps = true
-
-        assertDump(dp, "twoPanelLandscape3Button")
-    }
-
-    @Test
-    fun twoPanelLandscape() {
-        initializeVarsForTwoPanel(
-            deviceSpecs["twopanel-tablet"]!!,
-            deviceSpecs["twopanel-phone"]!!,
-            isLandscape = true
-        )
-        val dp = getDeviceProfileForGrid("4_by_4")
-        dp.isTaskbarPresentInApps = true
-
-        assertDump(dp, "twoPanelLandscape")
-    }
-
-    @Test
-    fun twoPanelPortrait3Button() {
-        initializeVarsForTwoPanel(
-            deviceSpecs["twopanel-tablet"]!!,
-            deviceSpecs["twopanel-phone"]!!,
-            isGestureMode = false
-        )
-        val dp = getDeviceProfileForGrid("4_by_4")
-        dp.isTaskbarPresentInApps = true
-
-        assertDump(dp, "twoPanelPortrait3Button")
-    }
-
-    @Test
-    fun twoPanelPortrait() {
-        initializeVarsForTwoPanel(deviceSpecs["twopanel-tablet"]!!, deviceSpecs["twopanel-phone"]!!)
-        val dp = getDeviceProfileForGrid("4_by_4")
-        dp.isTaskbarPresentInApps = true
-
-        assertDump(dp, "twoPanelPortrait")
+    private fun initializeDevice(deviceName: String, isGestureMode: Boolean, isLandscape: Boolean) {
+        val deviceSpec = deviceSpecs[instance.deviceName]!!
+        when (deviceName) {
+            "twopanel-phone",
+            "twopanel-tablet" ->
+                initializeVarsForTwoPanel(
+                    deviceSpecUnfolded = deviceSpecs["twopanel-tablet"]!!,
+                    deviceSpecFolded = deviceSpecs["twopanel-phone"]!!,
+                    isLandscape = isLandscape,
+                    isGestureMode = isGestureMode,
+                )
+            "tablet" ->
+                initializeVarsForTablet(
+                    deviceSpec = deviceSpec,
+                    isLandscape = isLandscape,
+                    isGestureMode = isGestureMode
+                )
+            else ->
+                initializeVarsForPhone(
+                    deviceSpec = deviceSpec,
+                    isVerticalBar = isLandscape,
+                    isGestureMode = isGestureMode
+                )
+        }
     }
 
     private fun getDeviceProfileForGrid(gridName: String): DeviceProfile {
@@ -153,6 +121,48 @@
     }
 
     private fun assertDump(dp: DeviceProfile, filename: String) {
-        assertDump(dp, folderName, filename);
+        assertDump(dp, folderName, filename)
+    }
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getInstances(): List<TestCase> {
+            return listOf(
+                TestCase("phone", gridName = "5_by_5"),
+                TestCase("tablet", gridName = "6_by_5", isTaskbarPresentInApps = true),
+                TestCase("twopanel-tablet", gridName = "4_by_4", isTaskbarPresentInApps = true),
+                TestCase(
+                    "twopanel-tablet",
+                    gridName = "4_by_4",
+                    isTaskbarPresentInApps = true,
+                    decoupleDepth = true
+                ),
+            )
+        }
+
+        data class TestCase(
+            val deviceName: String,
+            val gridName: String,
+            val isTaskbarPresentInApps: Boolean = false,
+            val decoupleDepth: Boolean = false
+        ) {
+            fun filename(testName: String = ""): String {
+                val device =
+                    when (deviceName) {
+                        "tablet" -> "tablet"
+                        "twopanel-tablet" -> "twoPanel"
+                        "twopanel-phone" -> "twoPanelFolded"
+                        else -> "phone"
+                    }
+                val depth =
+                    if (decoupleDepth) {
+                        "_decoupleDepth"
+                    } else {
+                        ""
+                    }
+                return "$device$testName$depth"
+            }
+        }
     }
 }
diff --git a/tests/src/com/android/launcher3/popup/SystemShortcutTest.java b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
index e459956..c663be0 100644
--- a/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
+++ b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
@@ -30,6 +30,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -56,6 +57,7 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.UserCache;
+import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext;
 import com.android.launcher3.util.TestSandboxModelContextWrapper;
@@ -87,6 +89,7 @@
     private PopupDataProvider mPopupDataProvider;
     private AppInfo mAppInfo;
     @Mock UserCache mUserCache;
+    @Mock ApiWrapper mApiWrapper;
     @Mock BaseDragLayer mBaseDragLayer;
     @Mock UserIconInfo mUserIconInfo;
     @Mock LauncherActivityInfo mLauncherActivityInfo;
@@ -97,6 +100,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mSandboxContext.putObject(UserCache.INSTANCE, mUserCache);
+        mSandboxContext.putObject(ApiWrapper.INSTANCE, mApiWrapper);
         mTestContext = new TestSandboxModelContextWrapper(mSandboxContext);
         mView = new View(mSandboxContext);
         spyOn(mTestContext);
@@ -244,7 +248,6 @@
         SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL
                 .getShortcut(mTestContext, mAppInfo, mView);
 
-        verify(mPrivateProfileManager, times(2)).getProfileUser();
         assertNull(systemShortcut);
     }
 
@@ -266,8 +269,7 @@
         SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL
                 .getShortcut(mTestContext, mAppInfo, mView);
 
-        verify(mPrivateProfileManager, times(3)).getProfileUser();
-        verify(mPrivateProfileManager).isEnabled();
+        verify(mPrivateProfileManager, atLeast(1)).isEnabled();
         assertNotNull(systemShortcut);
     }
 
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 99e15ba..115a6e6 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -98,7 +98,7 @@
 public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
 
     public static final long DEFAULT_ACTIVITY_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
-    public static final long DEFAULT_BROADCAST_TIMEOUT_SECS = 5;
+    public static final long DEFAULT_BROADCAST_TIMEOUT_SECS = 10;
 
     public static final long DEFAULT_UI_TIMEOUT = TestUtil.DEFAULT_UI_TIMEOUT;
     private static final String TAG = "AbstractLauncherUiTest";
@@ -548,7 +548,7 @@
         public Intent blockingGetIntent() throws InterruptedException {
             Log.d(WIDGET_CONFIG_NULL_EXTRA_INTENT,
                     "AbstractLauncherUiTest.blockingGetIntent()");
-            latch.await(DEFAULT_BROADCAST_TIMEOUT_SECS, TimeUnit.SECONDS);
+            assertTrue("Timed Out", latch.await(DEFAULT_BROADCAST_TIMEOUT_SECS, TimeUnit.SECONDS));
             mTargetContext.unregisterReceiver(this);
             Log.d(WIDGET_CONFIG_NULL_EXTRA_INTENT, mIntent == null
                     ? "AbstractLauncherUiTest.onReceive(): mIntent NULL"
diff --git a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
index c4e74f2..e5c5c19 100644
--- a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
+++ b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
@@ -57,7 +57,7 @@
                                         true));
 
                     } catch (Throwable e) {
-                        FailureWatcher.onError(mTest.mLauncher, description, e);
+                        FailureWatcher.onError(mTest.mLauncher, description);
                         throw e;
                     }
 
diff --git a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
index 70a3dd0..69b42cb 100644
--- a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
@@ -76,7 +76,6 @@
         String output =
                 mDevice.executeShellCommand(
                         "pm create-user --profileOf 0 --managed TestProfile");
-        // b/203817455
         updateWorkProfileSetupSuccessful("pm create-user", output);
 
         String[] tokens = output.split("\\s+");
diff --git a/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java
index 9dbd866..9b184ae 100644
--- a/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java
@@ -32,7 +32,6 @@
 import com.android.launcher3.ui.AbstractLauncherUiTest;
 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.ui.TestViewHelpers;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 import com.android.launcher3.util.rule.ShellCommandRule;
 import com.android.launcher3.util.rule.TestStabilityRule.Stability;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
@@ -54,7 +53,6 @@
 
     @Test
     @PortraitLandscape
-    @ScreenRecord // b/316910614
     public void testDragIcon() throws Throwable {
         mLauncher.enableDebugTracing(); // b/289161193
         commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext));
@@ -107,7 +105,6 @@
     @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/316910614
     @PlatinumTest(focusArea = "launcher")
     @Test
-    @ScreenRecord // b/316910614
     public void testResizeWidget() throws Throwable {
         commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext));
 
diff --git a/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java
index 2ce8eef..a672c01 100644
--- a/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java
@@ -20,6 +20,8 @@
 import static com.android.launcher3.util.TestConstants.AppNames.MAPS_APP_NAME;
 import static com.android.launcher3.util.TestConstants.AppNames.MESSAGES_APP_NAME;
 import static com.android.launcher3.util.TestConstants.AppNames.STORE_APP_NAME;
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -38,6 +40,7 @@
 import com.android.launcher3.util.LauncherLayoutBuilder;
 import com.android.launcher3.util.TestUtil;
 import com.android.launcher3.util.rule.ScreenRecordRule;
+import com.android.launcher3.util.rule.TestStabilityRule;
 
 import org.junit.After;
 import org.junit.Before;
@@ -242,6 +245,7 @@
     }
 
     @ScreenRecordRule.ScreenRecord // b/329935119
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/329935119
     @Test
     @PortraitLandscape
     public void testEmptyPageDoesNotGetRemovedIfPagePairIsNotEmpty() {
diff --git a/tests/src/com/android/launcher3/util/DisplayControllerTest.kt b/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
index 2e57ad5..273f0c4 100644
--- a/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
+++ b/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
@@ -31,6 +31,7 @@
 import androidx.test.filters.SmallTest
 import com.android.launcher3.LauncherPrefs
 import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING
+import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING_IN_DESKTOP_MODE
 import com.android.launcher3.util.DisplayController.CHANGE_DENSITY
 import com.android.launcher3.util.DisplayController.CHANGE_ROTATION
 import com.android.launcher3.util.DisplayController.CHANGE_TASKBAR_PINNING
@@ -94,6 +95,7 @@
         whenever(context.getObject(eq(WindowManagerProxy.INSTANCE))).thenReturn(windowManagerProxy)
         whenever(context.getObject(eq(LauncherPrefs.INSTANCE))).thenReturn(launcherPrefs)
         whenever(launcherPrefs.get(TASKBAR_PINNING)).thenReturn(false)
+        whenever(launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)).thenReturn(true)
 
         // Mock WindowManagerProxy
         val displayInfo = CachedDisplayInfo(Point(width, height), Surface.ROTATION_0)
@@ -170,4 +172,13 @@
         verify(displayInfoChangeListener)
             .onDisplayInfoChanged(any(), any(), eq(CHANGE_TASKBAR_PINNING))
     }
+
+    @Test
+    @UiThreadTest
+    fun testTaskbarPinningChangeInDesktopMode() {
+        whenever(launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)).thenReturn(false)
+        displayController.handleInfoChange(display)
+        verify(displayInfoChangeListener)
+            .onDisplayInfoChanged(any(), any(), eq(CHANGE_TASKBAR_PINNING))
+    }
 }
diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
index 7fba33e..7bdc040 100644
--- a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
+++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
@@ -30,6 +30,8 @@
 public class FailureWatcher extends TestWatcher {
     private static final String TAG = "FailureWatcher";
     private static boolean sSavedBugreport = false;
+    private static Description sDescriptionForLastSavedArtifacts;
+
     private final LauncherInstrumentation mLauncher;
     @NonNull
     private final Supplier<ExportedData> mViewCaptureDataSupplier;
@@ -41,6 +43,18 @@
     }
 
     @Override
+    protected void starting(Description description) {
+        mLauncher.setOnFailure(() -> onError(mLauncher, description, mViewCaptureDataSupplier));
+        super.starting(description);
+    }
+
+    @Override
+    protected void finished(Description description) {
+        super.finished(description);
+        mLauncher.setOnFailure(null);
+    }
+
+    @Override
     protected void succeeded(Description description) {
         super.succeeded(description);
         AbstractLauncherUiTest.checkDetectedLeaks(mLauncher);
@@ -70,7 +84,7 @@
 
     @Override
     protected void failed(Throwable e, Description description) {
-        onError(mLauncher, description, e, mViewCaptureDataSupplier);
+        onError(mLauncher, description, mViewCaptureDataSupplier);
     }
 
     static File diagFile(Description description, String prefix, String ext) {
@@ -79,13 +93,18 @@
                         + description.getMethodName() + "." + ext);
     }
 
-    public static void onError(LauncherInstrumentation launcher, Description description,
-            Throwable e) {
-        onError(launcher, description, e, null);
+    /** Action executed when an error condition is expected. Saves artifacts. */
+    public static void onError(LauncherInstrumentation launcher, Description description) {
+        onError(launcher, description, null);
     }
 
     private static void onError(LauncherInstrumentation launcher, Description description,
-            Throwable e, @Nullable Supplier<ExportedData> viewCaptureDataSupplier) {
+            @Nullable Supplier<ExportedData> viewCaptureDataSupplier) {
+        if (description.equals(sDescriptionForLastSavedArtifacts)) {
+            // This test has already saved its artifacts.
+            return;
+        }
+        sDescriptionForLastSavedArtifacts = description;
 
         final File sceenshot = diagFile(description, "TestScreenshot", "png");
         final File hierarchy = diagFile(description, "Hierarchy", "zip");
@@ -114,7 +133,7 @@
         Log.e(TAG, "Failed test " + description.getMethodName()
                 + ",\nscreenshot will be saved to " + sceenshot
                 + ",\nUI dump at: " + hierarchy
-                + " (use go/web-hv to open the dump file)", e);
+                + " (use go/web-hv to open the dump file)");
         final UiDevice device = launcher.getDevice();
         device.takeScreenshot(sceenshot);
 
diff --git a/tests/src_deviceless/com/android/launcher3/util/RobolectricDeviceRunner.kt b/tests/src_deviceless/com/android/launcher3/util/RobolectricDeviceRunner.kt
new file mode 100644
index 0000000..dc6d716
--- /dev/null
+++ b/tests/src_deviceless/com/android/launcher3/util/RobolectricDeviceRunner.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2024 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 androidx.test.annotation.UiThreadTest
+import androidx.test.platform.app.InstrumentationRegistry
+import java.lang.reflect.Method
+import java.util.concurrent.atomic.AtomicReference
+import org.junit.runners.model.FrameworkMethod
+import org.junit.runners.model.Statement
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.internal.bytecode.Sandbox
+import org.robolectric.util.ReflectionHelpers
+import org.robolectric.util.ReflectionHelpers.ClassParameter
+
+/** Runner which emulates the provided display before running the actual test */
+class RobolectricDeviceRunner(testClass: Class<*>?, private val deviceName: String?) :
+    RobolectricTestRunner(testClass) {
+
+    private val nameSuffix = deviceName?.let { "-$it" } ?: ""
+
+    override fun getName() = super.getName() + nameSuffix
+
+    override fun testName(method: FrameworkMethod) = super.testName(method) + nameSuffix
+
+    @Throws(Throwable::class)
+    override fun beforeTest(sandbox: Sandbox, method: FrameworkMethod, bootstrappedMethod: Method) {
+        super.beforeTest(sandbox, method, bootstrappedMethod)
+
+        deviceName ?: return
+
+        val emulator =
+            try {
+                ReflectionHelpers.loadClass(
+                    bootstrappedMethod.declaringClass.classLoader,
+                    DEVICE_EMULATOR
+                )
+            } catch (e: Exception) {
+                // Ignore, if the device emulator is not present
+                return
+            }
+        ReflectionHelpers.callStaticMethod<Any>(
+            emulator,
+            "updateDevice",
+            ClassParameter.from(String::class.java, deviceName)
+        )
+    }
+
+    override fun getHelperTestRunner(clazz: Class<*>) = MyHelperTestRunner(clazz)
+
+    class MyHelperTestRunner(clazz: Class<*>) : HelperTestRunner(clazz) {
+
+        override fun methodBlock(method: FrameworkMethod): Statement =
+            // this needs to be run in the test classLoader
+            ReflectionHelpers.callStaticMethod(
+                method.declaringClass.classLoader,
+                RobolectricDeviceRunner::class.qualifiedName,
+                "wrapUiThreadMethod",
+                ClassParameter.from(FrameworkMethod::class.java, method),
+                ClassParameter.from(Statement::class.java, super.methodBlock(method))
+            )
+    }
+
+    private class UiThreadStatement(val base: Statement) : Statement() {
+
+        override fun evaluate() {
+            val exceptionRef = AtomicReference<Throwable>()
+            InstrumentationRegistry.getInstrumentation().runOnMainSync {
+                try {
+                    base.evaluate()
+                } catch (throwable: Throwable) {
+                    exceptionRef.set(throwable)
+                }
+            }
+            exceptionRef.get()?.let { throw it }
+        }
+    }
+
+    companion object {
+
+        private const val DEVICE_EMULATOR = "com.android.launcher3.util.RoboDeviceEmulator"
+
+        @JvmStatic
+        fun wrapUiThreadMethod(method: FrameworkMethod, base: Statement): Statement =
+            if (
+                method.method.isAnnotationPresent(UiThreadTest::class.java) ||
+                    method.declaringClass.isAnnotationPresent(UiThreadTest::class.java)
+            ) {
+                UiThreadStatement(base)
+            } else {
+                base
+            }
+    }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index b490124..71cd19d 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -58,6 +58,7 @@
     private static final String FAST_SCROLLER_RES_ID = "fast_scroller";
     private static final Pattern EVENT_ALT_ESC_UP = Pattern.compile(
             "Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
+    private static final String UNLOCK_BUTTON_VIEW_RES_ID = "ps_lock_unlock_button";
 
     private final int mHeight;
     private final int mIconHeight;
@@ -433,7 +434,28 @@
     public PrivateSpaceContainer getPrivateSpaceUnlockedView() {
         final UiObject2 allAppsContainer = verifyActiveContainer();
         final UiObject2 appListRecycler = getAppListRecycler(allAppsContainer);
-        return new PrivateSpaceContainer(mLauncher, appListRecycler);
+        return new PrivateSpaceContainer(mLauncher, appListRecycler, this, true);
+    }
+
+    /** Returns PrivateSpaceContainer in locked state, if present in view. */
+    @NonNull
+    public PrivateSpaceContainer getPrivateSpaceLockedView() {
+        final UiObject2 allAppsContainer = verifyActiveContainer();
+        final UiObject2 appListRecycler = getAppListRecycler(allAppsContainer);
+        return new PrivateSpaceContainer(mLauncher, appListRecycler, this, false);
+    }
+
+    /**
+     * Toggles Lock/Unlock of Private Space, changing the All Apps Ui.
+     */
+    public void togglePrivateSpace() {
+        final UiObject2 allAppsContainer = verifyActiveContainer();
+        final UiObject2 appListRecycler = getAppListRecycler(allAppsContainer);
+        UiObject2 unLockButtonView = mLauncher.waitForObjectInContainer(appListRecycler,
+                UNLOCK_BUTTON_VIEW_RES_ID);
+        mLauncher.waitForObjectEnabled(unLockButtonView, "Private Space Unlock Button");
+        mLauncher.assertTrue("PS Unlock Button is non-clickable", unLockButtonView.isClickable());
+        unLockButtonView.click();
     }
 
     protected abstract void verifyVisibleContainerOnDismiss();
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 68829e0..2e3944d 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -359,6 +359,21 @@
     }
 
     /**
+     * Gets Overview Actions specific to grouped tasks.
+     *
+     * @return The Overview group actions bar
+     */
+    @NonNull
+    public OverviewActions getOverviewGroupActions() {
+        try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+                "want to get overview group actions")) {
+            verifyActiveContainer();
+            UiObject2 groupActions = mLauncher.waitForOverviewObject("group_action_buttons");
+            return new OverviewActions(groupActions, mLauncher);
+        }
+    }
+
+    /**
      * Returns if clear all button is visible.
      */
     public boolean isClearAllVisible() {
@@ -449,10 +464,18 @@
     private void verifyActionsViewVisibility() {
         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                 "want to assert overview actions view visibility")) {
+            boolean isTablet = mLauncher.isTablet();
+            OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask();
+
             if (isActionsViewVisible()) {
-                mLauncher.waitForOverviewObject("action_buttons");
+                if (task.isTaskSplit()) {
+                    mLauncher.waitForOverviewObject("group_action_buttons");
+                } else {
+                    mLauncher.waitForOverviewObject("action_buttons");
+                }
             } else {
                 mLauncher.waitUntilOverviewObjectGone("action_buttons");
+                mLauncher.waitUntilOverviewObjectGone("group_action_buttons");
             }
         }
     }
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 764a455..68b0a36 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -108,7 +108,7 @@
 public final class LauncherInstrumentation {
 
     private static final String TAG = "Tapl";
-    private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 15;
+    private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 5;
     private static final int GESTURE_STEP_MS = 16;
 
     static final Pattern EVENT_PILFER_POINTERS = Pattern.compile("pilferPointers");
@@ -204,6 +204,7 @@
     private Runnable mTestAnomalyChecker;
 
     private boolean mCheckEventsForSuccessfulGestures = false;
+    private Runnable mOnFailure;
     private Runnable mOnLauncherCrashed;
 
     private TrackpadGestureType mTrackpadGestureType = TrackpadGestureType.NONE;
@@ -342,6 +343,11 @@
         mCheckEventsForSuccessfulGestures = true;
     }
 
+    /** Sets a runnable that will be invoked upon assertion failures. */
+    public void setOnFailure(Runnable onFailure) {
+        mOnFailure = onFailure;
+    }
+
     public void setOnLauncherCrashed(Runnable onLauncherCrashed) {
         mOnLauncherCrashed = onLauncherCrashed;
     }
@@ -623,6 +629,7 @@
         final String systemAnomalyMessage =
                 getSystemAnomalyMessage(ignoreNavmodeChangeStates, ignoreOnlySystemUiViews);
         if (systemAnomalyMessage != null) {
+            if (mOnFailure != null) mOnFailure.run();
             Assert.fail(formatSystemHealthMessage(formatErrorWithEvents(
                     "http://go/tapl : Tests are broken by a non-Launcher system error: "
                             + systemAnomalyMessage, false)));
@@ -742,6 +749,7 @@
 
     void fail(String message) {
         checkForAnomaly();
+        if (mOnFailure != null) mOnFailure.run();
         Assert.fail(formatSystemHealthMessage(formatErrorWithEvents(
                 "http://go/tapl test failure: " + message + ";\nContext: " + getContextDescription()
                         + "; now visible state is " + getVisibleStateMessage(), true)));
diff --git a/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java
index daddd2f..a2814f0 100644
--- a/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java
+++ b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java
@@ -25,20 +25,30 @@
  */
 public class PrivateSpaceContainer {
     private static final String PS_HEADER_RES_ID = "ps_header_layout";
-    private static final String INSTALL_APP_TITLE = "Install apps";
+    private static final String INSTALL_APP_TITLE = "Install";
     private static final String DIVIDER_RES_ID = "private_space_divider";
 
     private final LauncherInstrumentation mLauncher;
     private final UiObject2 mAppListRecycler;
+    private final AllApps mAppList;
+    private final boolean mPrivateSpaceEnabled;
 
     PrivateSpaceContainer(LauncherInstrumentation launcherInstrumentation,
-            UiObject2 appListRecycler) {
+            UiObject2 appListRecycler, AllApps appList, boolean privateSpaceEnabled) {
         mLauncher = launcherInstrumentation;
         mAppListRecycler = appListRecycler;
+        mAppList = appList;
+        mPrivateSpaceEnabled = privateSpaceEnabled;
 
-        verifyHeaderIsPresent();
-        verifyInstallAppButtonIsPresent();
-        verifyDividerIsPresent();
+        if (mPrivateSpaceEnabled) {
+            verifyHeaderIsPresent();
+            verifyInstallAppButtonIsPresent();
+            verifyDividerIsPresent();
+        } else {
+            verifyHeaderIsPresent();
+            verifyInstallAppButtonIsNotPresent();
+            verifyDividerIsNotPresent();
+        }
     }
 
     // Assert PS Header is in view.
@@ -46,13 +56,18 @@
     private void verifyHeaderIsPresent() {
         final UiObject2 psHeader = mLauncher.waitForObjectInContainer(mAppListRecycler,
                 PS_HEADER_RES_ID);
-        new PrivateSpaceHeader(mLauncher, psHeader, true);
+        new PrivateSpaceHeader(mLauncher, psHeader, mPrivateSpaceEnabled);
     }
 
 
     // Assert Install App Item is present in view.
     private void verifyInstallAppButtonIsPresent() {
-        mLauncher.getAllApps().getAppIcon(INSTALL_APP_TITLE);
+        mAppList.getAppIcon(INSTALL_APP_TITLE);
+    }
+
+    // Assert Install App Item is not present in view.
+    private void verifyInstallAppButtonIsNotPresent() {
+        mLauncher.waitUntilLauncherObjectGone(DIVIDER_RES_ID);
     }
 
     // Assert Sys App Divider is present in view.
@@ -60,15 +75,20 @@
         mLauncher.waitForObjectInContainer(mAppListRecycler, DIVIDER_RES_ID);
     }
 
+    // Assert Sys App Divider is not present in view.
+    private void verifyDividerIsNotPresent() {
+        mLauncher.waitUntilLauncherObjectGone(DIVIDER_RES_ID);
+    }
+
     /**
      * Verifies that a user installed app is present above the divider.
      */
     public void verifyInstalledAppIsPresent(String appName) {
-        HomeAppIcon appIcon = mLauncher.getAllApps().getAppIcon(appName);
+        AppIcon appIcon = mAppList.getAppIcon(appName);
         final Point iconCenter = appIcon.mObject.getVisibleCenter();
         UiObject2 divider = mLauncher.waitForObjectInContainer(mAppListRecycler, DIVIDER_RES_ID);
         final Point dividerCenter = divider.getVisibleCenter();
         mLauncher.assertTrue("Installed App: " + appName + " is not above the divider",
                 iconCenter.y < dividerCenter.y);
     }
-}
+}
\ No newline at end of file
diff --git a/tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java
index 3a7f038..cc64aae 100644
--- a/tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java
+++ b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java
@@ -45,7 +45,7 @@
         if (mPrivateSpaceEnabled) {
             verifyUnlockedState();
         } else {
-            mLauncher.fail("Private Space found in non enabled state");
+            verifyLockedState();
         }
     }
 
@@ -74,4 +74,23 @@
         mLauncher.assertEquals("PS lock text is incorrect", "Lock", lockText.getText());
 
     }
+
+    /** Verify Locked State elements in Private Space Header */
+    private void verifyLockedState() {
+        UiObject2 headerText = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader,
+                PS_HEADER_TEXT_RES_ID);
+        mLauncher.assertEquals("PS Header Text is incorrect ",
+                "Private", headerText.getText());
+
+        UiObject2 unLockButtonView = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader,
+                UNLOCK_BUTTON_VIEW_RES_ID);
+        mLauncher.waitForObjectEnabled(unLockButtonView, "Private Space Unlock Button");
+        mLauncher.assertTrue("PS Unlock Button is non-clickable", unLockButtonView.isClickable());
+
+        mLauncher.waitForObjectInContainer(mPrivateSpaceHeader,
+                LOCK_ICON_RES_ID);
+
+        mLauncher.waitUntilLauncherObjectGone(SETTINGS_BUTTON_RES_ID);
+        mLauncher.waitUntilLauncherObjectGone(LOCK_TEXT_RES_ID);
+    }
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
index 8d3a631..4be46ab 100644
--- a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
+++ b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
@@ -17,6 +17,7 @@
 
 import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
 
+import android.text.TextUtils;
 import android.widget.TextView;
 
 import androidx.test.uiautomator.By;
@@ -117,4 +118,28 @@
     public SearchResultFromQsb getSearchResultForInput() {
         return this;
     }
+
+    /** Verify a tile is present by checking its title and subtitle. */
+    public void verifyTileIsPresent(String title, String subtitle) {
+        ArrayList<UiObject2> searchResults =
+                new ArrayList<>(mLauncher.waitForObjectsInContainer(
+                        mLauncher.waitForSystemLauncherObject(SEARCH_CONTAINER_RES_ID),
+                        By.clazz(TextView.class)));
+        boolean foundTitle = false;
+        boolean foundSubtitle = false;
+        for (UiObject2 uiObject: searchResults) {
+            String currentString = uiObject.getText();
+            if (TextUtils.equals(currentString, title)) {
+                foundTitle = true;
+            } else if (TextUtils.equals(currentString, subtitle)) {
+                foundSubtitle = true;
+            }
+        }
+        if (!foundTitle) {
+            mLauncher.fail("Tile not found for title: " + title);
+        }
+        if (!foundSubtitle) {
+            mLauncher.fail("Tile not found for subtitle: " + subtitle);
+        }
+    }
 }