Merge "Revert "Revert "Add debug logs for hotseat disapperaed bug""" into tm-qpr-dev
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 9123959..a77791f 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,2 +1,4 @@
 [Hook Scripts]
 checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --config_xml tools/checkstyle.xml --sha ${PREUPLOAD_COMMIT}
+
+ktfmt_hook = ${REPO_ROOT}/external/ktfmt/ktfmt.py --check ${PREUPLOAD_FILES}
\ No newline at end of file
diff --git a/go/quickstep/res/values-ky/strings.xml b/go/quickstep/res/values-ky/strings.xml
index e4a2474..55e70c8 100644
--- a/go/quickstep/res/values-ky/strings.xml
+++ b/go/quickstep/res/values-ky/strings.xml
@@ -9,7 +9,7 @@
     <string name="dialog_cancel" msgid="6464336969134856366">"ЖОККО ЧЫГАРУУ"</string>
     <string name="dialog_settings" msgid="6564397136021186148">"ЖӨНДӨӨЛӨР"</string>
     <string name="niu_actions_confirmation_title" msgid="3863451714863526143">"Экрандагы текстти которуу же угуу"</string>
-    <string name="niu_actions_confirmation_text" msgid="2105271481950866089">"Экрандагы текст, веб-даректер жана скриншоттор сыяктуу маалымат Google менен бөлүшүлүшү мүмкүн.\n\nБөлүшүлгөн маалыматты өзгөртүү үчүн"<b>"Жөндөөлөр &gt; Колдонмолор &gt; Демейки колдонмолор &gt; Санариптик жардамчы колдонмосуна өтүңүз"</b>"."</string>
+    <string name="niu_actions_confirmation_text" msgid="2105271481950866089">"Экрандагы текст, веб-даректер жана скриншоттор сыяктуу маалымат Google менен бөлүшүлүшү мүмкүн.\n\nБөлүшүлгөн маалыматты өзгөртүү үчүн"<b>"Параметрлер &gt; Колдонмолор &gt; Демейки колдонмолор &gt; Санариптик жардамчы колдонмосуна өтүңүз"</b>"."</string>
     <string name="assistant_not_selected_title" msgid="5017072974603345228">"Бул функцияны колдонуу үчүн жардамчыны тандаңыз"</string>
     <string name="assistant_not_selected_text" msgid="3244613673884359276">"Экраныңыздагы текстти угуу же которуу үчүн Жөндөөлөрдөн санариптик жардамчы колдонмосун тандаңыз"</string>
     <string name="assistant_not_supported_title" msgid="1675788067597484142">"Бул функцияны колдонуу үчүн жардамчыңызды өзгөртүңүз"</string>
diff --git a/go/src/com/android/launcher3/model/LoaderResults.java b/go/src/com/android/launcher3/model/LauncherBinder.java
similarity index 82%
rename from go/src/com/android/launcher3/model/LoaderResults.java
rename to go/src/com/android/launcher3/model/LauncherBinder.java
index 5f71061..437d8ca 100644
--- a/go/src/com/android/launcher3/model/LoaderResults.java
+++ b/go/src/com/android/launcher3/model/LauncherBinder.java
@@ -22,11 +22,11 @@
 import com.android.launcher3.model.BgDataModel.Callbacks;
 
 /**
- * Helper class to handle results of {@link com.android.launcher3.model.LoaderTask}.
+ * Binds the results of {@link com.android.launcher3.model.LoaderTask} to the Callbacks objects.
  */
-public class LoaderResults extends BaseLoaderResults {
+public class LauncherBinder extends BaseLauncherBinder {
 
-    public LoaderResults(LauncherAppState app, BgDataModel dataModel,
+    public LauncherBinder(LauncherAppState app, BgDataModel dataModel,
             AllAppsList allAppsList, Callbacks[] callbacks) {
         super(app, dataModel, allAppsList, callbacks, MAIN_EXECUTOR);
     }
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index 677c992..c8a7d85 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -130,7 +130,7 @@
   optional int32 cardinality = 2;
 }
 
-// Next value 41
+// Next value 43
 enum Attribute {
   UNKNOWN = 0;
   DEFAULT_LAYOUT = 1;       // icon automatically placed in workspace, folder, hotseat
@@ -174,6 +174,8 @@
   ALL_APPS_SEARCH_RESULT_PEOPLE_TILE = 27;
   ALL_APPS_SEARCH_RESULT_LEGACY_SHORTCUT = 30;
   ALL_APPS_SEARCH_RESULT_ASSISTANT_MEMORY = 31;
+  ALL_APPS_SEARCH_RESULT_VIDEO = 41;
+  ALL_APPS_SEARCH_RESULT_SYSTEM_POINTER = 42;
 
   // Web suggestions provided by AGA
   ALL_APPS_SEARCH_RESULT_WEB_SUGGEST = 39;
diff --git a/quickstep/res/drawable/bg_taskbar_edu_tooltip.xml b/quickstep/res/drawable/bg_taskbar_edu_tooltip.xml
new file mode 100644
index 0000000..a20f7da
--- /dev/null
+++ b/quickstep/res/drawable/bg_taskbar_edu_tooltip.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:shape="rectangle">
+
+    <corners android:radius="@dimen/dialogCornerRadius" />
+    <solid android:color="?androidprv:attr/colorSurface" />
+</shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/mock_app_icon.xml b/quickstep/res/drawable/mock_app_icon.xml
new file mode 100644
index 0000000..92cdea3
--- /dev/null
+++ b/quickstep/res/drawable/mock_app_icon.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="@color/mock_app_icon" />
+    <corners android:radius="@dimen/gesture_tutorial_taskbar_icon_corner_radius" />
+</shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/mock_taskbar_background.xml b/quickstep/res/drawable/mock_taskbar_background.xml
new file mode 100644
index 0000000..8ac9080
--- /dev/null
+++ b/quickstep/res/drawable/mock_taskbar_background.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="@color/gesture_tutorial_taskbar_color" />
+    <corners android:radius="@dimen/gesture_tutorial_taskbar_corner_radius" />
+</shape>
\ No newline at end of file
diff --git a/quickstep/res/layout-land/gesture_tutorial_mock_hotseat.xml b/quickstep/res/layout-land/gesture_tutorial_mock_hotseat.xml
index 20d2ecc..1e2e014 100644
--- a/quickstep/res/layout-land/gesture_tutorial_mock_hotseat.xml
+++ b/quickstep/res/layout-land/gesture_tutorial_mock_hotseat.xml
@@ -31,7 +31,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_1"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintVertical_chainStyle="spread_inside"
         app:layout_constraintTop_toTopOf="parent"
@@ -45,7 +45,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_2"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toBottomOf="@id/hotseat_icon_1"
         app:layout_constraintBottom_toTopOf="@id/hotseat_icon_3"
@@ -58,7 +58,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_3"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toBottomOf="@id/hotseat_icon_2"
         app:layout_constraintBottom_toTopOf="@id/hotseat_icon_4"
@@ -71,7 +71,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_4"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toBottomOf="@id/hotseat_icon_3"
         app:layout_constraintBottom_toBottomOf="parent"
diff --git a/quickstep/res/layout-land/gesture_tutorial_tablet_mock_hotseat.xml b/quickstep/res/layout-land/gesture_tutorial_tablet_mock_hotseat.xml
index 6877b89..f04fbb6 100644
--- a/quickstep/res/layout-land/gesture_tutorial_tablet_mock_hotseat.xml
+++ b/quickstep/res/layout-land/gesture_tutorial_tablet_mock_hotseat.xml
@@ -43,7 +43,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_1"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
@@ -57,7 +57,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_2"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
@@ -71,7 +71,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_3"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
@@ -85,7 +85,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_1"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
@@ -99,25 +99,11 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_4"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toEndOf="@id/hotseat_icon_4"
-        app:layout_constraintEnd_toStartOf="@id/hotseat_icon_6"/>
-
-    <androidx.cardview.widget.CardView
-        android:id="@+id/hotseat_icon_6"
-        android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
-        android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
-
-        app:cardElevation="0dp"
-        app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_2"
-        app:layout_constraintDimensionRatio="1:1"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toEndOf="@id/hotseat_icon_5"
         app:layout_constraintEnd_toEndOf="parent"/>
 
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_foldable_mock_hotseat.xml b/quickstep/res/layout/gesture_tutorial_foldable_mock_hotseat.xml
index 027e4a0..363f14e 100644
--- a/quickstep/res/layout/gesture_tutorial_foldable_mock_hotseat.xml
+++ b/quickstep/res/layout/gesture_tutorial_foldable_mock_hotseat.xml
@@ -42,7 +42,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_1"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintHorizontal_chainStyle="spread_inside"
         app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
@@ -57,7 +57,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_2"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
         app:layout_constraintStart_toEndOf="@id/hotseat_icon_1"
@@ -71,7 +71,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_3"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
         app:layout_constraintStart_toEndOf="@id/hotseat_icon_2"
@@ -85,7 +85,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_1"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
         app:layout_constraintStart_toEndOf="@id/hotseat_icon_3"
@@ -99,24 +99,10 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_4"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
         app:layout_constraintStart_toEndOf="@id/hotseat_icon_4"
-        app:layout_constraintEnd_toStartOf="@id/hotseat_icon_6"/>
-
-    <androidx.cardview.widget.CardView
-        android:id="@+id/hotseat_icon_6"
-        android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
-        android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
-        android:layout_marginTop="@dimen/gesture_tutorial_hotseat_icon_search_margin"
-
-        app:cardElevation="0dp"
-        app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_2"
-        app:layout_constraintDimensionRatio="1:1"
-        app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
-        app:layout_constraintStart_toEndOf="@id/hotseat_icon_5"
         app:layout_constraintEnd_toEndOf="parent"/>
 
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml
index b3ca297..8eeef67 100644
--- a/quickstep/res/layout/gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/gesture_tutorial_fragment.xml
@@ -102,11 +102,11 @@
     <include
         layout="@layout/gesture_tutorial_tablet_mock_taskbar"
         android:id="@+id/gesture_tutorial_fake_taskbar_view"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/gesture_tutorial_mock_taskbar_height"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
-        android:layout_alignParentStart="true"
-        android:layout_alignParentEnd="true" />
+        android:layout_centerHorizontal="true"
+        android:layout_marginBottom="@dimen/gesture_tutorial_taskbar_margin_bottom"/>
 
     <ImageView
         android:id="@+id/gesture_tutorial_edge_gesture_video"
diff --git a/quickstep/res/layout/gesture_tutorial_mock_hotseat.xml b/quickstep/res/layout/gesture_tutorial_mock_hotseat.xml
index b3e86cf..8513dcf 100644
--- a/quickstep/res/layout/gesture_tutorial_mock_hotseat.xml
+++ b/quickstep/res/layout/gesture_tutorial_mock_hotseat.xml
@@ -15,7 +15,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_1"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintHorizontal_chainStyle="spread_inside"
         app:layout_constraintTop_toTopOf="parent"
@@ -29,7 +29,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_2"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintStart_toEndOf="@id/hotseat_icon_1"
@@ -42,7 +42,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_3"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintStart_toEndOf="@id/hotseat_icon_2"
@@ -55,7 +55,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_4"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintStart_toEndOf="@id/hotseat_icon_3"
diff --git a/quickstep/res/layout/gesture_tutorial_tablet_mock_hotseat.xml b/quickstep/res/layout/gesture_tutorial_tablet_mock_hotseat.xml
index 027e4a0..363f14e 100644
--- a/quickstep/res/layout/gesture_tutorial_tablet_mock_hotseat.xml
+++ b/quickstep/res/layout/gesture_tutorial_tablet_mock_hotseat.xml
@@ -42,7 +42,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_1"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintHorizontal_chainStyle="spread_inside"
         app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
@@ -57,7 +57,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_2"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
         app:layout_constraintStart_toEndOf="@id/hotseat_icon_1"
@@ -71,7 +71,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_3"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
         app:layout_constraintStart_toEndOf="@id/hotseat_icon_2"
@@ -85,7 +85,7 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_1"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
         app:layout_constraintStart_toEndOf="@id/hotseat_icon_3"
@@ -99,24 +99,10 @@
 
         app:cardElevation="0dp"
         app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_4"
+        app:cardBackgroundColor="@color/mock_app_icon"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
         app:layout_constraintStart_toEndOf="@id/hotseat_icon_4"
-        app:layout_constraintEnd_toStartOf="@id/hotseat_icon_6"/>
-
-    <androidx.cardview.widget.CardView
-        android:id="@+id/hotseat_icon_6"
-        android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
-        android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
-        android:layout_marginTop="@dimen/gesture_tutorial_hotseat_icon_search_margin"
-
-        app:cardElevation="0dp"
-        app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
-        app:cardBackgroundColor="@color/mock_app_icon_2"
-        app:layout_constraintDimensionRatio="1:1"
-        app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
-        app:layout_constraintStart_toEndOf="@id/hotseat_icon_5"
         app:layout_constraintEnd_toEndOf="parent"/>
 
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_tablet_mock_taskbar.xml b/quickstep/res/layout/gesture_tutorial_tablet_mock_taskbar.xml
index ddfeeec..bc68928 100644
--- a/quickstep/res/layout/gesture_tutorial_tablet_mock_taskbar.xml
+++ b/quickstep/res/layout/gesture_tutorial_tablet_mock_taskbar.xml
@@ -2,115 +2,240 @@
 <com.android.quickstep.interaction.AnimatedTaskbarView
     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="@dimen/gesture_tutorial_mock_taskbar_height">
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:clipChildren="false">
 
+    <!-- Pill-shaped background -->
     <View
         android:id="@+id/taskbar_background"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@color/gesture_tutorial_taskbar_color"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:background="@drawable/mock_taskbar_background"
+        android:clipToOutline="true"
 
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"/>
 
+    <!-- Container for the all apps button and app icons -->
     <androidx.constraintlayout.widget.ConstraintLayout
         android:id="@+id/icon_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_margin="@dimen/gesture_tutorial_taskbar_padding"
 
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent">
 
-        <androidx.cardview.widget.CardView
+        <!-- All apps button -->
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:id="@+id/taskbar_all_apps"
+            android:layout_width="@dimen/gesture_tutorial_taskbar_icon_size"
+            android:layout_height="@dimen/gesture_tutorial_taskbar_icon_size"
+            android:layout_marginEnd="@dimen/taskbar_icon_spacing"
+            android:padding="@dimen/gesture_tutorial_taskbar_padding"
+
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/taskbar_icon_1"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent">
+
+            <!-- 9 mini circles representing the all apps button icon -->
+            <View
+                android:id="@+id/all_apps_mini_1"
+                android:layout_width="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:layout_height="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:background="@drawable/mock_app_icon"
+                android:clipToOutline="true"
+
+                app:layout_constraintDimensionRatio="1:1"
+                app:layout_constraintHorizontal_chainStyle="spread_inside"
+                app:layout_constraintVertical_chainStyle="spread_inside"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toTopOf="@id/all_apps_mini_4"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toStartOf="@id/all_apps_mini_2"/>
+
+            <View
+                android:id="@+id/all_apps_mini_2"
+                android:layout_width="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:layout_height="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:background="@drawable/mock_app_icon"
+                android:clipToOutline="true"
+
+                app:layout_constraintDimensionRatio="1:1"
+                app:layout_constraintVertical_chainStyle="spread_inside"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toTopOf="@id/all_apps_mini_5"
+                app:layout_constraintStart_toEndOf="@id/all_apps_mini_1"
+                app:layout_constraintEnd_toStartOf="@id/all_apps_mini_3"/>
+
+            <View
+                android:id="@+id/all_apps_mini_3"
+                android:layout_width="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:layout_height="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:background="@drawable/mock_app_icon"
+                android:clipToOutline="true"
+
+                app:layout_constraintDimensionRatio="1:1"
+                app:layout_constraintVertical_chainStyle="spread_inside"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toTopOf="@id/all_apps_mini_6"
+                app:layout_constraintStart_toEndOf="@id/all_apps_mini_2"
+                app:layout_constraintEnd_toEndOf="parent"/>
+
+            <View
+                android:id="@+id/all_apps_mini_4"
+                android:layout_width="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:layout_height="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:background="@drawable/mock_app_icon"
+                android:clipToOutline="true"
+
+                app:layout_constraintHorizontal_chainStyle="spread_inside"
+                app:layout_constraintDimensionRatio="1:1"
+                app:layout_constraintTop_toBottomOf="@id/all_apps_mini_1"
+                app:layout_constraintBottom_toTopOf="@id/all_apps_mini_7"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toStartOf="@id/all_apps_mini_5"/>
+
+            <View
+                android:id="@+id/all_apps_mini_5"
+                android:layout_width="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:layout_height="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:background="@drawable/mock_app_icon"
+                android:clipToOutline="true"
+
+                app:layout_constraintDimensionRatio="1:1"
+                app:layout_constraintTop_toBottomOf="@id/all_apps_mini_2"
+                app:layout_constraintBottom_toTopOf="@id/all_apps_mini_8"
+                app:layout_constraintStart_toEndOf="@id/all_apps_mini_4"
+                app:layout_constraintEnd_toStartOf="@id/all_apps_mini_6"/>
+
+            <View
+                android:id="@+id/all_apps_mini_6"
+                android:layout_width="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:layout_height="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:background="@drawable/mock_app_icon"
+                android:clipToOutline="true"
+
+                app:layout_constraintDimensionRatio="1:1"
+                app:layout_constraintTop_toBottomOf="@id/all_apps_mini_3"
+                app:layout_constraintBottom_toTopOf="@id/all_apps_mini_9"
+                app:layout_constraintStart_toEndOf="@id/all_apps_mini_5"
+                app:layout_constraintEnd_toEndOf="parent"/>
+
+            <View
+                android:id="@+id/all_apps_mini_7"
+                android:layout_width="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:layout_height="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:background="@drawable/mock_app_icon"
+                android:clipToOutline="true"
+
+                app:layout_constraintHorizontal_chainStyle="spread_inside"
+                app:layout_constraintTop_toBottomOf="@id/all_apps_mini_4"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toStartOf="@id/all_apps_mini_8"/>
+
+            <View
+                android:id="@+id/all_apps_mini_8"
+                android:layout_width="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:layout_height="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:background="@drawable/mock_app_icon"
+                android:clipToOutline="true"
+
+                app:layout_constraintTop_toBottomOf="@id/all_apps_mini_5"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintStart_toEndOf="@id/all_apps_mini_7"
+                app:layout_constraintEnd_toStartOf="@id/all_apps_mini_9"/>
+
+            <View
+                android:id="@+id/all_apps_mini_9"
+                android:layout_width="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:layout_height="@dimen/gesture_tutorial_taskbar_all_apps_mini_size"
+                android:background="@drawable/mock_app_icon"
+                android:clipToOutline="true"
+
+                app:layout_constraintTop_toBottomOf="@id/all_apps_mini_6"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintStart_toEndOf="@id/all_apps_mini_8"
+                app:layout_constraintEnd_toEndOf="parent"/>
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+
+        <!-- App icons -->
+        <View
             android:id="@+id/taskbar_icon_1"
             android:layout_width="@dimen/gesture_tutorial_taskbar_icon_size"
             android:layout_height="@dimen/gesture_tutorial_taskbar_icon_size"
-            android:layout_marginStart="@dimen/gesture_tutorial_taskbar_padding_start_end"
+            android:layout_marginStart="@dimen/taskbar_icon_spacing"
+            android:layout_marginEnd="@dimen/taskbar_icon_spacing"
+            android:background="@drawable/mock_app_icon"
+            android:clipToOutline="true"
 
-            app:cardElevation="0dp"
-            app:cardCornerRadius="@dimen/gesture_tutorial_taskbar_icon_corner_radius"
-            app:cardBackgroundColor="@color/mock_app_icon_1"
-            app:layout_constraintDimensionRatio="1:1"
             app:layout_constraintHorizontal_chainStyle="spread_inside"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintStart_toEndOf="@id/taskbar_all_apps"
             app:layout_constraintEnd_toStartOf="@id/taskbar_icon_2"/>
 
-        <androidx.cardview.widget.CardView
+        <View
             android:id="@+id/taskbar_icon_2"
             android:layout_width="@dimen/gesture_tutorial_taskbar_icon_size"
             android:layout_height="@dimen/gesture_tutorial_taskbar_icon_size"
+            android:layout_marginStart="@dimen/taskbar_icon_spacing"
+            android:layout_marginEnd="@dimen/taskbar_icon_spacing"
+            android:background="@drawable/mock_app_icon"
+            android:clipToOutline="true"
 
-            app:cardElevation="0dp"
-            app:cardCornerRadius="@dimen/gesture_tutorial_taskbar_icon_corner_radius"
-            app:cardBackgroundColor="@color/mock_app_icon_2"
-            app:layout_constraintDimensionRatio="1:1"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintStart_toEndOf="@id/taskbar_icon_1"
             app:layout_constraintEnd_toStartOf="@id/taskbar_icon_3"/>
 
-        <androidx.cardview.widget.CardView
+        <View
             android:id="@+id/taskbar_icon_3"
             android:layout_width="@dimen/gesture_tutorial_taskbar_icon_size"
             android:layout_height="@dimen/gesture_tutorial_taskbar_icon_size"
+            android:layout_marginStart="@dimen/taskbar_icon_spacing"
+            android:layout_marginEnd="@dimen/taskbar_icon_spacing"
+            android:background="@drawable/mock_app_icon"
+            android:clipToOutline="true"
 
-            app:cardElevation="0dp"
-            app:cardCornerRadius="@dimen/gesture_tutorial_taskbar_icon_corner_radius"
-            app:cardBackgroundColor="@color/mock_app_icon_3"
-            app:layout_constraintDimensionRatio="1:1"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintStart_toEndOf="@id/taskbar_icon_2"
             app:layout_constraintEnd_toStartOf="@id/taskbar_icon_4"/>
 
-        <androidx.cardview.widget.CardView
+        <View
             android:id="@+id/taskbar_icon_4"
             android:layout_width="@dimen/gesture_tutorial_taskbar_icon_size"
             android:layout_height="@dimen/gesture_tutorial_taskbar_icon_size"
+            android:layout_marginStart="@dimen/taskbar_icon_spacing"
+            android:layout_marginEnd="@dimen/taskbar_icon_spacing"
+            android:background="@drawable/mock_app_icon"
+            android:clipToOutline="true"
 
-            app:cardElevation="0dp"
-            app:cardCornerRadius="@dimen/gesture_tutorial_taskbar_icon_corner_radius"
-            app:cardBackgroundColor="@color/mock_app_icon_1"
-            app:layout_constraintDimensionRatio="1:1"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintStart_toEndOf="@id/taskbar_icon_3"
             app:layout_constraintEnd_toStartOf="@id/taskbar_icon_5"/>
 
-        <androidx.cardview.widget.CardView
+        <View
             android:id="@+id/taskbar_icon_5"
             android:layout_width="@dimen/gesture_tutorial_taskbar_icon_size"
             android:layout_height="@dimen/gesture_tutorial_taskbar_icon_size"
+            android:layout_marginStart="@dimen/taskbar_icon_spacing"
+            android:background="@drawable/mock_app_icon"
+            android:clipToOutline="true"
 
-            app:cardElevation="0dp"
-            app:cardCornerRadius="@dimen/gesture_tutorial_taskbar_icon_corner_radius"
-            app:cardBackgroundColor="@color/mock_app_icon_4"
-            app:layout_constraintDimensionRatio="1:1"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintStart_toEndOf="@id/taskbar_icon_4"
-            app:layout_constraintEnd_toStartOf="@id/taskbar_icon_6"/>
-
-        <androidx.cardview.widget.CardView
-            android:id="@+id/taskbar_icon_6"
-            android:layout_width="@dimen/gesture_tutorial_taskbar_icon_size"
-            android:layout_height="@dimen/gesture_tutorial_taskbar_icon_size"
-            android:layout_marginEnd="@dimen/gesture_tutorial_taskbar_padding_start_end"
-
-            app:cardElevation="0dp"
-            app:cardCornerRadius="@dimen/gesture_tutorial_taskbar_icon_corner_radius"
-            app:cardBackgroundColor="@color/mock_app_icon_2"
-            app:layout_constraintDimensionRatio="1:1"
-            app:layout_constraintTop_toTopOf="parent"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintStart_toEndOf="@id/taskbar_icon_5"
             app:layout_constraintEnd_toEndOf="parent"/>
 
     </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index 02a439d..bd11c1e 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -28,12 +28,14 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"/>
 
+    <!-- Filtering affects only alpha instead of the visibility since visibility can be altered
+         separately through RecentsView#resetFromSplitSelectionState() -->
     <ImageView
         android:id="@+id/show_windows"
         android:layout_height="@dimen/recents_filter_icon_size"
         android:layout_width="@dimen/recents_filter_icon_size"
         android:layout_gravity="end"
-        android:visibility="gone"
+        android:alpha="0"
         android:tint="@color/recents_filter_icon"
         android:contentDescription="@string/recents_filter_icon_desc"
         android:importantForAccessibility="no"
diff --git a/quickstep/res/layout/task_grouped.xml b/quickstep/res/layout/task_grouped.xml
index 7792801..ec03c69 100644
--- a/quickstep/res/layout/task_grouped.xml
+++ b/quickstep/res/layout/task_grouped.xml
@@ -38,23 +38,27 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"/>
 
+    <!-- Filtering affects only alpha instead of the visibility since visibility can be altered
+         separately through RecentsView#resetFromSplitSelectionState() -->
     <ImageView
         android:id="@+id/show_windows"
         android:layout_height="@dimen/recents_filter_icon_size"
         android:layout_width="@dimen/recents_filter_icon_size"
         android:layout_gravity="start"
-        android:visibility="gone"
+        android:alpha="0"
         android:tint="@color/recents_filter_icon"
         android:contentDescription="@string/recents_filter_icon_desc"
         android:importantForAccessibility="no"
         android:src="@drawable/ic_select_windows" />
 
+    <!-- Filtering affects only alpha instead of the visibility since visibility can be altered
+         separately through RecentsView#resetFromSplitSelectionState() -->
     <ImageView
         android:id="@+id/show_windows_right"
         android:layout_height="@dimen/recents_filter_icon_size"
         android:layout_width="@dimen/recents_filter_icon_size"
         android:layout_gravity="end"
-        android:visibility="gone"
+        android:alpha="0"
         android:tint="@color/recents_filter_icon"
         android:contentDescription="@string/recents_filter_icon_desc"
         android:importantForAccessibility="no"
diff --git a/quickstep/res/layout/taskbar_all_apps_button.xml b/quickstep/res/layout/taskbar_all_apps_button.xml
index 79d087a..6b665e5 100644
--- a/quickstep/res/layout/taskbar_all_apps_button.xml
+++ b/quickstep/res/layout/taskbar_all_apps_button.xml
@@ -13,10 +13,12 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
+<!-- Note: The actual size will match the taskbar icon sizes in TaskbarView#onLayout(). -->
 <com.android.launcher3.views.IconButtonView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="@dimen/taskbar_icon_touch_size"
-    android:layout_height="@dimen/taskbar_icon_touch_size"
+    android:layout_width="@dimen/taskbar_icon_min_touch_size"
+    android:layout_height="@dimen/taskbar_icon_min_touch_size"
     android:contentDescription="@string/all_apps_button_label"
     android:backgroundTint="@android:color/transparent"
     android:icon="@drawable/ic_all_apps_button"
diff --git a/quickstep/res/layout/taskbar_edu_features.xml b/quickstep/res/layout/taskbar_edu_features.xml
new file mode 100644
index 0000000..22b99e8
--- /dev/null
+++ b/quickstep/res/layout/taskbar_edu_features.xml
@@ -0,0 +1,87 @@
+<?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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <TextView
+        android:id="@+id/title"
+        style="@style/TextAppearance.TaskbarEduTooltip.Title"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:text="@string/taskbar_edu_features"
+        app:layout_constraintEnd_toEndOf="@id/suggestions_animation"
+        app:layout_constraintStart_toStartOf="@id/splitscreen_animation"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.airbnb.lottie.LottieAnimationView
+        android:id="@+id/splitscreen_animation"
+        android:layout_width="@dimen/taskbar_edu_features_lottie_width"
+        android:layout_height="@dimen/taskbar_edu_features_lottie_height"
+        android:layout_marginTop="@dimen/taskbar_edu_tooltip_vertical_margin"
+        android:scaleType="centerCrop"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/title"
+        app:lottie_autoPlay="true"
+        app:lottie_loop="true"
+        app:lottie_rawRes="@raw/taskbar_edu_splitscreen" />
+
+    <TextView
+        android:id="@+id/splitscreen_text"
+        style="@style/TextAppearance.TaskbarEduTooltip.Subtext"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:text="@string/taskbar_edu_splitscreen"
+        app:layout_constraintEnd_toEndOf="@id/splitscreen_animation"
+        app:layout_constraintStart_toStartOf="@id/splitscreen_animation"
+        app:layout_constraintTop_toBottomOf="@id/splitscreen_animation" />
+
+    <com.airbnb.lottie.LottieAnimationView
+        android:id="@+id/suggestions_animation"
+        android:layout_width="@dimen/taskbar_edu_features_lottie_width"
+        android:layout_height="@dimen/taskbar_edu_features_lottie_height"
+        android:layout_marginStart="@dimen/taskbar_edu_features_horizontal_spacing"
+        android:layout_marginTop="@dimen/taskbar_edu_tooltip_vertical_margin"
+        android:scaleType="centerCrop"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toEndOf="@id/splitscreen_animation"
+        app:layout_constraintTop_toBottomOf="@id/title"
+        app:lottie_autoPlay="true"
+        app:lottie_loop="true"
+        app:lottie_rawRes="@raw/taskbar_edu_suggestions" />
+
+    <TextView
+        android:id="@+id/suggestions_text"
+        style="@style/TextAppearance.TaskbarEduTooltip.Subtext"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:text="@string/taskbar_edu_suggestions"
+        app:layout_constraintEnd_toEndOf="@id/suggestions_animation"
+        app:layout_constraintStart_toStartOf="@id/suggestions_animation"
+        app:layout_constraintTop_toBottomOf="@id/suggestions_animation" />
+
+    <Button
+        android:id="@+id/done_button"
+        style="@style/TaskbarEdu.Button.Next"
+        android:layout_width="wrap_content"
+        android:layout_height="36dp"
+        android:layout_marginTop="32dp"
+        android:text="@string/taskbar_edu_done"
+        android:textColor="?androidprv:attr/textColorOnAccent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/suggestions_text" />
+</merge>
\ No newline at end of file
diff --git a/quickstep/res/layout/taskbar_edu_swipe.xml b/quickstep/res/layout/taskbar_edu_swipe.xml
new file mode 100644
index 0000000..d8b56b5
--- /dev/null
+++ b/quickstep/res/layout/taskbar_edu_swipe.xml
@@ -0,0 +1,43 @@
+<?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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <TextView
+        android:id="@+id/title"
+        style="@style/TextAppearance.TaskbarEduTooltip.Title"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:text="@string/taskbar_edu_stashing"
+        app:layout_constraintEnd_toEndOf="@id/swipe_animation"
+        app:layout_constraintStart_toStartOf="@id/swipe_animation"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.airbnb.lottie.LottieAnimationView
+        android:id="@+id/swipe_animation"
+        android:layout_width="@dimen/taskbar_edu_swipe_lottie_width"
+        android:layout_height="@dimen/taskbar_edu_swipe_lottie_height"
+        android:layout_marginTop="@dimen/taskbar_edu_tooltip_vertical_margin"
+        android:scaleType="centerCrop"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/title"
+        app:lottie_autoPlay="true"
+        app:lottie_loop="true"
+        app:lottie_rawRes="@raw/taskbar_edu_stashing" />
+
+</merge>
\ No newline at end of file
diff --git a/quickstep/res/layout/taskbar_edu_tooltip.xml b/quickstep/res/layout/taskbar_edu_tooltip.xml
new file mode 100644
index 0000000..29f4956
--- /dev/null
+++ b/quickstep/res/layout/taskbar_edu_tooltip.xml
@@ -0,0 +1,41 @@
+<?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.launcher3.taskbar.TaskbarEduTooltip xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="bottom|center"
+    android:layout_marginBottom="16dp"
+    android:clipChildren="false"
+    android:clipToPadding="false"
+    android:fitsSystemWindows="true"
+    android:gravity="center"
+    android:orientation="vertical">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/content"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:background="@drawable/bg_taskbar_edu_tooltip"
+        android:elevation="@dimen/taskbar_edu_tooltip_elevation"
+        android:paddingHorizontal="@dimen/taskbar_edu_tooltip_horizontal_margin"
+        android:paddingVertical="@dimen/taskbar_edu_tooltip_vertical_margin" />
+
+    <View
+        android:id="@+id/arrow"
+        android:layout_width="@dimen/popup_arrow_width"
+        android:layout_height="@dimen/popup_arrow_height"
+        android:elevation="@dimen/taskbar_edu_tooltip_elevation" />
+</com.android.launcher3.taskbar.TaskbarEduTooltip>
\ No newline at end of file
diff --git a/quickstep/res/raw/taskbar_edu_splitscreen.json b/quickstep/res/raw/taskbar_edu_splitscreen.json
new file mode 100644
index 0000000..09775b0
--- /dev/null
+++ b/quickstep/res/raw/taskbar_edu_splitscreen.json
@@ -0,0 +1 @@
+{"v":"5.9.0","fr":60,"ip":0,"op":240,"w":412,"h":300,"nm":"Taskbar_Transient_EDU_2","ddd":0,"assets":[{"id":"comp_0","nm":"Pre-comp_TaskBar_Transient_Step_2","fr":60,"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[237.75,183,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"ip":102,"op":255,"st":90,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"swipe up 2","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":100,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":110,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":207,"s":[100]},{"t":217,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":100,"s":[-45.3,33.917,0],"to":[5.5,9,0],"ti":[-12,-36,0]},{"i":{"x":0.3,"y":0.3},"o":{"x":0.333,"y":0.333},"t":127,"s":[-12.3,87.917,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":137,"s":[-12.3,87.917,0],"to":[0,0,0],"ti":[0,0,0]},{"t":187,"s":[59.5,-26.7,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.1,0.1,0.667],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.333],"y":[0,0,0]},"t":127,"s":[100,100,100]},{"t":137,"s":[80,80,100]}],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":63.75,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":8,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":30,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]},{"ty":25,"nm":"Drop Shadow 2","np":8,"mn":"ADBE Drop Shadow","ix":2,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":10.2,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":0,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":40,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":240,"s":[56,56]},{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":262,"s":[56,98]},{"t":288,"s":[56,56]}],"ix":2},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":137,"s":[0,0],"to":[0,0],"ti":[0,0]},{"t":187,"s":[0,14]}],"ix":3},"r":{"a":0,"k":67,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":50,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":102,"op":234,"st":77,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".grey300","cl":"grey300","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-83.044,0.454,0],"ix":2,"l":2},"a":{"a":0,"k":[121.456,227.454,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[125.547,231.545],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 18","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[125.547,227.455],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 17","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[125.547,223.364],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 16","np":1,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[121.453,231.545],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 15","np":1,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[121.453,227.455],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 14","np":1,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[121.453,223.364],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 13","np":1,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[117.364,231.545],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 12","np":1,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[117.364,227.455],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 11","np":1,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[117.364,223.364],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 10","np":1,"cix":2,"bm":0,"ix":9,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"green circle matte","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84.409,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.807843148708,0.917647063732,0.839215695858,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.807843137255,0.917647058824,0.839215686275,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":550,"s":[84.522,0.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":580,"s":[84.522,-19.999,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"green circle matte 2","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84.409,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.807843148708,0.917647063732,0.839215695858,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.807843137255,0.917647058824,0.839215686275,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".green400","cl":"green400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":553,"s":[84.522,20.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":583,"s":[84.522,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".green100","cl":"green100","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84.409,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.807843148708,0.917647063732,0.839215695858,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.807843137255,0.917647058824,0.839215686275,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"blue circle matte 2","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[55.772,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.541175991881,0.705881993911,0.972549019608,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".blue400","cl":"blue400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":544,"s":[55.772,0.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":574,"s":[55.772,-19.999,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"blue circle matte","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[55.772,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.541175991881,0.705881993911,0.972549019608,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":547,"s":[55.772,20.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":577,"s":[55.772,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue100","cl":"blue100","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[55.772,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.890196084976,0.988235294819,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.823529411765,0.890196078431,0.988235294118,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".yellow400","cl":"yellow400","parent":20,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":207,"s":[0]},{"t":217,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":977,"s":[27.135,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":987,"s":[27.135,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":997,"s":[27.135,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.988235294819,0.78823530674,0.203921571374,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":207,"op":11607,"st":207,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".yellow400","cl":"yellow400","parent":20,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":207,"s":[100]},{"t":217,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":137,"s":[27.135,0.001,0],"to":[0,0,0],"ti":[0,0,0]},{"t":187,"s":[63,-51.749,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.988235294819,0.78823530674,0.203921571374,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".grey400","cl":"grey400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":944,"s":[27.135,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":954,"s":[27.135,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":964,"s":[27.135,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.741176470588,0.756862745098,0.776470588235,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":137,"op":252,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".green400","cl":"green400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":941,"s":[-1.498,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":951,"s":[-1.498,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":961,"s":[-1.498,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".red400","cl":"red400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":938,"s":[-30.134,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":948,"s":[-30.134,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":958,"s":[-30.134,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333337307,0.403921574354,0.360784322023,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":935,"s":[-58.771,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":945,"s":[-58.771,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":955,"s":[-58.771,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".grey800","cl":"grey800","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[204.5,227.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0.001,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-8.284,0],[0,0],[0,-8.284],[0,0],[8.284,0],[0,0],[0,8.284],[0,0]],"o":[[0,0],[8.284,0],[0,0],[0,8.284],[0,0],[-8.284,0],[0,0],[0,-8.284]],"v":[[-86.5,-15],[86.5,-15],[101.5,0],[101.5,0],[86.5,15],[-86.5,15],[-101.5,0],[-101.5,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294118524,0.250980407,0.262745112181,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null_MasterScale","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[120,120,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"screen_matte","parent":1,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[81,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[320,204.01],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11306,"st":-94,"bm":0},{"ddd":0,"ind":3,"ty":0,"nm":"Pre-comp_TaskBar_Transient_Step_2","parent":1,"tt":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":262,"s":[-1.5,79.501,0],"to":[0,1.333,0],"ti":[0,-1.333,0]},{"i":{"x":0.1,"y":0.1},"o":{"x":0.167,"y":0.167},"t":292,"s":[-1.5,87.501,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":342,"s":[-1.5,87.501,0],"to":[0,-1.333,0],"ti":[0,1.333,0]},{"i":{"x":0.3,"y":0.3},"o":{"x":0.3,"y":0.3},"t":372,"s":[-1.5,79.501,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":380,"s":[-1.5,79.501,0],"to":[-42.083,-12.917,0],"ti":[42.083,12.917,0]},{"t":460,"s":[-254,2.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[206,227.625,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":380,"s":[100,100,100]},{"t":460,"s":[370,370,100]}],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":11306,"st":-94,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".blue100","cl":"blue100","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-73.438,0,0],"ix":2,"l":2},"a":{"a":0,"k":[-154.438,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":43,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":93,"s":[90,90,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.167],"y":[0,0,0]},"t":113,"s":[90,90,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":133,"s":[100,100,100]},{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":197,"s":[100,100,100]},{"t":217,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":43,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[13.125,-89.005],[13.125,89.005],[0.125,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[0.125,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.8,"y":0},"t":93,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[0,-89.005],[0,89.005],[-13,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[-13,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":113,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[0,-89.005],[0,89.005],[-13,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[-13,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.167,"y":0},"t":133,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[-2.561,-89.005],[-2.561,89.005],[-15.561,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[-15.561,-102.005]],"c":true}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":197,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[-2.561,-89.005],[-2.561,89.005],[-15.561,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[-15.561,-102.005]],"c":true}]},{"t":217,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[13.125,-89.005],[13.125,89.005],[0.125,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[0.125,-102.005]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.823529411765,0.890196078431,0.988235294118,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":491,"st":-94,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".blue100","cl":"blue100","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.8],"y":[0]},"t":43,"s":[100]},{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.8],"y":[0]},"t":93,"s":[0]},{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":113,"s":[0]},{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":123,"s":[100]},{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":207,"s":[100]},{"t":217,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[73.438,0,0],"ix":2,"l":2},"a":{"a":0,"k":[-7.562,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":43,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":93,"s":[90,90,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.167],"y":[0,0,0]},"t":113,"s":[90,90,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":133,"s":[100,100,100]},{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":197,"s":[100,100,100]},{"t":217,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":43,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[-0.125,102.005],[-13.125,89.005],[-13.125,-89.005],[-0.125,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.8,"y":0},"t":93,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[13,102.005],[0,89.005],[0,-89.005],[13,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":113,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[13,102.005],[0,89.005],[0,-89.005],[13,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.167,"y":0},"t":133,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[15.561,102.005],[2.561,89.005],[2.561,-89.005],[15.561,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":197,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[15.561,102.005],[2.561,89.005],[2.561,-89.005],[15.561,-102.005],[147,-102.005]],"c":true}]},{"t":217,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[-0.125,102.005],[-13.125,89.005],[-13.125,-89.005],[-0.125,-102.005],[147,-102.005]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.823529411765,0.890196078431,0.988235294118,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":491,"st":-94,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".yellow100","cl":"yellow100","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[73.438,0,0],"ix":2,"l":2},"a":{"a":0,"k":[-7.562,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":43,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":93,"s":[90,90,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.167],"y":[0,0,0]},"t":113,"s":[90,90,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":133,"s":[100,100,100]},{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":197,"s":[100,100,100]},{"t":217,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":43,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[-0.125,102.005],[-13.125,89.005],[-13.125,-89.005],[-0.125,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.8,"y":0},"t":93,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[13,102.005],[0,89.005],[0,-89.005],[13,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":113,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[13,102.005],[0,89.005],[0,-89.005],[13,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.167,"y":0},"t":133,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[15.561,102.005],[2.561,89.005],[2.561,-89.005],[15.561,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":197,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[15.561,102.005],[2.561,89.005],[2.561,-89.005],[15.561,-102.005],[147,-102.005]],"c":true}]},{"t":217,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[-0.125,102.005],[-13.125,89.005],[-13.125,-89.005],[-0.125,-102.005],[147,-102.005]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.996078431373,0.937254901961,0.764705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":491,"st":-94,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey800","cl":"grey800","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[81,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[320,204.01],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11306,"st":-94,"bm":0}],"markers":[{"tm":94,"cm":"","dr":0},{"tm":249,"cm":"","dr":0},{"tm":474,"cm":"","dr":0}]}
\ No newline at end of file
diff --git a/quickstep/res/raw/taskbar_edu_stashing.json b/quickstep/res/raw/taskbar_edu_stashing.json
new file mode 100644
index 0000000..5515a23
--- /dev/null
+++ b/quickstep/res/raw/taskbar_edu_stashing.json
@@ -0,0 +1 @@
+{"v":"5.9.0","fr":60,"ip":0,"op":212,"w":412,"h":300,"nm":"Taskbar_Transient_EDU_1","ddd":0,"assets":[{"id":"comp_0","nm":"Pre-comp_TaskBar_Transient_Step_1","fr":60,"layers":[{"ddd":0,"ind":3,"ty":4,"nm":".grey300","cl":"grey300","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-83.044,0.454,0],"ix":2,"l":2},"a":{"a":0,"k":[121.456,227.454,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[125.547,231.545],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 18","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[125.547,227.455],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 17","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[125.547,223.364],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 16","np":1,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[121.453,231.545],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 15","np":1,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[121.453,227.455],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 14","np":1,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[121.453,223.364],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 13","np":1,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[117.364,231.545],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 12","np":1,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[117.364,227.455],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 11","np":1,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[117.364,223.364],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 10","np":1,"cix":2,"bm":0,"ix":9,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"green circle matte","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84.409,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.807843148708,0.917647063732,0.839215695858,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.807843137255,0.917647058824,0.839215686275,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":550,"s":[84.522,0.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":580,"s":[84.522,-19.999,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"green circle matte 2","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84.409,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.807843148708,0.917647063732,0.839215695858,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.807843137255,0.917647058824,0.839215686275,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".green400","cl":"green400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":553,"s":[84.522,20.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":583,"s":[84.522,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".green100","cl":"green100","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84.409,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.807843148708,0.917647063732,0.839215695858,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.807843137255,0.917647058824,0.839215686275,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"blue circle matte 2","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[55.772,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.541175991881,0.705881993911,0.972549019608,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".blue400","cl":"blue400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":544,"s":[55.772,0.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":574,"s":[55.772,-19.999,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"blue circle matte","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[55.772,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.541175991881,0.705881993911,0.972549019608,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":547,"s":[55.772,20.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":577,"s":[55.772,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue100","cl":"blue100","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[55.772,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.890196084976,0.988235294819,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.823529411765,0.890196078431,0.988235294118,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".yellow400","cl":"yellow400","parent":20,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":208,"s":[0]},{"t":218,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":947,"s":[27.135,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":957,"s":[27.135,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":967,"s":[27.135,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.988235294819,0.78823530674,0.203921571374,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":208,"op":11577,"st":177,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".yellow400","cl":"yellow400","parent":20,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":198,"s":[100]},{"t":208,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":168,"s":[27.135,0.001,0],"to":[0.728,-9.542,0],"ti":[-45.478,19.292,0]},{"t":218,"s":[78,-76.749,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.988235294819,0.78823530674,0.203921571374,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".grey400","cl":"grey400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":944,"s":[27.135,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":954,"s":[27.135,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":964,"s":[27.135,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.741176470588,0.756862745098,0.776470588235,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":168,"op":252,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".green400","cl":"green400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":941,"s":[-1.498,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":951,"s":[-1.498,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":961,"s":[-1.498,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".red400","cl":"red400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":938,"s":[-30.134,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":948,"s":[-30.134,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":958,"s":[-30.134,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333337307,0.403921574354,0.360784322023,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":935,"s":[-58.771,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":945,"s":[-58.771,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":955,"s":[-58.771,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".grey800","cl":"grey800","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[204.5,227.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0.001,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-8.284,0],[0,0],[0,-8.284],[0,0],[8.284,0],[0,0],[0,8.284],[0,0]],"o":[[0,0],[8.284,0],[0,0],[0,8.284],[0,0],[-8.284,0],[0,0],[0,-8.284]],"v":[[-86.5,-15],[86.5,-15],[101.5,0],[101.5,0],[86.5,15],[-86.5,15],[-101.5,0],[-101.5,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294118524,0.250980407,0.262745112181,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null_MasterScale","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[120,120,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":3,"nm":"Null 1","parent":1,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,44,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"ip":15,"op":73,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"swipe up","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":15,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":25,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[100]},{"t":70,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":15,"s":[-48.3,37.417,0],"to":[5.5,9,0],"ti":[-12,-36,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":40,"s":[-15.3,91.417,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.45,"y":0},"t":50,"s":[-15.3,91.417,0],"to":[0,0,0],"ti":[0,0,0]},{"t":70,"s":[-15.3,10.917,0],"h":1}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.5,0.5,0.667],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.333],"y":[0,0,0]},"t":40,"s":[100,100,100]},{"i":{"x":[0.5,0.5,0.667],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.333],"y":[0,0,0]},"t":50,"s":[80,80,100]},{"i":{"x":[0.5,0.5,0.667],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.333],"y":[0,0,0]},"t":60,"s":[80,80,100]},{"t":70,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":63.75,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":8,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":30,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]},{"ty":25,"nm":"Drop Shadow 2","np":8,"mn":"ADBE Drop Shadow","ix":2,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":10.2,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":0,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":40,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":52,"s":[56,56]},{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":62,"s":[56,98]},{"t":72,"s":[56,56]}],"ix":2},"p":{"a":1,"k":[{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"t":52,"s":[0,0],"to":[0,0],"ti":[0,0]},{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"t":62,"s":[0,-16],"to":[0,0],"ti":[0,0]},{"t":72,"s":[0,0]}],"ix":3},"r":{"a":0,"k":67,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":50,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":15,"op":73,"st":-10,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey800","cl":"grey800","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.7,"y":0},"t":168,"s":[-0.5,81.5,0],"to":[0,1.667,0],"ti":[0,-1.667,0]},{"t":212,"s":[-0.5,91.5,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.381,0],[0,0],[0,-1.381],[0,0],[1.381,0],[0,0],[0,1.381],[0,0]],"o":[[0,0],[1.381,0],[0,0],[0,1.381],[0,0],[-1.381,0],[0,0],[0,-1.381]],"v":[[-42,-2.5],[42,-2.5],[44.5,0],[44.5,0],[42,2.5],[-42,2.5],[-44.5,0],[-44.5,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":186,"op":213,"st":89,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"screen_matte","parent":1,"td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":168,"s":[100]},{"t":212,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[81,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[320,204.01],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":186,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":0,"nm":"Pre-comp_TaskBar_Transient_Step_1","parent":1,"tt":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.7,"y":0},"t":50,"s":[-1.5,94.501,0],"to":[0,-2.5,0],"ti":[0,2.5,0]},{"i":{"x":0.1,"y":0.1},"o":{"x":0.167,"y":0.167},"t":94,"s":[-1.5,79.501,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.7,"y":0},"t":168,"s":[-1.5,79.501,0],"to":[0,2.5,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.7,"y":0},"t":212,"s":[-1.5,94.501,0],"to":[0,0,0],"ti":[0,1.167,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":356,"s":[-1.5,79.501,0],"to":[0,-1.167,0],"ti":[0,-1.333,0]},{"i":{"x":0.1,"y":0.1},"o":{"x":0.167,"y":0.167},"t":386,"s":[-1.5,87.501,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":436,"s":[-1.5,87.501,0],"to":[0,-1.333,0],"ti":[0,1.333,0]},{"i":{"x":0.3,"y":0.3},"o":{"x":0.3,"y":0.3},"t":466,"s":[-1.5,79.501,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":474,"s":[-1.5,79.501,0],"to":[-42.083,-12.917,0],"ti":[42.083,12.917,0]},{"t":554,"s":[-254,2.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[206,227.625,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":50,"s":[70,70,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":94,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":168,"s":[100,100,100]},{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":212,"s":[70,70,100]},{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":474,"s":[100,100,100]},{"t":554,"s":[370,370,100]}],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":65,"op":186,"st":65,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey800","cl":"grey800","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.9,"y":0},"t":46,"s":[-0.5,91.5,0],"to":[0,-1.667,0],"ti":[0,1.667,0]},{"t":76,"s":[-0.5,81.5,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.381,0],[0,0],[0,-1.381],[0,0],[1.381,0],[0,0],[0,1.381],[0,0]],"o":[[0,0],[1.381,0],[0,0],[0,1.381],[0,0],[-1.381,0],[0,0],[0,-1.381]],"v":[[-42,-2.5],[42,-2.5],[44.5,0],[44.5,0],[42,2.5],[-42,2.5],[-44.5,0],[-44.5,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":65,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".blue100","cl":"blue100","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-73.438,0,0],"ix":2,"l":2},"a":{"a":0,"k":[-154.438,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":257,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":307,"s":[95,95,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.167],"y":[0,0,0]},"t":369,"s":[95,95,100]},{"t":389,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":257,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[13.125,-89.005],[13.125,89.005],[0.125,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[0.125,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.8,"y":0},"t":307,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[0,-89.005],[0,89.005],[-13,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[-13,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":369,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[0,-89.005],[0,89.005],[-13,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[-13,-102.005]],"c":true}]},{"t":389,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[13.125,-89.005],[13.125,89.005],[0.125,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[0.125,-102.005]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.823529411765,0.890196078431,0.988235294118,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":286,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".blue100","cl":"blue100","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.8],"y":[0]},"t":257,"s":[100]},{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.8],"y":[0]},"t":307,"s":[0]},{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":369,"s":[0]},{"t":379,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[73.438,0,0],"ix":2,"l":2},"a":{"a":0,"k":[-7.562,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":257,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":307,"s":[95,95,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.167],"y":[0,0,0]},"t":369,"s":[95,95,100]},{"t":389,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":257,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[-0.125,102.005],[-13.125,89.005],[-13.125,-89.005],[-0.125,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.8,"y":0},"t":307,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[13,102.005],[0,89.005],[0,-89.005],[13,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":369,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[13,102.005],[0,89.005],[0,-89.005],[13,-102.005],[147,-102.005]],"c":true}]},{"t":389,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[-0.125,102.005],[-13.125,89.005],[-13.125,-89.005],[-0.125,-102.005],[147,-102.005]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.823529411765,0.890196078431,0.988235294118,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":286,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".yellow100","cl":"yellow100","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[73.438,0,0],"ix":2,"l":2},"a":{"a":0,"k":[-7.562,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":257,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":307,"s":[95,95,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.167],"y":[0,0,0]},"t":369,"s":[95,95,100]},{"t":389,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":257,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[-0.125,102.005],[-13.125,89.005],[-13.125,-89.005],[-0.125,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.8,"y":0},"t":307,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[13,102.005],[0,89.005],[0,-89.005],[13,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":369,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[13,102.005],[0,89.005],[0,-89.005],[13,-102.005],[147,-102.005]],"c":true}]},{"t":389,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[-0.125,102.005],[-13.125,89.005],[-13.125,-89.005],[-0.125,-102.005],[147,-102.005]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.996078431373,0.937254901961,0.764705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":286,"st":0,"bm":0}],"markers":[{"tm":94,"cm":"","dr":0},{"tm":249,"cm":"","dr":0},{"tm":474,"cm":"","dr":0}]}
\ No newline at end of file
diff --git a/quickstep/res/raw/taskbar_edu_suggestions.json b/quickstep/res/raw/taskbar_edu_suggestions.json
new file mode 100644
index 0000000..c8ba29c
--- /dev/null
+++ b/quickstep/res/raw/taskbar_edu_suggestions.json
@@ -0,0 +1 @@
+{"v":"5.9.0","fr":60,"ip":0,"op":120,"w":412,"h":300,"nm":"Taskbar_Transient_EDU_4","ddd":0,"assets":[{"id":"comp_0","nm":"Pre-comp_TaskBar_Transient","fr":60,"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[237.75,183,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"ip":102,"op":255,"st":90,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"swipe up 2","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":100,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":110,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":167,"s":[100]},{"t":177,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":100,"s":[-45.3,33.917,0],"to":[5.5,9,0],"ti":[-12,-36,0]},{"i":{"x":0.3,"y":0.3},"o":{"x":0.333,"y":0.333},"t":127,"s":[-12.3,87.917,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":137,"s":[-12.3,87.917,0],"to":[0,0,0],"ti":[-99.967,45.186,0]},{"t":187,"s":[89.5,-76.7,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.1,0.1,0.667],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.333],"y":[0,0,0]},"t":127,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.667],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.333],"y":[0,0,0]},"t":137,"s":[80,80,100]},{"i":{"x":[0.5,0.5,0.667],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.333],"y":[0,0,0]},"t":167,"s":[80,80,100]},{"t":179,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":63.75,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":8,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":30,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]},{"ty":25,"nm":"Drop Shadow 2","np":8,"mn":"ADBE Drop Shadow","ix":2,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":10.2,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":0,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":40,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":240,"s":[56,56]},{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":262,"s":[56,98]},{"t":288,"s":[56,56]}],"ix":2},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":137,"s":[0,0],"to":[0,0],"ti":[0,0]},{"i":{"x":0.5,"y":1},"o":{"x":0.8,"y":0},"t":187,"s":[0,14],"to":[0,0],"ti":[0,0]},{"t":189,"s":[0,0]}],"ix":3},"r":{"a":0,"k":67,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":50,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":102,"op":234,"st":77,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".grey300","cl":"grey300","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-83.044,0.454,0],"ix":2,"l":2},"a":{"a":0,"k":[121.456,227.454,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[125.547,231.545],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 18","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[125.547,227.455],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 17","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[125.547,223.364],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 16","np":1,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[121.453,231.545],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 15","np":1,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[121.453,227.455],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 14","np":1,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[121.453,223.364],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 13","np":1,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[117.364,231.545],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 12","np":1,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[117.364,227.455],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 11","np":1,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[117.364,223.364],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 10","np":1,"cix":2,"bm":0,"ix":9,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"green circle matte","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84.409,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.807843148708,0.917647063732,0.839215695858,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.807843137255,0.917647058824,0.839215686275,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":550,"s":[84.522,0.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":580,"s":[84.522,-19.999,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"green circle matte 2","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84.409,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.807843148708,0.917647063732,0.839215695858,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.807843137255,0.917647058824,0.839215686275,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".green400","cl":"green400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":553,"s":[84.522,20.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":583,"s":[84.522,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".green100","cl":"green100","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84.409,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.807843148708,0.917647063732,0.839215695858,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.807843137255,0.917647058824,0.839215686275,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"blue circle matte 2","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[55.772,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.541175991881,0.705881993911,0.972549019608,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".blue400","cl":"blue400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":544,"s":[55.772,0.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":574,"s":[55.772,-19.999,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"blue circle matte","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[55.772,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.541175991881,0.705881993911,0.972549019608,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":547,"s":[55.772,20.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":577,"s":[55.772,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue100","cl":"blue100","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[55.772,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.890196084976,0.988235294819,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.823529411765,0.890196078431,0.988235294118,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".yellow400","cl":"yellow400","parent":20,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":177,"s":[0]},{"t":187,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":947,"s":[27.135,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":957,"s":[27.135,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":967,"s":[27.135,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.988235294819,0.78823530674,0.203921571374,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":177,"op":11577,"st":177,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".yellow400","cl":"yellow400","parent":20,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":167,"s":[100]},{"t":177,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":137,"s":[27.135,0.001,0],"to":[0.728,-9.542,0],"ti":[-45.478,19.292,0]},{"t":187,"s":[78,-76.749,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.988235294819,0.78823530674,0.203921571374,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".grey400","cl":"grey400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":944,"s":[27.135,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":954,"s":[27.135,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":964,"s":[27.135,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.741176470588,0.756862745098,0.776470588235,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":137,"op":252,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".green400","cl":"green400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":941,"s":[-1.498,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":951,"s":[-1.498,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":961,"s":[-1.498,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".red400","cl":"red400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":938,"s":[-30.134,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":948,"s":[-30.134,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":958,"s":[-30.134,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333337307,0.403921574354,0.360784322023,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":935,"s":[-58.771,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":945,"s":[-58.771,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":955,"s":[-58.771,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".grey800","cl":"grey800","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[204.5,227.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0.001,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-8.284,0],[0,0],[0,-8.284],[0,0],[8.284,0],[0,0],[0,8.284],[0,0]],"o":[[0,0],[8.284,0],[0,0],[0,8.284],[0,0],[-8.284,0],[0,0],[0,-8.284]],"v":[[-86.5,-15],[86.5,-15],[101.5,0],[101.5,0],[86.5,15],[-86.5,15],[-101.5,0],[-101.5,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294118524,0.250980407,0.262745112181,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null_MasterScale","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[120,120,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"screen_matte","parent":1,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[81,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[320,204.01],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":10878,"st":-522,"bm":0},{"ddd":0,"ind":3,"ty":0,"nm":"Pre-comp_TaskBar_Transient","parent":1,"tt":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.7,"y":0},"t":-472,"s":[-1.5,94.501,0],"to":[0,-2.5,0],"ti":[0,2.5,0]},{"i":{"x":0.1,"y":0.1},"o":{"x":0.167,"y":0.167},"t":-428,"s":[-1.5,79.501,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":0.1},"o":{"x":0.3,"y":0.3},"t":-166,"s":[-1.5,79.501,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":0.3},"o":{"x":0.3,"y":0.3},"t":-136,"s":[-1.5,79.501,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.8,"y":0},"t":-128,"s":[-1.5,79.501,0],"to":[0,1.333,0],"ti":[42.083,12.917,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":-86,"s":[-1.5,87.501,0],"to":[-42.083,-12.917,0],"ti":[42.083,14.25,0]},{"t":-48,"s":[-254,2.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[206,227.625,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":-472,"s":[70,70,100]},{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":-428,"s":[100,100,100]},{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":-128,"s":[100,100,100]},{"t":-48,"s":[370,370,100]}],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":10878,"st":-522,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".blue100","cl":"blue100","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":-273,"s":[0]},{"t":-253,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[81,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.1,0.1],"y":[1,1]},"o":{"x":[0.3,0.3],"y":[0,0]},"t":-166,"s":[320,204.01]},{"i":{"x":[0.1,0.1],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":-136,"s":[320,173.01]},{"i":{"x":[0.1,0.1],"y":[1,1]},"o":{"x":[0.3,0.3],"y":[0,0]},"t":-86,"s":[320,173.01]},{"t":-56,"s":[320,204.01]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":12,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.823529411765,0.890196078431,0.988235294118,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":-166,"s":[-81,0],"to":[0,-2.542],"ti":[0,2.542]},{"i":{"x":0.1,"y":0.1},"o":{"x":0.167,"y":0.167},"t":-136,"s":[-81,-15.25],"to":[0,0],"ti":[0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":-86,"s":[-81,-15.25],"to":[0,2.542],"ti":[0,-2.542]},{"t":-56,"s":[-81,0]}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11113,"st":-287,"bm":0}],"markers":[{"tm":94,"cm":"","dr":0},{"tm":249,"cm":"","dr":0},{"tm":474,"cm":"","dr":0}]}
\ No newline at end of file
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index 1605c24..d1a5d5c 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taakbalkopvoeding"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Taakbalkopvoeding het verskyn"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Taakbalkopvoeding is toegemaak"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Sleep na die kant om 2 apps tegelyk te gebruik"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Sleep ’n app na die kant toe om 2 apps tegelyk te gebruik"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Kortswiep op om die taakbalk te wys"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Die taakbalk stel apps op grond van jou roetine voor"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Kry appvoorstelle op grond van jou roetine"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Doen meer met die taakbalk"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Volgende"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Terug"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Maak toe"</string>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index df9fe66..fad5d9e 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"የተግባር አሞሌ ትምህርት"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"የተግባር አሞሌ ትምህርት ይታያል"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"የተግባር አሞሌ ትምህርት ተዘግቷል"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"በአንድ ጊዜ 2 መተግበሪያዎችን ለመጠቀም ወደ ጎን ይጎትቱ"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"በአንድ ጊዜ 2 መተግበሪያዎችን ለመጠቀም አንድ መተግበሪያን ወደ ጎን ይጎትቱ"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"የተግባር አሞሌውን ለማሳየት አጭር ወደ ላይ ያንሸራትቱ"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"የተግባር አሞሌው የዕለት ተዕለት ተግባርዎ ላይ በመመስረት መተግበሪያዎችን ይጠቁማል"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"በዕለት ተዕለት ተግባርዎ መሠረት የመተግበሪያ አስተያየቶችን ያግኙ"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"በተግባር አሞሌው ተጨማሪ ነገር ያድርጉ"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"ቀጣይ"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"ተመለስ"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ዝጋ"</string>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index a6781ef..a98075b 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"التعريف بشريط التطبيقات"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"ظهرت لوحة تعليم استخدام شريط المهام."</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"تم إغلاق لوحة تعليم استخدام شريط المهام."</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"اسحبه إلى جانب الشاشة لاستخدام تطبيقَين في آنٍ واحد."</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"اسحب تطبيقًا إلى جانب الشاشة لاستخدام تطبيقََين في آنٍ واحد."</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"مرِّر سريعًا للأعلى تمريرة قصيرة لإظهار شريط التطبيقات."</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"يقترح شريط المهام تطبيقات بناءً على روتينك."</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"احصل على اقتراحات التطبيقات بناءً على سلسلة إجراءاتك."</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"إنجاز المزيد باستخدام شريط التطبيقات"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"الشاشة التالية"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"رجوع"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"إغلاق"</string>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index 6e43c19..e327395 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"টাস্কবাৰৰ শিক্ষা"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"টাস্কবাৰৰ শিক্ষাৰ পেনেলটো প্ৰদর্শিত হৈছে"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"টাস্কবাৰৰ শিক্ষাৰ পেনেলটো বন্ধ হৈছে"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"এবাৰতে দুটা এপ্‌ ব্যৱহাৰ কৰিবলৈ কাষলৈ টানি আনি এৰক"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"এবাৰতে ২ টা এপ্‌ ব্যৱহাৰ কৰিবলৈ কোনো এপ্‌ কাষলৈ টানি আনি এৰক"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"টাস্কবাৰ দেখুৱাবলৈ সামান্য পৰিমাণে ওপৰলৈ ছোৱাইপ কৰক"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"টাস্কবাৰে আপোনাৰ ৰুটিনৰ ভিত্তিত এপৰ পৰামৰ্শ দিয়ে"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"আপোনাৰ ৰুটিনৰ ওপৰত আধাৰিত এপৰ পৰামৰ্শ পাওক"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"টাস্কবাৰৰ জৰিয়তে অধিক কাৰ্য সম্পাদন কৰক"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"পৰৱৰ্তী"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"উভতি যাওক"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"বন্ধ কৰক"</string>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index e844ec1..c538613 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Tapşırıq panelində təhsil"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Tapşırıq panelindəki təlim bölməsi görünür"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Tapşırıq panelindəki təlim bölməsi bağlanıb"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Eyni anda 2 tətbiqi istifadə etmək üçün yan tərəfə çəkin"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Eyni anda 2 tətbiqi istifadə etmək üçün bir tətbiqi yan tərəfə çəkin"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Tapşırıq panelini göstərmək üçün azca yuxarı sürüşdürün"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Tapşırıq paneli rejiminizə əsasən tətbiqlər təklif edir"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Rejiminizə əsasən tətbiq təklifləri alın"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Tapşırıq paneli ilə daha çox şey edin"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Sonra"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Geri"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Bağlayın"</string>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 2699c3e..1bd9d10 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Uputstva na traci zadataka"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Edukativno okno iz trake zadataka se pojavilo"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Edukativno okno iz trake zadataka je zatvoreno"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Prevucite na stranu da biste koristili 2 aplikacije odjednom"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Prevucite na stranu da biste koristili 2 aplikacije odjednom"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Nakratko prevucite nagore da biste prikazali traku zadataka"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Traka zadataka predlaže aplikacije na osnovu rutine"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Dobijajte predloge aplikacija na osnovu rutine"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Uradite više pomoću trake zadataka"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Dalje"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Nazad"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zatvori"</string>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 0f38c75..0ff4aee 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Інфармацыя пра панэль задач"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"З\'явілася панэль навучання на панэлі задач"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Панэль навучання на панэлі задач закрыта"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Перацягніце ўбок, каб адначасова скарыстаць 2 праграмы"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Каб карыстацца 2 праграмамі, перацягніце адну з іх убок"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Хутка правядзіце пальцам уверх, каб убачыць панэль задач"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"На панэлі задач праграмы паказваюцца з улікам вашых дзеянняў"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Атрымлівайце прапановы праграм з улікам вашых дзеянняў"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Выкарыстоўвайце магчымасці панэлі задач"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Далей"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Назад"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Закрыць"</string>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index a284394..3e98fc8 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Урок за лентата на задачите"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Показва се урокът за лентата на задачите"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Урокът за лентата на задачите бе затворен"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Плъзнете встрани, за да използвате едновременно 2 приложения"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Плъзнете приложение встрани, за да използвате едновременно 2"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Прекарайте пръст нагоре, за да видите лентата на задачите"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Лентата на задачите предлага приложения според навиците ви"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Получавайте предложения за приложения според навиците си"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Правете повече неща с лентата на задачите"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Напред"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Назад"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Затваряне"</string>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index e769131..0bd38d1 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"টাস্কবার এডুকেশন"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"টাস্কবার এডুকেশন দেখানো হয়েছে"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"টাস্কবার এডুকেশন বন্ধ করা আছে"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"একসাথে ২টি অ্যাপ ব্যবহার করতে পাশে টেনে আনুন"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"একসাথে ২টি অ্যাপ ব্যবহার করতে একটি অ্যাপ পাশে টেনে আনুন"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"টাস্কবার দেখানোর জন্য শর্ট সোয়াইপ করুন"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"আপনার রুটিনের উপর নির্ভর করে টাস্কবার অ্যাপ সাজেস্ট করে"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"আপনার রুটিন অনুযায়ী অ্যাপ থেকে সাজেশন পান"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"\'টাস্কবার\' ফিচারের সাহায্যে আরও অনেক কিছু করুন"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"পরবর্তী"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"ফিরুন"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"বন্ধ করুন"</string>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index f0118a7..c51d74d 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Edukacija o traci zadataka"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Edukacija o programskoj traci je prikazana"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Edukacija o programskoj traci je zatvorena"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Prevucite u stranu da istovremeno koristite 2 aplikacije"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Prevucite aplikaciju ustranu da odjednom koristite 2 aplikacije"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Nakratko prevucite nagore da prikažete traku zadataka"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Traka zadataka predlaže aplikacije na osnovu vaše rutine"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Dobijajte prijedloge aplikacija zasnovane na vašoj rutini"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Ostvarite više pomoću trake zadataka"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Naprijed"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Nazad"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zatvori"</string>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index d1219ad..352e9cb 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informació sobre Barra de tasques"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Ha aparegut el tauler educatiu de la barra de tasques"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"S\'ha tancat el tauler educatiu de la barra de tasques"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Arrossega al costat per utilitzar 2 aplicacions alhora"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arrossega una app al costat per utilitzar 2 apps alhora"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Llisca una mica cap amunt per mostrar la barra de tasques"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"La barra de tasques suggereix apps basades en la teva rutina"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtén suggeriments d\'aplicacions basats en la teva rutina"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Fes més coses amb la barra de tasques"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Següent"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Enrere"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Tanca"</string>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index 868393d..392aae8 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informace o panelu aplikací"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Zobrazila se výuka k hlavnímu panelu"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Výuka k hlavnímu panelu byla zavřena"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Po přetažení na stranu lze používat dvě aplikace současně"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Pokud chcete používat 2 aplikace najednou, přetáhněte aplikaci na stranu"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Krátkým přejetím nahoru zobrazíte panel aplikací"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Panel aplikací navrhuje aplikace na základě vašeho používání"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Získejte návrhy aplikací na základě vašeho používání"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Pomocí panelu aplikací můžete dělat více věcí"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Další"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Zpět"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zavřít"</string>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index ae2a00a..34b950b 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Oplysninger om proceslinjen"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Vejledningen om proceslinjen blev åbnet"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Vejledningen om proceslinjen blev lukket"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Træk til siden for at bruge 2 apps samtidig"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Træk en app til siden for at bruge 2 apps på én gang"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Stryg hurtigt opad for at se proceslinjen"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Proceslinjen foreslår apps baseret på din rutine"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Få appforslag baseret på din rutine"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Få mere fra hånden med proceslinjen"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Næste"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Tilbage"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Luk"</string>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 86ea264..389486a 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -78,7 +78,7 @@
     <string name="allset_title" msgid="5021126669778966707">"Fertig!"</string>
     <string name="allset_hint" msgid="2384632994739392447">"Nach oben wischen, um den Startbildschirm aufzurufen"</string>
     <string name="allset_button_hint" msgid="2395219947744706291">"Startbildschirmtaste drücken, um zum Startbildschirm zu gehen"</string>
-    <string name="allset_description_generic" msgid="5385500062202019855">"Du kannst dein Gerät (<xliff:g id="DEVICE">%1$s</xliff:g>) jetzt verwenden"</string>
+    <string name="allset_description_generic" msgid="5385500062202019855">"Du kannst dein <xliff:g id="DEVICE">%1$s</xliff:g> jetzt verwenden"</string>
     <string name="default_device_name" msgid="6660656727127422487">"Gerät"</string>
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Einstellungen der Systemsteuerung"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Teilen"</string>
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informationen zur Taskleiste"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Anleitung für Taskleiste eingeblendet"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Anleitung für Taskleiste geschlossen"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Zur Seite ziehen, um zwei Apps gleichzeitig zu verwenden"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"App zur Seite ziehen, um zwei Apps gleichzeitig zu nutzen"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Kurz nach oben wischen, um die Taskleiste anzuzeigen"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Taskleiste empfiehlt Apps basierend auf deinen Gewohnheiten"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"App-Vorschläge auf Grundlage deiner Nutzung erhalten"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Mehr Möglichkeiten mit der Taskleiste"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Weiter"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Zurück"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Schließen"</string>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 807ce43..b21ef88 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Πληροφορίες χρήσης της Γραμμής εργαλείων"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Η εκπαίδευση για τη γραμμή εργασιών εμφανίστηκε"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Η εκπαίδευση για τη γραμμή εργασιών έκλεισε"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Σύρετε στο πλάι για ταυτόχρονη χρήση δύο εφαρμογών"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Σύρετε μια εφαρμ. στην άκρη για χρήση δύο εφαρμ. ταυτόχρονα"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Σύρετε σύντομα προς τα πάνω για εμφάνιση γραμμής εργαλείων"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Η γραμμή εργαλείων συνιστά εφαρμογές βάσει της ρουτίνας σας"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Λάβετε προτεινόμενες εφαρμογές με βάση τη ρουτίνα σας"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Κάντε περισσότερα με τη γραμμή εργαλείων"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Επόμενο"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Πίσω"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Κλείσιμο"</string>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index 414593a..2daea5a 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taskbar education"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Taskbar education appeared"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Taskbar education closed"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Drag to the side to use two apps at once"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Drag an app to the side to use two apps at once"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Short swipe up to show the taskbar"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"The taskbar suggests apps based on your routine"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Get app suggestions based on your routine"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Do more with the taskbar"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Next"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Back"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index 41fb803..14fc636 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taskbar education"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Taskbar education appeared"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Taskbar education closed"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Drag to the side to use 2 apps at once"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Drag an app to the side to use 2 apps at once"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Short swipe up to show the taskbar"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"The taskbar suggests apps based on your routine"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Get app suggestions based on your routine"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Do more with the taskbar"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Next"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Back"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index 414593a..2daea5a 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taskbar education"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Taskbar education appeared"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Taskbar education closed"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Drag to the side to use two apps at once"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Drag an app to the side to use two apps at once"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Short swipe up to show the taskbar"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"The taskbar suggests apps based on your routine"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Get app suggestions based on your routine"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Do more with the taskbar"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Next"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Back"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index 414593a..2daea5a 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taskbar education"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Taskbar education appeared"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Taskbar education closed"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Drag to the side to use two apps at once"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Drag an app to the side to use two apps at once"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Short swipe up to show the taskbar"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"The taskbar suggests apps based on your routine"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Get app suggestions based on your routine"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Do more with the taskbar"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Next"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Back"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index 45ce0c1..4c92a72 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‎‏‏‎‎‏‏‏‏‏‎‏‏‎Taskbar education‎‏‎‎‏‎"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‎‎‎‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎Taskbar education appeared‎‏‎‎‏‎"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‏‏‏‏‏‎‎Taskbar education closed‎‏‎‎‏‎"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‎‎‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‎Drag to the side to use 2 apps at once‎‏‎‎‏‎"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‎‎‎‏‏‎‎‏‎‎‎‎‎‏‎‏‎‏‏‏‎‎‏‏‎‎Drag an app to the side to use 2 apps at once‎‏‎‎‏‎"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‏‏‎‎‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‏‎‎‏‏‎‏‎‎‏‏‏‎‎Short swipe up to show the taskbar‎‏‎‎‏‎"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‎‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎The taskbar suggests apps based on your routine‎‏‎‎‏‎"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‎‏‏‎‏‏‎‎‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‎‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‎Get app suggestions based on your routine‎‏‎‎‏‎"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‎‏‏‎‏‏‎‎‏‏‏‎‎‏‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‏‎‏‎‏‏‎‏‎‏‎‏‎‎Do more with the taskbar‎‏‎‎‏‎"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‏‎‎‎‎‏‎Next‎‏‎‎‏‎"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‏‏‏‏‎‎‏‎‎‎‏‏‎‏‎‎‏‏‎‎Back‎‏‎‎‏‎"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‎‏‎‎‏‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‎‎‎‏‎Close‎‏‎‎‏‎"</string>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index cb7f519..0f4143b 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Información sobre la barra de tareas"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Se abrió la barra de herramientas Educación"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Se cerró la barra de herramientas Educación"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Arrastra a un lado para usar 2 apps a la vez"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arrastra una app a un lado para usar 2 apps a la vez"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Desliza un poco hacia arriba para mostrar la barra de tareas"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"La barra de tareas sugiere apps según tu rutina"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Recibe sugerencias de aplicaciones basadas en tu rutina"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Haz más con la barra de tareas"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Siguiente"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Atrás"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Cerrar"</string>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 09cd305..b1807f8 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Información sobre la barra de tareas"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Ha aparecido una nota sobre la barra de tareas"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Nota sobre la barra de tareas cerrada"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Arrastra hacia un lado para usar 2 aplicaciones a la vez"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arrastra una aplicación hacia un lado para usar 2 a la vez"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Desliza un poco hacia arriba para ver la barra de tareas"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"La barra de tareas sugiere aplicaciones según tus hábitos"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtén sugerencias de aplicaciones basadas en tu rutina"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Sácale más partido a la barra de tareas"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Siguiente"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Atrás"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Cerrar"</string>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 4160316..263aa44 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Tegumiriba tutvustus"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Tegumiriba juhised kuvati"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Tegumiriba juhised on suletud"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Kahe rakenduse korraga kasutamiseks lohistage külje poole"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"2 rakenduse korraga kasutamiseks lohistage rakendus kõrvale"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Tegumiriba kuvamiseks pühkige korraks"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Tegumiribal soovitatakse rakendusi teie rutiinide põhjal"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Hankige oma rutiini põhjal rakenduste soovitusi"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Tehke tegumiriba abil enamat"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Järgmine"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Tagasi"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Sule"</string>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index b302888..990ece2 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Zereginen barra erabiltzeko argibideak"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Agertu egin da zereginen barraren tutoriala"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Itxi egin da zereginen barraren tutoriala"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Bi aplikazio batera erabiltzeko, arrastatu hatza albo batera"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Bi aplikazio batera erabiltzeko, arrastatu bat albo batera"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Ataza-barra ikusteko, pasatu hatza bizkor gora"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Ataza-barran erabileran oinarritutako aplikazioak iradokitzen dira"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Jaso erabileran oinarritutako aplikazioen iradokizunak"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Egin gauza gehiago zereginen barrarekin"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Hurrengoa"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Atzera"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Itxi"</string>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index c922f80..0b9e557 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"آموزش نوار وظیفه"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"پانل آموزشی نوار وظیفه نمایان شد"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"پانل آموزشی نوار وظیفه بسته شد"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"برای استفاده هم‌زمان از دو برنامه، آن را به کنار بکشید"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"برای استفاده هم‌زمان از ۲ برنامه، برنامه‌ای را به‌کنار بکشید"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"برای نمایش نوار وظیفه، کمی به بالا بکشید"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"نوار وظیفه برنامه‌ها را براساس روال شما پیشنهاد می‌دهد"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"دریافت «پیشنهادهای برنامه» براساس روال همیشگی"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"انجام کارهای بیشتر با نوار وظیفه"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"بعدی"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"برگشت"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"بستن"</string>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index a07fdea..0ae7fd2 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Tehtäväpalkin ohje"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Tehtäväpalkin ohje näkyvissä"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Tehtäväpalkin ohje suljettu"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Vetämällä sivuun voit käyttää kahta sovellusta samaan aikaan"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Vedä sovellus sivuun, niin voit käyttää samalla 2 sellaista"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Näytä tehtäväpalkki pyyhkäisemällä ylös lyhyesti"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Tehtäväpalkki ehdottaa sovelluksia ohjelmasi perusteella"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Sovellussuosituksia käytön perusteella"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Vinkkejä tehtäväpalkin tehokkaampaan käyttöön"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Seuraava"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Takaisin"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Sulje"</string>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index cf0fef5..1048ac6 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informations sur la barre des tâches"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"La barre des tâches éducatives s\'est affichée"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"La barre des tâches éducatives est fermée"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Faites glisser vers le côté pour utiliser 2 applis à la fois"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Pour utiliser deux applis, faites-les glisser vers le côté"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Faites glisser vers le haut pour afficher la barre de tâches"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"La barre des tâches suggère des applis selon votre routine"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtenez des suggestions d\'applis en fonction de vos routines"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Faites-en plus avec la barre des tâches"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Suivant"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Retour"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Fermer"</string>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index a20fbc4..63d4cf8 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Fonctionnement de la barre des tâches"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Infos sur la barre des tâches affichées"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Infos sur la barre des tâches fermées"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Faites glisser sur le côté pour utiliser 2 applis à la fois"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Faites glisser une appli sur le côté pour utiliser 2 applis"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Balayez rapidement vers haut pour afficher barre des tâches"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"La barre des tâches suggère des applis selon vos habitudes"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtenez des suggestions d\'applis basées sur vos habitudes"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Exploitez les possibilités de la barre des tâches"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Suivant"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Retour"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Fermer"</string>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 528dd0a..e78502b 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Información sobre a función Barra de tarefas"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Panel de información de barra de tarefas aberto"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Panel de información de barra de tarefas pechado"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Para usar 2 aplicacións á vez, arrastra cara ao lado"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arrastra unha aplicación cara a un lado para usar dúas á vez"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Pasa o dedo un pouco cara arriba para ver a barra de tarefas"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Na barra de tarefas suxírense apps segundo a túa rutina"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtén suxestións de aplicacións en función da túa rutina"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Tira máis proveito da barra de tarefas"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Seguinte"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Atrás"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Pechar"</string>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 0ae9b03..f5cdbd0 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ટાસ્કબાર વિશે શિક્ષણ"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"ટાસ્કબારનું શિક્ષણ આપતી પૅનલ દેખાય છે"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"ટાસ્કબારનું શિક્ષણ આપતી પૅનલ બંધ થઈ છે"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"એક જ સમયે 2 ઍપનો ઉપયોગ કરવા માટે, ખેંચીને બાજુ પર લઈ જાઓ"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"એક સાથે 2 ઍપનો ઉપયોગ કરવા માટે, ઍપને ખેંચીને બાજુ પર લઈ જાઓ"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"ટાસ્કબાર બતાવવા માટે ઉપર થોડું સ્વાઇપ કરો"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"ટાસ્કબાર તમારા રૂટિનના આધારે ઍપ સૂચવે છે"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"તમારા રૂટિનના આધારે ઍપના સુઝાવો મેળવો"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"ટાસ્કબાર વડે બીજું ઘણું કરો"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"આગળ"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"પાછળ"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"બંધ કરો"</string>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index c9f3930..937dcc6 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"टास्कबार का ट्यूटोरियल"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"टास्कबार ट्यूटोरियल दिखाया गया"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"टास्कबार ट्यूटोरियल बंद किया गया"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"एक साथ दो ऐप इस्तेमाल करने के लिए, उन्हें किनारे की ओर खींचें और छोड़ें"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"किसी ऐप को किनारे की ओर ड्रैग करके, दो ऐप एक साथ यूज़ करें"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"टास्कबार दिखाने के लिए, ऊपर की ओर थोड़ा स्वाइप करें"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"टास्कबार, डिवाइस के इस्तेमाल के आधार पर ऐप के सुझाव देता है"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"डिवाइस के इस्तेमाल के आधार पर ऐप्लिकेशन के सुझाव पाएं"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"टास्कबार की मदद से अन्य काम करें"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"आगे बढ़ें"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"वापस जाएं"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"बंद करें"</string>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index dd7de8c..e9c6bab 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Upute za traku sa zadacima"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Upute za programsku traku su se pojavile"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Upute za programsku traku su zatvorene"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Povucite u stranu za istovremeno korištenje 2 aplikacije"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Povucite apl. u stranu radi istodobne upotrebe 2 aplikacije"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Kratki pokret prema gore za prikaz trake sa zadacima"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Traka sa zadacima predlaže aplikacije na temelju vaše rutine"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Primajte prijedloge aplikacija na temelju svoje rutine"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Učinite više uz pomoć trake sa zadacima"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Dalje"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Natrag"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zatvori"</string>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 4d01f69..33b781d 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Tálca használatának ismertetése"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Az eszköztár használatát ismertető panel megjelent"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Az eszköztár használatát ismertető panel bezárult"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Húzza oldalra, ha egyszerre két appot szeretne használni"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Húzzon egy appot oldalra, ha kettőt használna egyidejűleg"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Röviden csúsztasson fel a Feladatsáv megjelenítéséhez"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"A Feladatsávban a szokásai alapján javasolt appok láthatók"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Alkalmazásjavaslatokat kaphat a rutinja alapján"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Jobban kihasználhatja a feladatsávot"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Tovább"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Vissza"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Bezárás"</string>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 28f13a9..f6d0c3e 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Խնդրագոտու «Կրթություն» պատուհան"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Խնդրագոտու «Կրթություն» վահանակը բացվեց"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Խնդրագոտու «Կրթություն» վահանակը փակվեց"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Քաշեք մի կողմ՝ միաժամանակ 2 հավելված օգտագործելու համար"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Միաժամանակ օգտագործեք երկու հավելված՝ մեկը մի կողմ քաշելով"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Հավելվածների վահանակը բացելու համար մատն արագ սահեցրեք վերև"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Վահանակն առաջարկում է հավելվածներ ձեր գործողությունների հիման վրա"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Ստացեք առաջարկներ ձեր գործողությունների հիման վրա"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Օգտվեք հավելվածների վահանակի բոլոր հնարավորություններից"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Առաջ"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Հետ"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Փակել"</string>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 6d42c3d..689ade4 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Pengantar Taskbar"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Edukasi taskbar ditampilkan"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Edukasi taskbar ditutup"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Tarik ke samping untuk menggunakan 2 aplikasi sekaligus"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Tarik aplikasi ke samping untuk menggunakan 2 aplikasi sekaligus"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Geser sedikit ke atas untuk menampilkan taskbar"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Taskbar menyarankan aplikasi berdasarkan rutinitas Anda"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Dapatkan saran aplikasi berdasarkan rutinitas Anda"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Lakukan banyak hal dengan taskbar"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Berikutnya"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Kembali"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Tutup"</string>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 1b4ea2b..0a9fa11 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Leiðsögn verkefnastiku"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Leiðsögn verkefnastiku sýnileg"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Leiðsögn verkefnastiku lokað"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Dragðu til hliðar til að nota 2 forrit í einu"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Dragðu forrit til hliðar til að nota 2 forrit í einu"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Stutt stroka upp til að sýna forritastiku"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Forritastikan mælir með forritum byggt á rútínunni þinni"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Fáðu forritatillögur sem byggjast á rútínunni þinni"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Nýttu forritastikuna betur"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Áfram"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Til baka"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Loka"</string>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 9a5cc98..0ab984f 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informazioni sulla barra delle applicazioni"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Riquadro Formazione barra delle applicazioni visualizzato"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Riquadro Formazione barra delle applicazioni chiuso"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Trascina di lato per usare 2 app contemporaneamente"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Trascina un\'app di lato per usare due app contemporaneamente"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Scorri verso l\'alto per mostrare la barra delle applicazioni"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Barra delle applicazioni suggerisce app in base alla routine"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Ottieni app suggerite in base alla tua routine"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Fai di più con la barra delle app"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Avanti"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Indietro"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Chiudi"</string>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 8722476..863707c 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"הסבר על סרגל האפליקציות"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"חלונית ההסברים על שורת המשימות מופיעה"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"חלונית ההסברים על שורת המשימות נסגרה"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"כדי להשתמש בשתי אפליקציות בו-זמנית, צריך לגרור לצד"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"כדי להשתמש בשתי אפליקציות בו-זמנית, צריך לגרור אפליקציה לצד"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"צריך להחליק מעט כדי להציג את סרגל האפליקציות"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"האפליקציות מוצעות בסרגל האפליקציות על סמך השימוש השגרתי שלך"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"קבלת הצעות לאפליקציות על סמך השימוש השגרתי שלך"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"פעולות נוספות שאפשר לעשות עם סרגל האפליקציות"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"הבא"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"חזרה"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"סגירה"</string>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 7bdb5ec..ea3d69b 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"タスクバーの説明"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"タスクバーの説明を開きました"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"タスクバーの説明を閉じました"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"2 個のアプリを同時に使用するには、横にドラッグします"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"アプリを横にドラッグして 2 個のアプリを同時に使用できます"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"タスクバーを表示するには、上に短くスワイプします"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"ルーティンに基づくおすすめのアプリがタスクバーに表示されます"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"毎日の使用状況に基づいてアプリの候補が表示されます"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"タスクバーの各種機能"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"次へ"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"戻る"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"閉じる"</string>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index 7259f04..b1b27df 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ამოცანათა ზოლი: განათლება"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"ამოცანების ზოლის სასწავლო არე გამოჩნდა"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"ამოცანების ზოლის სასწავლო არე დაიხურა"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"გადაათრიეთ კიდეზე 2 აპის ერთდროულად გამოსაყენებლად"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"2 აპის ერთდროულად გამოსაყენებლად გადაათრიეთ აპი კიდეზე"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"მოკლედ გადაფურცლეთ ზემოთ, რომ ამოცანათა ზოლი გამოაჩინოთ"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"ამოცანათა ზოლი გთავაზობთ აპებს თქვენი რუტინის მიხედვით"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"მიიღეთ აპის შეთავაზებები თქვენი რუტინის მიხედვით"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"გააკეთეთ მეტი ამოცანათა ზოლის მეშვეობით"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"შემდეგი"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"უკან"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"დახურვა"</string>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index d0f6a9a..a5a367f 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Тапсырмалар жолағы: үйрену"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Тапсырмалар тақтасы бойынша нұсқаулық ашылды."</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Тапсырмалар тақтасы бойынша нұсқаулық жабылды."</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Екі қолданбаны бір уақытта пайдалану үшін шетке сүйреңіз."</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"2 қолданбаны бір мезгілде пайдалану үшін қолданбаны шетке сүйреңіз."</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Тапсырмалар жолағын көру үшін жоғары қарай тез сырғытыңыз."</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Тапсырмалар жолағындағы ұсыныстар әдеттеріңізге негізделеді."</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Іс-әрекеттеріңізге негізделген қолданба ұсыныстарын алыңыз."</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Тапсырмалар жолағы арқылы көп әрекетті орындаңыз"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Келесі"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Артқа"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Жабу"</string>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index f9a7209..6ee5bd7 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ការអប់រំលើរបារកិច្ចការ"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"ការបង្រៀនអំពីរបារកិច្ចការបានបង្ហាញ"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"ការបង្រៀនអំពីរបារកិច្ចការត្រូវបានបិទ"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"អូស​ទៅចំហៀង ដើម្បីប្រើ​កម្មវិធី 2 ក្នុងពេលតែមួយ"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"អូសកម្មវិធីទៅចំហៀង ដើម្បីប្រើកម្មវិធី 2 ក្នុងពេលតែមួយ"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"អូសឡើងលើបន្តិច ដើម្បីបង្ហាញរបារកិច្ចការ"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"របារកិច្ចការនេះណែនាំកម្មវិធីផ្អែកលើទម្លាប់របស់អ្នក"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ទទួលការណែនាំកម្មវិធីដោយផ្អែកលើទម្លាប់របស់អ្នក"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"ធ្វើបានកាន់តែច្រើនដោយប្រើរបារកិច្ចការ"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"បន្ទាប់"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"ថយក្រោយ"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"បិទ"</string>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index b7c774a..0d7cc2e 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ಟಾಸ್ಕ್‌ಬಾರ್ ಶಿಕ್ಷಣ"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"ಟಾಸ್ಕ್‌ಬಾರ್ ಶಿಕ್ಷಣ ಕಾಣಿಸಿಕೊಂಡಿದೆ"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"ಟಾಸ್ಕ್‌ಬಾರ್ ಶಿಕ್ಷಣ ಮುಚ್ಚಿದೆ"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"ಏಕಕಾಲದಲ್ಲಿ 2 ಆ್ಯಪ್‌ಗಳನ್ನು ಬಳಸಲು ಬದಿಗೆ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ಒಂದೇ ಬಾರಿಗೆ 2 ಆ್ಯಪ್‌ಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್ ಅನ್ನು ಬದಿಗೆ ಎಳೆಯಿರಿ"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"ಟಾಸ್ಕ್‌ಬಾರ್ ಅನ್ನು ತೋರಿಸಲು ಚಿಕ್ಕದಾಗಿ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"ಟಾಸ್ಕ್‌ಬಾರ್ ನಿಮ್ಮ ದಿನಚರಿ ಆಧರಿಸಿ ಆ್ಯಪ್‌ಗಳನ್ನು ಸೂಚಿಸುತ್ತದೆ"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ನಿಮ್ಮ ದಿನಚರಿಯ ಆಧಾರದ ಮೇಲೆ ಆ್ಯಪ್ ಸಲಹೆಗಳನ್ನು ಪಡೆಯಿರಿ"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"ಟಾಸ್ಕ್‌ಬಾರ್ ಮೂಲಕ ಹೆಚ್ಚಿನದನ್ನು ಮಾಡಿ"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"ಮುಂದೆ"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"ಹಿಂದೆ"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ಮುಚ್ಚಿರಿ"</string>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index 99309d2..2557e04 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"태스크 바 정보"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"작업 표시줄 튜토리얼 패널 표시됨"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"작업 표시줄 튜토리얼 패널 닫힘"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"옆으로 드래그하여 2개의 앱을 동시에 사용합니다."</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"앱을 옆으로 드래그하여 앱 2개를 동시에 사용합니다."</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"위로 짧게 스와이프하여 태스크 바를 표시합니다."</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"태스크 바에서 루틴에 따라 앱을 제안합니다."</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"루틴에 따라 앱 제안을 받습니다."</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"태스크 바로 더 많은 작업 하기"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"다음"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"뒤로"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"닫기"</string>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 55e5a11..f6177f9 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -22,7 +22,7 @@
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Кадап коюу"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Эркин форма режими"</string>
     <string name="recents_empty_message" msgid="7040467240571714191">"Акыркы колдонмолор жок"</string>
-    <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Колдонмону пайдалануу жөндөөлөрү"</string>
+    <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Колдонмону пайдалануу параметрлери"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Баарын тазалоо"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Акыркы колдонмолор"</string>
     <string name="task_view_closed" msgid="9170038230110856166">"Тапшырма жабылды"</string>
@@ -37,7 +37,7 @@
     <string name="hotseat_edu_message_migrate_landscape" msgid="4248943380443387697">"Көп иштетилген колдонмолорго Башкы экрандан оңой кириңиз. Сунуштар тартиптин негизинде өзгөрөт. Тандалмалардын катарындагы колдонмолор башкы экраныңызга жылдырылат."</string>
     <string name="hotseat_edu_accept" msgid="1611544083278999837">"Сунушталган колдонолорду алуу"</string>
     <string name="hotseat_edu_dismiss" msgid="2781161822780201689">"Жок, рахмат"</string>
-    <string name="hotseat_prediction_settings" msgid="6246554993566070818">"Жөндөөлөр"</string>
+    <string name="hotseat_prediction_settings" msgid="6246554993566070818">"Параметрлер"</string>
     <string name="hotseat_auto_enrolled" msgid="522100018967146807">"Көп иштетилген колдонмолор ушул жерде көрүнүп, тартиптин негизинде өзгөрөт"</string>
     <string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Сунуштарды алып туруу үчүн ылдый жактагы тилкедеги колдонмолорду сүйрөп келиңиз"</string>
     <string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"Сунушталган колдонмолор бош жерге кошулат"</string>
@@ -71,7 +71,7 @@
     <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Бир колдонмодон экинчисине өтүү үчүн экранды 2 манжа менен ылдыйдан өйдө сүрүп, коё бербей туруңуз."</string>
     <string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Дапдаяр!"</string>
     <string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Бүттү"</string>
-    <string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Жөндөөлөр"</string>
+    <string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Параметрлер"</string>
     <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Кайталап көрүңүз"</string>
     <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>
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Тапшырмалар панели жөнүндө маалымат"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Тапшырмалар тактасынын окутуу панели көрсөтүлдү"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Тапшырмалар тактасынын окутуу панели жабылды"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"2 колдонмону бир убакта пайдалануу үчүн капталга сүйрөңүз"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"2 колдонмону бир убакта пайдалануу үчүн капталга сүйрөңүз"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Тапшырмалар тактасын көрүү үчүн экранды өйдө серпиңиз"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Тапшырмалар тактасы колдонмолорду аракеттериңизге жараша сунуштайт"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Программаңыздын негизинде сунушталган колдонмолорду алуу"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Тапшырмалар панели менен көбүрөөк нерселерди аткарыңыз"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Кийинки"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Артка"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Жабуу"</string>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index 4be7c8c..7115617 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ແຖບໜ້າວຽກ Education"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"ສະແດງການສຶກສາແຖບໜ້າວຽກແລ້ວ"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"ປິດການສຶກສາແຖບໜ້າວຽກແລ້ວ"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"ລາກໄປທາງຂ້າງເພື່ອໃຊ້ 2 ແອັບພ້ອມກັນ"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ລາກແອັບໄປດ້ານຂ້າງເພື່ອໃຊ້ 2 ແອັບໃນເວລາດຽວກັນ"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"ປັດຂຶ້ນສັ້ນໆເພື່ອສະແດງແຖບໜ້າວຽກ"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"ແຖບໜ້າວຽກຈະແນະນຳແອັບໂດຍອີງຕາມສິ່ງທີ່ເຮັດປະຈຳຂອງທ່ານ"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ຮັບການແນະນຳແອັບໂດຍອີງໃສ່ສິ່ງທີ່ເຮັດປະຈຳຂອງທ່ານ"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"ເຮັດໄດ້ຫຼາຍຂຶ້ນດ້ວຍແຖບໜ້າວຽກ"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"ຕໍ່ໄປ"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"ກັບຄືນ"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ປິດ"</string>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 56a5d08..b94edb2 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Užduočių juostos mokomoji informacija"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Užduočių juostos patarimai rodomi"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Užduočių juostos patarimai uždaryti"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Nuvilkite į šoną, kad vienu metu naudotumėte dvi programas"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Nuvilkę programą į šoną vienu metu naudokite dvi programas"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Trumpai perbraukite, kad būtų rodoma užduočių juosta"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Užduočių juostoje siūlomos programos pagal jūsų veiklą"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Gaukite programų pasiūlymų pagal savo veiklą"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Atlikite daugiau naudodami užduočių juostą"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Kitas"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Atgal"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Uždaryti"</string>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index da911c1..7f6ba09 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informācija par uzdevumu joslu"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Tika atvērta uzdevumjoslas apmācība"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Tika aizvērta uzdevumjoslas apmācība"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Velciet uz malu, lai izmantotu divas lietotnes vienlaikus"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Velciet lietotni sānis, lai izmantotu 2 lietotnes vienlaikus"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Īsi velciet augšup, lai skatītu uzdevumu joslu"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Uzdevumu joslā tiek rādītas lietotnes, ņemot vērā lietojumu"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Skatiet ieteiktās lietotnes, balstoties uz jūsu ieradumiem"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Plašākas iespējas, izmantojot uzdevumu joslu"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Tālāk"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Atpakaļ"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Aizvērt"</string>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index 9deb0dc..85490c0 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Обука за лентата со задачи"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Се појави лентата за задачи за образование"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Затворена е лентата за задачи за образование"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Повлечете кон страната за да користите две апликации одеднаш"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Повлечете апликација настрана за да користите 2 апликации"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Кратко повлечете нагоре за да се прикаже лентата со задачи"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Лентата со задачи предложува апликации според вашата рутина"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Добивајте предлози за апликации според вашата рутина"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Правете повеќе со една лента со задачи"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Следно"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Назад"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Затвори"</string>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index bca7e35..3d6648b 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ടാസ്‌ക്ബാർ മാർഗ്ഗനിർദ്ദേശ വിൻഡോ"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"ടാസ്ക്ക്ബാർ വിവര പാനൽ ദൃശ്യമായി"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"ടാസ്ക്ക്ബാർ വിവര പാനൽ അടച്ചു"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"ഒരേ സമയം 2 ആപ്പുകൾ ഉപയോഗിക്കാൻ വശത്തേയ്‌ക്ക് വലിച്ചിടുക"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ഒരേ സമയം 2 ആപ്പുകൾ ഉപയോഗിക്കാൻ ഒരു ആപ്പ് വശത്തേക്ക് വലിച്ചിടൂ"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"ടാസ്‌ക്ബാർ ദൃശ്യമാക്കാൻ മുകളിലേക്ക് ചെറുതായി സ്വൈപ്പ് ചെയ്യൂ"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"ടാസ്‌ക്ബാർ നിങ്ങളുടെ ദിനചര്യ അനുസരിച്ച് ആപ്പുകൾ നിർദ്ദേശിക്കുന്നു"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"നിങ്ങളുടെ ദിനചര്യ അനുസരിച്ച് ആപ്പ് നിർദ്ദേശങ്ങൾ നേടുക"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"ടാസ്‌ക്‌ബാർ ഉപയോഗിച്ച് കൂടുതൽ ചെയ്യുക"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"അടുത്തത്"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"മടങ്ങുക"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"അടയ്ക്കുക"</string>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 9ad53c2..4cd07f9 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Ажлын хэсгийн боловсрол"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Боловсролын ажлын талбар гарч ирсэн"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Боловсролын ажлын талбарыг хаасан"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"2 аппыг зэрэг ашиглахын тулд хажуу тийш чирнэ үү"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"2 аппыг зэрэг ашиглахын тулд аппыг хажуу тийш чирнэ үү"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Ажлын хэсгийг харуулахын тулд бага зэрэг дээш шударна уу"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Ажлын хэсэг таны хэвшилд тулгуурлан аппууд санал болгодог"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Таны хэвшилд тулгуурлан санал болгож буй аппуудыг аваарай"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Ажлын хэсгээр илүү ихийг хийгээрэй"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Дараах"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Буцах"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Хаах"</string>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index ab97cc9..fd79f03 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"टास्कबारशी संबंधित माहिती"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"टास्कबारशी संबंधित माहिती देणारे पॅनल उघडले आहे"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"टास्कबारशी संबंधित माहिती देणारे पॅनल बंद केले आहे"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"दोन ॲप्स एकत्र वापरण्यासाठी, ती बाजूला ड्रॅग करा"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"दोन ॲप्स एकत्र वापरण्यासाठी एक अ‍ॅप बाजूला ड्रॅग करा"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"टास्कबार दाखवण्यासाठी थोडे वरती स्वाइप करा"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"टास्कबार हे तुमच्या दिनक्रमानुसार अ‍ॅप्स सुचवते"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"तुमच्या दिनक्रमावर आधारित ॲप सूचना मिळवा"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"टास्कबारसह आणखी बरेच काही करा"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"पुढे"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"मागे जा"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"बंद करा"</string>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index b7e82d0..7eda4d3 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Pendidikan bar tugas"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Pendidikan bar tugas muncul"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Pendidikan bar tugas ditutup"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Seret ke tepi untuk menggunakan 2 apl serentak"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Seret apl ke tepi untuk menggunakan 2 apl serentak"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Leret pendek ke atas untuk menunjukkan bar tugas"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Bar tugas mencadangkan apl berdasarkan rutin anda"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Dapatkan cadangan apl berdasarkan rutin anda"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Lakukan lebih banyak perkara dengan bar tugas"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Seterusnya"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Kembali"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Tutup"</string>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index a5100f1..0a3dd86 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"လုပ်ဆောင်စရာဘား ပညာပေး"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"ပညာရေး လုပ်ဆောင်စရာဘား ပြထားသည်"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"ပညာရေး လုပ်ဆောင်စရာဘား ပိတ်ထားသည်"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"အက်ပ် ၂ ခု တစ်ပြိုင်တည်းသုံးရန် ဘေးဖက်သို့ ဖိဆွဲပါ"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"အက်ပ် ၂ ခုကို တစ်ပြိုက်တည်းသုံးရန် အက်ပ်ကို ဘေးသို့ ဖိဆွဲပါ"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"လုပ်ဆောင်စရာဘားပြရန် အမြန် အပေါ်ပွတ်ဆွဲပါ"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"ပုံမှန်အစီအစဉ်ပေါ် အခြေခံ၍ လုပ်ဆောင်စရာဘားက အက်ပ်အကြံပြုသည်"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ပုံမှန်အစီအစဉ်ပေါ် အခြေခံ၍ အက်ပ်အကြံပြုချက်များကို ရယူပါ"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"လုပ်ဆောင်စရာဘားဖြင့် ပိုမိုလုပ်ဆောင်နိုင်ခြင်း"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"ရှေ့သို့"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"နောက်သို့"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ပိတ်ရန်"</string>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index ce7634b..bb592b2 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Veiledning for oppgavelinjen"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Opplæringen for oppgavelinjen vises"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Opplæringen for oppgavelinjen er lukket"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Dra til siden for å bruke to apper samtidig"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Dra en app til siden for å bruke 2 apper samtidig"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Kort sveip opp for å vise oppgavelinjen"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Oppgavelinjen foreslår apper basert på rutinene dine"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Få appforslag som er basert på rutinene dine"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Gjør mer med oppgavelinjen"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Neste"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Tilbake"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Lukk"</string>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index b984de8..ac782e8 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"टास्कबार एजुकेसन"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"टास्कबार एजुकेसन देखिएको छ"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"टास्कबार एजुकेसन बन्द गरिएको छ"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"टास्कबार छेउतिर ड्र्याग गरेर एकै पटक २ वटा एप चलाउनुहोस्"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"एपलाई छेउतिर ड्र्याग गरेर एकै पटक २ वटा एप चलाउनुहोस्"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"टास्कबार देखाउन माथितिर थोरै स्वाइप गर्नुहोस्"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"टास्कबारले तपाईंको रुटिनका आधारमा एपसम्बन्धी सुझाव देखाउँछ"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"आफ्नो रुटिनका आधारमा एपसम्बन्धी सुझावहरू प्राप्त गर्नुहोस्"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"टास्कबार प्रयोग गरेर अझ धेरै कार्य गर्नुहोस्"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"अर्को"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"पछाडि"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"बन्द गर्नुहोस्"</string>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index ad207c0..952b7f1 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taakbalk Onderwijs"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Uitleg van taakbalk geopend"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Uitleg van taakbalk gesloten"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Sleep naar de zijkant om 2 apps tegelijk te gebruiken"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Sleep een app naar de zijkant om 2 apps tegelijk te gebruiken"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Swipe kort omhoog om de taakbalk te bekijken"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"De taakbalk stelt apps voor op basis van je routine"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Krijg app-suggesties op basis van je routine"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Doe meer met de taakbalk"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Volgende"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Terug"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Sluiten"</string>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 2f0614c..9102860 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ଟାସ୍କବାର ଶିକ୍ଷା"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"ଟାସ୍କବାର୍ ଶିକ୍ଷା ଦେଖାଯାଇଛି"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"ଟାସ୍କବାର୍ ଶିକ୍ଷା ବନ୍ଦ ହୋଇଯାଇଛି"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"ଥରକେ 2ଟି ଆପ୍ସ ବ୍ୟବହାର କରିବା ପାଇଁ ପାର୍ଶ୍ୱକୁ ଡ୍ରାଗ କରନ୍ତୁ"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ଥରକେ 2ଟି ଆପ୍ସ ବ୍ୟବହାର କରିବା ପାଇଁ ଏକ ଆପକୁ ପାର୍ଶ୍ୱକୁ ଡ୍ରାଗ କର"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"ଟାସ୍କବାର ଦେଖାଇବା ପାଇଁ ଉପରକୁ ଅଳ୍ପ ସମୟ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"ଟାସ୍କବାର ଆପଣଙ୍କ ରୁଟିନ ଆଧାରରେ ଆପ୍ସ ପରାମର୍ଶ ଦିଏ"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ଆପଣଙ୍କ ରୁଟିନ ଆଧାରରେ ଆପ ପରାମର୍ଶଗୁଡ଼ିକୁ ପାଆନ୍ତୁ"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"ଟାସ୍କବାର ମାଧ୍ୟମରେ ଆହୁରି ଅନେକ କିଛି କରନ୍ତୁ"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"ପରବର୍ତ୍ତୀ"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"ପଛକୁ ଫେରନ୍ତୁ"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ବନ୍ଦ କରନ୍ତୁ"</string>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index dc9d78e..8ca7173 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ਟਾਸਕਬਾਰ ਸਿੱਖਿਆ"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"ਟਾਸਕਵਾਰ ਸਿੱਖਿਆ ਪੈਨਲ ਦਿਖਾਇਆ ਗਿਆ"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"ਟਾਸਕਵਾਰ ਸਿੱਖਿਆ ਪੈਨਲ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"ਇੱਕ ਵਾਰ ਵਿੱਚ 2 ਐਪਾਂ ਵਰਤਣ ਲਈ ਉਨ੍ਹਾਂ ਨੂੰ ਸਾਈਡ ਵੱਲ ਘਸੀਟੋ"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ਇੱਕ ਵਾਰ ਵਿੱਚ 2 ਐਪਾਂ ਵਰਤਣ ਲਈ, ਐਪ ਨੂੰ ਪਾਸੇ ਵੱਲ ਘਸੀਟੋ"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"ਟਾਸਕਬਾਰ ਦਿਖਾਉਣ ਲਈ ਥੋੜ੍ਹਾ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"ਟਾਸਕਬਾਰ ਤੁਹਾਡੇ ਨਿਯਮਬੱਧ ਕੰਮ ਮੁਤਾਬਕ ਐਪਾਂ ਦਾ ਸੁਝਾਅ ਦਿੰਦਾ ਹੈ"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ਤੁਹਾਡੇ ਨਿਯਮਬੱਧ ਕੰਮ ਦੇ ਆਧਾਰ \'ਤੇ ਐਪ ਸੁਝਾਅ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"ਟਾਸਕਬਾਰ ਦਾ ਹੋਰ ਲਾਹਾ ਲਓ"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"ਅੱਗੇ"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"ਪਿੱਛੇ"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ਬੰਦ ਕਰੋ"</string>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 08fc4e2..c67078f 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informacje o pasku aplikacji"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Wskazówki na temat paska zadań zostały wyświetlone"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Wskazówki na temat paska zadań zostały zamknięte"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Przeciągnij w bok, aby używać 2 aplikacji jednocześnie"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Przeciągnij aplikację w bok, aby używać 2 aplikacji naraz"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Przesuń palcem krótko w górę, aby wyświetlić pasek aplikacji"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Aplikacje na pasku są dobierane na podstawie Twojej rutyny"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Otrzymuj sugestie aplikacji na podstawie rutyny"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Wykorzystaj potencjał paska aplikacji"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Dalej"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Wstecz"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zamknij"</string>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index b663528..b9bee0c 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Educação da Barra de tarefas"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Informação da barra de tarefas apresentada"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Informação da barra de tarefas fechada"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Arraste para o lado para usar duas apps em simultâneo"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arraste uma app para o lado para usar 2 apps em simultâneo"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Deslize rápido curto para cima para ver a barra de tarefas"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"A barra de tarefas sugere apps baseadas na sua rotina"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtenha sugestões de apps baseadas na sua rotina"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Faça mais com a Barra de tarefas"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Seguinte"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Anterior"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Fechar"</string>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index fbd5b78..77d2079 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informações sobre a barra de tarefas"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"As dicas sobre a barra de tarefas foram abertas"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"As dicas sobre a barra de tarefas foram fechadas"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Arraste para o lado para usar dois apps ao mesmo tempo"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arraste um app para o lado e use dois apps ao mesmo tempo"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Deslize para cima para mostrar a barra de tarefas"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"A barra de tarefas sugere apps com base na sua rotina"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Receba sugestões de apps com base na sua rotina"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Aproveite ainda mais a barra de tarefas"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Próxima"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Voltar"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Fechar"</string>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index a324d4a..375d431 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informații despre bara de activități"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Panoul cu informații despre bara de activități s-a afișat"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Panoul cu informații despre bara de activități s-a închis"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Trage în lateral ca să folosești două aplicații deodată"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Trage în lateral o aplicație ca să folosești 2 aplicații deodată"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Glisează scurt în sus pentru a afișa bara de activități"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Bara de activități sugerează aplicații în funcție de rutina ta"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Primește sugestii de aplicații în funcție de rutina ta"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Fă mai multe din bara de activități"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Înainte"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Înapoi"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Închide"</string>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index d1c2e8d..f9f38c1 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Обучение по работе с панелью задач"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Обучение по работе с панелью задач показано"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Обучение по работе с панелью задач скрыто"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Перетащите в сторону, чтобы использовать 2 приложения сразу."</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Используйте два приложения сразу, перетащив одно в сторону."</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Чтобы открыть панель задач, быстро проведите снизу вверх."</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Панель задач предлагает приложения, учитывая ваши действия."</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Получайте рекомендации, основанные на ваших действиях."</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Используйте все возможности панели задач"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Далее"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Назад"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Закрыть"</string>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index e2f0944..eb55925 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"කාර්ය තීරු අධ්‍යාපනය"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"කාර්ය තීරු අධ්‍යාපනය දිස් විය"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"කාර්ය තීරු අධ්‍යාපනය වසා ඇත"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"එකවර යෙදුම් 2 ක් භාවිත කිරීමට පැත්තට අදින්න"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"එකවර යෙදුම් 2ක් භාවිතා කිරීමට යෙදුමක් පැත්තට අදින්න"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"කාර්ය තීරුව පෙන්වීමට ඉහළට කෙටි ස්වයිප් කරන්න"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"කාර්ය තීරුව ඔබේ දිනචරියාව මත පදනම්ව යෙදුම් යෝජනා කරයි"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ඔබේ දිනචරියාව මත පදනම්ව යෙදුම් යෝජනා ලබා ගන්න"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"කාර්ය තීරුව සමග තවත් කරන්න"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"ඊළඟ"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"ආපසු"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"වසන්න"</string>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index 573c17b..13b175c 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Panel vzdelávacích aplikácií"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Zobrazila sa výuka k hlavnému panelu"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Výuka k hlavnému panelu bola zatvorená"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Po presunutí na stranu je možné používať dve aplikácie naraz"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Ak chcete použ. dve aplikácie naraz, presuňte aplik. nabok"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Krátkym potiahnutím nahor zobrazíte panel aplikácií"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Panel aplikácií navrhuje aplikácie na základe vašich zvykov"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Získavajte návrhy aplikácií na základe svojich zvykov"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Panel aplikácií vám ponúka ďalšie možnosti"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Ďalej"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Späť"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zavrieť"</string>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 491b13d..0d948cc 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Poučni nasveti o opravilni vrstici"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Poučni nasveti o opravilni vrstici so prikazani."</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Poučni nasveti o opravilni vrstici so zaprti."</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Povlecite vstran za uporabo dveh aplikacij hkrati."</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Povlecite aplikacijo vstran za uporabo 2 aplikacij hkrati."</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Na kratko povlecite navzgor za prikaz opravilne vrstice."</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Opravilna vrstica predlaga aplikacije na podlagi vaših navad."</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Prejemajte predloge aplikacij na podlagi svojih navad."</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Naredite več z opravilno vrstico"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Naprej"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Nazaj"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zapri"</string>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index d73aa48..0e600dd 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Edukimi për shiritin e detyrave"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Edukimi i shiritit të detyrave u shfaq"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Edukimi nga shiriti i detyrave u mbyll"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Zvarrit në anë për të përdorur 2 aplikacione njëherësh"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Zvarrit një aplikacion në anë për të përdorur 2 aplikacione njëherësh"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Kryej një rrëshqitje të shkurtër lart për të shfaqur shiritin e detyrave"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Shiriti i detyrave sugjeron aplikacione bazuar në rutinën tënde"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Merr sugjerime për aplikacion bazuar në rutinën tënde"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Bëj më shumë me shiritin e detyrave"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Para"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Pas"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Mbyll"</string>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index 6e819ab..5c43c01 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Упутства на траци задатака"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Едукативно окно из траке задатака се појавило"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Едукативно окно из траке задатака је затворено"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Превуците на страну да бисте користили 2 апликације одједном"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Превуците на страну да бисте користили 2 апликације одједном"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Накратко превуците нагоре да бисте приказали траку задатака"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Трака задатака предлаже апликације на основу рутине"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Добијајте предлоге апликација на основу рутине"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Урадите више помоћу траке задатака"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Даље"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Назад"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Затвори"</string>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index bab1952..51cbc9c 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Aktivitetsfältsutbildning"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Information om aktivitetsfältet visades"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Information om aktivitetsfältet stängdes"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Dra till sidan om du vill använda två appar samtidigt"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Dra en app till sidan om du vill använda två appar samtidigt"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Svep en kort bit uppåt för att visa aktivitetsfältet"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"I aktivitetsfältet visas förslag på appar utifrån din rutin"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Få appförslag utifrån dina rutiner"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Gör mer med aktivitetsfältet"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Nästa"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Tillbaka"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Stäng"</string>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index f0990b3..e61f4a9 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Elimu ya Upauzana"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Paneli ya elimu kwenye upau wa shughuli inaonyeshwa"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Paneli ya elimu kwenye upau wa shughuli imefungwa"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Buruta pembeni ili utumie programu 2 kwa wakati mmoja"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Buruta programu pembeni ili utumie programu 2 kwa wakati mmoja"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Telezesha kidole juu ili uonyeshe upauzana"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Upauzana hupendekeza programu kulingana na ratiba yako"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Pata mapendekezo ya programu kulingana na ratiba yako"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Kamilisha mengi kwa kutumia upauzana huu"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Endelea"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Nyuma"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Funga"</string>
diff --git a/quickstep/res/values-sw600dp-land/dimens.xml b/quickstep/res/values-sw600dp-land/dimens.xml
index dc10c24..4ee388a 100644
--- a/quickstep/res/values-sw600dp-land/dimens.xml
+++ b/quickstep/res/values-sw600dp-land/dimens.xml
@@ -15,9 +15,6 @@
 */
 -->
 <resources>
-    <!--  Overview actions  -->
-    <dimen name="overview_actions_top_margin">12dp</dimen>
-
     <!-- All Set page -->
     <dimen name="allset_page_margin_horizontal">48dp</dimen>
 
diff --git a/quickstep/res/values-sw600dp/dimens.xml b/quickstep/res/values-sw600dp/dimens.xml
index 5899814..daf1f63 100644
--- a/quickstep/res/values-sw600dp/dimens.xml
+++ b/quickstep/res/values-sw600dp/dimens.xml
@@ -33,6 +33,8 @@
     <dimen name="overview_page_spacing">36dp</dimen>
     <!--  The space to the left and to the right of the "Clear all" button  -->
     <dimen name="overview_grid_side_margin">64dp</dimen>
+    <!--  Overview actions  -->
+    <dimen name="overview_actions_top_margin">24dp</dimen>
 
     <!-- All Set page -->
     <dimen name="allset_page_margin_horizontal">120dp</dimen>
diff --git a/quickstep/res/values-sw720dp-land/dimens.xml b/quickstep/res/values-sw720dp-land/dimens.xml
deleted file mode 100644
index 02d1189..0000000
--- a/quickstep/res/values-sw720dp-land/dimens.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- * 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.
-*/
--->
-<resources>
-    <!--  Overview actions  -->
-    <dimen name="overview_actions_top_margin">20dp</dimen>
-</resources>
diff --git a/quickstep/res/values-sw720dp/dimens.xml b/quickstep/res/values-sw720dp/dimens.xml
index 28f7c5d..d27561a 100644
--- a/quickstep/res/values-sw720dp/dimens.xml
+++ b/quickstep/res/values-sw720dp/dimens.xml
@@ -40,4 +40,5 @@
 
     <!-- Transient taskbar -->
     <dimen name="transient_taskbar_size">76dp</dimen>
+    <dimen name="transient_taskbar_icon_size">52dp</dimen>
 </resources>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index 1db0fab..51aaed1 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"செயல் பட்டியைப் பயன்படுத்தும் விதம்"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"பணிப்பட்டியை எவ்வாறு பயன்படுத்துவது என்பது பற்றிய பலகம் காட்டப்படுகிறது"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"பணிப்பட்டியை எவ்வாறு பயன்படுத்துவது என்பது பற்றிய பலகம் மூடப்பட்டது"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"ஒரே நேரத்தில் 2 ஆப்ஸை உபயோகிக்க பக்கவாட்டிற்கு இழுக்கவும்"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ஒரே நேரத்தில் 2 ஆப்ஸைப் பயன்படுத்தப் பக்கவாட்டில் இழுக்கவும்"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"செயல் பட்டியைக் காட்டுவதற்கு மேலே சிறிது ஸ்வைப் செய்யவும்"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"உங்கள் வழக்கத்திற்கேற்ப ஆப்ஸை செயல் பட்டி பரிந்துரைக்கும்"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"உங்கள் வழக்கத்திற்கேற்ப ஆப்ஸ் பரிந்துரைகளைப் பெறுவீர்கள்"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"செயல் பட்டி மூலம் மேலும் பலவற்றைச் செய்யலாம்"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"அடுத்து"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"பின்செல்"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"மூடுக"</string>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index c5564dd..e68fbec 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"టాస్క్‌బార్ ఎడ్యుకేషన్"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"టాస్క్‌బార్ శిక్షణకు సంబంధించిన ప్యానెల్ కనిపించింది"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"టాస్క్‌బార్ శిక్షణకు సంబంధించిన ప్యానెల్ మూసివేయబడింది"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"ఒకేసారి 2 యాప్‌లను ఉపయోగించడానికి పక్కకు లాగండి"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ఒకేసారి 2 యాప్‌లను ఉపయోగించడానికి యాప్‌ను పక్కకు లాగండి"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"టాస్క్‌బార్‌ను చూపడానికి చిన్నగా పైకి స్వైప్ చేయండి"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"మీ రొటీన్ ఆధారంగా టాస్క్‌బార్ యాప్‌లను సూచిస్తుంది"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"మీ రొటీన్ ఆధారంగా యాప్ సూచనలను పొందండి"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"టాస్క్‌బార్‌తో మరిన్ని చేయండి"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"తర్వాత"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"వెనుకకు"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"మూసివేయండి"</string>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 7c7f44d..2fa2a34 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"แถบงาน Education"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"แถบงาน Education ปรากฎขึ้น"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"ปิดแถบงาน Education แล้ว"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"ลากไปด้านข้างเพื่อใช้ 2 แอปพร้อมกัน"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ลากแอปไปด้านข้างเพื่อใช้ 2 แอปพร้อมกัน"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"ปัดขึ้นสั้นๆ เพื่อแสดงแถบงาน"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"แถบงานจะแนะนำแอปโดยอิงตามกิจวัตรของคุณ"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"รับคำแนะนำเกี่ยวกับแอปตามกิจวัตรของคุณ"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"ทำสิ่งต่างๆ ได้มากขึ้นด้วยแถบงาน"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"ถัดไป"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"กลับ"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ปิด"</string>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index 7dcae6b..4c2d5ec 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Impormasyon sa taskbar"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Lumabas ang edukasyon sa taskbar"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Sarado ang edukasyon sa taskbar"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"I-drag sa gilid para makagamit ng 2 app nang sabay"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Mag-drag ng app sa gilid para makagamit ng 2 app nang sabay"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Mag-swipe nang bahagya pataas para ipakita ang taskbar"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Nagmumungkahi ang taskbar ng mga app batay sa iyong routine"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Makakuha ng mga iminumungkahing app batay sa iyong routine"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Gumawa ng higit pa sa taskbar"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Susunod"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Bumalik"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Isara"</string>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index ea3fb5e..d79d8f0 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Görev çubuğu eğitimi"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Görev çubuğu eğitimi görüntülendi"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Görev çubuğu eğitimi kapatıldı"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Tek seferde iki uygulamayı kullanmak için yana sürükleyin"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Aynı anda iki uygulama kullanmak için birini yana sürükleyin"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Görev çubuğunu göstermek için yukarı doğru kısa kaydırın"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Görev çubuğu, rutininize dayalı olarak uygulamalar önerir"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Rutininize göre uygulama önerileri alın"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Görev çubuğuyla daha fazla şey yapın"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"İleri"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Geri"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Kapat"</string>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index b426c8b..2f9a424 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Панель завдань Education"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Панель завдань Education відкрито"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Панель завдань Education закрито"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Перетягніть убік, щоб використовувати 2 додатки одночасно"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Перетягніть убік, щоб використовувати 2 додатки одночасно"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Швидко проведіть пальцем угору, щоб відкрити панель завдань"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Панель завдань пропонує додатки на основі вашої програми"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Отримуйте рекомендації додатків залежно від їх використання"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Більше можливостей завдяки панелі завдань"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Далі"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Назад"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Закрити"</string>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 576386a..4ddcb3b 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ٹاسک بار کی تعلیم"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"ٹاکس بار کا تعلیمی پینل ظاہر ہو گیا"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"ٹاسک بار کا تعلیمی پینل بند ہو گیا"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"ایک وقت میں 2 ایپس استعمال کرنے کے لیے سائیڈ پر گھسیٹیں"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ایک وقت میں 2 ایپس استعمال کرنے کیلئے ایپ سائیڈ پر گھسیٹیں"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"ٹاسک بار دکھانے کے لیے تھوڑا اوپر سوائپ کریں"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"ٹاسک بار آپ کی روٹین کی بنیاد پر ایپس تجویز کرتا ہے"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"اپنی روٹین پر مبنی ایپس کی تجاویز حاصل کریں"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"ٹاسک بار سے بہت کچھ کریں"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"آگے"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"پیچھے"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"بند کریں"</string>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 65197a4..f188000 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Vazifalar paneli qoʻllanmasi"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Taʼlim vazifalar paneli chiqdi"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Taʼlim vazifalar paneli yopildi"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Bir vaqtda 2 ta ilova ochish uchun birini yoniga torting"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Bitta ilovani yon tomonga sudrab, bir vaqtda 2 ta ilovadan foydalaning."</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Vazifalar panelini koʻrsatish uchun tepaga qisqa suring"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Vazifalar paneli harakatlaringiz asosida ilova taklif qiladi"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Harakatlaringiz asosida tavsiyalar oling."</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Vazifalar panelidan maksimal darajada foydalaning"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Keyingisi"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Orqaga"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Yopish"</string>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index b0a6dab..cfba7ba 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Cách sử dụng thanh tác vụ"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Đã hiện bảng hướng dẫn trên thanh tác vụ"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Đã đóng bảng hướng dẫn trên thanh tác vụ"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Kéo sang bên để dùng 2 ứng dụng cùng một lúc"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Kéo một ứng dụng sang bên để dùng 2 ứng dụng cùng lúc"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Vuốt lên một chút để hiển thị thanh tác vụ"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"Thanh tác vụ đề xuất các ứng dụng dựa trên thói quen của bạn"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Nhận ứng dụng đề xuất dựa trên quy trình của bạn"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Làm nhiều việc hơn bằng thanh tác vụ"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Tiếp theo"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Quay lại"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Đóng"</string>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index 6b8f3e3..05cf3f4 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"任务栏教程"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"任务栏教程已显示"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"任务栏教程已关闭"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"拖动到一侧,即可一次使用两个应用"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"将一个应用拖动到一侧,即可一次使用两个应用"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"稍微向上滑动即可显示任务栏"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"任务栏会根据您的日常安排向您推荐应用"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"根据您的日常安排获取应用建议"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"体验任务栏的更多功能"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"继续"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"返回"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"关闭"</string>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index 5a9e0a1..cefea7a 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"工作列教學"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"顯示咗工作列教學"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"閂咗工作列教學"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"拖曳到一邊即可同時使用 2 個應用程式"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"將應用程式拖曳到一邊,即可同時使用 2 個應用程式"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"輕輕向上滑動即可顯示工作列"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"工作列會根據您的日常安排提供應用程式建議"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"根據您的日常安排提供應用程式建議"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"工作列助您事半功倍"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"繼續"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"返回"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"關閉"</string>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index 30ea100..1cf77e8 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"工作列教學課程"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"工作列教學課程已顯示"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"工作列教學課程已關閉"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"拖曳到一邊即可同時使用 2 個應用程式"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"將應用程式拖曳到一邊即可同時使用 2 個應用程式"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"稍微向上滑動即可讓工作列顯示在畫面上"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"工作列會根據你的日常習慣提供應用程式建議"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"根據你的日常安排建議應用程式"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"充分發揮工作列的功用"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"繼續"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"返回"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"關閉"</string>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index 0a7e418..a27f78e 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -95,9 +95,10 @@
     <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Imfundo ye-taskbar"</string>
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"Imfuno yebha yomsebenzi ivelile"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"Imfundo yebha yomsebenzi ivaliwe"</string>
-    <string name="taskbar_edu_splitscreen" msgid="5563823414110661454">"Hudula ngaseceleni ukuze usebenzise ama-app angu-2 ngesikhathi esisodwa"</string>
+    <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Hudula i-app ukusebenzisa ama-app ama-2 ngesikhathi esisodwa"</string>
     <string name="taskbar_edu_stashing" msgid="2805035263048176462">"Swayiphela phezulu okufushane ukuze ubonise i-taskbar"</string>
-    <string name="taskbar_edu_suggestions" msgid="1416699696825090402">"I-taskbar iphakamisa ama-app ezisuselwe kumjikelezo wakho"</string>
+    <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Thola iziphakamiso ze-app ngokusekelwe kumjikelezo wakho"</string>
+    <string name="taskbar_edu_features" msgid="2338325667726857642">"Yenza okwengeziwe ngebha yomsebenzi"</string>
     <string name="taskbar_edu_next" msgid="4007618274426775841">"Okulandelayo"</string>
     <string name="taskbar_edu_previous" msgid="459202320127201702">"Emuva"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Vala"</string>
diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml
index f63997b..86244b9 100644
--- a/quickstep/res/values/colors.xml
+++ b/quickstep/res/values/colors.xml
@@ -40,13 +40,10 @@
     <color name="gesture_tutorial_fake_task_view_color">#6DA1FF</color> <!-- Light Blue -->
     <!-- Must contrast gesture_tutorial_fake_wallpaper_color -->
     <color name="gesture_tutorial_fake_previous_task_view_color">#3C4043</color> <!-- Gray -->
-    <color name="gesture_tutorial_taskbar_color">#202124</color>
+    <color name="gesture_tutorial_taskbar_color">#E8EAED</color>
 
     <!-- Mock hotseat -->
-    <color name="mock_app_icon_1">#8AB4F8</color>
-    <color name="mock_app_icon_2">#F28B82</color>
-    <color name="mock_app_icon_3">#FDD663</color>
-    <color name="mock_app_icon_4">#81C995</color>
+    <color name="mock_app_icon">#BDC1C6</color>
     <color name="mock_search_bar">#3C4043</color>
 
     <!-- Mock conversation -->
@@ -79,4 +76,16 @@
     <!-- Recents overview -->
     <color name="recents_filter_icon">#333333</color>
 
+    <!-- Lottie light theme colors. -->
+    <color name="lottie_blue400">#669df6</color>
+    <color name="lottie_blue600">#1a73e8</color>
+    <color name="lottie_green400">#5bb974</color>
+    <color name="lottie_green600">#1e8e3e</color>
+    <color name="lottie_grey200">#e8eaed</color>
+    <color name="lottie_grey600">#80868b</color>
+    <color name="lottie_grey700">#5f6368</color>
+    <color name="lottie_red600">#d93025</color>
+    <color name="lottie_yellow400">#fcc934</color>
+    <color name="lottie_yellow600">#f9ab00</color>
+
 </resources>
\ No newline at end of file
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 403d6bd..d339d28 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -196,9 +196,13 @@
     <integer name="gesture_tutorial_webpage_extra_lines_visibility">0</integer> <!-- VISIBLE -->
 
     <!-- Gesture Tutorial mock taskbar -->
-    <dimen name="gesture_tutorial_taskbar_icon_size">44dp</dimen>
+    <dimen name="gesture_tutorial_taskbar_icon_size">52dp</dimen>
+    <dimen name="gesture_tutorial_taskbar_all_apps_mini_size">7dp</dimen>
     <dimen name="gesture_tutorial_taskbar_icon_corner_radius">100dp</dimen>
-    <dimen name="gesture_tutorial_taskbar_padding_start_end">52dp</dimen>
+    <dimen name="gesture_tutorial_taskbar_corner_radius">100dp</dimen>
+    <dimen name="gesture_tutorial_taskbar_padding">12dp</dimen>
+    <dimen name="gesture_tutorial_taskbar_icon_spacing">24dp</dimen>
+    <dimen name="gesture_tutorial_taskbar_margin_bottom">24dp</dimen>
 
     <!-- All Set page -->
     <dimen name="allset_page_margin_horizontal">40dp</dimen>
@@ -255,7 +259,10 @@
     <!-- Taskbar -->
     <dimen name="taskbar_size">@*android:dimen/taskbar_frame_height</dimen>
     <dimen name="taskbar_ime_size">48dp</dimen>
-    <dimen name="taskbar_icon_touch_size">48dp</dimen>
+    <dimen name="taskbar_icon_size">44dp</dimen>
+    <dimen name="taskbar_icon_min_touch_size">48dp</dimen>
+    <!-- Note that this applies to both sides of all icons, so visible space is double this. -->
+    <dimen name="taskbar_icon_spacing">12dp</dimen>
     <dimen name="taskbar_icon_drag_icon_size">54dp</dimen>
     <dimen name="taskbar_folder_margin">16dp</dimen>
     <dimen name="taskbar_contextual_button_padding">16dp</dimen>
@@ -282,11 +289,11 @@
 
     <!-- Transient taskbar -->
     <dimen name="transient_taskbar_size">72dp</dimen>
+    <dimen name="transient_taskbar_icon_size">48dp</dimen>
     <dimen name="transient_taskbar_margin">24dp</dimen>
     <dimen name="transient_taskbar_shadow_blur">40dp</dimen>
     <dimen name="transient_taskbar_key_shadow_distance">10dp</dimen>
     <dimen name="transient_taskbar_stashed_size">32dp</dimen>
-    <dimen name="transient_taskbar_icon_spacing">10dp</dimen>
     <!-- An additional touch slop to prevent x-axis movement during the swipe up to show taskbar -->
     <dimen name="transient_taskbar_clamped_offset_bound">16dp</dimen>
     <!-- Taskbar swipe up thresholds -->
@@ -306,6 +313,18 @@
     <dimen name="taskbar_button_margin_6_5">75dp</dimen>
     <dimen name="taskbar_button_margin_default">48dp</dimen>
 
+    <!-- Taskbar education tooltip -->
+    <dimen name="taskbar_edu_tooltip_elevation">14dp</dimen>
+    <dimen name="taskbar_edu_tooltip_horizontal_margin">32dp</dimen>
+    <dimen name="taskbar_edu_tooltip_vertical_margin">24dp</dimen>
+    <dimen name="taskbar_edu_tooltip_enter_y_delta">20dp</dimen>
+    <dimen name="taskbar_edu_tooltip_exit_y_delta">-10dp</dimen>
+    <dimen name="taskbar_edu_swipe_lottie_width">348dp</dimen>
+    <dimen name="taskbar_edu_swipe_lottie_height">217dp</dimen>
+    <dimen name="taskbar_edu_features_lottie_width">170dp</dimen>
+    <dimen name="taskbar_edu_features_lottie_height">106dp</dimen>
+    <dimen name="taskbar_edu_features_horizontal_spacing">24dp</dimen>
+
     <!-- Recents overview -->
     <dimen name="recents_filter_icon_size">30dp</dimen>
 
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index e691522..4f30791 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -231,18 +231,20 @@
     <string name="accessibility_rotate_button">Rotate screen</string>
 
     <!-- ******* Taskbar Edu ******* -->
-    <!-- Accessibility title for the taskbar education window. [CHAR_LIMIT=NONE] -->
+    <!-- Accessibility title for the Taskbar education window. [CHAR_LIMIT=NONE] -->
     <string name="taskbar_edu_a11y_title">Taskbar education</string>
-    <!-- Accessibility text spoken when the taskbar education panel appears [CHAR_LIMIT=NONE] -->
+    <!-- Accessibility text spoken when the Taskbar education panel appears [CHAR_LIMIT=NONE] -->
     <string name="taskbar_edu_opened">Taskbar education appeared</string>
-    <!-- Accessibility text spoken when the taskbar education panel disappears [CHAR_LIMIT=NONE] -->
+    <!-- Accessibility text spoken when the Taskbar education panel disappears [CHAR_LIMIT=NONE] -->
     <string name="taskbar_edu_closed">Taskbar education closed</string>
-    <!-- Text in dialog that lets a user know how they can use the taskbar to use multiple apps at once on their device. [CHAR_LIMIT=60] -->
-    <string name="taskbar_edu_splitscreen">Drag to the side to use 2 apps at once</string>
-    <!-- Text in dialog that lets a user know how they can show the taskbar on their device. [CHAR_LIMIT=60] -->
-    <string name="taskbar_edu_stashing">Short swipe up to show the taskbar</string>
-    <!-- Text in dialog that lets a user know how the taskbar suggests apps based on their usage. [CHAR_LIMIT=60] -->
-    <string name="taskbar_edu_suggestions">The taskbar suggests apps based on your routine</string>
+    <!-- Text in dialog that lets a user know how they can use the Taskbar to use multiple apps at once on their device. [CHAR_LIMIT=60] -->
+    <string name="taskbar_edu_splitscreen">Drag an app to the side to use 2 apps at once</string>
+    <!-- Text in dialog that lets a user know how they can show the Taskbar on their device. [CHAR_LIMIT=60] -->
+    <string name="taskbar_edu_stashing">Slow swipe up to show the Taskbar</string>
+    <!-- Text in dialog that lets a user know how the Taskbar suggests apps based on their usage. [CHAR_LIMIT=60] -->
+    <string name="taskbar_edu_suggestions">Get app suggestions based on your routine</string>
+    <!-- Title in dialog that shows a user what they can do with the Taskbar. [CHAR_LIMIT=60] -->
+    <string name="taskbar_edu_features">Do more with the Taskbar</string>
     <!-- Text on button to go to the next screen of a tutorial [CHAR_LIMIT=16] -->
     <string name="taskbar_edu_next">Next</string>
     <!-- Text on button to go to the previous screen of a tutorial [CHAR_LIMIT=16] -->
@@ -265,13 +267,13 @@
     <string name="taskbar_button_notifications">Notifications</string>
     <!-- Content description for quick settings button [CHAR_LIMIT=16] -->
     <string name="taskbar_button_quick_settings">Quick Settings</string>
-    <!-- Accessibility title for the taskbar window. [CHAR_LIMIT=NONE] -->
+    <!-- Accessibility title for the Taskbar window. [CHAR_LIMIT=NONE] -->
     <string name="taskbar_a11y_title">Taskbar</string>
-    <!-- Accessibility title for the taskbar window on phones. [CHAR_LIMIT=NONE] -->
+    <!-- Accessibility title for the Taskbar window on phones. [CHAR_LIMIT=NONE] -->
     <string name="taskbar_phone_a11y_title">Navigation bar</string>
 
-    <!-- Label for moving drop target to the top or left side of the screen, depending on orientation (from the taskbar only). -->
+    <!-- Label for moving drop target to the top or left side of the screen, depending on orientation (from the Taskbar only). -->
     <string name="move_drop_target_top_or_left">Move to top&#47;left</string>
-    <!-- Label for moving drop target to the bottom or right side of the screen, depending on orientation (from the taskbar only). -->
+    <!-- Label for moving drop target to the bottom or right side of the screen, depending on orientation (from the Taskbar only). -->
     <string name="move_drop_target_bottom_or_right">Move to bottom&#47;right</string>
 </resources>
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index eb75084..5256e29 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -186,4 +186,16 @@
         <item name="android:textSize">24sp</item>
         <item name="android:lines">2</item>
     </style>
+
+    <style name="TextAppearance.TaskbarEduTooltip.Title" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle">
+        <item name="android:gravity">center_horizontal</item>
+        <item name="android:fontFamily">google-sans</item>
+        <item name="android:textSize">24sp</item>
+    </style>
+
+    <style name="TextAppearance.TaskbarEduTooltip.Subtext" parent="android:TextAppearance.Material.Body1">
+        <item name="android:layout_marginTop">16dp</item>
+        <item name="android:fontFamily">google-sans-text</item>
+        <item name="android:textSize">14sp</item>
+    </style>
 </resources>
\ No newline at end of file
diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
index 95a94ec..9f9f2c8 100644
--- a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
+++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
@@ -28,12 +28,15 @@
 import android.content.Context;
 import android.os.Build;
 import android.os.Handler;
+import android.os.RemoteException;
+import android.view.IRemoteAnimationFinishedCallback;
 import android.view.RemoteAnimationTarget;
 
 import androidx.annotation.BinderThread;
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
 
+import com.android.systemui.animation.RemoteAnimationDelegate;
 import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
 
 import java.lang.ref.WeakReference;
@@ -89,7 +92,7 @@
         Runnable r = () -> {
             finishExistingAnimation();
             mAnimationResult = new AnimationResult(() -> mAnimationResult = null, runnable);
-            getFactory().onCreateAnimation(transit, appTargets, wallpaperTargets, nonAppTargets,
+            getFactory().onAnimationStart(transit, appTargets, wallpaperTargets, nonAppTargets,
                     mAnimationResult);
         };
         if (mStartAtFrontOfQueue) {
@@ -124,7 +127,11 @@
         });
     }
 
-    public static final class AnimationResult {
+    /**
+     * Used by RemoteAnimationFactory implementations to run the actual animation and its lifecycle
+     * callbacks.
+     */
+    public static final class AnimationResult extends IRemoteAnimationFinishedCallback.Stub {
 
         private final Runnable mSyncFinishRunnable;
         private final Runnable mASyncFinishRunnable;
@@ -199,25 +206,41 @@
                 }
             }
         }
+
+        /**
+         * When used as a simple IRemoteAnimationFinishedCallback, this method is used to run the
+         * animation finished runnable.
+         */
+        @Override
+        public void onAnimationFinished() throws RemoteException {
+            mASyncFinishRunnable.run();
+        }
     }
 
     /**
      * Used with LauncherAnimationRunner as an interface for the runner to call back to the
      * implementation.
      */
-    @FunctionalInterface
-    public interface RemoteAnimationFactory {
+    public interface RemoteAnimationFactory extends RemoteAnimationDelegate<AnimationResult> {
 
         /**
          * Called on the UI thread when the animation targets are received. The implementation must
          * call {@link AnimationResult#setAnimation} with the target animation to be run.
          */
-        void onCreateAnimation(int transit,
+        @Override
+        @UiThread
+        void onAnimationStart(int transit,
                 RemoteAnimationTarget[] appTargets,
                 RemoteAnimationTarget[] wallpaperTargets,
                 RemoteAnimationTarget[] nonAppTargets,
                 LauncherAnimationRunner.AnimationResult result);
 
+        @Override
+        @UiThread
+        default void onAnimationCancelled(boolean isKeyguardOccluded) {
+            onAnimationCancelled();
+        }
+
         /**
          * Called when the animation is cancelled. This can happen with or without
          * the create being called.
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 2aa0af4..b880a7e 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -89,6 +89,7 @@
 import android.util.Pair;
 import android.util.Size;
 import android.view.CrossWindowBlurListeners;
+import android.view.IRemoteAnimationFinishedCallback;
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationDefinition;
 import android.view.RemoteAnimationTarget;
@@ -114,6 +115,7 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.icons.FastBitmapDrawable;
+import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.shortcuts.DeepShortcutView;
 import com.android.launcher3.statehandlers.DepthController;
 import com.android.launcher3.taskbar.LauncherTaskbarUIController;
@@ -143,6 +145,9 @@
 import com.android.quickstep.util.WorkspaceRevealAnim;
 import com.android.quickstep.views.FloatingWidgetView;
 import com.android.quickstep.views.RecentsView;
+import com.android.systemui.animation.ActivityLaunchAnimator;
+import com.android.systemui.animation.DelegateLaunchAnimatorController;
+import com.android.systemui.animation.RemoteAnimationDelegate;
 import com.android.systemui.shared.system.BlurUtils;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
@@ -222,7 +227,6 @@
     private RemoteAnimationProvider mRemoteAnimationProvider;
     // Strong refs to runners which are cleared when the launcher activity is destroyed
     private RemoteAnimationFactory mWallpaperOpenRunner;
-    private RemoteAnimationFactory mAppLaunchRunner;
     private RemoteAnimationFactory mKeyguardGoingAwayRunner;
 
     private RemoteAnimationFactory mWallpaperOpenTransitionRunner;
@@ -291,9 +295,18 @@
     public ActivityOptionsWrapper getActivityLaunchOptions(View v) {
         boolean fromRecents = isLaunchingFromRecents(v, null /* targets */);
         RunnableList onEndCallback = new RunnableList();
-        mAppLaunchRunner = new AppLaunchAnimationRunner(v, onEndCallback);
+
+        RemoteAnimationFactory delegateRunner = new AppLaunchAnimationRunner(v, onEndCallback);
+        ItemInfo tag = (ItemInfo) v.getTag();
+        if (tag != null && tag.shouldUseBackgroundAnimation()) {
+            ContainerAnimationRunner containerAnimationRunner =
+                    ContainerAnimationRunner.from(v, mStartingWindowListener);
+            if (containerAnimationRunner != null) {
+                delegateRunner = containerAnimationRunner;
+            }
+        }
         RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(
-                mHandler, mAppLaunchRunner, true /* startAtFrontOfQueue */);
+                mHandler, delegateRunner, true /* startAtFrontOfQueue */);
 
         // Note that this duration is a guess as we do not know if the animation will be a
         // recents launch or not for sure until we know the opening app targets.
@@ -699,7 +712,7 @@
             @Override
             public void onAnimationStart(Animator animation) {
                 LauncherTaskbarUIController taskbarController = mLauncher.getTaskbarUIController();
-                if (taskbarController != null && taskbarController.shouldShowEdu()) {
+                if (taskbarController != null && taskbarController.shouldShowEduOnAppLaunch()) {
                     // LAUNCHER_TASKBAR_EDUCATION_SHOWING is set to true here, when the education
                     // flow is about to start, to avoid a race condition with other components
                     // that would show something else to the user as soon as the app is opened.
@@ -715,7 +728,7 @@
                 }
                 LauncherTaskbarUIController taskbarController = mLauncher.getTaskbarUIController();
                 if (taskbarController != null) {
-                    taskbarController.showEdu();
+                    taskbarController.showEduOnAppLaunch();
                 }
                 openingTargets.release();
             }
@@ -1160,7 +1173,6 @@
             // Also clear strong references to the runners registered with the remote animation
             // definition so we don't have to wait for the system gc
             mWallpaperOpenRunner = null;
-            mAppLaunchRunner = null;
             mKeyguardGoingAwayRunner = null;
         }
     }
@@ -1560,7 +1572,8 @@
             RemoteAnimationTarget[] wallpaperTargets,
             boolean fromUnlock,
             RectF startRect,
-            float startWindowCornerRadius) {
+            float startWindowCornerRadius,
+            boolean fromPredictiveBack) {
         AnimatorSet anim = null;
         RectFSpringAnim rectFSpringAnim = null;
 
@@ -1594,7 +1607,11 @@
                 rectFSpringAnim = getClosingWindowAnimators(
                         anim, appTargets, launcherView, velocity, startRect,
                         startWindowCornerRadius);
-                if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
+                if (mLauncher.isInState(LauncherState.ALL_APPS)) {
+                    // Skip scaling all apps, otherwise FloatingIconView will get wrong
+                    // layout bounds.
+                    skipAllAppsScale = true;
+                } else if (!fromPredictiveBack) {
                     anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
                             true /* animateOverviewScrim */, launcherView).getAnimators());
 
@@ -1606,10 +1623,6 @@
 
                     // We play StaggeredWorkspaceAnim as a part of the closing window animation.
                     playWorkspaceReveal = false;
-                } else {
-                    // Skip scaling all apps, otherwise FloatingIconView will get wrong
-                    // layout bounds.
-                    skipAllAppsScale = true;
                 }
             } else {
                 anim.play(getFallbackClosingWindowAnimators(appTargets));
@@ -1665,7 +1678,7 @@
         }
 
         @Override
-        public void onCreateAnimation(int transit,
+        public void onAnimationStart(int transit,
                 RemoteAnimationTarget[] appTargets,
                 RemoteAnimationTarget[] wallpaperTargets,
                 RemoteAnimationTarget[] nonAppTargets,
@@ -1686,7 +1699,8 @@
                     new RectF(getWindowTargetBounds(appTargets, getRotationChange(appTargets)));
             Pair<RectFSpringAnim, AnimatorSet> pair = createWallpaperOpenAnimations(
                     appTargets, wallpaperTargets, mFromUnlock, windowTargetBounds,
-                    QuickStepContract.getWindowCornerRadius(mLauncher));
+                    QuickStepContract.getWindowCornerRadius(mLauncher),
+                    false /* fromPredictiveBack */);
 
             mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL);
             result.setAnimation(pair.second, mLauncher);
@@ -1707,7 +1721,7 @@
         }
 
         @Override
-        public void onCreateAnimation(int transit,
+        public void onAnimationStart(int transit,
                 RemoteAnimationTarget[] appTargets,
                 RemoteAnimationTarget[] wallpaperTargets,
                 RemoteAnimationTarget[] nonAppTargets,
@@ -1752,6 +1766,79 @@
         }
     }
 
+    /** Remote animation runner to launch an app using System UI's animation library. */
+    private static class ContainerAnimationRunner implements RemoteAnimationFactory {
+
+        /** The delegate runner that handles the actual animation. */
+        private final RemoteAnimationDelegate<IRemoteAnimationFinishedCallback> mDelegate;
+
+        private ContainerAnimationRunner(
+                RemoteAnimationDelegate<IRemoteAnimationFinishedCallback> delegate) {
+            mDelegate = delegate;
+        }
+
+        @Nullable
+        private static ContainerAnimationRunner from(
+                View v, StartingWindowListener startingWindowListener) {
+            View viewToUse = findViewWithBackground(v);
+            if (viewToUse == null) {
+                viewToUse = v;
+            }
+
+            // TODO(b/265134143): create a CUJ type for interaction jank monitoring.
+            ActivityLaunchAnimator.Controller controllerDelegate =
+                    ActivityLaunchAnimator.Controller.fromView(viewToUse, null /* cujType */);
+
+            if (controllerDelegate == null) {
+                return null;
+            }
+
+            // This wrapper allows us to override the default value, telling the controller that the
+            // current window is below the animating window.
+            ActivityLaunchAnimator.Controller controller =
+                    new DelegateLaunchAnimatorController(controllerDelegate) {
+                        @Override
+                        public boolean isBelowAnimatingWindow() {
+                            return true;
+                        }
+                    };
+
+            ActivityLaunchAnimator.Callback callback = task -> ColorUtils.setAlphaComponent(
+                    startingWindowListener.getBackgroundColor(), 255);
+
+            return new ContainerAnimationRunner(
+                    new ActivityLaunchAnimator.AnimationDelegate(controller, callback));
+        }
+
+        /** Finds the closest parent of [view] (inclusive) with a background drawable. */
+        @Nullable
+        private static View findViewWithBackground(View view) {
+            View current = view;
+            while (current.getBackground() == null) {
+                if (!(current.getParent() instanceof View)) {
+                    return null;
+                }
+
+                current = (View) view.getParent();
+            }
+
+            return current;
+        }
+
+        @Override
+        public void onAnimationStart(int transit, RemoteAnimationTarget[] appTargets,
+                RemoteAnimationTarget[] wallpaperTargets, RemoteAnimationTarget[] nonAppTargets,
+                LauncherAnimationRunner.AnimationResult result) {
+            mDelegate.onAnimationStart(
+                    transit, appTargets, wallpaperTargets, nonAppTargets, result);
+        }
+
+        @Override
+        public void onAnimationCancelled(boolean isKeyguardOccluded) {
+            mDelegate.onAnimationCancelled(isKeyguardOccluded);
+        }
+    }
+
     /**
      * Class that holds all the variables for the app open animation.
      */
@@ -1820,8 +1907,9 @@
         }
     }
 
-    private static class StartingWindowListener extends IStartingWindowListener.Stub {
+    private class StartingWindowListener extends IStartingWindowListener.Stub {
         private QuickstepTransitionManager mTransitionManager;
+        private int mBackgroundColor;
 
         public void setTransitionManager(QuickstepTransitionManager transitionManager) {
             mTransitionManager = transitionManager;
@@ -1830,6 +1918,13 @@
         @Override
         public void onTaskLaunching(int taskId, int supportedType, int color) {
             mTransitionManager.mTaskStartParams.put(taskId, Pair.create(supportedType, color));
+            mBackgroundColor = color;
+        }
+
+        public int getBackgroundColor() {
+            return mBackgroundColor == Color.TRANSPARENT
+                    ? mLauncher.getScrimView().getBackgroundColor()
+                    : mBackgroundColor;
         }
     }
 
diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
index fb2d0dc..d8fd51a 100644
--- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java
+++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
@@ -18,6 +18,8 @@
 
 import static android.content.ContentResolver.SCHEME_CONTENT;
 
+import static com.android.launcher3.util.SimpleBroadcastReceiver.getPackageFilter;
+
 import android.annotation.TargetApi;
 import android.app.RemoteAction;
 import android.content.ContentProviderClient;
@@ -55,7 +57,6 @@
 import com.android.launcher3.popup.SystemShortcut;
 import com.android.launcher3.util.BgObjectWithLooper;
 import com.android.launcher3.util.MainThreadInitializedObject;
-import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.Preconditions;
 import com.android.launcher3.util.SimpleBroadcastReceiver;
 
@@ -117,7 +118,7 @@
         if (!TextUtils.isEmpty(mWellbeingProviderPkg)) {
             mContext.registerReceiver(
                     new SimpleBroadcastReceiver(t -> restartObserver()),
-                    PackageManagerHelper.getPackageFilter(mWellbeingProviderPkg,
+                    getPackageFilter(mWellbeingProviderPkg,
                             Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_CHANGED,
                             Intent.ACTION_PACKAGE_REMOVED, Intent.ACTION_PACKAGE_DATA_CLEARED,
                             Intent.ACTION_PACKAGE_RESTARTED),
diff --git a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
index 9554bd3..184ea71 100644
--- a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
+++ b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
@@ -15,38 +15,14 @@
  */
 package com.android.launcher3.popup;
 
-import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
-import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
-import static com.android.quickstep.util.SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
 import android.view.View;
 
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.R;
-import com.android.launcher3.anim.PendingAnimation;
-import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.splitscreen.SplitShortcut;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
-import com.android.quickstep.util.SplitSelectStateController;
-import com.android.quickstep.views.FloatingTaskView;
-import com.android.quickstep.views.RecentsView;
-import com.android.systemui.shared.recents.model.Task;
 
-import java.util.function.Consumer;
-
+/** {@link SystemShortcut.Factory} implementation to create workspace split shortcuts */
 public interface QuickstepSystemShortcut {
 
     String TAG = QuickstepSystemShortcut.class.getSimpleName();
@@ -58,116 +34,12 @@
                         originalView, position);
     }
 
-    class SplitSelectSystemShortcut extends SystemShortcut<QuickstepLauncher> {
-
-        private final int mSplitPlaceholderSize;
-        private final int mSplitPlaceholderInset;
-
-        private final Rect mTempRect = new Rect();
-        private final SplitPositionOption mPosition;
+    class SplitSelectSystemShortcut extends SplitShortcut<QuickstepLauncher> {
 
         public SplitSelectSystemShortcut(QuickstepLauncher launcher, ItemInfo itemInfo,
                 View originalView, SplitPositionOption position) {
-            super(position.iconResId, position.textResId, launcher, itemInfo, originalView);
-
-            mPosition = position;
-
-            mSplitPlaceholderSize = launcher.getResources().getDimensionPixelSize(
-                    R.dimen.split_placeholder_size);
-            mSplitPlaceholderInset = launcher.getResources().getDimensionPixelSize(
-                    R.dimen.split_placeholder_inset);
-        }
-
-        @Override
-        public void onClick(View view) {
-            // Initiate splitscreen from the Home screen or Home All Apps
-            Bitmap bitmap;
-            Intent intent;
-            if (mItemInfo instanceof WorkspaceItemInfo) {
-                final WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) mItemInfo;
-                bitmap = workspaceItemInfo.bitmap.icon;
-                intent = workspaceItemInfo.intent;
-            } else if (mItemInfo instanceof com.android.launcher3.model.data.AppInfo) {
-                final com.android.launcher3.model.data.AppInfo appInfo =
-                        (com.android.launcher3.model.data.AppInfo) mItemInfo;
-                bitmap = appInfo.bitmap.icon;
-                intent = appInfo.intent;
-            } else {
-                Log.e(TAG, "unknown item type");
-                return;
-            }
-
-            StatsLogManager.EventEnum splitEvent = getLogEventForPosition(mPosition.stagePosition);
-            RecentsView recentsView = mTarget.getOverviewPanel();
-            // Check if there is already an instance of this app running, if so, initiate the split
-            // using that.
-            recentsView.findLastActiveTaskAndDoSplitOperation(
-                    intent.getComponent(),
-                    (Consumer<Task>) foundTask -> {
-                        SplitSelectSource source = new SplitSelectSource(mOriginalView,
-                                new BitmapDrawable(bitmap), intent, mPosition, mItemInfo,
-                                splitEvent, foundTask);
-                        if (ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
-                            startSplitToHome(source);
-                        } else {
-                            recentsView.initiateSplitSelect(source);
-                        }
-                    }
-            );
-        }
-
-        private void startSplitToHome(SplitSelectSource source) {
-            AbstractFloatingView.closeAllOpenViews(mTarget);
-
-            SplitSelectStateController controller = mTarget.getSplitSelectStateController();
-            controller.setInitialTaskSelect(source.intent, source.position.stagePosition,
-                    source.itemInfo, source.splitEvent, source.alreadyRunningTask);
-
-            RecentsView recentsView = mTarget.getOverviewPanel();
-            recentsView.getPagedOrientationHandler().getInitialSplitPlaceholderBounds(
-                    mSplitPlaceholderSize, mSplitPlaceholderInset, mTarget.getDeviceProfile(),
-                    controller.getActiveSplitStagePosition(), mTempRect);
-
-            PendingAnimation anim = new PendingAnimation(TABLET_HOME_TO_SPLIT.getDuration());
-            RectF startingTaskRect = new RectF();
-            final FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(mTarget,
-                    source.view, null /* thumbnail */, source.drawable, startingTaskRect);
-            floatingTaskView.setAlpha(1);
-            floatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
-                    false /* fadeWithThumbnail */, true /* isStagedTask */);
-            controller.setFirstFloatingTaskView(floatingTaskView);
-            anim.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationCancel(Animator animation) {
-                    mTarget.getDragLayer().removeView(floatingTaskView);
-                    controller.resetState();
-                }
-            });
-            anim.buildAnim().start();
-        }
-    }
-
-    class SplitSelectSource {
-
-        public final View view;
-        public final Drawable drawable;
-        public final Intent intent;
-        public final SplitPositionOption position;
-        public final ItemInfo itemInfo;
-        public final StatsLogManager.EventEnum splitEvent;
-        @Nullable
-        public final Task alreadyRunningTask;
-
-        public SplitSelectSource(View view, Drawable drawable, Intent intent,
-                SplitPositionOption position, ItemInfo itemInfo,
-                StatsLogManager.EventEnum splitEvent, @Nullable Task foundTask) {
-            this.view = view;
-            this.drawable = drawable;
-            this.intent = intent;
-            this.position = position;
-            this.itemInfo = itemInfo;
-            this.splitEvent = splitEvent;
-            this.alreadyRunningTask = foundTask;
+            super(position.iconResId, position.textResId, launcher, itemInfo, originalView,
+                    position);
         }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt b/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt
new file mode 100644
index 0000000..20c8c44
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt
@@ -0,0 +1,93 @@
+/*
+ * 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.splitscreen
+
+import android.content.Context
+import android.content.Intent
+import android.graphics.Bitmap
+import android.graphics.drawable.BitmapDrawable
+import android.util.Log
+import android.view.View
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.WorkspaceItemInfo
+import com.android.launcher3.popup.QuickstepSystemShortcut
+import com.android.launcher3.popup.SystemShortcut
+import com.android.launcher3.util.SplitConfigurationOptions
+import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption
+import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource
+import com.android.launcher3.views.ActivityContext
+
+/**
+ * Shortcut to allow starting split. Default interaction for [onClick] is to launch
+ * split selection mode
+ */
+abstract class SplitShortcut<T>(
+    iconResId: Int,
+    labelResId: Int,
+    target: T,
+    itemInfo: ItemInfo?,
+    originalView: View?,
+    protected val position: SplitPositionOption
+) : SystemShortcut<T>(iconResId, labelResId, target, itemInfo, originalView) where
+T : Context?,
+T : ActivityContext? {
+    private val TAG = SystemShortcut::class.java.simpleName
+
+    // Initiate splitscreen from the Home screen or Home All Apps
+    protected val splitSelectSource: SplitSelectSource?
+        get() {
+            // Initiate splitscreen from the Home screen or Home All Apps
+            val bitmap: Bitmap
+            val intent: Intent
+            when (mItemInfo) {
+                is WorkspaceItemInfo -> {
+                    val workspaceItemInfo = mItemInfo
+                    bitmap = workspaceItemInfo.bitmap.icon
+                    intent = workspaceItemInfo.intent
+                }
+                is com.android.launcher3.model.data.AppInfo -> {
+                    val appInfo = mItemInfo
+                    bitmap = appInfo.bitmap.icon
+                    intent = appInfo.intent
+                }
+                else -> {
+                    Log.e(TAG, "unknown item type")
+                    return null
+                }
+            }
+            val splitEvent =
+                SplitConfigurationOptions.getLogEventForPosition(position.stagePosition)
+            return SplitSelectSource(
+                mOriginalView,
+                BitmapDrawable(bitmap),
+                intent,
+                position,
+                mItemInfo,
+                splitEvent
+            )
+        }
+
+    /** Starts split selection on the provided [mTarget] */
+    override fun onClick(view: View?) {
+        val splitSelectSource = splitSelectSource
+        if (splitSelectSource == null) {
+            Log.w(QuickstepSystemShortcut.TAG, "no split selection source")
+            return
+        }
+        mTarget!!.startSplitSelection(splitSelectSource)
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
index bbc0627..ae121e2 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
@@ -33,6 +33,7 @@
 
     private boolean mFreeformTasksVisible;
     private boolean mInOverviewState;
+    private boolean mGestureInProgress;
 
     public DesktopVisibilityController(Launcher launcher) {
         mLauncher = launcher;
@@ -57,9 +58,24 @@
      * Sets whether freeform windows are visible and updates launcher visibility based on that.
      */
     public void setFreeformTasksVisible(boolean freeformTasksVisible) {
+        if (!isDesktopModeSupported()) {
+            return;
+        }
         if (freeformTasksVisible != mFreeformTasksVisible) {
             mFreeformTasksVisible = freeformTasksVisible;
-            updateLauncherVisibility();
+            if (mFreeformTasksVisible) {
+                setLauncherViewsVisibility(View.INVISIBLE);
+                if (!mInOverviewState) {
+                    // When freeform is visible & we're not in overview, we want launcher to appear
+                    // paused, this ensures that taskbar displays.
+                    markLauncherPaused();
+                }
+            } else {
+                setLauncherViewsVisibility(View.VISIBLE);
+                // If freeform isn't visible ensure that launcher appears resumed to behave
+                // normally.
+                markLauncherResumed();
+            }
         }
     }
 
@@ -67,40 +83,67 @@
      * Sets whether the overview is visible and updates launcher visibility based on that.
      */
     public void setOverviewStateEnabled(boolean overviewStateEnabled) {
+        if (!isDesktopModeSupported()) {
+            return;
+        }
         if (overviewStateEnabled != mInOverviewState) {
             mInOverviewState = overviewStateEnabled;
-            updateLauncherVisibility();
+            if (mInOverviewState) {
+                setLauncherViewsVisibility(View.VISIBLE);
+                markLauncherResumed();
+            } else if (mFreeformTasksVisible) {
+                setLauncherViewsVisibility(View.INVISIBLE);
+                markLauncherPaused();
+            }
         }
     }
 
     /**
-     * Updates launcher visibility and state to look like it is paused or resumed depending on
-     * whether freeform windows are showing in desktop mode.
+     * Whether recents gesture is currently in progress.
      */
-    private void updateLauncherVisibility() {
-        StatefulActivity<LauncherState> activity =
-                QuickstepLauncher.ACTIVITY_TRACKER.getCreatedActivity();
-        View workspaceView = mLauncher.getWorkspace();
-        if (activity == null || workspaceView == null || !isDesktopModeSupported()) {
+    public boolean isGestureInProgress() {
+        return mGestureInProgress;
+    }
+
+    /**
+     * Sets whether recents gesture is in progress.
+     */
+    public void setGestureInProgress(boolean gestureInProgress) {
+        if (!isDesktopModeSupported()) {
             return;
         }
+        if (gestureInProgress != mGestureInProgress) {
+            mGestureInProgress = gestureInProgress;
+        }
+    }
 
-        if (mFreeformTasksVisible) {
-            workspaceView.setVisibility(View.INVISIBLE);
-            if (!mInOverviewState) {
-                // When freeform is visible & we're not in overview, we want launcher to appear
-                // paused, this ensures that taskbar displays.
-                activity.setPaused();
-            }
-        } else {
-            workspaceView.setVisibility(View.VISIBLE);
-            // If freeform isn't visible ensure that launcher appears resumed to behave normally.
-            // Check activity state before calling setResumed(). Launcher may have been actually
-            // paused (eg fullscreen task moved to front).
-            // In this case we should not mark the activity as resumed.
-            if (activity.isResumed()) {
-                activity.setResumed();
-            }
+    private void setLauncherViewsVisibility(int visibility) {
+        View workspaceView = mLauncher.getWorkspace();
+        if (workspaceView != null) {
+            workspaceView.setVisibility(visibility);
+        }
+        View dragLayer = mLauncher.getDragLayer();
+        if (dragLayer != null) {
+            dragLayer.setVisibility(visibility);
+        }
+    }
+
+    private void markLauncherPaused() {
+        StatefulActivity<LauncherState> activity =
+                QuickstepLauncher.ACTIVITY_TRACKER.getCreatedActivity();
+        if (activity != null) {
+            activity.setPaused();
+        }
+    }
+
+    private void markLauncherResumed() {
+        StatefulActivity<LauncherState> activity =
+                QuickstepLauncher.ACTIVITY_TRACKER.getCreatedActivity();
+        // Check activity state before calling setResumed(). Launcher may have been actually
+        // paused (eg fullscreen task moved to front).
+        // In this case we should not mark the activity as resumed.
+        if (activity != null && activity.isResumed()) {
+            activity.setResumed();
         }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
index 82d1830..48352a2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
@@ -20,6 +20,8 @@
 import android.view.LayoutInflater;
 
 import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
+import com.android.launcher3.LauncherPrefs;
+import com.android.launcher3.util.OnboardingPrefs;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.ActivityContext;
 
@@ -32,10 +34,12 @@
 
     protected final LayoutInflater mLayoutInflater;
     private final List<OnDeviceProfileChangeListener> mDPChangeListeners = new ArrayList<>();
+    private final OnboardingPrefs<BaseTaskbarContext> mOnboardingPrefs;
 
     public BaseTaskbarContext(Context windowContext) {
         super(windowContext, Themes.getActivityThemeRes(windowContext));
         mLayoutInflater = LayoutInflater.from(this).cloneInContext(this);
+        mOnboardingPrefs = new OnboardingPrefs<>(this, LauncherPrefs.getPrefs(this));
     }
 
     @Override
@@ -48,6 +52,11 @@
         return mDPChangeListeners;
     }
 
+    @Override
+    public OnboardingPrefs<BaseTaskbarContext> getOnboardingPrefs() {
+        return mOnboardingPrefs;
+    }
+
     /** Callback invoked when a drag is initiated within this context. */
     public abstract void onDragStart();
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
index df867cb..474dc3d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
@@ -73,12 +73,12 @@
         boolean useStashedLauncherState = toState.hasOverviewActions();
         boolean stashedLauncherState =
                 useStashedLauncherState && !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get();
-        TaskbarStashController controller = mControllers.taskbarStashController;
+        TaskbarStashController stashController = mControllers.taskbarStashController;
         // Set both FLAG_IN_STASHED_LAUNCHER_STATE and FLAG_IN_APP to ensure the state is respected.
         // For all other states, just use the current stashed-in-app setting (e.g. if long clicked).
-        controller.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE, stashedLauncherState);
-        controller.updateStateForFlag(FLAG_IN_APP, !useStashedLauncherState);
-        return controller.applyStateWithoutStart(duration);
+        stashController.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE, stashedLauncherState);
+        stashController.updateStateForFlag(FLAG_IN_APP, !useStashedLauncherState);
+        return stashController.createApplyStateAnimator(duration);
     }
 
     private void animateToRecentsState(RecentsState toState) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 22f7f13..335482c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -18,6 +18,8 @@
 import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
 
 import static com.android.launcher3.QuickstepTransitionManager.TRANSIENT_TASKBAR_TRANSITION_DURATION;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_EDU_TOOLTIP;
+import static com.android.launcher3.taskbar.TaskbarEduTooltipControllerKt.TOOLTIP_STEP_FEATURES;
 import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_RESUMED;
 import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
 
@@ -26,7 +28,6 @@
 import android.annotation.ColorInt;
 import android.os.RemoteException;
 import android.util.Log;
-import android.util.SparseArray;
 import android.view.TaskTransitionSpec;
 import android.view.WindowManagerGlobal;
 
@@ -45,13 +46,13 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.MultiPropertyFactory;
 import com.android.launcher3.util.OnboardingPrefs;
 import com.android.quickstep.RecentsAnimationCallbacks;
 import com.android.quickstep.views.RecentsView;
 
 import java.io.PrintWriter;
 import java.util.Set;
-import java.util.stream.Stream;
 
 /**
  * A data source which integrates with a Launcher instance
@@ -65,7 +66,12 @@
     public static final int WIDGETS_PAGE_PROGRESS_INDEX = 2;
     public static final int SYSUI_SURFACE_PROGRESS_INDEX = 3;
 
-    private final SparseArray<Float> mTaskbarInAppDisplayProgress = new SparseArray<>(4);
+    private static final int DISPLAY_PROGRESS_COUNT = 4;
+
+    private final AnimatedFloat mTaskbarInAppDisplayProgress = new AnimatedFloat();
+    private final MultiPropertyFactory<AnimatedFloat> mTaskbarInAppDisplayProgressMultiProp =
+            new MultiPropertyFactory<>(mTaskbarInAppDisplayProgress,
+                    AnimatedFloat.VALUE, DISPLAY_PROGRESS_COUNT, Float::max);
 
     private final QuickstepLauncher mLauncher;
 
@@ -255,23 +261,51 @@
     }
 
     /**
-     * Starts the taskbar education flow, if the user hasn't seen it yet.
+     * Starts a Taskbar EDU flow, if the user should see one upon launching an application.
      */
-    public void showEdu() {
-        if (!shouldShowEdu()) {
+    public void showEduOnAppLaunch() {
+        if (!shouldShowEduOnAppLaunch()) {
             return;
         }
-        mLauncher.getOnboardingPrefs().markChecked(OnboardingPrefs.TASKBAR_EDU_SEEN);
 
-        mControllers.taskbarEduController.showEdu();
+        // Transient and persistent bottom sheet.
+        if (!ENABLE_TASKBAR_EDU_TOOLTIP.get()) {
+            mLauncher.getOnboardingPrefs().markChecked(OnboardingPrefs.TASKBAR_EDU_SEEN);
+            mControllers.taskbarEduController.showEdu();
+            return;
+        }
+
+        // Persistent features EDU tooltip.
+        if (!DisplayController.isTransientTaskbar(mLauncher)) {
+            mControllers.taskbarEduTooltipController.maybeShowFeaturesEdu();
+            return;
+        }
+
+        // Transient swipe EDU tooltip.
+        mControllers.taskbarEduTooltipController.maybeShowSwipeEdu();
     }
 
     /**
-     * Whether the taskbar education should be shown.
+     * Returns {@code true} if a Taskbar education should be shown on application launch.
      */
-    public boolean shouldShowEdu() {
-        return !Utilities.IS_RUNNING_IN_TEST_HARNESS
-                && !mLauncher.getOnboardingPrefs().getBoolean(OnboardingPrefs.TASKBAR_EDU_SEEN);
+    public boolean shouldShowEduOnAppLaunch() {
+        if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+            return false;
+        }
+
+        // Transient and persistent bottom sheet.
+        if (!ENABLE_TASKBAR_EDU_TOOLTIP.get()) {
+            return !mLauncher.getOnboardingPrefs().getBoolean(OnboardingPrefs.TASKBAR_EDU_SEEN);
+        }
+
+        // Persistent features EDU tooltip.
+        if (!DisplayController.isTransientTaskbar(mLauncher)) {
+            return !mLauncher.getOnboardingPrefs().hasReachedMaxCount(
+                    OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP);
+        }
+
+        // Transient swipe EDU tooltip.
+        return mControllers.taskbarEduTooltipController.getTooltipStep() < TOOLTIP_STEP_FEATURES;
     }
 
     @Override
@@ -305,42 +339,25 @@
      *                 1 => use in-app layout
      */
     public void onTaskbarInAppDisplayProgressUpdate(float progress, int progressIndex) {
+        mTaskbarInAppDisplayProgressMultiProp.get(progressIndex).setValue(progress);
         if (mControllers == null) {
             // This method can be called before init() is called.
             return;
         }
-        mTaskbarInAppDisplayProgress.put(progressIndex, progress);
-        if (!mControllers.taskbarStashController.isInApp()
+        if (mControllers.uiController.isIconAlignedWithHotseat()
                 && !mTaskbarLauncherStateController.isAnimatingToLauncher()) {
             // Only animate the nav buttons while home and not animating home, otherwise let
             // the TaskbarViewController handle it.
             mControllers.navbarButtonsViewController
                     .getTaskbarNavButtonTranslationYForInAppDisplay()
                     .updateValue(mLauncher.getDeviceProfile().getTaskbarOffsetY()
-                            * getInAppDisplayProgress());
+                            * mTaskbarInAppDisplayProgress.value);
         }
     }
 
     /** Returns true iff any in-app display progress > 0. */
     public boolean shouldUseInAppLayout() {
-        return getInAppDisplayProgress() > 0;
-    }
-
-    private float getInAppDisplayProgress(int index) {
-        if (!mTaskbarInAppDisplayProgress.contains(index)) {
-            mTaskbarInAppDisplayProgress.put(index, 0f);
-        }
-        return mTaskbarInAppDisplayProgress.get(index);
-    }
-
-    private float getInAppDisplayProgress() {
-        return Stream.of(
-                getInAppDisplayProgress(MINUS_ONE_PAGE_PROGRESS_INDEX),
-                getInAppDisplayProgress(ALL_APPS_PAGE_PROGRESS_INDEX),
-                getInAppDisplayProgress(WIDGETS_PAGE_PROGRESS_INDEX),
-                getInAppDisplayProgress(SYSUI_SURFACE_PROGRESS_INDEX))
-                .max(Float::compareTo)
-                .get();
+        return mTaskbarInAppDisplayProgress.value > 0;
     }
 
     @Override
@@ -358,7 +375,8 @@
     @Override
     public boolean isHotseatIconOnTopWhenAligned() {
         return mTaskbarLauncherStateController.isInHotseatOnTopStates()
-                && getInAppDisplayProgress(MINUS_ONE_PAGE_PROGRESS_INDEX) == 0;
+                && mTaskbarInAppDisplayProgressMultiProp.get(MINUS_ONE_PAGE_PROGRESS_INDEX)
+                    .getValue() == 0;
     }
 
     @Override
@@ -369,28 +387,15 @@
                 "%s\tmTaskbarOverrideBackgroundAlpha=%.2f",
                 prefix,
                 mTaskbarOverrideBackgroundAlpha.value));
-
         pw.println(String.format("%s\tTaskbar in-app display progress:", prefix));
-        if (mControllers == null) {
-            pw.println(String.format("%s\t\tMissing mControllers", prefix));
-        } else {
-            pw.println(String.format(
-                    "%s\t\tprogress at MINUS_ONE_PAGE_PROGRESS_INDEX=%.2f",
-                    prefix,
-                    getInAppDisplayProgress(MINUS_ONE_PAGE_PROGRESS_INDEX)));
-            pw.println(String.format(
-                    "%s\t\tprogress at ALL_APPS_PAGE_PROGRESS_INDEX=%.2f",
-                    prefix,
-                    getInAppDisplayProgress(ALL_APPS_PAGE_PROGRESS_INDEX)));
-            pw.println(String.format(
-                    "%s\t\tprogress at WIDGETS_PAGE_PROGRESS_INDEX=%.2f",
-                    prefix,
-                    getInAppDisplayProgress(WIDGETS_PAGE_PROGRESS_INDEX)));
-            pw.println(String.format(
-                    "%s\t\tprogress at SYSUI_SURFACE_PROGRESS_INDEX=%.2f",
-                    prefix,
-                    getInAppDisplayProgress(SYSUI_SURFACE_PROGRESS_INDEX)));
-        }
+        mTaskbarInAppDisplayProgressMultiProp.dump(
+                prefix + "\t",
+                pw,
+                "mTaskbarInAppDisplayProgressMultiProp",
+                "MINUS_ONE_PAGE_PROGRESS_INDEX",
+                "ALL_APPS_PAGE_PROGRESS_INDEX",
+                "WIDGETS_PAGE_PROGRESS_INDEX",
+                "SYSUI_SURFACE_PROGRESS_INDEX");
 
         mTaskbarLauncherStateController.dumpLogs(prefix + "\t", pw);
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index cbee58b..4b7d8fc 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -51,7 +51,6 @@
 import android.annotation.LayoutRes;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
-import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.Point;
@@ -300,7 +299,8 @@
                     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.dimen.key_button_ripple_max_width,
+                    R.bool.floating_rotation_button_position_left);
             mControllers.rotationButtonController.setRotationButton(mFloatingRotationButton,
                     mRotationButtonListener);
 
@@ -487,13 +487,6 @@
     }
 
     /**
-     * Returns true if IME switcher is visible
-     */
-    public boolean isImeSwitcherVisible() {
-        return (mState & FLAG_SWITCHER_SHOWING) != 0;
-    }
-
-    /**
      * Returns true if the home button is disabled
      */
     public boolean isHomeDisabled() {
@@ -725,13 +718,6 @@
             mPropertyHolders.add(new StatePropertyHolder(
                     mBackButtonAlpha.get(ALPHA_INDEX_SUW),
                     flags -> (flags & FLAG_IME_VISIBLE) == 0));
-
-            // TODO(b/210906568) Dark intensity is currently not propagated during setup, so set
-            //  it based on dark theme for now.
-            int mode = res.getConfiguration().uiMode
-                    & Configuration.UI_MODE_NIGHT_MASK;
-            boolean isDarkTheme = mode == Configuration.UI_MODE_NIGHT_YES;
-            mTaskbarNavButtonDarkIntensity.updateValue(isDarkTheme ? 0 : 1);
         } else if (isInKidsMode) {
             int iconSize = res.getDimensionPixelSize(
                     R.dimen.taskbar_icon_size_kids);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 731eea7..20e4b55 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -15,7 +15,9 @@
  */
 package com.android.launcher3.taskbar;
 
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.content.pm.PackageManager.FEATURE_PC;
+import static android.os.Trace.TRACE_TAG_APP;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -46,6 +48,7 @@
 import android.graphics.Rect;
 import android.os.Process;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.provider.Settings;
 import android.util.Log;
 import android.view.Display;
@@ -90,10 +93,12 @@
 import com.android.launcher3.util.NavigationMode;
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.SettingsCache;
+import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
 import com.android.launcher3.util.TraceHelper;
 import com.android.launcher3.util.ViewCache;
 import com.android.launcher3.views.ActivityContext;
 import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.rotation.RotationButtonController;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -101,6 +106,7 @@
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
 
 import java.io.PrintWriter;
+import java.util.function.Consumer;
 
 /**
  * The {@link ActivityContext} with which we inflate Taskbar-related Views. This allows UI elements
@@ -229,7 +235,8 @@
                 new TaskbarTranslationController(this),
                 isDesktopMode
                         ? new DesktopTaskbarRecentAppsController(this)
-                        : TaskbarRecentAppsController.DEFAULT);
+                        : TaskbarRecentAppsController.DEFAULT,
+                new TaskbarEduTooltipController(this));
     }
 
     public void init(@NonNull TaskbarSharedState sharedState) {
@@ -266,6 +273,13 @@
         dispatchDeviceProfileChanged();
     }
 
+    @Override
+    public void dispatchDeviceProfileChanged() {
+        super.dispatchDeviceProfileChanged();
+        Trace.instantForTrack(TRACE_TAG_APP, "TaskbarActivityContext#DeviceProfileChanged",
+                getDeviceProfile().toSmallString());
+    }
+
     /**
      * Copy the original DeviceProfile, match the number of hotseat icons and qsb width and update
      * the icon size
@@ -543,8 +557,6 @@
                 fromInit);
         mControllers.taskbarViewController.setImeIsVisible(
                 mControllers.navbarButtonsViewController.isImeVisible());
-        mControllers.taskbarViewController.setIsImeSwitcherVisible(
-                mControllers.navbarButtonsViewController.isImeSwitcherVisible());
         int shadeExpandedFlags = SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
                 | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
         onNotificationShadeExpandChanged((systemUiStateFlags & shadeExpandedFlags) != 0, fromInit);
@@ -598,9 +610,6 @@
     }
 
     public void onNavButtonsDarkIntensityChanged(float darkIntensity) {
-        if (!isUserSetupComplete()) {
-            return;
-        }
         mControllers.navbarButtonsViewController.getTaskbarNavButtonDarkIntensity()
                 .updateValue(darkIntensity);
     }
@@ -745,6 +754,11 @@
         }
     }
 
+    @Override
+    public void startSplitSelection(SplitSelectSource splitSelectSource) {
+        mControllers.uiController.startSplitSelection(splitSelectSource);
+    }
+
     protected void onTaskbarIconClicked(View view) {
         Object tag = view.getTag();
         if (tag instanceof Task) {
@@ -781,12 +795,12 @@
                 });
             });
         } else if (tag instanceof WorkspaceItemInfo) {
+            // Tapping a launchable icon on Taskbar
             WorkspaceItemInfo info = (WorkspaceItemInfo) tag;
             if (!info.isDisabled() || !ItemClickHandler.handleDisabledItemClicked(info, this)) {
                 TaskbarUIController taskbarUIController = mControllers.uiController;
                 RecentsView recents = taskbarUIController.getRecentsView();
-                if (recents != null
-                        && taskbarUIController.getRecentsView().isSplitSelectionActive()) {
+                if (recents != null && recents.isSplitSelectionActive()) {
                     // If we are selecting a second app for split, launch the split tasks
                     taskbarUIController.triggerSecondAppForSplit(info, info.intent, view);
                 } else {
@@ -813,7 +827,7 @@
                             getSystemService(LauncherApps.class)
                                     .startShortcut(packageName, id, null, null, info.user);
                         } else {
-                            startItemInfoActivity(info);
+                            launchFromTaskbarPreservingSplitIfVisible(recents, info);
                         }
 
                         mControllers.uiController.onTaskbarIconLaunched(info);
@@ -828,6 +842,7 @@
                 mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
             }
         } else if (tag instanceof AppInfo) {
+            // Tapping an item in AllApps
             AppInfo info = (AppInfo) tag;
             TaskbarUIController taskbarUIController = mControllers.uiController;
             RecentsView recents = taskbarUIController.getRecentsView();
@@ -836,9 +851,8 @@
                 // If we are selecting a second app for split, launch the split tasks
                 taskbarUIController.triggerSecondAppForSplit(info, info.intent, view);
             } else {
-                // Else launch the selected task
-                startItemInfoActivity((AppInfo) tag);
-                mControllers.uiController.onTaskbarIconLaunched((AppInfo) tag);
+                launchFromTaskbarPreservingSplitIfVisible(recents, info);
+                mControllers.uiController.onTaskbarIconLaunched(info);
             }
             mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
         } else if (tag instanceof ItemClickProxy) {
@@ -850,6 +864,31 @@
         AbstractFloatingView.closeAllOpenViews(this);
     }
 
+    /**
+     * Run when the user taps a Taskbar icon while in Overview. If the tapped app is currently
+     * visible to the user in Overview, or is part of a visible split pair, we expand the TaskView
+     * as if the user tapped on it (preserving the split pair). Otherwise, launch it normally
+     * (potentially breaking a split pair).
+     */
+    private void launchFromTaskbarPreservingSplitIfVisible(RecentsView recents, ItemInfo info) {
+        recents.findLastActiveTaskAndRunCallback(
+                info.getTargetComponent(),
+                (Consumer<Task>) foundTask -> {
+                    if (foundTask != null) {
+                        TaskView foundTaskView =
+                                recents.getTaskViewByTaskId(foundTask.key.id);
+                        if (foundTaskView != null
+                                && foundTaskView.isVisibleToUser()) {
+                            TestLogging.recordEvent(
+                                    TestProtocol.SEQUENCE_MAIN, "start: taskbarAppIcon");
+                            foundTaskView.launchTasks();
+                            return;
+                        }
+                    }
+                    startItemInfoActivity(info);
+                });
+    }
+
     private void startItemInfoActivity(ItemInfo info) {
         Intent intent = new Intent(info.getIntent())
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -882,6 +921,7 @@
      */
     public void onSwipeToUnstashTaskbar() {
         mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(false);
+        mControllers.taskbarEduTooltipController.hide();
     }
 
     /** Returns {@code true} if taskbar All Apps is open. */
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
index 4350e9c..2bfc7dd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
@@ -39,11 +39,14 @@
     public static final int FLAG_AUTOHIDE_SUSPEND_DRAGGING = 1 << 1;
     // User has touched down but has not lifted finger.
     public static final int FLAG_AUTOHIDE_SUSPEND_TOUCHING = 1 << 2;
+    // Taskbar EDU overlay is open above the Taskbar. */
+    public static final int FLAG_AUTOHIDE_SUSPEND_EDU_OPEN = 1 << 3;
 
     @IntDef(flag = true, value = {
             FLAG_AUTOHIDE_SUSPEND_FULLSCREEN,
             FLAG_AUTOHIDE_SUSPEND_DRAGGING,
             FLAG_AUTOHIDE_SUSPEND_TOUCHING,
+            FLAG_AUTOHIDE_SUSPEND_EDU_OPEN,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface AutohideSuspendFlag {}
@@ -102,6 +105,7 @@
                 "FLAG_AUTOHIDE_SUSPEND_FULLSCREEN");
         appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_DRAGGING, "FLAG_AUTOHIDE_SUSPEND_DRAGGING");
         appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_TOUCHING, "FLAG_AUTOHIDE_SUSPEND_TOUCHING");
+        appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_EDU_OPEN, "FLAG_AUTOHIDE_SUSPEND_EDU_OPEN");
         return str.toString();
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index ff7e8e9..cf3af08 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -16,20 +16,17 @@
 
 package com.android.launcher3.taskbar
 
-import com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound
-import com.android.launcher3.Utilities.mapToRange
-
 import android.graphics.Canvas
 import android.graphics.Color
 import android.graphics.Paint
 import android.graphics.Path
 import com.android.launcher3.R
+import com.android.launcher3.Utilities.mapToRange
 import com.android.launcher3.anim.Interpolators
+import com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound
 import com.android.launcher3.util.DisplayController
 
-/**
- * Helps draw the taskbar background, made up of a rectangle plus two inverted rounded corners.
- */
+/** Helps draw the taskbar background, made up of a rectangle plus two inverted rounded corners. */
 class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {
 
     val paint: Paint = Paint()
@@ -39,7 +36,7 @@
     private var maxBackgroundHeight = context.deviceProfile.taskbarSize.toFloat()
     private val transientBackgroundBounds = context.transientTaskbarBounds
 
-    private val isTransientTaskbar = DisplayController.isTransientTaskbar(context);
+    private val isTransientTaskbar = DisplayController.isTransientTaskbar(context)
 
     private var shadowBlur = 0f
     private var keyShadowDistance = 0f
@@ -98,9 +95,7 @@
         invertedRightCornerPath.op(square, circle, Path.Op.DIFFERENCE)
     }
 
-    /**
-     * Draws the background with the given paint and height, on the provided canvas.
-     */
+    /** Draws the background with the given paint and height, on the provided canvas. */
     fun draw(canvas: Canvas) {
         canvas.save()
         canvas.translate(0f, canvas.height - backgroundHeight - bottomMargin)
@@ -124,21 +119,26 @@
             canvas.translate(0f, bottomMargin * ((1f - scaleFactor) / 2f))
 
             // Draw shadow.
-            val shadowAlpha = mapToRange(paint.alpha.toFloat(), 0f, 255f, 0f, 25f,
-                Interpolators.LINEAR)
-            paint.setShadowLayer(shadowBlur, 0f, keyShadowDistance,
+            val shadowAlpha =
+                mapToRange(paint.alpha.toFloat(), 0f, 255f, 0f, 25f, Interpolators.LINEAR)
+            paint.setShadowLayer(
+                shadowBlur,
+                0f,
+                keyShadowDistance,
                 setColorAlphaBound(Color.BLACK, Math.round(shadowAlpha))
             )
 
             // Draw background.
-            val radius = backgroundHeight / 2f;
+            val radius = backgroundHeight / 2f
 
             canvas.drawRoundRect(
                 transientBackgroundBounds.left + (delta / 2f),
                 translationYForSwipe,
                 transientBackgroundBounds.right - (delta / 2f),
                 backgroundHeight + translationYForSwipe,
-                radius, radius, paint
+                radius,
+                radius,
+                paint
             )
         }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index bc41c2b..ea70de4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -58,6 +58,7 @@
     public final TaskbarRecentAppsController taskbarRecentAppsController;
     public final TaskbarTranslationController taskbarTranslationController;
     public final TaskbarOverlayController taskbarOverlayController;
+    public final TaskbarEduTooltipController taskbarEduTooltipController;
 
     @Nullable private LoggableTaskbarController[] mControllersToLog = null;
     @Nullable private BackgroundRendererController[] mBackgroundRendererControllers = null;
@@ -73,6 +74,13 @@
     // Roundness property for round corner above taskbar .
     private final AnimatedFloat mCornerRoundness = new AnimatedFloat(this::updateCornerRoundness);
 
+    /**
+     * Want to add a new controller? Don't forget to:
+     *   * Call init
+     *   * Call onDestroy
+     *   * Add to mControllersToLog
+     *   * Add tests by adding this controller to TaskbarBaseTestCase.kt and extending that class
+     */
     public TaskbarControllers(TaskbarActivityContext taskbarActivityContext,
             TaskbarDragController taskbarDragController,
             TaskbarNavButtonController navButtonController,
@@ -94,7 +102,8 @@
             TaskbarInsetsController taskbarInsetsController,
             VoiceInteractionWindowController voiceInteractionWindowController,
             TaskbarTranslationController taskbarTranslationController,
-            TaskbarRecentAppsController taskbarRecentAppsController) {
+            TaskbarRecentAppsController taskbarRecentAppsController,
+            TaskbarEduTooltipController taskbarEduTooltipController) {
         this.taskbarActivityContext = taskbarActivityContext;
         this.taskbarDragController = taskbarDragController;
         this.navButtonController = navButtonController;
@@ -117,6 +126,7 @@
         this.voiceInteractionWindowController = voiceInteractionWindowController;
         this.taskbarTranslationController = taskbarTranslationController;
         this.taskbarRecentAppsController = taskbarRecentAppsController;
+        this.taskbarEduTooltipController = taskbarEduTooltipController;
     }
 
     /**
@@ -148,6 +158,7 @@
         voiceInteractionWindowController.init(this);
         taskbarRecentAppsController.init(this);
         taskbarTranslationController.init(this);
+        taskbarEduTooltipController.init(this);
 
         mControllersToLog = new LoggableTaskbarController[] {
                 taskbarDragController, navButtonController, navbarButtonsViewController,
@@ -155,7 +166,8 @@
                 taskbarUnfoldAnimationController, taskbarKeyguardController,
                 stashedHandleViewController, taskbarStashController, taskbarEduController,
                 taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController,
-                voiceInteractionWindowController, taskbarTranslationController
+                voiceInteractionWindowController, taskbarTranslationController,
+                taskbarEduTooltipController
         };
         mBackgroundRendererControllers = new BackgroundRendererController[] {
                 taskbarDragLayerController, taskbarScrimViewController,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index d0059f7..7114849 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -194,7 +194,8 @@
     public boolean dispatchKeyEvent(KeyEvent event) {
         if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
             AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
-            if (topView != null && topView.onBackPressed()) {
+            if (topView != null && topView.canHandleBack()) {
+                topView.onBackInvoked();
                 // Handled by the floating view.
                 return true;
             }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt
new file mode 100644
index 0000000..7dda73f
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt
@@ -0,0 +1,187 @@
+/*
+ * 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
+
+import android.animation.AnimatorSet
+import android.animation.ValueAnimator
+import android.content.Context
+import android.provider.Settings
+import android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING
+import android.util.AttributeSet
+import android.view.MotionEvent
+import android.view.MotionEvent.ACTION_DOWN
+import android.view.View
+import android.view.ViewGroup
+import android.view.animation.Interpolator
+import com.android.launcher3.AbstractFloatingView
+import com.android.launcher3.R
+import com.android.launcher3.anim.AnimatorListeners
+import com.android.launcher3.popup.RoundedArrowDrawable
+import com.android.launcher3.util.Themes
+import com.android.launcher3.views.ActivityContext
+import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE
+import com.android.systemui.animation.Interpolators.STANDARD
+
+private const val ENTER_DURATION_MS = 300L
+private const val EXIT_DURATION_MS = 150L
+
+/** Floating tooltip for Taskbar education. */
+class TaskbarEduTooltip
+@JvmOverloads
+constructor(
+    context: Context,
+    attrs: AttributeSet? = null,
+    defStyleAttr: Int = 0,
+) : AbstractFloatingView(context, attrs, defStyleAttr) {
+
+    private val activityContext: ActivityContext = ActivityContext.lookupContext(context)
+
+    private val backgroundColor =
+        Themes.getAttrColor(context, com.android.internal.R.attr.colorSurface)
+
+    private val tooltipCornerRadius = Themes.getDialogCornerRadius(context)
+    private val arrowWidth = resources.getDimension(R.dimen.popup_arrow_width)
+    private val arrowHeight = resources.getDimension(R.dimen.popup_arrow_height)
+    private val arrowPointRadius = resources.getDimension(R.dimen.popup_arrow_corner_radius)
+
+    private val enterYDelta = resources.getDimension(R.dimen.taskbar_edu_tooltip_enter_y_delta)
+    private val exitYDelta = resources.getDimension(R.dimen.taskbar_edu_tooltip_exit_y_delta)
+
+    /** Container where the tooltip's body should be inflated. */
+    lateinit var content: ViewGroup
+        private set
+    private lateinit var arrow: View
+
+    /** Callback invoked when the tooltip is being closed. */
+    var onCloseCallback: () -> Unit = {}
+    private var openCloseAnimator: AnimatorSet? = null
+
+    /** Animates the tooltip into view. */
+    fun show() {
+        if (isOpen) {
+            return
+        }
+        mIsOpen = true
+        activityContext.dragLayer.addView(this)
+        openCloseAnimator = createOpenCloseAnimator(isOpening = true).apply { start() }
+    }
+
+    override fun onFinishInflate() {
+        super.onFinishInflate()
+
+        content = findViewById(R.id.content)
+        arrow = findViewById(R.id.arrow)
+        arrow.background =
+            RoundedArrowDrawable(
+                arrowWidth,
+                arrowHeight,
+                arrowPointRadius,
+                tooltipCornerRadius,
+                measuredWidth.toFloat(),
+                measuredHeight.toFloat(),
+                (measuredWidth - arrowWidth) / 2, // arrowOffsetX
+                0f, // arrowOffsetY
+                false, // isPointingUp
+                true, // leftAligned
+                backgroundColor,
+            )
+    }
+
+    override fun handleClose(animate: Boolean) {
+        if (!isOpen) {
+            return
+        }
+
+        onCloseCallback()
+        if (!animate) {
+            return closeComplete()
+        }
+
+        openCloseAnimator?.cancel()
+        openCloseAnimator = createOpenCloseAnimator(isOpening = false)
+        openCloseAnimator?.addListener(AnimatorListeners.forEndCallback(this::closeComplete))
+        openCloseAnimator?.start()
+    }
+
+    override fun isOfType(type: Int): Boolean = type and TYPE_TASKBAR_EDUCATION_DIALOG != 0
+
+    override fun onControllerInterceptTouchEvent(ev: MotionEvent?): Boolean {
+        if (ev?.action == ACTION_DOWN && !activityContext.dragLayer.isEventOverView(this, ev)) {
+            close(true)
+        }
+        return false
+    }
+
+    override fun onDetachedFromWindow() {
+        super.onDetachedFromWindow()
+        Settings.Secure.putInt(mContext.contentResolver, LAUNCHER_TASKBAR_EDUCATION_SHOWING, 0)
+    }
+
+    private fun closeComplete() {
+        openCloseAnimator?.cancel()
+        openCloseAnimator = null
+        mIsOpen = false
+        activityContext.dragLayer.removeView(this)
+    }
+
+    private fun createOpenCloseAnimator(isOpening: Boolean): AnimatorSet {
+        val duration: Long
+        val alphaValues: FloatArray
+        val translateYValues: FloatArray
+        val fadeInterpolator: Interpolator
+        val translateYInterpolator: Interpolator
+
+        if (isOpening) {
+            duration = ENTER_DURATION_MS
+            alphaValues = floatArrayOf(0f, 1f)
+            translateYValues = floatArrayOf(enterYDelta, 0f)
+            fadeInterpolator = STANDARD
+            translateYInterpolator = EMPHASIZED_DECELERATE
+        } else {
+            duration = EXIT_DURATION_MS
+            alphaValues = floatArrayOf(1f, 0f)
+            translateYValues = floatArrayOf(0f, exitYDelta)
+            fadeInterpolator = EMPHASIZED_ACCELERATE
+            translateYInterpolator = EMPHASIZED_ACCELERATE
+        }
+
+        val fade =
+            ValueAnimator.ofFloat(*alphaValues).apply {
+                interpolator = fadeInterpolator
+                addUpdateListener {
+                    val alpha = it.animatedValue as Float
+                    content.alpha = alpha
+                    arrow.alpha = alpha
+                }
+            }
+
+        val translateY =
+            ValueAnimator.ofFloat(*translateYValues).apply {
+                interpolator = translateYInterpolator
+                addUpdateListener {
+                    val translationY = it.animatedValue as Float
+                    content.translationY = translationY
+                    arrow.translationY = translationY
+                }
+            }
+
+        return AnimatorSet().apply {
+            this.duration = duration
+            playTogether(fade, translateY)
+        }
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
new file mode 100644
index 0000000..c4d1ab2
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -0,0 +1,193 @@
+/*
+ * 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
+
+import android.graphics.PorterDuff.Mode.SRC_ATOP
+import android.graphics.PorterDuffColorFilter
+import android.view.View
+import android.view.ViewGroup
+import androidx.annotation.IntDef
+import androidx.annotation.LayoutRes
+import com.airbnb.lottie.LottieAnimationView
+import com.airbnb.lottie.LottieProperty.COLOR_FILTER
+import com.airbnb.lottie.model.KeyPath
+import com.android.launcher3.R
+import com.android.launcher3.Utilities
+import com.android.launcher3.Utilities.IS_RUNNING_IN_TEST_HARNESS
+import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_EDU_TOOLTIP
+import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_EDU_OPEN
+import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
+import com.android.launcher3.util.DisplayController
+import com.android.launcher3.util.OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP
+import java.io.PrintWriter
+
+/** First EDU step for swiping up to show transient Taskbar. */
+const val TOOLTIP_STEP_SWIPE = 0
+/** Second EDU step for explaining Taskbar functionality when unstashed. */
+const val TOOLTIP_STEP_FEATURES = 1
+/**
+ * EDU is completed.
+ *
+ * This value should match the maximum count for [TASKBAR_EDU_TOOLTIP_STEP].
+ */
+const val TOOLTIP_STEP_NONE = 2
+
+/** Current step in the tooltip EDU flow. */
+@Retention(AnnotationRetention.SOURCE)
+@IntDef(TOOLTIP_STEP_SWIPE, TOOLTIP_STEP_FEATURES, TOOLTIP_STEP_NONE)
+annotation class TaskbarEduTooltipStep
+
+/** Controls stepping through the Taskbar tooltip EDU. */
+class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
+    LoggableTaskbarController {
+
+    private val isTooltipEnabled = !IS_RUNNING_IN_TEST_HARNESS && ENABLE_TASKBAR_EDU_TOOLTIP.get()
+    private val isOpen: Boolean
+        get() = tooltip?.isOpen ?: false
+
+    private lateinit var controllers: TaskbarControllers
+
+    @TaskbarEduTooltipStep
+    var tooltipStep: Int
+        get() {
+            return activityContext.onboardingPrefs?.getCount(TASKBAR_EDU_TOOLTIP_STEP)
+                ?: TOOLTIP_STEP_NONE
+        }
+        private set(step) {
+            activityContext.onboardingPrefs?.setEventCount(step, TASKBAR_EDU_TOOLTIP_STEP)
+        }
+
+    private var tooltip: TaskbarEduTooltip? = null
+
+    fun init(controllers: TaskbarControllers) {
+        this.controllers = controllers
+    }
+
+    /** Shows swipe EDU tooltip if it is the current [tooltipStep]. */
+    fun maybeShowSwipeEdu() {
+        if (
+            !isTooltipEnabled ||
+                !DisplayController.isTransientTaskbar(activityContext) ||
+                tooltipStep > TOOLTIP_STEP_SWIPE
+        ) {
+            return
+        }
+
+        tooltipStep = TOOLTIP_STEP_FEATURES
+        inflateTooltip(R.layout.taskbar_edu_swipe)
+        tooltip?.apply {
+            findViewById<LottieAnimationView>(R.id.swipe_animation).supportLightTheme()
+            show()
+        }
+    }
+
+    /**
+     * Shows feature EDU tooltip if this step has not been seen.
+     *
+     * If [TOOLTIP_STEP_SWIPE] has not been seen at this point, the first step is skipped because a
+     * swipe up is necessary to show this step.
+     */
+    fun maybeShowFeaturesEdu() {
+        if (!isTooltipEnabled || tooltipStep > TOOLTIP_STEP_FEATURES) {
+            return
+        }
+
+        tooltipStep = TOOLTIP_STEP_NONE
+        inflateTooltip(R.layout.taskbar_edu_features)
+        tooltip?.apply {
+            findViewById<LottieAnimationView>(R.id.splitscreen_animation).supportLightTheme()
+            findViewById<LottieAnimationView>(R.id.suggestions_animation).supportLightTheme()
+
+            findViewById<View>(R.id.done_button)?.setOnClickListener { hide() }
+            if (DisplayController.isTransientTaskbar(activityContext)) {
+                (layoutParams as ViewGroup.MarginLayoutParams).bottomMargin +=
+                    activityContext.deviceProfile.taskbarSize
+            }
+            show()
+        }
+    }
+
+    /** Closes the current [tooltip]. */
+    fun hide() = tooltip?.close(true)
+
+    /** Initializes [tooltip] with content from [contentResId]. */
+    private fun inflateTooltip(@LayoutRes contentResId: Int) {
+        val overlayContext = controllers.taskbarOverlayController.requestWindow()
+        val tooltip =
+            overlayContext.layoutInflater.inflate(
+                R.layout.taskbar_edu_tooltip,
+                overlayContext.dragLayer,
+                false
+            ) as TaskbarEduTooltip
+
+        controllers.taskbarAutohideSuspendController.updateFlag(
+            FLAG_AUTOHIDE_SUSPEND_EDU_OPEN,
+            true
+        )
+        tooltip.onCloseCallback = {
+            this.tooltip = null
+            controllers.taskbarAutohideSuspendController.updateFlag(
+                FLAG_AUTOHIDE_SUSPEND_EDU_OPEN,
+                false
+            )
+            controllers.taskbarStashController.updateAndAnimateTransientTaskbar(true)
+        }
+
+        overlayContext.layoutInflater.inflate(contentResId, tooltip.content, true)
+        this.tooltip = tooltip
+    }
+
+    override fun dumpLogs(prefix: String?, pw: PrintWriter?) {
+        pw?.println("$(prefix)TaskbarEduController:")
+        pw?.println("$prefix\tisTooltipEnabled=$isTooltipEnabled")
+        pw?.println("$prefix\tisOpen=$isOpen")
+        pw?.println("$prefix\ttooltipStep=$tooltipStep")
+    }
+}
+
+/**
+ * Maps colors in the dark-themed Lottie assets to their light-themed equivalents.
+ *
+ * For instance, `".blue100" to R.color.lottie_blue400` means objects that are material blue100 in
+ * dark theme should be changed to material blue400 in light theme.
+ */
+private val DARK_TO_LIGHT_COLORS =
+    mapOf(
+        ".blue100" to R.color.lottie_blue400,
+        ".blue400" to R.color.lottie_blue600,
+        ".green100" to R.color.lottie_green400,
+        ".green400" to R.color.lottie_green600,
+        ".grey300" to R.color.lottie_grey600,
+        ".grey400" to R.color.lottie_grey700,
+        ".grey800" to R.color.lottie_grey200,
+        ".red400" to R.color.lottie_red600,
+        ".yellow100" to R.color.lottie_yellow400,
+        ".yellow400" to R.color.lottie_yellow600,
+    )
+
+private fun LottieAnimationView.supportLightTheme() {
+    if (Utilities.isDarkTheme(context)) {
+        return
+    }
+
+    addLottieOnCompositionLoadedListener {
+        DARK_TO_LIGHT_COLORS.forEach { (key, color) ->
+            addValueCallback(KeyPath("**", key, "**"), COLOR_FILTER) {
+                PorterDuffColorFilter(context.getColor(color), SRC_ATOP)
+            }
+        }
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index a48b88f..9f24565 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -36,10 +36,8 @@
 import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
 import java.io.PrintWriter
 
-/**
- * Handles the insets that Taskbar provides to underlying apps and the IME.
- */
-class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTaskbarController {
+/** Handles the insets that Taskbar provides to underlying apps and the IME. */
+class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTaskbarController {
 
     /** The bottom insets taskbar provides to the IME when IME is visible. */
     val taskbarHeightForIme: Int = context.resources.getDimensionPixelSize(R.dimen.taskbar_ime_size)
@@ -77,13 +75,19 @@
 
     fun onTaskbarWindowHeightOrInsetsChanged() {
         val touchableHeight = controllers.taskbarStashController.touchableHeight
-        touchableRegion.set(0, windowLayoutParams.height - touchableHeight,
-            context.deviceProfile.widthPx, windowLayoutParams.height)
+        touchableRegion.set(
+            0,
+            windowLayoutParams.height - touchableHeight,
+            context.deviceProfile.widthPx,
+            windowLayoutParams.height
+        )
         val contentHeight = controllers.taskbarStashController.contentHeightToReportToApps
         val tappableHeight = controllers.taskbarStashController.tappableHeightToReportToApps
         for (provider in windowLayoutParams.providedInsets) {
-            if (provider.type == ITYPE_EXTRA_NAVIGATION_BAR
-                    || provider.type == ITYPE_BOTTOM_MANDATORY_GESTURES) {
+            if (
+                provider.type == ITYPE_EXTRA_NAVIGATION_BAR ||
+                    provider.type == ITYPE_BOTTOM_MANDATORY_GESTURES
+            ) {
                 provider.insetsSize = getInsetsByNavMode(contentHeight)
             } else if (provider.type == ITYPE_BOTTOM_TAPPABLE_ELEMENT) {
                 provider.insetsSize = getInsetsByNavMode(tappableHeight)
@@ -91,24 +95,20 @@
         }
 
         val imeInsetsSize = getInsetsByNavMode(taskbarHeightForIme)
-        val insetsSizeOverride = arrayOf(
-            InsetsFrameProvider.InsetsSizeOverride(
-                TYPE_INPUT_METHOD,
-                imeInsetsSize
-            ),
-        )
+        val insetsSizeOverride =
+            arrayOf(
+                InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, imeInsetsSize),
+            )
         // Use 0 tappableElement insets for the VoiceInteractionWindow when gesture nav is enabled.
         val visInsetsSizeForGestureNavTappableElement = getInsetsByNavMode(0)
-        val insetsSizeOverrideForGestureNavTappableElement = arrayOf(
-            InsetsFrameProvider.InsetsSizeOverride(
-                TYPE_INPUT_METHOD,
-                imeInsetsSize
-            ),
-            InsetsFrameProvider.InsetsSizeOverride(
-                TYPE_VOICE_INTERACTION,
-                visInsetsSizeForGestureNavTappableElement
-            ),
-        )
+        val insetsSizeOverrideForGestureNavTappableElement =
+            arrayOf(
+                InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, imeInsetsSize),
+                InsetsFrameProvider.InsetsSizeOverride(
+                    TYPE_VOICE_INTERACTION,
+                    visInsetsSizeForGestureNavTappableElement
+                ),
+            )
         for (provider in windowLayoutParams.providedInsets) {
             if (context.isGestureNav && provider.type == ITYPE_BOTTOM_TAPPABLE_ELEMENT) {
                 provider.insetsSizeOverrides = insetsSizeOverrideForGestureNavTappableElement
@@ -120,9 +120,11 @@
 
     /**
      * @return [Insets] where the [bottomInset] is either used as a bottom inset or
+     * ```
      *         right/left inset if using 3 button nav
+     * ```
      */
-    private fun getInsetsByNavMode(bottomInset: Int) : Insets {
+    private fun getInsetsByNavMode(bottomInset: Int): Insets {
         val devicePortrait = !context.deviceProfile.isLandscape
         if (!TaskbarManager.isPhoneButtonNavMode(context) || devicePortrait) {
             // Taskbar or portrait phone mode
@@ -139,9 +141,9 @@
      * @param providesInsetsTypes The inset types we would like this layout params to provide.
      */
     fun setProvidesInsetsTypes(params: WindowManager.LayoutParams, providesInsetsTypes: IntArray) {
-        params.providedInsets = arrayOfNulls<InsetsFrameProvider>(providesInsetsTypes.size);
+        params.providedInsets = arrayOfNulls<InsetsFrameProvider>(providesInsetsTypes.size)
         for (i in providesInsetsTypes.indices) {
-            params.providedInsets[i] = InsetsFrameProvider(providesInsetsTypes[i]);
+            params.providedInsets[i] = InsetsFrameProvider(providesInsetsTypes[i])
         }
     }
 
@@ -153,14 +155,17 @@
         insetsInfo.touchableRegion.setEmpty()
         // Always have nav buttons be touchable
         controllers.navbarButtonsViewController.addVisibleButtonsRegion(
-            context.dragLayer, insetsInfo.touchableRegion
+            context.dragLayer,
+            insetsInfo.touchableRegion
         )
         var insetsIsTouchableRegion = true
         if (context.dragLayer.alpha < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) {
             // Let touches pass through us.
             insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
-        } else if (controllers.navbarButtonsViewController.isImeVisible
-                && controllers.taskbarStashController.isStashed()) {
+        } else if (
+            controllers.navbarButtonsViewController.isImeVisible &&
+                controllers.taskbarStashController.isStashed()
+        ) {
             insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
         } else if (!controllers.uiController.isTaskbarTouchable) {
             // Let touches pass through us.
@@ -174,9 +179,10 @@
                 insetsInfo.touchableRegion.set(touchableRegion)
             }
             insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
-        } else if (controllers.taskbarViewController.areIconsVisible()
-            || AbstractFloatingView.hasOpenView(context, AbstractFloatingView.TYPE_ALL)
-            || context.isNavBarKidsModeActive
+        } else if (
+            controllers.taskbarViewController.areIconsVisible() ||
+                AbstractFloatingView.hasOpenView(context, AbstractFloatingView.TYPE_ALL) ||
+                context.isNavBarKidsModeActive
         ) {
             // Taskbar has some touchable elements, take over the full taskbar area
             insetsInfo.setTouchableInsets(
@@ -198,8 +204,12 @@
         pw.println(prefix + "TaskbarInsetsController:")
         pw.println("$prefix\twindowHeight=${windowLayoutParams.height}")
         for (provider in windowLayoutParams.providedInsets) {
-            pw.print("$prefix\tprovidedInsets: (type=" + InsetsState.typeToString(provider.type)
-                    + " insetsSize=" + provider.insetsSize)
+            pw.print(
+                "$prefix\tprovidedInsets: (type=" +
+                    InsetsState.typeToString(provider.type) +
+                    " insetsSize=" +
+                    provider.insetsSize
+            )
             if (provider.insetsSizeOverrides != null) {
                 pw.print(" insetsSizeOverrides={")
                 for ((i, overrideSize) in provider.insetsSizeOverrides.withIndex()) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
index 0808fab..edf4648 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
@@ -10,12 +10,10 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
 
 import android.app.KeyguardManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 
 import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.util.ScreenOnTracker;
+import com.android.launcher3.util.ScreenOnTracker.ScreenOnListener;
 import com.android.systemui.shared.system.QuickStepContract;
 
 import java.io.PrintWriter;
@@ -30,6 +28,7 @@
             SYSUI_STATE_OVERVIEW_DISABLED | SYSUI_STATE_HOME_DISABLED |
             SYSUI_STATE_BACK_DISABLED | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
 
+    private final ScreenOnListener mScreenOnListener;
     private final TaskbarActivityContext mContext;
     private int mKeyguardSysuiFlags;
     private boolean mBouncerShowing;
@@ -37,22 +36,20 @@
     private final KeyguardManager mKeyguardManager;
     private boolean mIsScreenOff;
 
-    private final BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            mIsScreenOff = true;
-            AbstractFloatingView.closeOpenViews(mContext, false, TYPE_ALL);
-        }
-    };
-
     public TaskbarKeyguardController(TaskbarActivityContext context) {
         mContext = context;
+        mScreenOnListener = isOn -> {
+            if (!isOn) {
+                mIsScreenOff = true;
+                AbstractFloatingView.closeOpenViews(mContext, false, TYPE_ALL);
+            }
+        };
         mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
     }
 
     public void init(NavbarButtonsViewController navbarButtonUIController) {
         mNavbarButtonsViewController = navbarButtonUIController;
-        mContext.registerReceiver(mScreenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
+        ScreenOnTracker.INSTANCE.get(mContext).addListener(mScreenOnListener);
     }
 
     public void updateStateForSysuiFlags(int systemUiStateFlags) {
@@ -104,7 +101,7 @@
     }
 
     public void onDestroy() {
-        mContext.unregisterReceiver(mScreenOffReceiver);
+        ScreenOnTracker.INSTANCE.get(mContext).removeListener(mScreenOnListener);
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 7a75661..3e51e67 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -125,7 +125,8 @@
                     mControllers.taskbarDragController.setDisallowLongClick(disallowLongClick);
                     mControllers.taskbarAllAppsController.setDisallowGlobalDrag(disallowGlobalDrag);
                     mControllers.taskbarAllAppsController.setDisallowLongClick(disallowLongClick);
-                    mControllers.taskbarPopupController.setHideSplitOptions(disallowGlobalDrag);
+                    mControllers.taskbarPopupController.setAllowInitialSplitSelection(
+                            disallowGlobalDrag);
                 }
             };
 
@@ -184,7 +185,7 @@
         stashController.updateStateForFlag(FLAG_IN_APP, false);
 
         updateStateForFlag(FLAG_RECENTS_ANIMATION_RUNNING, true);
-        animatorSet.play(stashController.applyStateWithoutStart(duration));
+        animatorSet.play(stashController.createApplyStateAnimator(duration));
         animatorSet.play(applyState(duration, false));
 
         if (mTaskBarRecentsAnimationListener != null) {
@@ -259,8 +260,9 @@
     }
 
     private Animator onStateChangeApplied(int changedFlags, long duration, boolean start) {
-        boolean goingToLauncher = isInLauncher();
+        final boolean goingToLauncher = isInLauncher();
         final float toAlignment = isIconAlignedWithHotseat() ? 1 : 0;
+        boolean handleOpenFloatingViews = false;
         if (DEBUG) {
             Log.d(TAG, "onStateChangeApplied - mState: " + getStateString(mState)
                     + ", changedFlags: " + getStateString(changedFlags)
@@ -281,6 +283,10 @@
                 updateStateForFlag(FLAG_RESUMED, false);
                 applyState(0 /* duration */);
             }
+            if (mLauncherState == LauncherState.NORMAL) {
+                // We're changing state to home, should close open popups e.g. Taskbar AllApps
+                handleOpenFloatingViews = true;
+            }
         }
 
         if (hasAnyFlag(changedFlags, FLAGS_LAUNCHER)) {
@@ -304,10 +310,11 @@
                 }
             });
 
-            if (goingToLauncher) {
-                // Handle closing open popups when going home/overview
-                AbstractFloatingView.closeAllOpenViews(mControllers.taskbarActivityContext);
-            }
+            // Handle closing open popups when going home/overview
+            handleOpenFloatingViews = true;
+        }
+        if (handleOpenFloatingViews && goingToLauncher) {
+            AbstractFloatingView.closeAllOpenViews(mControllers.taskbarActivityContext);
         }
 
         float backgroundAlpha =
@@ -398,7 +405,7 @@
         boolean isInStashedState = mLauncherState.isTaskbarStashed(mLauncher);
         TaskbarStashController stashController = mControllers.taskbarStashController;
         stashController.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE, isInStashedState);
-        Animator stashAnimator = stashController.applyStateWithoutStart(duration);
+        Animator stashAnimator = stashController.createApplyStateAnimator(duration);
         if (stashAnimator != null) {
             stashAnimator.addListener(new AnimatorListenerAdapter() {
                 @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 049c672..a58906f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -32,7 +32,6 @@
 import android.os.Handler;
 import android.os.SystemProperties;
 import android.provider.Settings;
-import android.util.Log;
 import android.view.Display;
 
 import androidx.annotation.NonNull;
@@ -157,10 +156,14 @@
                 } else {
                     // Config change might be handled without re-creating the taskbar
                     if (mTaskbarActivityContext != null) {
-                        if (dp != null && isTaskbarPresent(dp)) {
-                            mTaskbarActivityContext.updateDeviceProfile(dp, mNavMode);
+                        if (dp != null && !isTaskbarPresent(dp)) {
+                            destroyExistingTaskbar();
+                        } else {
+                            if (dp != null && isTaskbarPresent(dp)) {
+                                mTaskbarActivityContext.updateDeviceProfile(dp, mNavMode);
+                            }
+                            mTaskbarActivityContext.onConfigurationChanged(configDiff);
                         }
-                        mTaskbarActivityContext.onConfigurationChanged(configDiff);
                     }
                 }
                 mOldConfig = newConfig;
@@ -227,10 +230,6 @@
         mActivity = activity;
         UnfoldTransitionProgressProvider unfoldTransitionProgressProvider =
                 getUnfoldTransitionProgressProviderForActivity(activity);
-        if (unfoldTransitionProgressProvider == null) {
-            Log.e("b/261320823", "UnfoldTransitionProgressProvider null in setActivity. "
-                    + "Unfold animation for launcher will not work.");
-        }
         mUnfoldProgressProvider.setSourceProvider(unfoldTransitionProgressProvider);
 
         if (mTaskbarActivityContext != null) {
@@ -320,6 +319,12 @@
         }
     }
 
+    public void onLongPressHomeEnabled(boolean assistantLongPressEnabled) {
+        if (mNavButtonController != null) {
+            mNavButtonController.setAssistantLongPressEnabled(assistantLongPressEnabled);
+        }
+    }
+
     /**
      * Sets the flag indicating setup UI is visible
      */
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index a395548..5bb958a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -67,6 +67,7 @@
 
     private long mLastScreenPinLongPress;
     private boolean mScreenPinned;
+    private boolean mAssistantLongPressEnabled;
 
     @Override
     public void dumpLogs(String prefix, PrintWriter pw) {
@@ -251,6 +252,10 @@
         mStatsLogManager = null;
     }
 
+    public void setAssistantLongPressEnabled(boolean assistantLongPressEnabled) {
+        mAssistantLongPressEnabled = assistantLongPressEnabled;
+    }
+
     private void logEvent(StatsLogManager.LauncherEvent event) {
         if (mStatsLogManager == null) {
             Log.w(TAG, "No stats log manager to log taskbar button event");
@@ -289,7 +294,7 @@
     }
 
     private void startAssistant() {
-        if (mScreenPinned) {
+        if (mScreenPinned || !mAssistantLongPressEnabled) {
             return;
         }
         Bundle args = new Bundle();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 9b27c9d..30d6eb4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -17,11 +17,9 @@
 
 import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
 
-import android.content.ClipDescription;
 import android.content.Intent;
 import android.content.pm.LauncherApps;
 import android.graphics.Point;
-import android.os.Bundle;
 import android.util.Pair;
 import android.view.MotionEvent;
 import android.view.View;
@@ -46,6 +44,7 @@
 import com.android.launcher3.popup.PopupLiveUpdateHandler;
 import com.android.launcher3.popup.SystemShortcut;
 import com.android.launcher3.shortcuts.DeepShortcutView;
+import com.android.launcher3.splitscreen.SplitShortcut;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.LauncherBindableItemsContainer;
 import com.android.launcher3.util.PackageUserKey;
@@ -75,7 +74,7 @@
 
     // Initialized in init.
     private TaskbarControllers mControllers;
-    private boolean mHideSplitOptions;
+    private boolean mAllowInitialSplitSelection;
 
     public TaskbarPopupController(TaskbarActivityContext context) {
         mContext = context;
@@ -101,8 +100,8 @@
         mPopupDataProvider.setDeepShortcutMap(deepShortcutMapCopy);
     }
 
-    public void setHideSplitOptions(boolean hideSplitOptions) {
-        mHideSplitOptions = hideSplitOptions;
+    public void setAllowInitialSplitSelection(boolean allowInitialSplitSelection) {
+        mAllowInitialSplitSelection = allowInitialSplitSelection;
     }
 
     private void updateNotificationDots(Predicate<PackageUserKey> updatedDots) {
@@ -188,13 +187,9 @@
     }
 
     // Create a Stream of all applicable system shortcuts
-    // TODO(b/227800345): Add "Split bottom" option when tablet is in portrait mode.
     private Stream<SystemShortcut.Factory> getSystemShortcuts() {
         // concat a Stream of split options with a Stream of APP_INFO
         Stream<SystemShortcut.Factory> appInfo = Stream.of(APP_INFO);
-        if (mHideSplitOptions) {
-            return appInfo;
-        }
 
         return Stream.concat(
                 Utilities.getSplitPositionOptions(mContext.getDeviceProfile())
@@ -261,7 +256,7 @@
     private SystemShortcut.Factory<BaseTaskbarContext> createSplitShortcutFactory(
             SplitPositionOption position) {
         return (context, itemInfo, originalView) -> new TaskbarSplitShortcut(context, itemInfo,
-                originalView, position);
+                originalView, position, mAllowInitialSplitSelection);
     }
 
      /**
@@ -269,32 +264,43 @@
      * from the taskbar, as if the user performed a drag and drop split.
      * Includes an onClick method that initiates the actual split.
      */
-    private static class TaskbarSplitShortcut extends SystemShortcut<BaseTaskbarContext> {
-        private final SplitPositionOption mPosition;
+    private static class TaskbarSplitShortcut extends
+             SplitShortcut<BaseTaskbarContext> {
+         /**
+          * If {@code true}, clicking this shortcut will not attempt to start a split app directly,
+          * but be the first app in split selection mode
+          */
+         private final boolean mAllowInitialSplitSelection;
 
-        TaskbarSplitShortcut(BaseTaskbarContext context, ItemInfo itemInfo, View originalView,
-                SplitPositionOption position) {
-            super(position.iconResId, position.textResId, context, itemInfo, originalView);
-            mPosition = position;
-        }
+         TaskbarSplitShortcut(BaseTaskbarContext context, ItemInfo itemInfo, View originalView,
+                SplitPositionOption position, boolean allowInitialSplitSelection) {
+             super(position.iconResId, position.textResId, context, itemInfo, originalView,
+                     position);
+             mAllowInitialSplitSelection = allowInitialSplitSelection;
+         }
 
         @Override
         public void onClick(View view) {
+            AbstractFloatingView.closeAllOpenViews(mTarget);
+             if (mAllowInitialSplitSelection) {
+                 super.onClick(view);
+                 return;
+             }
+
             // Initiate splitscreen from the in-app Taskbar or Taskbar All Apps
             Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
                     LogUtils.getShellShareableInstanceId();
             mTarget.getStatsLogManager().logger()
                     .withItemInfo(mItemInfo)
                     .withInstanceId(instanceIds.second)
-                    .log(getLogEventForPosition(mPosition.stagePosition));
+                    .log(getLogEventForPosition(getPosition().stagePosition));
 
-            AbstractFloatingView.closeAllOpenViews(mTarget);
             if (mItemInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
                 WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) mItemInfo;
                 SystemUiProxy.INSTANCE.get(mTarget).startShortcut(
                         workspaceItemInfo.getIntent().getPackage(),
                         workspaceItemInfo.getDeepShortcutId(),
-                        mPosition.stagePosition,
+                        getPosition().stagePosition,
                         null,
                         workspaceItemInfo.user,
                         instanceIds.first);
@@ -305,7 +311,7 @@
                                 null,
                                 mItemInfo.user),
                         new Intent(),
-                        mPosition.stagePosition,
+                        getPosition().stagePosition,
                         null,
                         instanceIds.first);
             }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index c269648..a717136 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -35,7 +35,6 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
-import android.annotation.Nullable;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.util.Log;
@@ -44,6 +43,7 @@
 import android.view.ViewConfiguration;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.jank.InteractionJankMonitor;
@@ -69,8 +69,6 @@
  */
 public class TaskbarStashController implements TaskbarControllers.LoggableTaskbarController {
 
-    private static final String TAG = "TaskbarStashController";
-
     public static final int FLAG_IN_APP = 1 << 0;
     public static final int FLAG_STASHED_IN_APP_MANUAL = 1 << 1; // long press, persisted
     public static final int FLAG_STASHED_IN_SYSUI_STATE = 1 << 2; // app pinning, keyguard, etc.
@@ -185,12 +183,13 @@
             flags -> {
                 boolean inApp = hasAnyFlag(flags, FLAGS_IN_APP);
                 boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP);
+                boolean stashedSysUIState = hasAnyFlag(flags, FLAG_STASHED_IN_SYSUI_STATE);
                 boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE);
                 boolean stashedInTaskbarAllApps =
                         hasAnyFlag(flags, FLAG_STASHED_IN_TASKBAR_ALL_APPS);
                 boolean stashedForSmallScreen = hasAnyFlag(flags, FLAG_STASHED_SMALL_SCREEN);
                 return (inApp && stashedInApp) || (!inApp && stashedLauncherState)
-                        || stashedInTaskbarAllApps || stashedForSmallScreen;
+                        || stashedInTaskbarAllApps || stashedForSmallScreen || stashedSysUIState;
             });
 
     public TaskbarStashController(TaskbarActivityContext activity) {
@@ -364,13 +363,18 @@
      * Returns the height that taskbar will be touchable.
      */
     public int getTouchableHeight() {
-        return mIsStashed ? mStashedHeight : mUnstashedHeight;
+        int bottomMargin = 0;
+        if (DisplayController.isTransientTaskbar(mActivity)) {
+            bottomMargin = mActivity.getResources().getDimensionPixelSize(
+                    R.dimen.transient_taskbar_margin);
+        }
+        return mIsStashed ? mStashedHeight : (mUnstashedHeight + bottomMargin);
     }
 
     /**
      * Returns the height that taskbar will inset when inside apps.
-     * @see WindowInsets.Type#navigationBars()
-     * @see WindowInsets.Type#systemBars()
+     * @see android.view.WindowInsets.Type#navigationBars()
+     * @see android.view.WindowInsets.Type#systemBars()
      */
     public int getContentHeightToReportToApps() {
         if ((isPhoneMode() && !mActivity.isThreeButtonNav())
@@ -403,7 +407,7 @@
 
     /**
      * Returns the height that taskbar will inset when inside apps.
-     * @see WindowInsets.Type#tappableElement()
+     * @see android.view.WindowInsets.Type#tappableElement()
      */
     public int getTappableHeightToReportToApps() {
         int contentHeight = getContentHeightToReportToApps();
@@ -422,6 +426,11 @@
             return;
         }
 
+        if (stash && mControllers.taskbarAutohideSuspendController.isSuspended()) {
+            // Avoid stashing if autohide is currently suspended.
+            return;
+        }
+
         if (hasAnyFlag(FLAG_STASHED_IN_APP_AUTO) != stash) {
             updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, stash);
             applyState();
@@ -489,7 +498,6 @@
         createAnimToIsStashed(
                 /* isStashed= */ false,
                 placeholderDuration,
-                /* startDelay= */ 0,
                 /* animateBg= */ false,
                 /* changedFlags=*/ 0);
         animation.play(mAnimator);
@@ -499,11 +507,10 @@
      * Create a stash animation and save to {@link #mAnimator}.
      * @param isStashed whether it's a stash animation or an unstash animation
      * @param duration duration of the animation
-     * @param startDelay how many milliseconds to delay the animation after starting it.
      * @param animateBg whether the taskbar's background should be animated
      */
-    private void createAnimToIsStashed(boolean isStashed, long duration, long startDelay,
-            boolean animateBg, int changedFlags) {
+    private void createAnimToIsStashed(boolean isStashed, long duration, boolean animateBg,
+            int changedFlags) {
         if (mAnimator != null) {
             mAnimator.cancel();
         }
@@ -523,13 +530,7 @@
                     .setDuration(duration));
             mAnimator.play(mTaskbarImeBgAlpha.animateToValue(
                     hasAnyFlag(FLAG_STASHED_IN_APP_IME) ? 0 : 1).setDuration(duration));
-            mAnimator.setStartDelay(startDelay);
-            mAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mAnimator = null;
-                }
-            });
+            mAnimator.addListener(AnimatorListeners.forEndCallback(() -> mAnimator = null));
             return;
         }
 
@@ -610,7 +611,6 @@
 
         mAnimator.playTogether(fullLengthAnimatorSet, firstHalfAnimatorSet,
                 secondHalfAnimatorSet);
-        mAnimator.setStartDelay(startDelay);
         mAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
@@ -696,19 +696,28 @@
     }
 
     public void applyState(long duration) {
-        mStatePropertyHolder.setState(mState, duration, true);
+        Animator animator = createApplyStateAnimator(duration);
+        if (animator != null) {
+            animator.start();
+        }
     }
 
     public void applyState(long duration, long startDelay) {
-        mStatePropertyHolder.setState(mState, duration, startDelay, true);
+        Animator animator = createApplyStateAnimator(duration);
+        if (animator != null) {
+            animator.setStartDelay(startDelay);
+            animator.start();
+        }
     }
 
-    public Animator applyStateWithoutStart() {
-        return applyStateWithoutStart(TASKBAR_STASH_DURATION);
-    }
 
-    public Animator applyStateWithoutStart(long duration) {
-        return mStatePropertyHolder.setState(mState, duration, false);
+    /**
+     * Returns an animator which applies the latest state if mIsStashed is changed, or {@code null}
+     * otherwise.
+     */
+    @Nullable
+    public Animator createApplyStateAnimator(long duration) {
+        return mStatePropertyHolder.createSetStateAnimator(mState, duration);
     }
 
     /**
@@ -943,22 +952,14 @@
         }
 
         /**
-         * @see #setState(int, long, long, boolean) with a default startDelay = 0.
-         */
-        public Animator setState(int flags, long duration, boolean start) {
-            return setState(flags, duration, 0 /* startDelay */, start);
-        }
-
-        /**
-         * Applies the latest state, potentially calling onStateChangeApplied() and creating a new
-         * animation (stored in mAnimator) which is started if {@param start} is true.
+         * Creates an animator (stored in mAnimator) which applies the latest state, potentially
+         * creating a new animation (stored in mAnimator).
          * @param flags The latest flags to apply (see the top of this file).
          * @param duration The length of the animation.
-         * @param startDelay How long to delay the animation after calling start().
-         * @param start Whether to start mAnimator immediately.
-         * @return mAnimator if mIsStashed changed, else null.
+         * @return mAnimator if mIsStashed changed, or {@code null} otherwise.
          */
-        public Animator setState(int flags, long duration, long startDelay, boolean start) {
+        @Nullable
+        public Animator createSetStateAnimator(int flags, long duration) {
             int changedFlags = mPrevFlags ^ flags;
             if (mPrevFlags != flags) {
                 onStateChangeApplied(changedFlags);
@@ -974,21 +975,16 @@
                     && mAnimator != null && mAnimator.isStarted())) {
                 if (TestProtocol.sDebugTracing) {
                     Log.d(TestProtocol.TASKBAR_IN_APP_STATE, String.format(
-                            "setState: mIsStashed=%b, isStashed=%b, duration=%d, start=:%b",
+                            "setState: mIsStashed=%b, isStashed=%b, duration=%d",
                             mIsStashed,
                             isStashed,
-                            duration,
-                            start));
+                            duration));
                 }
                 mIsStashed = isStashed;
                 mIsHotseatIconOnTopWhenAligned = isHotseatIconOnTopWhenAligned;
 
                 // This sets mAnimator.
-                createAnimToIsStashed(
-                        mIsStashed, duration, startDelay, /* animateBg= */ true, changedFlags);
-                if (start) {
-                    mAnimator.start();
-                }
+                createAnimToIsStashed(mIsStashed, duration, /* animateBg= */ true, changedFlags);
                 return mAnimator;
             }
             return null;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
index 5dba444..586115d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
@@ -109,8 +109,12 @@
                 .setStiffness(SpringForce.STIFFNESS_LOW)
                 .build(mTranslationYForSwipe, VALUE);
         mSpringBounce.addListener(forEndCallback(() -> {
-            if (mGestureEnded) {
-                reset();
+            if (!mGestureEnded) {
+                return;
+            }
+            reset();
+            if (mControllers.taskbarStashController.isInAppAndNotStashed()) {
+                mControllers.taskbarEduTooltipController.maybeShowFeaturesEdu();
             }
         }));
         mSpringBounce.start();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 7b03746..1c11bf7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -15,6 +15,8 @@
  */
 package com.android.launcher3.taskbar;
 
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+
 import android.content.Intent;
 import android.graphics.drawable.BitmapDrawable;
 import android.view.MotionEvent;
@@ -26,6 +28,7 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task;
@@ -165,12 +168,29 @@
         return null;
     }
 
+    public void startSplitSelection(SplitConfigurationOptions.SplitSelectSource splitSelectSource) {
+        RecentsView recentsView = getRecentsView();
+        if (recentsView == null) {
+            return;
+        }
+        recentsView.findLastActiveTaskAndRunCallback(
+                splitSelectSource.intent.getComponent(),
+                (Consumer<Task>) foundTask -> {
+                    splitSelectSource.alreadyRunningTaskId = foundTask == null
+                            ? INVALID_TASK_ID
+                            : foundTask.key.id;
+                    splitSelectSource.animateCurrentTaskDismissal = foundTask != null;
+                    recentsView.initiateSplitSelect(splitSelectSource);
+                }
+        );
+    }
+
     /**
      * Uses the clicked Taskbar icon to launch a second app for splitscreen.
      */
     public void triggerSecondAppForSplit(ItemInfoWithIcon info, Intent intent, View startingView) {
         RecentsView recents = getRecentsView();
-        recents.findLastActiveTaskAndDoSplitOperation(
+        recents.findLastActiveTaskAndRunCallback(
                 info.getTargetComponent(),
                 (Consumer<Task>) foundTask -> {
                     if (foundTask != null) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 2433a34..db584d8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -15,8 +15,9 @@
  */
 package com.android.launcher3.taskbar;
 
+import static android.content.pm.PackageManager.FEATURE_PC;
+
 import android.content.Context;
-import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Rect;
@@ -81,6 +82,9 @@
     // Only non-null when device supports having an All Apps button.
     private @Nullable View mAllAppsButton;
 
+    // Only non-null when device supports having an All Apps button.
+    private @Nullable View mTaskbarDivider;
+
     private View mQsb;
 
     public TaskbarView(@NonNull Context context) {
@@ -101,16 +105,15 @@
         super(context, attrs, defStyleAttr, defStyleRes);
         mActivityContext = ActivityContext.lookupContext(context);
         mIconLayoutBounds = mActivityContext.getTransientTaskbarBounds();
-        mIsRtl = Utilities.isRtl(getResources());
-
         Resources resources = getResources();
-        mIconTouchSize = resources.getDimensionPixelSize(R.dimen.taskbar_icon_touch_size);
+        mIsRtl = Utilities.isRtl(resources);
 
-        int actualMargin = DisplayController.isTransientTaskbar(mActivityContext)
-                ? resources.getDimensionPixelSize(R.dimen.transient_taskbar_icon_spacing)
-                : resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
+        int actualMargin = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
         int actualIconSize = mActivityContext.getDeviceProfile().iconSizePx;
 
+        mIconTouchSize = Math.max(actualIconSize,
+                resources.getDimensionPixelSize(R.dimen.taskbar_icon_min_touch_size));
+
         // We layout the icons to be of mIconTouchSize in width and height
         mItemMarginLeftRight = actualMargin - (mIconTouchSize - actualIconSize) / 2;
         mItemPadding = (mIconTouchSize - actualIconSize) / 2;
@@ -120,13 +123,16 @@
 
         mThemeIconsBackground = calculateThemeIconsBackground();
 
-        if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
+        if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()
+                && !mActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
             mAllAppsButton = LayoutInflater.from(context)
                     .inflate(R.layout.taskbar_all_apps_button, this, false);
             mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
             mAllAppsButton.setScaleX(mIsRtl ? -1 : 1);
-            if (mActivityContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PC)) {
-                mAllAppsButton.setVisibility(GONE);
+
+            if (FeatureFlags.ENABLE_TASKBAR_PINNING.get()) {
+                mTaskbarDivider = LayoutInflater.from(context).inflate(R.layout.taskbar_divider,
+                        this, false);
             }
         }
 
@@ -160,6 +166,9 @@
         if (mAllAppsButton != null) {
             mAllAppsButton.setOnClickListener(mControllerCallbacks.getAllAppsButtonClickListener());
         }
+        if (mTaskbarDivider != null) {
+            //TODO(b/265434705): set long press listener
+        }
     }
 
     private void removeAndRecycle(View view) {
@@ -181,6 +190,10 @@
 
         if (mAllAppsButton != null) {
             removeView(mAllAppsButton);
+
+            if (mTaskbarDivider != null) {
+                removeView(mTaskbarDivider);
+            }
         }
         removeView(mQsb);
 
@@ -257,8 +270,11 @@
         }
 
         if (mAllAppsButton != null) {
-            int index = mIsRtl ? getChildCount() : 0;
-            addView(mAllAppsButton, index);
+            addView(mAllAppsButton, mIsRtl ? getChildCount() : 0);
+
+            if (mTaskbarDivider != null) {
+                addView(mTaskbarDivider, mIsRtl ? (getChildCount() - 1) : 1);
+            }
         }
         if (mActivityContext.getDeviceProfile().isQsbInline) {
             addView(mQsb, mIsRtl ? getChildCount() : 0);
@@ -329,6 +345,11 @@
                 int qsbTop = (bottom - top - deviceProfile.hotseatQsbHeight) / 2;
                 int qsbBottom = qsbTop + deviceProfile.hotseatQsbHeight;
                 child.layout(qsbStart, qsbTop, qsbEnd, qsbBottom);
+            } else if (child == mTaskbarDivider) {
+                iconEnd += mItemMarginLeftRight;
+                int iconStart = iconEnd - mIconTouchSize;
+                child.layout(iconStart, mIconLayoutBounds.top, iconEnd, mIconLayoutBounds.bottom);
+                iconEnd = iconStart + mItemMarginLeftRight;
             } else {
                 iconEnd -= mItemMarginLeftRight;
                 int iconStart = iconEnd - mIconTouchSize;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 168c353..69f79ba 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -79,9 +79,8 @@
     public static final int ALPHA_INDEX_RECENTS_DISABLED = 3;
     public static final int ALPHA_INDEX_NOTIFICATION_EXPANDED = 4;
     public static final int ALPHA_INDEX_ASSISTANT_INVOKED = 5;
-    public static final int ALPHA_INDEX_IME_BUTTON_NAV = 6;
-    public static final int ALPHA_INDEX_SMALL_SCREEN = 7;
-    private static final int NUM_ALPHA_CHANNELS = 8;
+    public static final int ALPHA_INDEX_SMALL_SCREEN = 6;
+    private static final int NUM_ALPHA_CHANNELS = 7;
 
     private final TaskbarActivityContext mActivity;
     private final TaskbarView mTaskbarView;
@@ -201,14 +200,6 @@
     }
 
     /**
-     * Should be called when the IME switcher visibility changes.
-     */
-    public void setIsImeSwitcherVisible(boolean isImeSwitcherVisible) {
-        mTaskbarIconAlpha.get(ALPHA_INDEX_IME_BUTTON_NAV).setValue(
-                isImeSwitcherVisible ? 0 : 1);
-    }
-
-    /**
      * Should be called when the recents button is disabled, so we can hide taskbar icons as well.
      */
     public void setRecentsButtonDisabled(boolean isDisabled) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
index a033507..be34fb1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
@@ -10,12 +10,9 @@
 private const val TASKBAR_ICONS_FADE_DURATION = 300L
 private const val STASHED_HANDLE_FADE_DURATION = 180L
 
-/**
- * Controls Taskbar behavior while Voice Interaction Window (assistant) is showing.
- */
-class VoiceInteractionWindowController(val context: TaskbarActivityContext)
-    : TaskbarControllers.LoggableTaskbarController,
-        TaskbarControllers.BackgroundRendererController {
+/** Controls Taskbar behavior while Voice Interaction Window (assistant) is showing. */
+class VoiceInteractionWindowController(val context: TaskbarActivityContext) :
+    TaskbarControllers.LoggableTaskbarController, TaskbarControllers.BackgroundRendererController {
 
     private val taskbarBackgroundRenderer = TaskbarBackgroundRenderer(context)
 
@@ -37,8 +34,10 @@
 
                 override fun draw(canvas: Canvas) {
                     super.draw(canvas)
-                    if (this@VoiceInteractionWindowController.context.isGestureNav
-                        && controllers.taskbarStashController.isInAppAndNotStashed) {
+                    if (
+                        this@VoiceInteractionWindowController.context.isGestureNav &&
+                            controllers.taskbarStashController.isInAppAndNotStashed
+                    ) {
                         taskbarBackgroundRenderer.draw(canvas)
                     }
                 }
@@ -46,8 +45,8 @@
         separateWindowForTaskbarBackground.recreateControllers()
         separateWindowForTaskbarBackground.setWillNotDraw(false)
 
-        separateWindowLayoutParams = context.createDefaultWindowLayoutParams(
-            TYPE_APPLICATION_OVERLAY)
+        separateWindowLayoutParams =
+            context.createDefaultWindowLayoutParams(TYPE_APPLICATION_OVERLAY)
         separateWindowLayoutParams.isSystemApplicationOverlay = true
     }
 
@@ -63,14 +62,16 @@
 
         // Fade out taskbar icons and stashed handle.
         val taskbarIconAlpha = if (isVoiceInteractionWindowVisible) 0f else 1f
-        val fadeTaskbarIcons = controllers.taskbarViewController.taskbarIconAlpha
-            .get(TaskbarViewController.ALPHA_INDEX_ASSISTANT_INVOKED)
-            .animateToValue(taskbarIconAlpha)
-            .setDuration(TASKBAR_ICONS_FADE_DURATION)
-        val fadeStashedHandle = controllers.stashedHandleViewController.stashedHandleAlpha
-            .get(StashedHandleViewController.ALPHA_INDEX_ASSISTANT_INVOKED)
-            .animateToValue(taskbarIconAlpha)
-            .setDuration(STASHED_HANDLE_FADE_DURATION)
+        val fadeTaskbarIcons =
+            controllers.taskbarViewController.taskbarIconAlpha
+                .get(TaskbarViewController.ALPHA_INDEX_ASSISTANT_INVOKED)
+                .animateToValue(taskbarIconAlpha)
+                .setDuration(TASKBAR_ICONS_FADE_DURATION)
+        val fadeStashedHandle =
+            controllers.stashedHandleViewController.stashedHandleAlpha
+                .get(StashedHandleViewController.ALPHA_INDEX_ASSISTANT_INVOKED)
+                .animateToValue(taskbarIconAlpha)
+                .setDuration(STASHED_HANDLE_FADE_DURATION)
         fadeTaskbarIcons.start()
         fadeStashedHandle.start()
         if (skipAnim) {
@@ -83,23 +84,30 @@
 
     /**
      * Either:
+     *
      * Hides the TaskbarDragLayer background and creates a new window to draw just that background.
+     *
      * OR
+     *
      * Removes the temporary window and show the TaskbarDragLayer background again.
      */
     private fun moveTaskbarBackgroundToAppropriateLayer(skipAnim: Boolean) {
-        val taskbarBackgroundOverride = controllers.taskbarDragLayerController
-            .overrideBackgroundAlpha
+        val taskbarBackgroundOverride =
+            controllers.taskbarDragLayerController.overrideBackgroundAlpha
         val moveToLowerLayer = isVoiceInteractionWindowVisible
-        val onWindowsSynchronized = if (moveToLowerLayer) {
-            // First add the temporary window, then hide the overlapping taskbar background.
-            context.addWindowView(separateWindowForTaskbarBackground, separateWindowLayoutParams);
-            { taskbarBackgroundOverride.updateValue(0f) }
-        } else {
-            // First reapply the original taskbar background, then remove the temporary window.
-            taskbarBackgroundOverride.updateValue(1f);
-            { context.removeWindowView(separateWindowForTaskbarBackground) }
-        }
+        val onWindowsSynchronized =
+            if (moveToLowerLayer) {
+                // First add the temporary window, then hide the overlapping taskbar background.
+                context.addWindowView(
+                    separateWindowForTaskbarBackground,
+                    separateWindowLayoutParams
+                );
+                { taskbarBackgroundOverride.updateValue(0f) }
+            } else {
+                // First reapply the original taskbar background, then remove the temporary window.
+                taskbarBackgroundOverride.updateValue(1f);
+                { context.removeWindowView(separateWindowForTaskbarBackground) }
+            }
 
         if (skipAnim) {
             onWindowsSynchronized()
@@ -121,4 +129,4 @@
         pw.println(prefix + "VoiceInteractionWindowController:")
         pw.println("$prefix\tisVoiceInteractionWindowVisible=$isVoiceInteractionWindowVisible")
     }
-}
\ No newline at end of file
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
index 68ea27a..a82902f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
@@ -30,20 +30,17 @@
  * [navButtonContainer]
  *
  * @property navButtonContainer ViewGroup that holds the 3 navigation buttons.
- * @property endContextualContainer ViewGroup that holds the end contextual button (ex, IME dismiss).
+ * @property endContextualContainer ViewGroup that holds the end contextual button (ex, IME
+ * dismiss).
  * @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
+    val resources: Resources,
+    val navButtonContainer: LinearLayout,
+    protected val endContextualContainer: ViewGroup,
+    protected val startContextualContainer: ViewGroup
 ) : NavButtonLayoutter {
-    protected val homeButton: ImageView = navButtonContainer
-            .findViewById(R.id.home)
-    protected val recentsButton: ImageView = navButtonContainer
-            .findViewById(R.id.recent_apps)
-    protected val backButton: ImageView = navButtonContainer
-            .findViewById(R.id.back)
+    protected val homeButton: ImageView = navButtonContainer.findViewById(R.id.home)
+    protected val recentsButton: ImageView = navButtonContainer.findViewById(R.id.recent_apps)
+    protected val backButton: ImageView = navButtonContainer.findViewById(R.id.back)
 }
-
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt
index c67ab79..c093c92 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt
@@ -35,56 +35,47 @@
 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.DRAWABLE_SYSBAR_HOME_KIDS
 
 class KidsNavLayoutter(
-        resources: Resources,
-        navBarContainer: LinearLayout,
-        endContextualContainer: ViewGroup,
-        startContextualContainer: ViewGroup
-) : AbstractNavButtonLayoutter(
+    resources: Resources,
+    navBarContainer: LinearLayout,
+    endContextualContainer: ViewGroup,
+    startContextualContainer: ViewGroup
+) :
+    AbstractNavButtonLayoutter(
         resources,
         navBarContainer,
         endContextualContainer,
         startContextualContainer
-) {
+    ) {
 
     override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
-        val iconSize: Int = resources.getDimensionPixelSize(
-                DIMEN_TASKBAR_ICON_SIZE_KIDS)
-        val buttonWidth: Int = resources.getDimensionPixelSize(
-                DIMEN_TASKBAR_NAV_BUTTONS_WIDTH_KIDS)
-        val buttonHeight: Int = resources.getDimensionPixelSize(
-                DIMEN_TASKBAR_NAV_BUTTONS_HEIGHT_KIDS)
-        val buttonRadius: Int = resources.getDimensionPixelSize(
-                DIMEN_TASKBAR_NAV_BUTTONS_CORNER_RADIUS_KIDS)
+        val iconSize: Int = resources.getDimensionPixelSize(DIMEN_TASKBAR_ICON_SIZE_KIDS)
+        val buttonWidth: Int = resources.getDimensionPixelSize(DIMEN_TASKBAR_NAV_BUTTONS_WIDTH_KIDS)
+        val buttonHeight: Int =
+            resources.getDimensionPixelSize(DIMEN_TASKBAR_NAV_BUTTONS_HEIGHT_KIDS)
+        val buttonRadius: Int =
+            resources.getDimensionPixelSize(DIMEN_TASKBAR_NAV_BUTTONS_CORNER_RADIUS_KIDS)
         val paddingLeft = (buttonWidth - iconSize) / 2
         val paddingTop = (buttonHeight - iconSize) / 2
 
         // Update icons
-        backButton.setImageDrawable(
-                backButton.context.getDrawable(DRAWABLE_SYSBAR_BACK_KIDS))
+        backButton.setImageDrawable(backButton.context.getDrawable(DRAWABLE_SYSBAR_BACK_KIDS))
         backButton.scaleType = ImageView.ScaleType.FIT_CENTER
         backButton.setPadding(paddingLeft, paddingTop, paddingLeft, paddingTop)
-        homeButton.setImageDrawable(
-                homeButton.getContext().getDrawable(DRAWABLE_SYSBAR_HOME_KIDS))
+        homeButton.setImageDrawable(homeButton.getContext().getDrawable(DRAWABLE_SYSBAR_HOME_KIDS))
         homeButton.scaleType = ImageView.ScaleType.FIT_CENTER
         homeButton.setPadding(paddingLeft, paddingTop, paddingLeft, paddingTop)
 
         // Home button layout
-        val homeLayoutparams = LinearLayout.LayoutParams(
-                buttonWidth,
-                buttonHeight
-        )
-        val homeButtonLeftMargin: Int = resources.getDimensionPixelSize(
-                DIMEN_TASKBAR_HOME_BUTTON_LEFT_MARGIN_KIDS)
+        val homeLayoutparams = LinearLayout.LayoutParams(buttonWidth, buttonHeight)
+        val homeButtonLeftMargin: Int =
+            resources.getDimensionPixelSize(DIMEN_TASKBAR_HOME_BUTTON_LEFT_MARGIN_KIDS)
         homeLayoutparams.setMargins(homeButtonLeftMargin, 0, 0, 0)
         homeButton.layoutParams = homeLayoutparams
 
         // Back button layout
-        val backLayoutParams = LinearLayout.LayoutParams(
-                buttonWidth,
-                buttonHeight
-        )
-        val backButtonLeftMargin: Int = resources.getDimensionPixelSize(
-                DIMEN_TASKBAR_BACK_BUTTON_LEFT_MARGIN_KIDS)
+        val backLayoutParams = LinearLayout.LayoutParams(buttonWidth, buttonHeight)
+        val backButtonLeftMargin: Int =
+            resources.getDimensionPixelSize(DIMEN_TASKBAR_BACK_BUTTON_LEFT_MARGIN_KIDS)
         backLayoutParams.setMargins(backButtonLeftMargin, 0, 0, 0)
         backButton.layoutParams = backLayoutParams
 
@@ -106,4 +97,4 @@
 
         homeButton.onLongClickListener = null
     }
-}
\ No newline at end of file
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
index db0a2d8..2092721 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
@@ -30,10 +30,9 @@
 /**
  * Select the correct layout for nav buttons
  *
- * Since layouts are done dynamically for the nav buttons on Taskbar, this
- * class returns a corresponding [NavButtonLayoutter] via
- * [Companion.getUiLayoutter]
- * that can help position the buttons based on the current [DeviceProfile]
+ * Since layouts are done dynamically for the nav buttons on Taskbar, this class returns a
+ * corresponding [NavButtonLayoutter] via [Companion.getUiLayoutter] that can help position the
+ * buttons based on the current [DeviceProfile]
  */
 class NavButtonLayoutFactory {
     companion object {
@@ -41,11 +40,10 @@
          * Get the correct instance of [NavButtonLayoutter]
          *
          * No layouts supported for configurations where:
-         *  * taskbar isn't showing AND
-         *  * the device is not in [phoneMode]
-         * OR
-         *  * phone is showing
-         *  * device is using gesture navigation
+         * * taskbar isn't showing AND
+         * * the device is not in [phoneMode] OR
+         * * phone is showing
+         * * device is using gesture navigation
          *
          * @param navButtonsView ViewGroup that contains start, end, nav button ViewGroups
          * @param isKidsMode no-op when taskbar is hidden/not showing
@@ -53,44 +51,64 @@
          * @param phoneMode refers to the device using the taskbar window on phones
          * @param isThreeButtonNav are no-ops when taskbar is present/showing
          */
-        fun getUiLayoutter(deviceProfile: DeviceProfile,
-                           navButtonsView: FrameLayout,
-                           resources: Resources,
-                           isKidsMode: Boolean,
-                           isInSetup: Boolean,
-                           isThreeButtonNav: Boolean,
-                           phoneMode: Boolean):
-                NavButtonLayoutter {
-            val navButtonContainer =
-                    navButtonsView.findViewById<LinearLayout>(ID_END_NAV_BUTTONS)
+        fun getUiLayoutter(
+            deviceProfile: DeviceProfile,
+            navButtonsView: FrameLayout,
+            resources: Resources,
+            isKidsMode: Boolean,
+            isInSetup: Boolean,
+            isThreeButtonNav: Boolean,
+            phoneMode: Boolean
+        ): NavButtonLayoutter {
+            val navButtonContainer = navButtonsView.findViewById<LinearLayout>(ID_END_NAV_BUTTONS)
             val endContextualContainer =
-                    navButtonsView.findViewById<ViewGroup>(ID_END_CONTEXTUAL_BUTTONS)
+                navButtonsView.findViewById<ViewGroup>(ID_END_CONTEXTUAL_BUTTONS)
             val startContextualContainer =
-                    navButtonsView.findViewById<ViewGroup>(ID_START_CONTEXTUAL_BUTTONS)
+                navButtonsView.findViewById<ViewGroup>(ID_START_CONTEXTUAL_BUTTONS)
             val isPhoneNavMode = phoneMode && isThreeButtonNav
             return when {
                 isPhoneNavMode -> {
                     if (!deviceProfile.isLandscape) {
-                        PhonePortraitNavLayoutter(resources, navButtonContainer,
-                                endContextualContainer, startContextualContainer)
+                        PhonePortraitNavLayoutter(
+                            resources,
+                            navButtonContainer,
+                            endContextualContainer,
+                            startContextualContainer
+                        )
                     } else {
-                        PhoneLandscapeNavLayoutter(resources, navButtonContainer,
-                                endContextualContainer, startContextualContainer)
+                        PhoneLandscapeNavLayoutter(
+                            resources,
+                            navButtonContainer,
+                            endContextualContainer,
+                            startContextualContainer
+                        )
                     }
                 }
                 deviceProfile.isTaskbarPresent -> {
                     return when {
                         isInSetup -> {
-                            SetupNavLayoutter(resources, navButtonContainer, endContextualContainer,
-                                    startContextualContainer)
+                            SetupNavLayoutter(
+                                resources,
+                                navButtonContainer,
+                                endContextualContainer,
+                                startContextualContainer
+                            )
                         }
                         isKidsMode -> {
-                            KidsNavLayoutter(resources, navButtonContainer, endContextualContainer,
-                                    startContextualContainer)
+                            KidsNavLayoutter(
+                                resources,
+                                navButtonContainer,
+                                endContextualContainer,
+                                startContextualContainer
+                            )
                         }
                         else ->
-                            TaskbarNavLayoutter(resources, navButtonContainer, endContextualContainer,
-                                    startContextualContainer)
+                            TaskbarNavLayoutter(
+                                resources,
+                                navButtonContainer,
+                                endContextualContainer,
+                                startContextualContainer
+                            )
                     }
                 }
                 else -> error("No layoutter found")
@@ -98,8 +116,8 @@
         }
     }
 
-    /** Lays out and provides access to the home, recents, and back buttons for various mischief  */
+    /** Lays out and provides access to the home, recents, and back buttons for various mischief */
     interface NavButtonLayoutter {
         fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean)
     }
-}
\ No newline at end of file
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt
index a89476e..201895f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt
@@ -28,24 +28,24 @@
 import com.android.launcher3.util.DimensionUtils
 
 class PhoneLandscapeNavLayoutter(
-        resources: Resources,
-        navBarContainer: LinearLayout,
-        endContextualContainer: ViewGroup,
-        startContextualContainer: ViewGroup
-) : AbstractNavButtonLayoutter(
+    resources: Resources,
+    navBarContainer: LinearLayout,
+    endContextualContainer: ViewGroup,
+    startContextualContainer: ViewGroup
+) :
+    AbstractNavButtonLayoutter(
         resources,
         navBarContainer,
         endContextualContainer,
         startContextualContainer
-) {
+    ) {
 
     override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
         // TODO(b/230395757): Polish pending, this is just to make it usable
         val navContainerParams = navButtonContainer.layoutParams as FrameLayout.LayoutParams
-        val endStartMargins =
-                resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
-        val taskbarDimensions = DimensionUtils.getTaskbarPhoneDimensions(dp, resources,
-                TaskbarManager.isPhoneMode(dp))
+        val endStartMargins = resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
+        val taskbarDimensions =
+            DimensionUtils.getTaskbarPhoneDimensions(dp, resources, TaskbarManager.isPhoneMode(dp))
         navButtonContainer.removeAllViews()
         navButtonContainer.orientation = LinearLayout.VERTICAL
 
@@ -68,7 +68,7 @@
 
         // Add the spaces in between the nav buttons
         val spaceInBetween: Int =
-                resources.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween_phone)
+            resources.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween_phone)
         navButtonContainer.children.forEachIndexed { i, navButton ->
             val buttonLayoutParams = navButton.layoutParams as LinearLayout.LayoutParams
             buttonLayoutParams.weight = 1f
@@ -86,4 +86,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt
index 275f59f..f7ac974 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt
@@ -26,17 +26,24 @@
 import com.android.launcher3.taskbar.TaskbarManager
 import com.android.launcher3.util.DimensionUtils
 
-class PhonePortraitNavLayoutter(resources: Resources, navBarContainer: LinearLayout,
-                                endContextualContainer: ViewGroup,
-                                startContextualContainer: ViewGroup) :
-        AbstractNavButtonLayoutter(resources, navBarContainer, endContextualContainer,
-                startContextualContainer) {
+class PhonePortraitNavLayoutter(
+    resources: Resources,
+    navBarContainer: LinearLayout,
+    endContextualContainer: ViewGroup,
+    startContextualContainer: ViewGroup
+) :
+    AbstractNavButtonLayoutter(
+        resources,
+        navBarContainer,
+        endContextualContainer,
+        startContextualContainer
+    ) {
 
     override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
         // TODO(b/230395757): Polish pending, this is just to make it usable
         val navContainerParams = navButtonContainer.layoutParams as FrameLayout.LayoutParams
-        val taskbarDimensions = DimensionUtils.getTaskbarPhoneDimensions(dp, resources,
-                TaskbarManager.isPhoneMode(dp))
+        val taskbarDimensions =
+            DimensionUtils.getTaskbarPhoneDimensions(dp, resources, TaskbarManager.isPhoneMode(dp))
         val endStartMargins = resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
         navContainerParams.width = taskbarDimensions.x
         navContainerParams.height = ViewGroup.LayoutParams.MATCH_PARENT
@@ -58,7 +65,7 @@
 
         // Add the spaces in between the nav buttons
         val spaceInBetween =
-                resources.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween_phone)
+            resources.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween_phone)
         for (i in 0 until navButtonContainer.childCount) {
             val navButton = navButtonContainer.getChildAt(i)
             val buttonLayoutParams = navButton.layoutParams as LinearLayout.LayoutParams
@@ -80,4 +87,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
index afe70d6..a24002c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
@@ -24,16 +24,17 @@
 import com.android.launcher3.DeviceProfile
 
 class SetupNavLayoutter(
-        resources: Resources,
-        navButtonContainer: LinearLayout,
-        endContextualContainer: ViewGroup,
-        startContextualContainer: ViewGroup
-) : AbstractNavButtonLayoutter(
+    resources: Resources,
+    navButtonContainer: LinearLayout,
+    endContextualContainer: ViewGroup,
+    startContextualContainer: ViewGroup
+) :
+    AbstractNavButtonLayoutter(
         resources,
         navButtonContainer,
         endContextualContainer,
         startContextualContainer
-) {
+    ) {
 
     override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
         // Since setup wizard only has back button enabled, it looks strange to be
@@ -46,4 +47,4 @@
         }
         navButtonContainer.requestLayout()
     }
-}
\ No newline at end of file
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
index b2ca2af..5ec7ca0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
@@ -24,20 +24,19 @@
 import com.android.launcher3.DeviceProfile
 import com.android.launcher3.R
 
-/**
- * Layoutter for showing 3 button navigation on large screen
- */
+/** Layoutter for showing 3 button navigation on large screen */
 class TaskbarNavLayoutter(
-        resources: Resources,
-        navBarContainer: LinearLayout,
-        endContextualContainer: ViewGroup,
-        startContextualContainer: ViewGroup
-) : AbstractNavButtonLayoutter(
+    resources: Resources,
+    navBarContainer: LinearLayout,
+    endContextualContainer: ViewGroup,
+    startContextualContainer: ViewGroup
+) :
+    AbstractNavButtonLayoutter(
         resources,
         navBarContainer,
         endContextualContainer,
         startContextualContainer
-) {
+    ) {
 
     override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
         // Add spacing after the end of the last nav button
@@ -80,4 +79,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
index 38b6dfd..3edb375 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
@@ -15,11 +15,12 @@
  */
 package com.android.launcher3.taskbar.overlay;
 
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+
 import android.content.Context;
 import android.view.View;
 
 import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.R;
 import com.android.launcher3.dot.DotInfo;
 import com.android.launcher3.model.data.ItemInfo;
@@ -29,8 +30,13 @@
 import com.android.launcher3.taskbar.TaskbarControllers;
 import com.android.launcher3.taskbar.TaskbarDragController;
 import com.android.launcher3.taskbar.TaskbarStashController;
+import com.android.launcher3.taskbar.TaskbarUIController;
 import com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView;
-import com.android.launcher3.util.OnboardingPrefs;
+import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
+import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.recents.model.Task;
+
+import java.util.function.Consumer;
 
 /**
  * Window context for the taskbar overlays such as All Apps and EDU.
@@ -40,7 +46,6 @@
  */
 public class TaskbarOverlayContext extends BaseTaskbarContext {
     private final TaskbarActivityContext mTaskbarContext;
-    private final OnboardingPrefs<TaskbarOverlayContext> mOnboardingPrefs;
 
     private final TaskbarOverlayController mOverlayController;
     private final TaskbarDragController mDragController;
@@ -49,6 +54,7 @@
     // We automatically stash taskbar when All Apps is opened in gesture navigation mode.
     private final boolean mWillTaskbarBeVisuallyStashed;
     private final int mStashedTaskbarHeight;
+    private final TaskbarUIController mUiController;
 
     public TaskbarOverlayContext(
             Context windowContext,
@@ -59,12 +65,13 @@
         mOverlayController = controllers.taskbarOverlayController;
         mDragController = new TaskbarDragController(this);
         mDragController.init(controllers);
-        mOnboardingPrefs = new OnboardingPrefs<>(this, LauncherPrefs.getPrefs(this));
         mDragLayer = new TaskbarOverlayDragLayer(this);
 
         TaskbarStashController taskbarStashController = controllers.taskbarStashController;
         mWillTaskbarBeVisuallyStashed = taskbarStashController.supportsVisualStashing();
         mStashedTaskbarHeight = taskbarStashController.getStashedHeight();
+
+        mUiController = controllers.uiController;
     }
 
     boolean willTaskbarBeVisuallyStashed() {
@@ -100,11 +107,6 @@
     }
 
     @Override
-    public OnboardingPrefs<TaskbarOverlayContext> getOnboardingPrefs() {
-        return mOnboardingPrefs;
-    }
-
-    @Override
     public boolean isBindingItems() {
         return mTaskbarContext.isBindingItems();
     }
@@ -120,6 +122,11 @@
     }
 
     @Override
+    public void startSplitSelection(SplitSelectSource splitSelectSource) {
+        mUiController.startSplitSelection(splitSelectSource);
+    }
+
+    @Override
     public DotInfo getDotInfoForItem(ItemInfo info) {
         return mTaskbarContext.getDotInfoForItem(info);
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
index 044afd6..d91b650 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
@@ -71,7 +71,8 @@
     public boolean dispatchKeyEvent(KeyEvent event) {
         if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
             AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
-            if (topView != null && topView.onBackPressed()) {
+            if (topView != null && topView.canHandleBack()) {
+                topView.onBackInvoked();
                 return true;
             }
         }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 9be569e..abbd01d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -15,6 +15,9 @@
  */
 package com.android.launcher3.uioverrides;
 
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.os.Trace.TRACE_TAG_APP;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OPTIMIZE_MEASURE;
 import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
 
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
@@ -30,6 +33,7 @@
 import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
 import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_WIDGET_PICKER_DEPTH;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
 import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
@@ -43,10 +47,12 @@
 import static com.android.launcher3.testing.shared.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
 import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
 import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
-import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.quickstep.util.SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
 import android.app.ActivityManager;
@@ -56,6 +62,8 @@
 import android.content.IntentSender;
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.graphics.RectF;
 import android.hardware.SensorManager;
 import android.hardware.devicestate.DeviceStateManager;
 import android.media.permission.SafeCloseable;
@@ -63,22 +71,28 @@
 import android.os.CancellationSignal;
 import android.os.IBinder;
 import android.os.SystemProperties;
-import android.util.Log;
+import android.os.Trace;
 import android.view.Display;
 import android.view.HapticFeedbackConstants;
 import android.view.RemoteAnimationTarget;
 import android.view.View;
 import android.view.WindowManagerGlobal;
+import android.window.BackEvent;
+import android.window.OnBackAnimationCallback;
+import android.window.OnBackInvokedDispatcher;
 import android.window.SplashScreen;
 
 import androidx.annotation.BinderThread;
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.app.viewcapture.ViewCapture;
+import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.LauncherState;
+import com.android.launcher3.OnBackPressedHandler;
 import com.android.launcher3.QuickstepAccessibilityDelegate;
 import com.android.launcher3.QuickstepTransitionManager;
 import com.android.launcher3.R;
@@ -86,6 +100,7 @@
 import com.android.launcher3.Workspace;
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
 import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.appprediction.PredictionRowView;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragOptions;
@@ -105,6 +120,8 @@
 import com.android.launcher3.statemanager.StateManager.StateHandler;
 import com.android.launcher3.taskbar.LauncherTaskbarUIController;
 import com.android.launcher3.taskbar.TaskbarManager;
+import com.android.launcher3.testing.TestLogging;
+import com.android.launcher3.testing.shared.TestProtocol;
 import com.android.launcher3.uioverrides.QuickstepWidgetHolder.QuickstepHolderFactory;
 import com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory;
 import com.android.launcher3.uioverrides.touchcontrollers.NavBarToHomeTouchController;
@@ -125,6 +142,7 @@
 import com.android.launcher3.util.PendingSplitSelectInfo;
 import com.android.launcher3.util.RunnableList;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
+import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
 import com.android.launcher3.util.TouchController;
 import com.android.launcher3.widget.LauncherWidgetHolder;
 import com.android.quickstep.OverviewCommandHelper;
@@ -142,9 +160,11 @@
 import com.android.quickstep.util.SplitWithKeyboardShortcutController;
 import com.android.quickstep.util.TISBindHelper;
 import com.android.quickstep.views.DesktopTaskView;
+import com.android.quickstep.views.FloatingTaskView;
 import com.android.quickstep.views.OverviewActionsView;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.unfold.UnfoldSharedComponent;
 import com.android.systemui.unfold.UnfoldTransitionFactory;
@@ -160,6 +180,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
 
@@ -354,7 +375,7 @@
         Stream<SystemShortcut.Factory> base = Stream.of(WellbeingModel.SHORTCUT_FACTORY);
         if (ENABLE_SPLIT_FROM_WORKSPACE.get() && mDeviceProfile.isTablet) {
             RecentsView recentsView = getOverviewPanel();
-            // TODO: Pull it out of PagedOrentationHandler for split from workspace.
+            // TODO(b/266482558): Pull it out of PagedOrentationHandler for split from workspace.
             List<SplitPositionOption> positions =
                     recentsView.getPagedOrientationHandler().getSplitPositionOptions(
                             mDeviceProfile);
@@ -537,9 +558,68 @@
         if (FeatureFlags.CONTINUOUS_VIEW_TREE_CAPTURE.get()) {
             mViewCapture = ViewCapture.getInstance().startCapture(getWindow());
         }
+        getWindow().addPrivateFlags(PRIVATE_FLAG_OPTIMIZE_MEASURE);
     }
 
     @Override
+    public void startSplitSelection(SplitSelectSource splitSelectSource) {
+        RecentsView recentsView = getOverviewPanel();
+        // Check if there is already an instance of this app running, if so, initiate the split
+        // using that.
+        recentsView.findLastActiveTaskAndRunCallback(
+                splitSelectSource.intent.getComponent(),
+                (Consumer<Task>) foundTask -> {
+                    splitSelectSource.alreadyRunningTaskId = foundTask == null
+                            ? INVALID_TASK_ID
+                            : foundTask.key.id;
+                    if (ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+                        startSplitToHome(splitSelectSource);
+                    } else {
+                        recentsView.initiateSplitSelect(splitSelectSource);
+                    }
+                }
+        );
+    }
+
+    /** TODO(b/266482558) Migrate into SplitSelectStateController or someplace split specific. */
+    private void startSplitToHome(
+            SplitSelectSource source) {
+        AbstractFloatingView.closeAllOpenViews(this);
+        int splitPlaceholderSize = getResources().getDimensionPixelSize(
+                R.dimen.split_placeholder_size);
+        int splitPlaceholderInset = getResources().getDimensionPixelSize(
+                R.dimen.split_placeholder_inset);
+        Rect tempRect = new Rect();
+
+        SplitSelectStateController controller = getSplitSelectStateController();
+        controller.setInitialTaskSelect(source.intent, source.position.stagePosition,
+                source.itemInfo, source.splitEvent, source.alreadyRunningTaskId);
+
+        RecentsView recentsView = getOverviewPanel();
+        recentsView.getPagedOrientationHandler().getInitialSplitPlaceholderBounds(
+                splitPlaceholderSize, splitPlaceholderInset, getDeviceProfile(),
+                controller.getActiveSplitStagePosition(), tempRect);
+
+        PendingAnimation anim = new PendingAnimation(TABLET_HOME_TO_SPLIT.getDuration());
+        RectF startingTaskRect = new RectF();
+        final FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(this,
+                source.view, null /* thumbnail */, source.drawable, startingTaskRect);
+        floatingTaskView.setAlpha(1);
+        floatingTaskView.addStagingAnimation(anim, startingTaskRect, tempRect,
+                false /* fadeWithThumbnail */, true /* isStagedTask */);
+        controller.setFirstFloatingTaskView(floatingTaskView);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                getDragLayer().removeView(floatingTaskView);
+                controller.resetState();
+            }
+        });
+        anim.buildAnim().start();
+    }
+
+
+    @Override
     protected void onResume() {
         super.onResume();
 
@@ -601,10 +681,12 @@
     }
 
     @Override
-    protected void onScreenOff() {
-        super.onScreenOff();
-        RecentsView recentsView = getOverviewPanel();
-        recentsView.finishRecentsAnimation(true /* toRecents */, null);
+    protected void onScreenOnChanged(boolean isOn) {
+        super.onScreenOnChanged(isOn);
+        if (!isOn) {
+            RecentsView recentsView = getOverviewPanel();
+            recentsView.finishRecentsAnimation(true /* toRecents */, null);
+        }
     }
 
     @Override
@@ -623,6 +705,58 @@
         }
     }
 
+    @Override
+    protected void registerBackDispatcher() {
+        getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
+                OnBackInvokedDispatcher.PRIORITY_DEFAULT,
+                new OnBackAnimationCallback() {
+
+                    @Nullable OnBackPressedHandler mActiveOnBackPressedHandler;
+
+                    @Override
+                    public void onBackStarted(@NonNull BackEvent backEvent) {
+                        if (mActiveOnBackPressedHandler != null) {
+                            mActiveOnBackPressedHandler.onBackCancelled();
+                        }
+                        mActiveOnBackPressedHandler = getOnBackPressedHandler();
+                        mActiveOnBackPressedHandler.onBackStarted();
+                    }
+
+                    @Override
+                    public void onBackInvoked() {
+                        // Recreate mActiveOnBackPressedHandler if necessary to avoid NPE because:
+                        // 1. b/260636433: In 3-button-navigation mode, onBackStarted() is not
+                        // called on ACTION_DOWN before onBackInvoked() is called in ACTION_UP.
+                        // 2. Launcher#onBackPressed() will call onBackInvoked() without calling
+                        // onBackInvoked() beforehand.
+                        if (mActiveOnBackPressedHandler == null) {
+                            mActiveOnBackPressedHandler = getOnBackPressedHandler();
+                        }
+                        mActiveOnBackPressedHandler.onBackInvoked();
+                        mActiveOnBackPressedHandler = null;
+                        TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onBackInvoked");
+                    }
+
+                    @Override
+                    public void onBackProgressed(@NonNull BackEvent backEvent) {
+                        if (!FeatureFlags.IS_STUDIO_BUILD && mActiveOnBackPressedHandler == null) {
+                            return;
+                        }
+                        mActiveOnBackPressedHandler
+                                .onBackProgressed(backEvent.getProgress());
+                    }
+
+                    @Override
+                    public void onBackCancelled() {
+                        if (!FeatureFlags.IS_STUDIO_BUILD && mActiveOnBackPressedHandler == null) {
+                            return;
+                        }
+                        mActiveOnBackPressedHandler.onBackCancelled();
+                        mActiveOnBackPressedHandler = null;
+                    }
+                });
+    }
+
     private void onTaskbarInAppDisplayProgressUpdate(float progress, int flag) {
         if (mTaskbarManager == null
                 || mTaskbarManager.getCurrentActivityContext() == null
@@ -668,7 +802,8 @@
     public void setResumed() {
         if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
             DesktopVisibilityController controller = mDesktopVisibilityController;
-            if (controller != null && controller.areFreeformTasksVisible()) {
+            if (controller != null && controller.areFreeformTasksVisible()
+                    && !controller.isGestureInProgress()) {
                 // Return early to skip setting activity to appear as resumed
                 // TODO(b/255649902): shouldn't be needed when we have a separate launcher state
                 //  for desktop that we can use to control other parts of launcher
@@ -721,7 +856,7 @@
                             getSystemService(SensorManager.class),
                             getMainThreadHandler(),
                             getMainExecutor(),
-                            /* backgroundExecutor= */ THREAD_POOL_EXECUTOR,
+                            /* backgroundExecutor= */ UI_HELPER_EXECUTOR,
                             /* tracingTagPrefix= */ "launcher",
                             WindowManagerGlobal.getWindowManagerService()
                     );
@@ -738,7 +873,6 @@
                     mUnfoldTransitionProgressProvider,
                     mRotationChangeProvider
             );
-            Log.d("b/261320823", "initUnfoldTransitionProgressProvider completed");
         }
     }
 
@@ -1001,6 +1135,21 @@
         mPendingSplitSelectInfo = null;
     }
 
+    @Override
+    public boolean areFreeformTasksVisible() {
+        if (mDesktopVisibilityController != null) {
+            return mDesktopVisibilityController.areFreeformTasksVisible();
+        }
+        return false;
+    }
+
+    @Override
+    public void dispatchDeviceProfileChanged() {
+        super.dispatchDeviceProfileChanged();
+        Trace.instantForTrack(TRACE_TAG_APP, "QuickstepLauncher#DeviceProfileChanged",
+                getDeviceProfile().toSmallString());
+    }
+
     private static final class LauncherTaskViewController extends
             TaskViewTouchController<Launcher> {
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index 733c6a8..95eb128 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -28,6 +28,7 @@
 import com.android.launcher3.allapps.AllAppsTransitionController;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.quickstep.util.LayoutUtils;
+import com.android.quickstep.views.DesktopTaskView;
 import com.android.quickstep.views.RecentsView;
 
 /**
@@ -91,6 +92,12 @@
 
     @Override
     protected float getDepthUnchecked(Context context) {
+        if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
+            if (Launcher.getLauncher(context).areFreeformTasksVisible()) {
+                // Don't blur the background while freeform tasks are visible
+                return 0;
+            }
+        }
         return 1;
     }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
index 969abc2..7392469 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
@@ -17,10 +17,13 @@
 
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
 
+import android.graphics.Color;
+
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.util.Themes;
+import com.android.quickstep.views.DesktopTaskView;
 
 /**
  * State to indicate we are about to launch a recent task. Note that this state is only used when
@@ -43,6 +46,12 @@
 
     @Override
     public int getWorkspaceScrimColor(Launcher launcher) {
+        if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
+            if (launcher.areFreeformTasksVisible()) {
+                // No scrim while freeform tasks are visible
+                return Color.TRANSPARENT;
+            }
+        }
         DeviceProfile dp = launcher.getDeviceProfile();
         if (dp.isTaskbarPresentInApps) {
             return launcher.getColor(R.color.taskbar_background);
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 857ace2..e3427b7 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -127,6 +127,7 @@
 import com.android.quickstep.util.SurfaceTransactionApplier;
 import com.android.quickstep.util.SwipePipToHomeAnimator;
 import com.android.quickstep.util.TaskViewSimulator;
+import com.android.quickstep.views.DesktopTaskView;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task;
@@ -323,6 +324,11 @@
     private final boolean mIsTransientTaskbar;
     // May be set to false when mIsTransientTaskbar is true.
     private boolean mCanSlowSwipeGoHome = true;
+    private boolean mHasReachedOverviewThreshold = false;
+    private boolean mDividerHiddenBeforeAnimation = false;
+
+    @Nullable
+    private RemoteAnimationTargets.ReleaseCheck mSwipePipToHomeReleaseCheck = null;
 
     public AbsSwipeUpHandler(Context context, RecentsAnimationDeviceState deviceState,
             TaskAnimationManager taskAnimationManager, GestureState gestureState,
@@ -365,10 +371,13 @@
                 .getDimensionPixelSize(ENABLE_TASKBAR_REVISED_THRESHOLDS.get()
                         ? R.dimen.taskbar_app_window_threshold_v2
                         : R.dimen.taskbar_app_window_threshold);
-        mTaskbarHomeOverviewThreshold = res.getDimensionPixelSize(
-                ENABLE_TASKBAR_REVISED_THRESHOLDS.get()
-                        ? R.dimen.taskbar_home_overview_threshold_v2
-                        : R.dimen.taskbar_home_overview_threshold);
+        boolean swipeWillNotShowTaskbar = mTaskbarAlreadyOpen;
+        mTaskbarHomeOverviewThreshold = swipeWillNotShowTaskbar
+                ? 0
+                : res.getDimensionPixelSize(
+                        ENABLE_TASKBAR_REVISED_THRESHOLDS.get()
+                                ? R.dimen.taskbar_home_overview_threshold_v2
+                                : R.dimen.taskbar_home_overview_threshold);
         mTaskbarCatchUpThreshold = res.getDimensionPixelSize(R.dimen.taskbar_catch_up_threshold);
     }
 
@@ -762,6 +771,10 @@
 
     private void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask, boolean animate) {
         if (mIsLikelyToStartNewTask != isLikelyToStartNewTask) {
+            if (isLikelyToStartNewTask && mIsTransientTaskbar) {
+                setDividerShown(false /* shown */, true /* immediate */);
+            }
+
             mIsLikelyToStartNewTask = isLikelyToStartNewTask;
             maybeUpdateRecentsAttachedState(animate);
         }
@@ -866,9 +879,16 @@
     public void onRecentsAnimationStart(RecentsAnimationController controller,
             RecentsAnimationTargets targets) {
         super.onRecentsAnimationStart(controller, targets);
-        mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(mContext, targets);
+        if (DesktopTaskView.DESKTOP_MODE_SUPPORTED && targets.hasDesktopTasks()) {
+            mRemoteTargetHandles = mTargetGluer.assignTargetsForDesktop(targets);
+        } else {
+            mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(mContext, targets);
+        }
         mRecentsAnimationController = controller;
         mRecentsAnimationTargets = targets;
+        mSwipePipToHomeReleaseCheck = new RemoteAnimationTargets.ReleaseCheck();
+        mSwipePipToHomeReleaseCheck.setCanRelease(true);
+        mRecentsAnimationTargets.addReleaseCheck(mSwipePipToHomeReleaseCheck);
 
         // Only initialize the device profile, if it has not been initialized before, as in some
         // configurations targets.homeContentInsets may not be correct.
@@ -1430,9 +1450,16 @@
                 mSwipePipToHomeAnimator = createWindowAnimationToPip(
                         homeAnimFactory, runningTaskTarget, start);
                 mSwipePipToHomeAnimators[0] = mSwipePipToHomeAnimator;
+                if (mSwipePipToHomeReleaseCheck != null) {
+                    mSwipePipToHomeReleaseCheck.setCanRelease(false);
+                }
                 windowAnim = mSwipePipToHomeAnimators;
             } else {
                 mSwipePipToHomeAnimator = null;
+                if (mSwipePipToHomeReleaseCheck != null) {
+                    mSwipePipToHomeReleaseCheck.setCanRelease(true);
+                    mSwipePipToHomeReleaseCheck = null;
+                }
                 windowAnim = createWindowAnimationToHome(start, homeAnimFactory);
 
                 windowAnim[0].addAnimatorListener(new AnimationSuccessListener() {
@@ -1656,7 +1683,10 @@
         mRecentsAnimationController.enableInputConsumer();
 
         // Start hiding the divider
-        setDividerShown(false /* shown */, true /* immediate */);
+        if (!mIsTransientTaskbar || mTaskbarAlreadyOpen || mIsTaskbarAllAppsOpen
+                || mDividerHiddenBeforeAnimation) {
+            setDividerShown(false /* shown */, true /* immediate */);
+        }
     }
 
     private void computeRecentsScrollIfInvisible() {
@@ -1954,6 +1984,10 @@
             finishRecentsControllerToHome(
                     () -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
         }
+        if (mSwipePipToHomeReleaseCheck != null) {
+            mSwipePipToHomeReleaseCheck.setCanRelease(true);
+            mSwipePipToHomeReleaseCheck = null;
+        }
         doLogGesture(HOME, mRecentsView == null ? null : mRecentsView.getCurrentPageTaskView());
     }
 
@@ -2288,6 +2322,10 @@
 
         // "Catch up" with the displacement at mTaskbarCatchUpThreshold.
         if (displacement < mTaskbarCatchUpThreshold) {
+            if (!mHasReachedOverviewThreshold) {
+                setDividerShown(false /* shown */, true /* immediate */);
+                mHasReachedOverviewThreshold = true;
+            }
             return Utilities.mapToRange(displacement, mTaskbarAppWindowThreshold,
                     mTaskbarCatchUpThreshold, 0, mTaskbarCatchUpThreshold, ACCEL_DEACCEL);
         }
@@ -2296,6 +2334,12 @@
     }
 
     private void setDividerShown(boolean shown, boolean immediate) {
+        if (mRecentsAnimationTargets == null) {
+            if (!shown) {
+                mDividerHiddenBeforeAnimation = true;
+            }
+            return;
+        }
         if (mDividerAnimator != null) {
             mDividerAnimator.cancel();
         }
diff --git a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
index 2741751..03042c9 100644
--- a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
+++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
@@ -36,6 +36,7 @@
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.window.BackEvent;
+import android.window.BackMotionEvent;
 import android.window.BackProgressAnimator;
 import android.window.IOnBackInvokedCallback;
 
@@ -134,14 +135,14 @@
             }
 
             @Override
-            public void onBackProgressed(BackEvent backEvent) {
+            public void onBackProgressed(BackMotionEvent backEvent) {
                 handler.post(() -> {
                     mProgressAnimator.onBackProgressed(backEvent);
                 });
             }
 
             @Override
-            public void onBackStarted(BackEvent backEvent) {
+            public void onBackStarted(BackMotionEvent backEvent) {
                 handler.post(() -> {
                     startBack(backEvent);
                     mProgressAnimator.onBackStarted(backEvent, event -> {
@@ -185,7 +186,7 @@
         mBackCallback = null;
     }
 
-    private void startBack(BackEvent backEvent) {
+    private void startBack(BackMotionEvent backEvent) {
         mBackInProgress = true;
         RemoteAnimationTarget appTarget = backEvent.getDepartingAnimationTarget();
 
@@ -289,7 +290,8 @@
                     new RemoteAnimationTarget[0],
                     false /* fromUnlock */,
                     mCurrentRect,
-                    cornerRadius);
+                    cornerRadius,
+                    mBackInProgress /* fromPredictiveBack */);
         startTransitionAnimations(pair.first, pair.second);
         mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL);
     }
diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
index 83f2a0a..589459f 100644
--- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
+++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
@@ -21,15 +21,12 @@
 import static android.content.Intent.ACTION_PACKAGE_REMOVED;
 
 import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY;
-import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;
 import static com.android.systemui.shared.system.PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED;
 
 import android.content.ActivityNotFoundException;
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
@@ -57,9 +54,9 @@
 public final class OverviewComponentObserver {
     private static final String TAG = "OverviewComponentObserver";
 
-    private final BroadcastReceiver mUserPreferenceChangeReceiver =
+    private final SimpleBroadcastReceiver mUserPreferenceChangeReceiver =
             new SimpleBroadcastReceiver(this::updateOverviewTargets);
-    private final BroadcastReceiver mOtherHomeAppUpdateReceiver =
+    private final SimpleBroadcastReceiver mOtherHomeAppUpdateReceiver =
             new SimpleBroadcastReceiver(this::updateOverviewTargets);
 
     private final Context mContext;
@@ -102,8 +99,7 @@
             mConfigChangesMap.append(fallbackComponent.hashCode(), fallbackInfo.configChanges);
         } catch (PackageManager.NameNotFoundException ignored) { /* Impossible */ }
 
-        mContext.registerReceiver(mUserPreferenceChangeReceiver,
-                new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED));
+        mUserPreferenceChangeReceiver.register(mContext, ACTION_PREFERRED_ACTIVITY_CHANGED);
         updateOverviewTargets();
     }
 
@@ -181,9 +177,8 @@
                 unregisterOtherHomeAppUpdateReceiver();
 
                 mUpdateRegisteredPackage = defaultHome.getPackageName();
-                mContext.registerReceiver(mOtherHomeAppUpdateReceiver, getPackageFilter(
-                        mUpdateRegisteredPackage, ACTION_PACKAGE_ADDED, ACTION_PACKAGE_CHANGED,
-                        ACTION_PACKAGE_REMOVED));
+                mOtherHomeAppUpdateReceiver.registerPkgActions(mContext, mUpdateRegisteredPackage,
+                        ACTION_PACKAGE_ADDED, ACTION_PACKAGE_CHANGED, ACTION_PACKAGE_REMOVED);
             }
         }
         mOverviewChangeListener.accept(mIsHomeAndOverviewSame);
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index dc405ff..f26189c 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -15,6 +15,7 @@
  */
 package com.android.quickstep;
 
+import static android.os.Trace.TRACE_TAG_APP;
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
 
@@ -36,6 +37,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.Trace;
 import android.view.Display;
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationTarget;
@@ -240,7 +242,7 @@
 
         mActivityLaunchAnimationRunner = new RemoteAnimationFactory() {
             @Override
-            public void onCreateAnimation(int transit, RemoteAnimationTarget[] appTargets,
+            public void onAnimationStart(int transit, RemoteAnimationTarget[] appTargets,
                     RemoteAnimationTarget[] wallpaperTargets,
                     RemoteAnimationTarget[] nonAppTargets, AnimationResult result) {
                 mHandler.removeCallbacks(mAnimationStartTimeoutRunnable);
@@ -407,28 +409,24 @@
     }
 
     private final RemoteAnimationFactory mAnimationToHomeFactory =
-            new RemoteAnimationFactory() {
-        @Override
-        public void onCreateAnimation(int transit, RemoteAnimationTarget[] appTargets,
-                RemoteAnimationTarget[] wallpaperTargets,
-                RemoteAnimationTarget[] nonAppTargets, AnimationResult result) {
-            AnimatorPlaybackController controller = getStateManager()
-                    .createAnimationToNewWorkspace(RecentsState.BG_LAUNCHER, HOME_APPEAR_DURATION);
-            controller.dispatchOnStart();
+            (transit, appTargets, wallpaperTargets, nonAppTargets, result) -> {
+                AnimatorPlaybackController controller =
+                        getStateManager().createAnimationToNewWorkspace(
+                                RecentsState.BG_LAUNCHER, HOME_APPEAR_DURATION);
+                controller.dispatchOnStart();
 
-            RemoteAnimationTargets targets = new RemoteAnimationTargets(
-                    appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
-            for (RemoteAnimationTarget app : targets.apps) {
-                new Transaction().setAlpha(app.leash, 1).apply();
-            }
-            AnimatorSet anim = new AnimatorSet();
-            anim.play(controller.getAnimationPlayer());
-            anim.setDuration(HOME_APPEAR_DURATION);
-            result.setAnimation(anim, RecentsActivity.this,
-                    () -> getStateManager().goToState(RecentsState.HOME, false),
-                    true /* skipFirstFrame */);
-        }
-    };
+                RemoteAnimationTargets targets = new RemoteAnimationTargets(
+                        appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
+                for (RemoteAnimationTarget app : targets.apps) {
+                    new Transaction().setAlpha(app.leash, 1).apply();
+                }
+                AnimatorSet anim = new AnimatorSet();
+                anim.play(controller.getAnimationPlayer());
+                anim.setDuration(HOME_APPEAR_DURATION);
+                result.setAnimation(anim, RecentsActivity.this,
+                        () -> getStateManager().goToState(RecentsState.HOME, false),
+                        true /* skipFirstFrame */);
+            };
 
     @Override
     protected void collectStateHandlers(List<StateHandler> out) {
@@ -452,6 +450,13 @@
         return new RecentsAtomicAnimationFactory<>(this);
     }
 
+    @Override
+    public void dispatchDeviceProfileChanged() {
+        super.dispatchDeviceProfileChanged();
+        Trace.instantForTrack(TRACE_TAG_APP, "RecentsActivity#DeviceProfileChanged",
+                getDeviceProfile().toSmallString());
+    }
+
     private AnimatorListenerAdapter resetStateListener() {
         return new AnimatorListenerAdapter() {
             @Override
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 9e25555..1f522c1 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -17,7 +17,6 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.content.Intent.ACTION_USER_UNLOCKED;
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
@@ -33,6 +32,7 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED;
 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_HOME_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
@@ -43,6 +43,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_STATUS_BAR_KEYGUARD_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
 
 import android.app.ActivityTaskManager;
@@ -50,10 +51,8 @@
 import android.graphics.Region;
 import android.inputmethodservice.InputMethodService;
 import android.net.Uri;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemProperties;
-import android.os.UserManager;
 import android.provider.Settings;
 import android.view.MotionEvent;
 
@@ -63,9 +62,9 @@
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
 import com.android.launcher3.util.DisplayController.Info;
+import com.android.launcher3.util.LockedUserState;
 import com.android.launcher3.util.NavigationMode;
 import com.android.launcher3.util.SettingsCache;
-import com.android.launcher3.util.SimpleBroadcastReceiver;
 import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
 import com.android.quickstep.util.NavBarPosition;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -109,15 +108,6 @@
     private final boolean mIsOneHandedModeSupported;
     private boolean mPipIsActive;
 
-    private boolean mIsUserUnlocked;
-    private final ArrayList<Runnable> mUserUnlockedActions = new ArrayList<>();
-    private final SimpleBroadcastReceiver mUserUnlockedReceiver = new SimpleBroadcastReceiver(i -> {
-        if (ACTION_USER_UNLOCKED.equals(i.getAction())) {
-            mIsUserUnlocked = true;
-            notifyUserUnlocked();
-        }
-    });
-
     private int mGestureBlockingTaskId = -1;
     private @NonNull Region mExclusionRegion = new Region();
     private SystemGestureExclusionListenerCompat mExclusionListener;
@@ -143,14 +133,6 @@
             runOnDestroy(mRotationTouchHelper::destroy);
         }
 
-        // Register for user unlocked if necessary
-        mIsUserUnlocked = context.getSystemService(UserManager.class)
-                .isUserUnlocked(Process.myUserHandle());
-        if (!mIsUserUnlocked) {
-            mUserUnlockedReceiver.register(mContext, ACTION_USER_UNLOCKED);
-        }
-        runOnDestroy(() -> mUserUnlockedReceiver.unregisterReceiverSafely(mContext));
-
         // Register for exclusion updates
         mExclusionListener = new SystemGestureExclusionListenerCompat(mDisplayId) {
             @Override
@@ -310,39 +292,12 @@
     }
 
     /**
-     * Adds a callback for when a user is unlocked. If the user is already unlocked, this listener
-     * will be called back immediately.
-     */
-    public void runOnUserUnlocked(Runnable action) {
-        if (mIsUserUnlocked) {
-            action.run();
-        } else {
-            mUserUnlockedActions.add(action);
-        }
-    }
-
-    /**
-     * @return whether the user is unlocked.
-     */
-    public boolean isUserUnlocked() {
-        return mIsUserUnlocked;
-    }
-
-    /**
      * @return whether the user has completed setup wizard
      */
     public boolean isUserSetupComplete() {
         return mIsUserSetupComplete;
     }
 
-    private void notifyUserUnlocked() {
-        for (Runnable action : mUserUnlockedActions) {
-            action.run();
-        }
-        mUserUnlockedActions.clear();
-        mUserUnlockedReceiver.unregisterReceiverSafely(mContext);
-    }
-
     /**
      * Sets the task id where gestures should be blocked
      */
@@ -381,10 +336,12 @@
                 || mRotationTouchHelper.isTaskListFrozen();
         return canStartWithNavHidden
                 && (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0
+                && (mSystemUiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING) == 0
                 && (mSystemUiStateFlags & SYSUI_STATE_QUICK_SETTINGS_EXPANDED) == 0
                 && (mSystemUiStateFlags & SYSUI_STATE_MAGNIFICATION_OVERLAP) == 0
                 && ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0
-                        || (mSystemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0);
+                        || (mSystemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0)
+                && (mSystemUiStateFlags & SYSUI_STATE_DEVICE_DREAMING) == 0;
     }
 
     /**
@@ -585,7 +542,7 @@
         pw.println("  assistantAvailable=" + mAssistantAvailable);
         pw.println("  assistantDisabled="
                 + QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags));
-        pw.println("  isUserUnlocked=" + mIsUserUnlocked);
+        pw.println("  isUserUnlocked=" + LockedUserState.get(mContext).isUserUnlocked());
         pw.println("  isOneHandedModeEnabled=" + mIsOneHandedModeEnabled);
         pw.println("  isSwipeToNotificationEnabled=" + mIsSwipeToNotificationEnabled);
         pw.println("  deferredGestureRegion=" + mDeferredGestureRegion.getBounds());
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java
index 388e125..15e1365 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java
@@ -15,11 +15,15 @@
  */
 package com.android.quickstep;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 
+import android.app.WindowConfiguration;
 import android.graphics.Rect;
 import android.view.RemoteAnimationTarget;
 
+import com.android.quickstep.views.DesktopTaskView;
+
 /**
  * Extension of {@link RemoteAnimationTargets} with additional information about swipe
  * up animation
@@ -40,4 +44,22 @@
     public boolean hasTargets() {
         return unfilteredApps.length != 0;
     }
+
+    /**
+     * Check if target apps contain desktop tasks which have windowing mode set to {@link
+     * WindowConfiguration#WINDOWING_MODE_FREEFORM}
+     *
+     * @return {@code true} if at least one target app is a desktop task
+     */
+    public boolean hasDesktopTasks() {
+        if (!DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
+            return false;
+        }
+        for (RemoteAnimationTarget target : apps) {
+            if (target.windowConfiguration.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index 4c41bef..9b00dcf 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -26,6 +26,7 @@
 import com.android.quickstep.util.AnimatorControllerWithResistance;
 import com.android.quickstep.util.TaskViewSimulator;
 import com.android.quickstep.util.TransformParams;
+import com.android.quickstep.views.DesktopTaskView;
 
 import java.util.ArrayList;
 
@@ -41,8 +42,8 @@
      * Use this constructor if remote targets are split-screen independent
      */
     public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy,
-            RemoteAnimationTargets targets) {
-        mRemoteTargetHandles = createHandles(context, sizingStrategy, targets.apps.length);
+            RemoteAnimationTargets targets, boolean forDesktop) {
+        init(context, sizingStrategy, targets.apps.length, forDesktop);
     }
 
     /**
@@ -50,15 +51,31 @@
      * running tasks
      */
     public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy) {
+        if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
+            // TODO: binder call, only for prototyping. Creating the gluer should be postponed so
+            //  we can create it when we have the remote animation targets ready.
+            int desktopTasks = SystemUiProxy.INSTANCE.get(context).getVisibleDesktopTaskCount();
+            if (desktopTasks > 0) {
+                init(context, sizingStrategy, desktopTasks, true /* forDesktop */);
+                return;
+            }
+        }
+
         int[] splitIds = TopTaskTracker.INSTANCE.get(context).getRunningSplitTaskIds();
-        mRemoteTargetHandles = createHandles(context, sizingStrategy, splitIds.length == 2 ? 2 : 1);
+        init(context, sizingStrategy, splitIds.length == 2 ? 2 : 1, false /* forDesktop */);
+    }
+
+    private void init(Context context, BaseActivityInterface sizingStrategy, int numHandles,
+            boolean forDesktop) {
+        mRemoteTargetHandles = createHandles(context, sizingStrategy, numHandles, forDesktop);
     }
 
     private RemoteTargetHandle[] createHandles(Context context,
-            BaseActivityInterface sizingStrategy, int numHandles) {
+            BaseActivityInterface sizingStrategy, int numHandles, boolean forDesktop) {
         RemoteTargetHandle[] handles = new RemoteTargetHandle[numHandles];
         for (int i = 0; i < numHandles; i++) {
             TaskViewSimulator tvs = new TaskViewSimulator(context, sizingStrategy);
+            tvs.setIsDesktopTask(forDesktop);
             TransformParams transformParams = new TransformParams();
             handles[i] = new RemoteTargetHandle(tvs, transformParams);
         }
@@ -135,6 +152,20 @@
         return mRemoteTargetHandles;
     }
 
+    /**
+     * Similar to {@link #assignTargets(RemoteAnimationTargets)}, except this creates distinct
+     * transform params per app in {@code targets.apps} list.
+     */
+    public RemoteTargetHandle[] assignTargetsForDesktop(RemoteAnimationTargets targets) {
+        for (int i = 0; i < mRemoteTargetHandles.length; i++) {
+            RemoteAnimationTarget primaryTaskTarget = targets.apps[i];
+            mRemoteTargetHandles[i].mTransformParams.setTargetSet(
+                    createRemoteAnimationTargetsForTaskId(targets, primaryTaskTarget.taskId));
+            mRemoteTargetHandles[i].mTaskViewSimulator.setPreview(primaryTaskTarget, null);
+        }
+        return mRemoteTargetHandles;
+    }
+
     private Rect getStartBounds(RemoteAnimationTarget target) {
         return target.startBounds == null ? target.screenSpaceBounds : target.startBounds;
     }
@@ -172,6 +203,33 @@
                 filteredApps, targets.wallpapers, targets.nonApps, targets.targetMode);
     }
 
+    /**
+     * Ensures that we only animate one specific app target. Includes ancillary targets such as
+     * home/recents
+     *
+     * @param targets remote animation targets to filter
+     * @param taskId  id for a task that we want this remote animation to apply to
+     * @return {@link RemoteAnimationTargets} where app target only includes the app that has the
+     * {@code taskId} that was passed in
+     */
+    private RemoteAnimationTargets createRemoteAnimationTargetsForTaskId(
+            RemoteAnimationTargets targets, int taskId) {
+        RemoteAnimationTarget[] targetApp = null;
+        for (RemoteAnimationTarget targetCompat : targets.unfilteredApps) {
+            if (targetCompat.taskId == taskId) {
+                targetApp = new RemoteAnimationTarget[]{targetCompat};
+                break;
+            }
+        }
+
+        if (targetApp == null) {
+            targetApp = new RemoteAnimationTarget[0];
+        }
+
+        return new RemoteAnimationTargets(targetApp, targets.wallpapers, targets.nonApps,
+                targets.targetMode);
+    }
+
     public RemoteTargetHandle[] getRemoteTargetHandles() {
         return mRemoteTargetHandles;
     }
diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
index f8b6966..4c66dbb 100644
--- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java
+++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
@@ -321,9 +321,9 @@
         if (enable && !mInOverview && !TestProtocol.sDisableSensorRotation) {
             // Clear any previous state from sensor manager
             mSensorRotation = mCurrentAppRotation;
-            mOrientationListener.enable();
+            UI_HELPER_EXECUTOR.execute(mOrientationListener::enable);
         } else {
-            mOrientationListener.disable();
+            UI_HELPER_EXECUTOR.execute(mOrientationListener::disable);
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index bb97334..2200b35 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -29,7 +29,6 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ShortcutInfo;
-import android.graphics.Insets;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
@@ -51,10 +50,10 @@
 import androidx.annotation.WorkerThread;
 
 import com.android.internal.logging.InstanceId;
+import com.android.internal.util.ScreenshotRequest;
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.systemui.shared.recents.ISystemUiProxy;
-import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.system.smartspace.ILauncherUnlockAnimationController;
 import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
 import com.android.systemui.shared.system.smartspace.SmartspaceState;
@@ -384,14 +383,12 @@
     }
 
     @Override
-    public void handleImageBundleAsScreenshot(Bundle screenImageBundle, Rect locationInScreen,
-            Insets visibleInsets, Task.TaskKey task) {
+    public void takeScreenshot(ScreenshotRequest request) {
         if (mSystemUiProxy != null) {
             try {
-                mSystemUiProxy.handleImageBundleAsScreenshot(screenImageBundle, locationInScreen,
-                    visibleInsets, task);
+                mSystemUiProxy.takeScreenshot(request);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed call handleImageBundleAsScreenshot");
+                Log.w(TAG, "Failed call takeScreenshot");
             }
         }
     }
@@ -952,4 +949,16 @@
             }
         }
     }
+
+    /** Call shell to get number of visible freeform tasks */
+    public int getVisibleDesktopTaskCount() {
+        if (mDesktopMode != null) {
+            try {
+                return mDesktopMode.getVisibleTaskCount();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call getVisibleDesktopTaskCount", e);
+            }
+        }
+        return 0;
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index b7252bc..1a72e3f 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -22,6 +22,8 @@
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
 import static com.android.launcher3.LauncherState.BACKGROUND_APP;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.QuickstepTransitionManager.ANIMATION_DELAY_NAV_FADE_IN;
@@ -37,6 +39,7 @@
 import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
 import static com.android.launcher3.anim.Interpolators.clampToProgress;
 import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
+import static com.android.quickstep.views.DesktopTaskView.DESKTOP_MODE_SUPPORTED;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -76,6 +79,7 @@
 import com.android.quickstep.util.SurfaceTransactionApplier;
 import com.android.quickstep.util.TaskViewSimulator;
 import com.android.quickstep.util.TransformParams;
+import com.android.quickstep.views.DesktopTaskView;
 import com.android.quickstep.views.GroupedTaskView;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskThumbnailView;
@@ -180,9 +184,12 @@
             // Re-use existing handles
             remoteTargetHandles = recentsViewHandles;
         } else {
+            boolean forDesktop = DESKTOP_MODE_SUPPORTED && v instanceof DesktopTaskView;
             RemoteTargetGluer gluer = new RemoteTargetGluer(v.getContext(),
-                    recentsView.getSizeStrategy(), targets);
-            if (v.containsMultipleTasks()) {
+                    recentsView.getSizeStrategy(), targets, forDesktop);
+            if (forDesktop) {
+                remoteTargetHandles = gluer.assignTargetsForDesktop(targets);
+            } else if (v.containsMultipleTasks()) {
                 remoteTargetHandles = gluer.assignTargetsForSplitScreen(targets, v.getTaskIds());
             } else {
                 remoteTargetHandles = gluer.assignTargets(targets);
@@ -330,6 +337,17 @@
                 Matrix localMti = new Matrix();
                 localMt.invert(localMti);
                 mti[i] = localMti;
+
+                // Translations for child thumbnails also get scaled as the parent taskView scales
+                // Add inverse scaling to keep translations the same
+                float translationY = ttv.getTranslationY();
+                float translationX = ttv.getTranslationX();
+                float fullScreenScale =
+                        topMostSimulators[i].getTaskViewSimulator().getFullScreenScale();
+                out.addFloat(ttv, VIEW_TRANSLATE_Y, translationY,
+                        translationY / fullScreenScale, TOUCH_RESPONSE_INTERPOLATOR);
+                out.addFloat(ttv, VIEW_TRANSLATE_X, translationX,
+                         translationX / fullScreenScale, TOUCH_RESPONSE_INTERPOLATOR);
             }
 
             Matrix[] k0i = new Matrix[matrixSize];
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 2565697..d19f124 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -87,6 +87,7 @@
 import com.android.launcher3.tracing.TouchInteractionServiceProto;
 import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
 import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.LockedUserState;
 import com.android.launcher3.util.OnboardingPrefs;
 import com.android.launcher3.util.TraceHelper;
 import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
@@ -216,10 +217,12 @@
 
         @BinderThread
         @Override
-        public void onAssistantAvailable(boolean available) {
+        public void onAssistantAvailable(boolean available, boolean longPressHomeEnabled) {
             MAIN_EXECUTOR.execute(() -> {
                 mDeviceState.setAssistantAvailable(available);
                 TouchInteractionService.this.onAssistantVisibilityChanged();
+                executeForTaskbarManager(() -> mTaskbarManager
+                        .onLongPressHomeEnabled(longPressHomeEnabled));
             });
         }
 
@@ -404,8 +407,8 @@
         mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
 
         // Call runOnUserUnlocked() before any other callbacks to ensure everything is initialized.
-        mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
-        mDeviceState.runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
+        LockedUserState.get(this).runOnUserUnlocked(this::onUserUnlocked);
+        LockedUserState.get(this).runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
         mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
 
         ProtoTracer.INSTANCE.get(this).add(this);
@@ -475,7 +478,7 @@
     }
 
     private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
-        if (!mDeviceState.isUserUnlocked() || mDeviceState.isButtonNavMode()) {
+        if (!LockedUserState.get(this).isUserUnlocked() || mDeviceState.isButtonNavMode()) {
             // Skip if not yet unlocked (can't read user shared prefs) or if the current navigation
             // mode doesn't have gestures
             return;
@@ -518,7 +521,7 @@
 
     @UiThread
     private void onSystemUiFlagsChanged(int lastSysUIFlags) {
-        if (mDeviceState.isUserUnlocked()) {
+        if (LockedUserState.get(this).isUserUnlocked()) {
             int systemUiStateFlags = mDeviceState.getSystemUiStateFlags();
             SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(systemUiStateFlags);
             mOverviewComponentObserver.onSystemUiStateChanged();
@@ -563,7 +566,7 @@
 
     @UiThread
     private void onAssistantVisibilityChanged() {
-        if (mDeviceState.isUserUnlocked()) {
+        if (LockedUserState.get(this).isUserUnlocked()) {
             mOverviewComponentObserver.getActivityInterface().onAssistantVisibilityChanged(
                     mDeviceState.getAssistantVisibility());
         }
@@ -573,7 +576,7 @@
     public void onDestroy() {
         Log.d(TAG, "Touch service destroyed: user=" + getUserId());
         sIsInitialized = false;
-        if (mDeviceState.isUserUnlocked()) {
+        if (LockedUserState.get(this).isUserUnlocked()) {
             mInputConsumer.unregisterInputConsumer();
             mOverviewComponentObserver.onDestroy();
         }
@@ -607,7 +610,7 @@
         TestLogging.recordMotionEvent(
                 TestProtocol.SEQUENCE_TIS, "TouchInteractionService.onInputEvent", event);
 
-        if (!mDeviceState.isUserUnlocked()) {
+        if (!LockedUserState.get(this).isUserUnlocked()) {
             return;
         }
 
@@ -629,7 +632,8 @@
                 mGestureState = newGestureState;
                 mConsumer = newConsumer(prevGestureState, mGestureState, event);
                 mUncheckedConsumer = mConsumer;
-            } else if (mDeviceState.isUserUnlocked() && mDeviceState.isFullyGesturalNavMode()
+            } else if (LockedUserState.get(this).isUserUnlocked()
+                    && mDeviceState.isFullyGesturalNavMode()
                     && mDeviceState.canTriggerAssistantAction(event)) {
                 mGestureState = createGestureState(mGestureState);
                 // Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we
@@ -749,7 +753,7 @@
 
         boolean canStartSystemGesture = mDeviceState.canStartSystemGesture();
 
-        if (!mDeviceState.isUserUnlocked()) {
+        if (!LockedUserState.get(this).isUserUnlocked()) {
             CompoundString reasonString = newCompoundString("device locked");
             InputConsumer consumer;
             if (canStartSystemGesture) {
@@ -798,7 +802,7 @@
 
             // If Taskbar is present, we listen for long press to unstash it.
             TaskbarActivityContext tac = mTaskbarManager.getCurrentActivityContext();
-            if (tac != null) {
+            if (tac != null && canStartSystemGesture) {
                 reasonString.append(NEWLINE_PREFIX)
                         .append(reasonPrefix)
                         .append(SUBSTRING_PREFIX)
@@ -1096,7 +1100,7 @@
     }
 
     private void preloadOverview(boolean fromInit, boolean forSUWAllSet) {
-        if (!mDeviceState.isUserUnlocked()) {
+        if (!LockedUserState.get(this).isUserUnlocked()) {
             return;
         }
 
@@ -1128,7 +1132,7 @@
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
-        if (!mDeviceState.isUserUnlocked()) {
+        if (!LockedUserState.get(this).isUserUnlocked()) {
             return;
         }
         final BaseActivityInterface activityInterface =
@@ -1169,7 +1173,7 @@
         } else {
             // Dump everything
             FeatureFlags.dump(pw);
-            if (mDeviceState.isUserUnlocked()) {
+            if (LockedUserState.get(this).isUserUnlocked()) {
                 PluginManagerWrapper.INSTANCE.get(getBaseContext()).dump(pw);
             }
             mDeviceState.dump(pw);
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index bcaae99..db6d56b 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -34,9 +34,9 @@
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.logging.StatsLogManager;
-import com.android.launcher3.popup.QuickstepSystemShortcut;
 import com.android.launcher3.statemanager.StateManager.StateListener;
 import com.android.launcher3.util.SplitConfigurationOptions;
+import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
 import com.android.quickstep.FallbackActivityInterface;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.RecentsActivity;
@@ -269,7 +269,7 @@
     }
 
     @Override
-    public void initiateSplitSelect(QuickstepSystemShortcut.SplitSelectSource splitSelectSource) {
+    public void initiateSplitSelect(SplitSelectSource splitSelectSource) {
         super.initiateSplitSelect(splitSelectSource);
         mActivity.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
     }
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
index 45ffa1c..ab70272 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
@@ -20,6 +20,7 @@
 import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_POSITIVE;
 import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
 import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
+import static com.android.quickstep.OverviewComponentObserver.startHomeIntentSafely;
 import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
 
 import android.animation.ObjectAnimator;
@@ -102,8 +103,7 @@
         mStateCallback = new MultiStateCallback(STATE_NAMES);
         mStateCallback.runOnceAtState(STATE_TARGET_RECEIVED | STATE_HANDLER_INVALIDATED,
                 this::endRemoteAnimation);
-        mStateCallback.runOnceAtState(STATE_TARGET_RECEIVED | STATE_FLING_FINISHED,
-                this::onFlingFinished);
+        mStateCallback.runOnceAtState(STATE_FLING_FINISHED, this::onFlingFinished);
 
         mSwipeDetector = new SingleAxisSwipeDetector(mContext, this, VERTICAL);
         mSwipeDetector.setDetectableScrollConditions(DIRECTION_POSITIVE, false);
@@ -159,10 +159,12 @@
     }
 
     private void onFlingFinished() {
+        boolean endToRecents = mFlingEndsOnHome == null ? true : mFlingEndsOnHome;
         if (mRecentsAnimationController != null) {
-            boolean endToRecents = mFlingEndsOnHome == null ? true : mFlingEndsOnHome;
             mRecentsAnimationController.finishController(endToRecents /* toRecents */,
                     null /* callback */, false /* sendUserLeaveHint */);
+        } else if (endToRecents) {
+            startHomeIntentSafely(mContext, null);
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/interaction/AnimatedTaskbarView.java b/quickstep/src/com/android/quickstep/interaction/AnimatedTaskbarView.java
index e8cc45b..d706711 100644
--- a/quickstep/src/com/android/quickstep/interaction/AnimatedTaskbarView.java
+++ b/quickstep/src/com/android/quickstep/interaction/AnimatedTaskbarView.java
@@ -43,12 +43,12 @@
 
     private View mBackground;
     private View mIconContainer;
+    private View mAllAppsButton;
     private View mIcon1;
     private View mIcon2;
     private View mIcon3;
     private View mIcon4;
     private View mIcon5;
-    private View mIcon6;
 
     @Nullable private Animator mRunningAnimator;
 
@@ -78,12 +78,12 @@
 
         mBackground = findViewById(R.id.taskbar_background);
         mIconContainer = findViewById(R.id.icon_container);
+        mAllAppsButton = findViewById(R.id.taskbar_all_apps);
         mIcon1 = findViewById(R.id.taskbar_icon_1);
         mIcon2 = findViewById(R.id.taskbar_icon_2);
         mIcon3 = findViewById(R.id.taskbar_icon_3);
         mIcon4 = findViewById(R.id.taskbar_icon_4);
         mIcon5 = findViewById(R.id.taskbar_icon_5);
-        mIcon6 = findViewById(R.id.taskbar_icon_6);
     }
 
     /**
@@ -92,22 +92,20 @@
     public void animateDisappearanceToHotseat(ViewGroup hotseat) {
         ArrayList<Animator> animators = new ArrayList<>();
         int hotseatTop = hotseat.getTop();
+        int hotseatLeft = hotseat.getLeft();
 
-        animators.add(ObjectAnimator.ofFloat(
-                mBackground, View.TRANSLATION_Y, 0, mBackground.getHeight()));
         animators.add(ObjectAnimator.ofFloat(mBackground, View.ALPHA, 1f, 0f));
+        animators.add(ObjectAnimator.ofFloat(mAllAppsButton, View.ALPHA, 1f, 0f));
         animators.add(createIconDisappearanceToHotseatAnimator(
-                mIcon1, hotseat.findViewById(R.id.hotseat_icon_1), hotseatTop));
+                mIcon1, hotseat.findViewById(R.id.hotseat_icon_1), hotseatTop, hotseatLeft));
         animators.add(createIconDisappearanceToHotseatAnimator(
-                mIcon2, hotseat.findViewById(R.id.hotseat_icon_2), hotseatTop));
+                mIcon2, hotseat.findViewById(R.id.hotseat_icon_2), hotseatTop, hotseatLeft));
         animators.add(createIconDisappearanceToHotseatAnimator(
-                mIcon3, hotseat.findViewById(R.id.hotseat_icon_3), hotseatTop));
+                mIcon3, hotseat.findViewById(R.id.hotseat_icon_3), hotseatTop, hotseatLeft));
         animators.add(createIconDisappearanceToHotseatAnimator(
-                mIcon4, hotseat.findViewById(R.id.hotseat_icon_4), hotseatTop));
+                mIcon4, hotseat.findViewById(R.id.hotseat_icon_4), hotseatTop, hotseatLeft));
         animators.add(createIconDisappearanceToHotseatAnimator(
-                mIcon5, hotseat.findViewById(R.id.hotseat_icon_5), hotseatTop));
-        animators.add(createIconDisappearanceToHotseatAnimator(
-                mIcon6, hotseat.findViewById(R.id.hotseat_icon_6), hotseatTop));
+                mIcon5, hotseat.findViewById(R.id.hotseat_icon_5), hotseatTop, hotseatLeft));
 
         AnimatorSet animatorSet = new AnimatorSet();
 
@@ -135,22 +133,20 @@
     public void animateAppearanceFromHotseat(ViewGroup hotseat) {
         ArrayList<Animator> animators = new ArrayList<>();
         int hotseatTop = hotseat.getTop();
+        int hotseatLeft = hotseat.getLeft();
 
-        animators.add(ObjectAnimator.ofFloat(
-                mBackground, View.TRANSLATION_Y, mBackground.getHeight(), 0));
         animators.add(ObjectAnimator.ofFloat(mBackground, View.ALPHA, 0f, 1f));
+        animators.add(ObjectAnimator.ofFloat(mAllAppsButton, View.ALPHA, 0f, 1f));
         animators.add(createIconAppearanceFromHotseatAnimator(
-                mIcon1, hotseat.findViewById(R.id.hotseat_icon_1), hotseatTop));
+                mIcon1, hotseat.findViewById(R.id.hotseat_icon_1), hotseatTop, hotseatLeft));
         animators.add(createIconAppearanceFromHotseatAnimator(
-                mIcon2, hotseat.findViewById(R.id.hotseat_icon_2), hotseatTop));
+                mIcon2, hotseat.findViewById(R.id.hotseat_icon_2), hotseatTop, hotseatLeft));
         animators.add(createIconAppearanceFromHotseatAnimator(
-                mIcon3, hotseat.findViewById(R.id.hotseat_icon_3), hotseatTop));
+                mIcon3, hotseat.findViewById(R.id.hotseat_icon_3), hotseatTop, hotseatLeft));
         animators.add(createIconAppearanceFromHotseatAnimator(
-                mIcon4, hotseat.findViewById(R.id.hotseat_icon_4), hotseatTop));
+                mIcon4, hotseat.findViewById(R.id.hotseat_icon_4), hotseatTop, hotseatLeft));
         animators.add(createIconAppearanceFromHotseatAnimator(
-                mIcon5, hotseat.findViewById(R.id.hotseat_icon_5), hotseatTop));
-        animators.add(createIconAppearanceFromHotseatAnimator(
-                mIcon6, hotseat.findViewById(R.id.hotseat_icon_6), hotseatTop));
+                mIcon5, hotseat.findViewById(R.id.hotseat_icon_5), hotseatTop, hotseatLeft));
 
         AnimatorSet animatorSet = new AnimatorSet();
 
@@ -166,98 +162,6 @@
         start(animatorSet);
     }
 
-    /**
-     * Animates this fake taskbar's disappearance to the bottom of the screen.
-     */
-    public void animateDisappearanceToBottom() {
-        ArrayList<Animator> animators = new ArrayList<>();
-
-        animators.add(ObjectAnimator.ofFloat(
-                mBackground, View.TRANSLATION_Y, 0, mBackground.getHeight()));
-        animators.add(ObjectAnimator.ofFloat(mBackground, View.ALPHA, 1f, 0f));
-        animators.add(ObjectAnimator.ofFloat(mIconContainer, View.SCALE_X, 1f, 0f));
-        animators.add(ObjectAnimator.ofFloat(mIconContainer, View.SCALE_Y, 1f, 0f));
-
-        initializeIconContainerPivot();
-
-        AnimatorSet animatorSet = new AnimatorSet();
-
-        animatorSet.playTogether(animators);
-        animatorSet.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                super.onAnimationEnd(animation);
-                setVisibility(INVISIBLE);
-                resetIconContainerPivot();
-            }
-
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                super.onAnimationCancel(animation);
-                resetIconContainerPivot();
-            }
-
-            @Override
-            public void onAnimationStart(Animator animation) {
-                super.onAnimationStart(animation);
-                setVisibility(VISIBLE);
-            }
-        });
-
-        start(animatorSet);
-    }
-
-    /**
-     * Animates this fake taskbar's appearance from the bottom of the screen.
-     */
-    public void animateAppearanceFromBottom() {
-        ArrayList<Animator> animators = new ArrayList<>();
-
-        animators.add(ObjectAnimator.ofFloat(
-                mBackground, View.TRANSLATION_Y, mBackground.getHeight(), 0));
-        animators.add(ObjectAnimator.ofFloat(mBackground, View.ALPHA, 0f, 1f));
-        animators.add(ObjectAnimator.ofFloat(mIconContainer, View.SCALE_X, 0f, 1f));
-        animators.add(ObjectAnimator.ofFloat(mIconContainer, View.SCALE_Y, 0f, 1f));
-
-        initializeIconContainerPivot();
-
-        AnimatorSet animatorSet = new AnimatorSet();
-
-        animatorSet.playTogether(animators);
-        animatorSet.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationStart(Animator animation) {
-                super.onAnimationStart(animation);
-                setVisibility(VISIBLE);
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                super.onAnimationEnd(animation);
-                resetIconContainerPivot();
-            }
-
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                super.onAnimationCancel(animation);
-                resetIconContainerPivot();
-            }
-        });
-
-        start(animatorSet);
-    }
-
-    private void initializeIconContainerPivot() {
-        mIconContainer.setPivotX(getWidth() / 2f);
-        mIconContainer.setPivotY(getHeight() * 0.8f);
-    }
-
-    private void resetIconContainerPivot() {
-        mIconContainer.resetPivot();
-        mIconContainer.setScaleX(1f);
-        mIconContainer.setScaleY(1f);
-    }
-
     private void start(Animator animator) {
         if (mRunningAnimator != null) {
             mRunningAnimator.cancel();
@@ -287,7 +191,7 @@
     }
 
     private Animator createIconDisappearanceToHotseatAnimator(
-            View taskbarIcon, View hotseatIcon, int hotseatTop) {
+            View taskbarIcon, View hotseatIcon, int hotseatTop, int hotseatLeft) {
         ArrayList<Animator> animators = new ArrayList<>();
 
         animators.add(ObjectAnimator.ofFloat(
@@ -296,7 +200,10 @@
                 0,
                 (hotseatTop + hotseatIcon.getTop()) - (getTop() + taskbarIcon.getTop())));
         animators.add(ObjectAnimator.ofFloat(
-                taskbarIcon, View.TRANSLATION_X, 0, hotseatIcon.getLeft() - taskbarIcon.getLeft()));
+                taskbarIcon,
+                View.TRANSLATION_X,
+                0,
+                (hotseatLeft + hotseatIcon.getLeft()) - (getLeft() + taskbarIcon.getLeft())));
         animators.add(ObjectAnimator.ofFloat(
                 taskbarIcon,
                 View.SCALE_X,
@@ -330,7 +237,7 @@
     }
 
     private Animator createIconAppearanceFromHotseatAnimator(
-            View taskbarIcon, View hotseatIcon, int hotseatTop) {
+            View taskbarIcon, View hotseatIcon, int hotseatTop, int hotseatLeft) {
         ArrayList<Animator> animators = new ArrayList<>();
 
         animators.add(ObjectAnimator.ofFloat(
@@ -339,7 +246,10 @@
                 (hotseatTop + hotseatIcon.getTop()) - (getTop() + taskbarIcon.getTop()),
                 0));
         animators.add(ObjectAnimator.ofFloat(
-                taskbarIcon, View.TRANSLATION_X, hotseatIcon.getLeft() - taskbarIcon.getLeft(), 0));
+                taskbarIcon,
+                View.TRANSLATION_X,
+                (hotseatLeft + hotseatIcon.getLeft()) - (getLeft() + taskbarIcon.getLeft()),
+                0));
         animators.add(ObjectAnimator.ofFloat(
                 taskbarIcon,
                 View.SCALE_X,
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
index 05b246b..b00dc47 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -154,7 +154,6 @@
 
         AnimatorSet animset = new AnimatorSet();
         animset.playTogether(animators);
-        hideFakeTaskbar(/* animateToHotseat= */ false);
         animset.start();
         mRunningWindowAnim = SwipeUpAnimationLogic.RunningWindowAnim.wrap(animset);
     }
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
index 4e1521f..1e8b48d0 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
@@ -76,7 +76,7 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 super.onAnimationEnd(animation);
-                controller.resetFakeTaskView(false);
+                controller.resetFakeTaskViewFromOverview();
             }
         });
         ArrayList<Animator> animators = new ArrayList<>();
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index 670ee9b..de93818 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -203,7 +203,15 @@
         mRunningWindowAnim = RunningWindowAnim.wrap(animset);
     }
 
+    void resetFakeTaskViewFromOverview() {
+        resetFakeTaskView(false, false);
+    }
+
     void resetFakeTaskView(boolean animateFromHome) {
+        resetFakeTaskView(animateFromHome, true);
+    }
+
+    void resetFakeTaskView(boolean animateFromHome, boolean animateTaskbar) {
         mFakeTaskView.setVisibility(View.VISIBLE);
         PendingAnimation anim = new PendingAnimation(300);
         anim.setFloat(mTaskViewSwipeUpAnimation
@@ -211,7 +219,9 @@
         anim.setViewAlpha(mFakeTaskView, 1, ACCEL);
         anim.addListener(mResetTaskView);
         AnimatorSet animset = anim.buildAnim();
-        showFakeTaskbar(animateFromHome);
+        if (animateTaskbar) {
+            showFakeTaskbar(animateFromHome);
+        }
         animset.start();
         mRunningWindowAnim = RunningWindowAnim.wrap(animset);
     }
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index fa7d848..e775ce3 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -478,8 +478,6 @@
         if (animateToHotseat) {
             mFakeTaskbarViewCallback = () ->
                     mFakeTaskbarView.animateDisappearanceToHotseat(mFakeHotseatView);
-        } else {
-            mFakeTaskbarViewCallback = mFakeTaskbarView::animateDisappearanceToBottom;
         }
         mFakeTaskbarView.post(mFakeTaskbarViewCallback);
     }
@@ -494,8 +492,6 @@
         if (animateFromHotseat) {
             mFakeTaskbarViewCallback = () ->
                     mFakeTaskbarView.animateAppearanceFromHotseat(mFakeHotseatView);
-        } else {
-            mFakeTaskbarViewCallback = mFakeTaskbarView::animateAppearanceFromBottom;
         }
         mFakeTaskbarView.post(mFakeTaskbarViewCallback);
     }
diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
index 5efc45e..3d5c143 100644
--- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
+++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
@@ -16,6 +16,7 @@
 
 package com.android.quickstep.logging;
 
+import static com.android.launcher3.LauncherPrefs.THEMED_ICONS;
 import static com.android.launcher3.LauncherPrefs.getDevicePrefs;
 import static com.android.launcher3.LauncherPrefs.getPrefs;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_SCREEN_SUGGESTIONS_DISABLED;
@@ -39,6 +40,7 @@
 import android.util.Xml;
 
 import com.android.launcher3.AutoInstallsLayout;
+import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.R;
 import com.android.launcher3.logging.InstanceId;
 import com.android.launcher3.logging.StatsLogManager;
@@ -178,7 +180,7 @@
                 logger::log);
 
         SharedPreferences prefs = getPrefs(mContext);
-        logger.log(prefs.getBoolean(KEY_THEMED_ICONS, false)
+        logger.log(LauncherPrefs.get(mContext).get(THEMED_ICONS)
                 ? LAUNCHER_THEMED_ICON_ENABLED
                 : LAUNCHER_THEMED_ICON_DISABLED);
 
diff --git a/quickstep/src/com/android/quickstep/util/BaseDepthController.java b/quickstep/src/com/android/quickstep/util/BaseDepthController.java
index 877e28a..cecf58d 100644
--- a/quickstep/src/com/android/quickstep/util/BaseDepthController.java
+++ b/quickstep/src/com/android/quickstep/util/BaseDepthController.java
@@ -108,7 +108,10 @@
         float depth = mDepth;
         IBinder windowToken = mLauncher.getRootView().getWindowToken();
         if (windowToken != null) {
-            mWallpaperManager.setWallpaperZoomOut(windowToken, depth);
+            // The API's full zoom-out is three times larger than the zoom-out we apply to the
+            // icons. To keep the two consistent throughout the animation while keeping Launcher's
+            // concept of full depth unchanged, we divide the depth by 3 here.
+            mWallpaperManager.setWallpaperZoomOut(windowToken, depth / 3);
         }
 
         if (!BlurUtils.supportsBlursOnWindows()) {
diff --git a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
index 9fe24de..3a1c99b 100644
--- a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
+++ b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
@@ -18,6 +18,8 @@
 
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
+import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_OVERVIEW;
+import static android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE;
 
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
@@ -47,7 +49,7 @@
 import androidx.core.content.FileProvider;
 
 import com.android.internal.app.ChooserActivity;
-import com.android.internal.util.ScreenshotHelper;
+import com.android.internal.util.ScreenshotRequest;
 import com.android.launcher3.BuildConfig;
 import com.android.quickstep.SystemUiProxy;
 import com.android.systemui.shared.recents.model.Task;
@@ -74,11 +76,17 @@
      * Saves screenshot to location determine by SystemUiProxy
      */
     public static void saveScreenshot(SystemUiProxy systemUiProxy, Bitmap screenshot,
-            Rect screenshotBounds,
-            Insets visibleInsets, Task.TaskKey task) {
-        systemUiProxy.handleImageBundleAsScreenshot(
-                ScreenshotHelper.HardwareBitmapBundler.hardwareBitmapToBundle(screenshot),
-                screenshotBounds, visibleInsets, task);
+            Rect screenshotBounds, Insets visibleInsets, Task.TaskKey task) {
+        ScreenshotRequest request =
+                new ScreenshotRequest.Builder(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OVERVIEW)
+                .setTopComponent(task.sourceComponent)
+                .setTaskId(task.id)
+                .setUserId(task.userId)
+                .setBitmap(screenshot)
+                .setBoundsOnScreen(screenshotBounds)
+                .setInsets(visibleInsets)
+                .build();
+        systemUiProxy.takeScreenshot(request);
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/util/LogUtils.kt b/quickstep/src/com/android/quickstep/util/LogUtils.kt
index bad8506..300c4a1 100644
--- a/quickstep/src/com/android/quickstep/util/LogUtils.kt
+++ b/quickstep/src/com/android/quickstep/util/LogUtils.kt
@@ -20,15 +20,14 @@
 import com.android.launcher3.logging.InstanceId
 
 object LogUtils {
-  /**
-   * @return a [Pair] of two InstanceIds but with different types, one that can be used by framework
-   * (if needing to pass through an intent or such) and one used in Launcher
-   */
-  @JvmStatic
-  fun getShellShareableInstanceId():
-    Pair<com.android.internal.logging.InstanceId, InstanceId> {
-    val internalInstanceId = InstanceIdSequence(InstanceId.INSTANCE_ID_MAX).newInstanceId()
-    val launcherInstanceId = InstanceId(internalInstanceId.id)
-    return Pair(internalInstanceId, launcherInstanceId)
-  }
+    /**
+     * @return a [Pair] of two InstanceIds but with different types, one that can be used by
+     * framework (if needing to pass through an intent or such) and one used in Launcher
+     */
+    @JvmStatic
+    fun getShellShareableInstanceId(): Pair<com.android.internal.logging.InstanceId, InstanceId> {
+        val internalInstanceId = InstanceIdSequence(InstanceId.INSTANCE_ID_MAX).newInstanceId()
+        val launcherInstanceId = InstanceId(internalInstanceId.id)
+        return Pair(internalInstanceId, launcherInstanceId)
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 681f068..e5d54d7 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -90,6 +90,8 @@
     private Intent mSecondTaskIntent;
     private int mSecondTaskId = INVALID_TASK_ID;
     private boolean mRecentsAnimationRunning;
+    /** If {@code true}, animates the existing task view split placeholder view */
+    private boolean mAnimateCurrentTaskDismissal;
     @Nullable
     private UserHandle mUser;
     /** If not null, this is the TaskView we want to launch from */
@@ -111,22 +113,15 @@
     }
 
     /**
-     * To be called after first task selected in Overview.
+     * @param alreadyRunningTask if set to {@link android.app.ActivityTaskManager#INVALID_TASK_ID}
+     *                           then @param intent will be used to launch the initial task
+     * @param intent will be ignored if @param alreadyRunningTask is set
      */
-    public void setInitialTaskSelect(Task task, @StagePosition int stagePosition,
-            StatsLogManager.EventEnum splitEvent, ItemInfo itemInfo) {
-        mInitialTaskId = task.key.id;
-        setInitialData(stagePosition, splitEvent, itemInfo);
-    }
-
-    /**
-     * To be called after first task selected from home or all apps.
-     */
-    public void setInitialTaskSelect(Intent intent, @StagePosition int stagePosition,
+    public void setInitialTaskSelect(@Nullable Intent intent, @StagePosition int stagePosition,
             @NonNull ItemInfo itemInfo, StatsLogManager.EventEnum splitEvent,
-            @Nullable Task alreadyRunningTask) {
-        if (alreadyRunningTask != null) {
-            mInitialTaskId = alreadyRunningTask.key.id;
+            int alreadyRunningTask) {
+        if (alreadyRunningTask != INVALID_TASK_ID) {
+            mInitialTaskId = alreadyRunningTask;
         } else {
             mInitialTaskIntent = intent;
             mUser = itemInfo.user;
@@ -348,6 +343,14 @@
         return null;
     }
 
+    public boolean isAnimateCurrentTaskDismissal() {
+        return mAnimateCurrentTaskDismissal;
+    }
+
+    public void setAnimateCurrentTaskDismissal(boolean animateCurrentTaskDismissal) {
+        mAnimateCurrentTaskDismissal = animateCurrentTaskDismissal;
+    }
+
     /**
      * Requires Shell Transitions
      */
@@ -454,6 +457,7 @@
         mLaunchingTaskView = null;
         mItemInfo = null;
         mSplitEvent = null;
+        mAnimateCurrentTaskDismissal = false;
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index ad54a70..cd5edab 100644
--- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -124,7 +124,7 @@
                 for (int i = hotseatIcons.getChildCount() - 1; i >= 0; i--) {
                     View child = hotseatIcons.getChildAt(i);
                     CellLayoutLayoutParams lp = ((CellLayoutLayoutParams) child.getLayoutParams());
-                    addStaggeredAnimationForView(child, lp.cellY + 1, totalRows, duration);
+                    addStaggeredAnimationForView(child, lp.getCellY() + 1, totalRows, duration);
                 }
             } else {
                 final int hotseatRow, qsbRow;
@@ -194,7 +194,7 @@
         for (int i = itemsContainer.getChildCount() - 1; i >= 0; i--) {
             View child = itemsContainer.getChildAt(i);
             CellLayoutLayoutParams lp = ((CellLayoutLayoutParams) child.getLayoutParams());
-            addStaggeredAnimationForView(child, lp.cellY + lp.cellVSpan, totalRows, duration);
+            addStaggeredAnimationForView(child, lp.getCellY() + lp.cellVSpan, totalRows, duration);
         }
 
         mAnimators.addListener(new AnimatorListenerAdapter() {
diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
index 74e4acc..ca4365f 100644
--- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
@@ -22,27 +22,23 @@
 import android.animation.RectEvaluator;
 import android.content.ComponentName;
 import android.content.Context;
-import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.util.Log;
 import android.view.Surface;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.view.View;
 import android.window.PictureInPictureSurfaceTransaction;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
-import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimationSuccessListener;
-import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.util.Themes;
 import com.android.quickstep.TaskAnimationManager;
 import com.android.systemui.shared.pip.PipSurfaceTransactionHelper;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
+import com.android.wm.shell.pip.PipContentOverlay;
 
 /**
  * Subclass of {@link RectFSpringAnim} that animates an Activity to PiP (picture-in-picture) window
@@ -65,7 +61,10 @@
     private final Rect mDestinationBounds = new Rect();
     private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
 
-    /** for calculating transform in {@link #onAnimationUpdate(AppCloseConfig, RectF, float)} */
+    /**
+     * For calculating transform in
+     * {@link #onAnimationUpdate(SurfaceControl.Transaction, RectF, float)}
+     */
     private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect());
     private final Rect mSourceHintRectInsets;
     private final Rect mSourceInsets = new Rect();
@@ -144,31 +143,17 @@
             mSourceRectHint.setEmpty();
             mSourceHintRectInsets = null;
 
-            // Create a new overlay layer
-            SurfaceSession session = new SurfaceSession();
-            mContentOverlay = new SurfaceControl.Builder(session)
-                    .setCallsite("SwipePipToHomeAnimator")
-                    .setName("PipContentOverlay")
-                    .setColorLayer()
-                    .build();
-            SurfaceControl.Transaction t = new SurfaceControl.Transaction();
-            t.show(mContentOverlay);
-            t.setLayer(mContentOverlay, Integer.MAX_VALUE);
-            int color = Themes.getColorBackground(view.getContext());
-            float[] bgColor = new float[] {Color.red(color) / 255f, Color.green(color) / 255f,
-                    Color.blue(color) / 255f};
-            t.setColor(mContentOverlay, bgColor);
-            t.setAlpha(mContentOverlay, 0f);
-            t.reparent(mContentOverlay, mLeash);
-            t.apply();
-
+            // Create a new overlay layer. We do not call detach on this instance, it's propagated
+            // to other classes like PipTaskOrganizer / RecentsAnimationController to complete
+            // the cleanup.
+            final PipContentOverlay.PipColorOverlay overlay =
+                    new PipContentOverlay.PipColorOverlay(view.getContext());
+            final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
+            mContentOverlay = overlay.getLeash();
+            overlay.attach(tx, mLeash);
             addOnUpdateListener((currentRect, progress) -> {
-                float alpha = progress < 0.5f
-                        ? 0
-                        : Utilities.mapToRange(Math.min(progress, 1f), 0.5f, 1f,
-                                0f, 1f, Interpolators.FAST_OUT_SLOW_IN);
-                t.setAlpha(mContentOverlay, alpha);
-                t.apply();
+                overlay.onAnimationUpdate(tx, progress);
+                tx.apply();
             });
         } else {
             mSourceRectHint.set(sourceRectHint);
diff --git a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
index 5dc4613..a34888f 100644
--- a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
+++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
@@ -23,6 +23,7 @@
 import android.view.WindowManager;
 import android.view.WindowMetrics;
 
+import com.android.internal.policy.SystemBarUtils;
 import com.android.launcher3.util.WindowBounds;
 import com.android.launcher3.util.window.CachedDisplayInfo;
 import com.android.launcher3.util.window.WindowManagerProxy;
@@ -45,6 +46,13 @@
     }
 
     @Override
+    protected int getStatusBarHeight(Context context, boolean isPortrait, int statusBarInset) {
+        // See b/264656380, calculate the status bar height manually as the inset in the system
+        // server might not be updated by this point yet causing extra DeviceProfile updates
+        return SystemBarUtils.getStatusBarHeight(context);
+    }
+
+    @Override
     public ArrayMap<CachedDisplayInfo, WindowBounds[]> estimateInternalDisplayBounds(
             Context displayInfoContext) {
         ArrayMap<CachedDisplayInfo, WindowBounds[]> result = new ArrayMap<>();
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 04af19f..69f9ce3 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -104,6 +104,7 @@
     private SplitBounds mSplitBounds;
     private Boolean mDrawsBelowRecents = null;
     private boolean mIsGridTask;
+    private boolean mIsDesktopTask;
     private int mTaskRectTranslationX;
     private int mTaskRectTranslationY;
 
@@ -145,6 +146,13 @@
         if (mDp == null) {
             return 1;
         }
+
+        if (mIsDesktopTask) {
+            mTaskRect.set(mThumbnailPosition);
+            mPivot.set(mTaskRect.centerX(), mTaskRect.centerY());
+            return 1;
+        }
+
         if (mIsGridTask) {
             mSizeStrategy.calculateGridTaskSize(mContext, mDp, mTaskRect,
                     mOrientationState.getOrientationHandler());
@@ -228,6 +236,13 @@
     }
 
     /**
+     * Sets whether this task is part of desktop tasks in overview.
+     */
+    public void setIsDesktopTask(boolean desktop) {
+        mIsDesktopTask = desktop;
+    }
+
+    /**
      * Apply translations on TaskRect's starting location.
      */
     public void setTaskRectTranslation(int taskRectTranslationX, int taskRectTranslationY) {
diff --git a/quickstep/src/com/android/quickstep/views/AllAppsEduView.java b/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
index d79b318..716d389 100644
--- a/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
+++ b/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
@@ -112,11 +112,6 @@
     }
 
     @Override
-    public boolean onBackPressed() {
-        return true;
-    }
-
-    @Override
     public boolean canInterceptEventsInSystemGestureRegion() {
         return true;
     }
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
index c878278..44aa41a 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
@@ -18,6 +18,7 @@
 
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
+import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
 
 import android.content.Context;
@@ -35,6 +36,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.touch.PagedOrientationHandler;
 import com.android.launcher3.util.RunnableList;
@@ -81,6 +83,8 @@
 
     private final ArrayList<CancellableTask<?>> mPendingThumbnailRequests = new ArrayList<>();
 
+    private ShapeDrawable mBackground;
+
     public DesktopTaskView(Context context) {
         this(context, null);
     }
@@ -99,10 +103,11 @@
         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));
+        mBackground = new ShapeDrawable(shape);
+        mBackground.setTint(getResources().getColor(android.R.color.system_neutral2_300,
+                getContext().getTheme()));
         // TODO(b/244348395): this should be wallpaper
-        setBackground(background);
+        setBackground(mBackground);
 
         mSnapshotViews.add(mSnapshotView);
     }
@@ -292,7 +297,7 @@
     @Override
     public RunnableList launchTasks() {
         SystemUiProxy.INSTANCE.get(getContext()).showDesktopApps();
-        getRecentsView().startHome();
+        Launcher.getLauncher(mActivity).getStateManager().goToState(NORMAL, false /* animated */);
         return null;
     }
 
@@ -427,6 +432,12 @@
         // TODO(b/249371338): this copies parent implementation and makes it work for N thumbs
         progress = Utilities.boundToRange(progress, 0, 1);
         mFullscreenProgress = progress;
+        if (mFullscreenProgress > 0) {
+            // Don't show background while we are transitioning to/from fullscreen
+            setBackground(null);
+        } else {
+            setBackground(mBackground);
+        }
         for (int i = 0; i < mSnapshotViewMap.size(); i++) {
             TaskThumbnailView thumbnailView = mSnapshotViewMap.valueAt(i);
             thumbnailView.getTaskOverlay().setFullscreenProgress(progress);
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 6c27587..886fc80 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -34,14 +34,17 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.logging.StatsLogManager;
-import com.android.launcher3.popup.QuickstepSystemShortcut;
 import com.android.launcher3.statehandlers.DepthController;
+import com.android.launcher3.statehandlers.DesktopVisibilityController;
 import com.android.launcher3.statemanager.StateManager.StateListener;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.launcher3.util.PendingSplitSelectInfo;
 import com.android.launcher3.util.SplitConfigurationOptions;
+import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
 import com.android.quickstep.LauncherActivityInterface;
+import com.android.quickstep.RotationTouchHelper;
 import com.android.quickstep.util.SplitSelectStateController;
+import com.android.systemui.shared.recents.model.Task;
 
 /**
  * {@link RecentsView} used in Launcher activity
@@ -196,7 +199,7 @@
     }
 
     @Override
-    public void initiateSplitSelect(QuickstepSystemShortcut.SplitSelectSource splitSelectSource) {
+    public void initiateSplitSelect(SplitSelectSource splitSelectSource) {
         super.initiateSplitSelect(splitSelectSource);
         mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
     }
@@ -205,4 +208,25 @@
     protected boolean canLaunchFullscreenTask() {
         return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
     }
+
+    @Override
+    public void onGestureAnimationStart(Task[] runningTasks,
+            RotationTouchHelper rotationTouchHelper) {
+        super.onGestureAnimationStart(runningTasks, rotationTouchHelper);
+        DesktopVisibilityController desktopVisibilityController =
+                mActivity.getDesktopVisibilityController();
+        if (desktopVisibilityController != null) {
+            desktopVisibilityController.setGestureInProgress(true);
+        }
+    }
+
+    @Override
+    public void onGestureAnimationEnd() {
+        super.onGestureAnimationEnd();
+        DesktopVisibilityController desktopVisibilityController =
+                mActivity.getDesktopVisibilityController();
+        if (desktopVisibilityController != null) {
+            desktopVisibilityController.setGestureInProgress(false);
+        }
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 6862874..8facb0a 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -16,6 +16,7 @@
 
 package com.android.quickstep.views;
 
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.view.Surface.ROTATION_0;
 import static android.view.View.MeasureSpec.EXACTLY;
 import static android.view.View.MeasureSpec.makeMeasureSpec;
@@ -144,7 +145,6 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.icons.cache.HandlerRunnable;
 import com.android.launcher3.logging.StatsLogManager;
-import com.android.launcher3.popup.QuickstepSystemShortcut;
 import com.android.launcher3.statehandlers.DepthController;
 import com.android.launcher3.statemanager.BaseState;
 import com.android.launcher3.statemanager.StatefulActivity;
@@ -156,6 +156,7 @@
 import com.android.launcher3.util.ResourceBasedOverride.Overrides;
 import com.android.launcher3.util.RunnableList;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds;
+import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
 import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.TranslateEdgeEffect;
@@ -677,7 +678,7 @@
     private SplitInstructionsView mSplitInstructionsView;
 
     @Nullable
-    private QuickstepSystemShortcut.SplitSelectSource mSplitSelectSource;
+    private SplitSelectSource mSplitSelectSource;
 
     /**
      * Keeps track of the index of the TaskView that split screen was initialized with so we know
@@ -1275,14 +1276,14 @@
     }
 
     /**
-     * Pulls the list of active Tasks from RecentModel, and finds the most recently active Task
+     * Pulls the list of active Tasks from RecentsModel, and finds the most recently active Task
      * matching a given ComponentName. Then uses that Task (which could be null) with the given
      * callback.
      *
-     * Used in various splitscreen operations when we need to check if there is a currently running
-     * Task of a certain type and use the most recent one.
+     * Used in various task-switching or splitscreen operations when we need to check if there is a
+     * currently running Task of a certain type and use the most recent one.
      */
-    public void findLastActiveTaskAndDoSplitOperation(ComponentName componentName,
+    public void findLastActiveTaskAndRunCallback(ComponentName componentName,
             Consumer<Task> callback) {
         mModel.getTasks(taskGroups -> {
             Task lastActiveTask = null;
@@ -1351,8 +1352,10 @@
         if (!mActivity.getDeviceProfile().isTablet) {
             mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, true);
         }
-        InteractionJankMonitorWrapper.begin(/* view= */ this,
-                InteractionJankMonitorWrapper.CUJ_RECENTS_SCROLLING);
+        if (mOverviewStateEnabled) { // only when in overview
+            InteractionJankMonitorWrapper.begin(/* view= */ this,
+                    InteractionJankMonitorWrapper.CUJ_RECENTS_SCROLLING);
+        }
     }
 
     @Override
@@ -1557,6 +1560,11 @@
                 ActiveGestureErrorDetector.GestureEvent.SCROLLER_ANIMATION_ABORTED);
     }
 
+    @Override
+    protected boolean isPageScrollsInitialized() {
+        return super.isPageScrollsInitialized() && mLoadPlanEverApplied;
+    }
+
     protected void applyLoadPlan(ArrayList<GroupTask> taskGroups) {
         if (mPendingAnimation != null) {
             mPendingAnimation.addEndListener(success -> applyLoadPlan(taskGroups));
@@ -1570,6 +1578,9 @@
             // With all tasks removed, touch handling in PagedView is disabled and we need to reset
             // touch state or otherwise values will be obsolete.
             resetTouchState();
+            if (isPageScrollsInitialized()) {
+                onPageScrollsInitialized();
+            }
             return;
         }
 
@@ -1597,8 +1608,9 @@
 
         // 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.
-        Task stagedTaskToBeRemovedFromGrid =
-                mSplitSelectSource != null ? mSplitSelectSource.alreadyRunningTask : null;
+        int stagedTaskIdToBeRemovedFromGrid = mSplitSelectSource != null
+                ? mSplitSelectSource.alreadyRunningTaskId
+                : INVALID_TASK_ID;
 
         // update the map of instance counts
         mFilterState.updateInstanceCountMap(taskGroups);
@@ -1607,8 +1619,8 @@
         // 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 = stagedTaskToBeRemovedFromGrid != null
-                    && groupTask.containsTask(stagedTaskToBeRemovedFromGrid.key.id);
+            boolean isRemovalNeeded = stagedTaskIdToBeRemovedFromGrid != INVALID_TASK_ID
+                    && groupTask.containsTask(stagedTaskIdToBeRemovedFromGrid);
 
             TaskView taskView;
             if (isRemovalNeeded && groupTask.hasMultipleTasks()) {
@@ -1622,7 +1634,7 @@
             addView(taskView);
 
             if (isRemovalNeeded && groupTask.hasMultipleTasks()) {
-                if (groupTask.task1.equals(stagedTaskToBeRemovedFromGrid)) {
+                if (groupTask.task1.key.id == stagedTaskIdToBeRemovedFromGrid) {
                     taskView.bind(groupTask.task2, mOrientationState);
                 } else {
                     taskView.bind(groupTask.task1, mOrientationState);
@@ -1723,6 +1735,9 @@
         resetTaskVisuals();
         onTaskStackUpdated();
         updateEnabledOverlays();
+        if (isPageScrollsInitialized()) {
+            onPageScrollsInitialized();
+        }
     }
 
     private boolean isModal() {
@@ -2066,7 +2081,7 @@
         if (!mActivity.getDeviceProfile().isTablet) {
             return super.getDestinationPage(scaledScroll);
         }
-        if (!pageScrollsInitialized()) {
+        if (!isPageScrollsInitialized()) {
             Log.e(TAG,
                     "Cannot get destination page: RecentsView not properly initialized",
                     new IllegalStateException());
@@ -3006,7 +3021,7 @@
 
         RectF startingTaskRect = new RectF();
         safeRemoveDragLayerView(mFirstFloatingTaskView);
-        if (mSplitHiddenTaskView != null) {
+        if (mSplitSelectStateController.isAnimateCurrentTaskDismissal()) {
             // Create the split select animation from Overview
             mSplitHiddenTaskView.setThumbnailVisibility(INVISIBLE);
             anim.setViewAlpha(mSplitHiddenTaskView.getIconView(), 0, clampToProgress(LINEAR,
@@ -3029,7 +3044,7 @@
                     false /* fadeWithThumbnail */, true /* isStagedTask */);
         }
 
-        // TODO (b/257513449): Launch animation not fully complete. OK to remove flag once it is.
+        // Allow user to click staged app to launch into fullscreen
         if (ENABLE_LAUNCH_FROM_STAGED_APP.get()) {
             mFirstFloatingTaskView.setOnClickListener(this::animateToFullscreen);
         }
@@ -3100,7 +3115,9 @@
                 false /* fadeWithThumbnail */,
                 true /* isStagedTask */);
 
-        pendingAnimation.addEndListener(success -> launchStagedTask());
+        pendingAnimation.addEndListener(animationSuccess ->
+                mSplitSelectStateController.launchSplitTasks(launchSuccess ->
+                        resetFromSplitSelectionState()));
 
         pendingAnimation.buildAnim().start();
     }
@@ -3178,8 +3195,6 @@
             }
         }
 
-        announceForAccessibility(getResources().getString(R.string.task_view_closed));
-
         float dismissTranslationInterpolationEnd = 1;
         boolean closeGapBetweenClearAll = false;
         boolean isClearAllHidden = isClearAllHidden();
@@ -3506,6 +3521,8 @@
                             } else {
                                 removeTaskInternal(dismissedTaskViewId);
                             }
+                            announceForAccessibility(
+                                    getResources().getString(R.string.task_view_closed));
                             mActivity.getStatsLogManager().logger()
                                     .withItemInfo(dismissedTaskView.getItemInfo())
                                     .log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
@@ -4378,29 +4395,38 @@
         initiateSplitSelect(taskView, defaultSplitPosition, LAUNCHER_OVERVIEW_ACTIONS_SPLIT);
     }
 
+    /** TODO(b/266477929): Consolidate this call w/ the one below */
     public void initiateSplitSelect(TaskView taskView, @StagePosition int stagePosition,
             StatsLogManager.EventEnum splitEvent) {
         mSplitHiddenTaskView = taskView;
-        mSplitSelectStateController.setInitialTaskSelect(taskView.getTask(),
-                stagePosition, splitEvent, taskView.getItemInfo());
+        mSplitSelectStateController.setInitialTaskSelect(null /*intent*/,
+                stagePosition, taskView.getItemInfo(), splitEvent, taskView.mTask.key.id);
+        mSplitSelectStateController.setAnimateCurrentTaskDismissal(
+                true /*animateCurrentTaskDismissal*/);
         mSplitHiddenTaskViewIndex = indexOfChild(taskView);
     }
 
     /**
-     * Called when staging a split from Home/AllApps, using the icon long-press menu.
+     * Called when staging a split from Home/AllApps/Overview (Taskbar),
+     * using the icon long-press menu.
+     * Attempts to initiate split with an existing taskView, if one exists
      */
-    public void initiateSplitSelect(QuickstepSystemShortcut.SplitSelectSource splitSelectSource) {
+    public void initiateSplitSelect(SplitSelectSource splitSelectSource) {
         mSplitSelectSource = splitSelectSource;
+        mSplitHiddenTaskView = getTaskViewByTaskId(splitSelectSource.alreadyRunningTaskId);
+        mSplitHiddenTaskViewIndex = indexOfChild(mSplitHiddenTaskView);
+        mSplitSelectStateController
+                .setAnimateCurrentTaskDismissal(splitSelectSource.animateCurrentTaskDismissal);
         mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
                 splitSelectSource.position.stagePosition, splitSelectSource.itemInfo,
-                splitSelectSource.splitEvent, splitSelectSource.alreadyRunningTask);
+                splitSelectSource.splitEvent, splitSelectSource.alreadyRunningTaskId);
     }
 
     /**
      * Modifies a PendingAnimation with the animations for entering split staging
      */
     public void createSplitSelectInitAnimation(PendingAnimation builder, int duration) {
-        if (mSplitHiddenTaskView != null) {
+        if (mSplitSelectStateController.isAnimateCurrentTaskDismissal()) {
             // Splitting from Overview
             createTaskDismissAnimation(builder, mSplitHiddenTaskView, true, false, duration,
                     true /* dismissingForSplitSelection*/);
@@ -4807,16 +4833,6 @@
         return mPendingAnimation;
     }
 
-    protected void launchStagedTask() {
-        if (mSplitHiddenTaskView != null) {
-            // Split staging was started from an existing running task (in Overview)
-            mSplitHiddenTaskView.launchTask(success -> resetFromSplitSelectionState());
-        } else {
-            // Split staging was started from a new intent (from app menu in Home/AllApps)
-            mActivity.startActivity(mSplitSelectSource.intent);
-        }
-    }
-
     protected void onTaskLaunchAnimationEnd(boolean success) {
         if (success) {
             resetTaskVisuals();
@@ -4906,9 +4922,16 @@
             return;
         }
 
-        RemoteTargetGluer gluer = new RemoteTargetGluer(getContext(), getSizeStrategy());
-        mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(
-                getContext(), recentsAnimationTargets);
+        RemoteTargetGluer gluer;
+        if (DESKTOP_MODE_SUPPORTED && recentsAnimationTargets.hasDesktopTasks()) {
+            gluer = new RemoteTargetGluer(getContext(), getSizeStrategy(), recentsAnimationTargets,
+                    true /* forDesktop */);
+            mRemoteTargetHandles = gluer.assignTargetsForDesktop(recentsAnimationTargets);
+        } else {
+            gluer = new RemoteTargetGluer(getContext(), getSizeStrategy());
+            mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(
+                    getContext(), recentsAnimationTargets);
+        }
         mSplitBoundsConfig = gluer.getSplitBounds();
         // Add release check to the targets from the RemoteTargetGluer and not the targets
         // passed in because in the event we're in split screen, we use the passed in targets
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
index bdc0585..54b58b9 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
@@ -48,13 +48,15 @@
             taskContainer: TaskIdAttributeContainer,
             alignSecondRow: Boolean = false
         ): Boolean {
-            val activity = BaseDraggingActivity
-                .fromContext<BaseDraggingActivity>(taskContainer.taskView.context)
-            val taskMenuViewWithArrow = activity.layoutInflater
-                .inflate(
-                        R.layout.task_menu_with_arrow,
-                        activity.dragLayer,
-                        false
+            val activity =
+                BaseDraggingActivity.fromContext<BaseDraggingActivity>(
+                    taskContainer.taskView.context
+                )
+            val taskMenuViewWithArrow =
+                activity.layoutInflater.inflate(
+                    R.layout.task_menu_with_arrow,
+                    activity.dragLayer,
+                    false
                 ) as TaskMenuViewWithArrow<*>
 
             return taskMenuViewWithArrow.populateAndShowForTask(taskContainer, alignSecondRow)
@@ -63,11 +65,11 @@
 
     constructor(context: Context) : super(context)
     constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
-    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
-        context,
-        attrs,
-        defStyleAttr
-    )
+    constructor(
+        context: Context,
+        attrs: AttributeSet,
+        defStyleAttr: Int
+    ) : super(context, attrs, defStyleAttr)
 
     init {
         clipToOutline = true
@@ -91,10 +93,10 @@
 
     private var optionMeasuredHeight = 0
     private val arrowHorizontalPadding: Int
-        get() = if (taskView.isFocusedTask)
-            resources.getDimensionPixelSize(R.dimen.task_menu_horizontal_padding)
-        else
-            0
+        get() =
+            if (taskView.isFocusedTask)
+                resources.getDimensionPixelSize(R.dimen.task_menu_horizontal_padding)
+            else 0
 
     private var iconView: IconView? = null
     private var scrim: View? = null
@@ -139,19 +141,20 @@
     }
 
     private fun addScrim() {
-        scrim = View(context).apply {
-            layoutParams = FrameLayout.LayoutParams(
-                FrameLayout.LayoutParams.MATCH_PARENT,
-                FrameLayout.LayoutParams.MATCH_PARENT
-            )
-            setBackgroundColor(Themes.getAttrColor(context, R.attr.overviewScrimColor))
-            alpha = 0f
-        }
+        scrim =
+            View(context).apply {
+                layoutParams =
+                    FrameLayout.LayoutParams(
+                        FrameLayout.LayoutParams.MATCH_PARENT,
+                        FrameLayout.LayoutParams.MATCH_PARENT
+                    )
+                setBackgroundColor(Themes.getAttrColor(context, R.attr.overviewScrimColor))
+                alpha = 0f
+            }
         popupContainer.addView(scrim)
     }
 
-    /** @return true if successfully able to populate task view menu, false otherwise
-     */
+    /** @return true if successfully able to populate task view menu, false otherwise */
     private fun populateMenu(): Boolean {
         // Icon may not be loaded
         if (taskContainer.task.icon == null) return false
@@ -162,9 +165,9 @@
 
     private fun addMenuOptions() {
         // Add the options
-        TaskOverlayFactory
-            .getEnabledShortcuts(taskView, taskContainer)
-            .forEach { this.addMenuOption(it) }
+        TaskOverlayFactory.getEnabledShortcuts(taskView, taskContainer).forEach {
+            this.addMenuOption(it)
+        }
 
         // Add the spaces between items
         val divider = ShapeDrawable(RectShape())
@@ -185,9 +188,9 @@
     }
 
     private fun addMenuOption(menuOption: SystemShortcut<*>) {
-        val menuOptionView = mActivityContext.layoutInflater.inflate(
-                R.layout.task_view_menu_option, this, false
-        ) as LinearLayout
+        val menuOptionView =
+            mActivityContext.layoutInflater.inflate(R.layout.task_view_menu_option, this, false)
+                as LinearLayout
         menuOption.setIconAndLabelFor(
             menuOptionView.findViewById(R.id.icon),
             menuOptionView.findViewById(R.id.text)
@@ -230,24 +233,25 @@
     }
 
     /**
-     * Copy the iconView from taskView to dragLayer so it can stay on top of the scrim.
-     * It needs to be called after [getTargetObjectLocation] because [mTempRect] needs to be
-     * populated.
+     * Copy the iconView from taskView to dragLayer so it can stay on top of the scrim. It needs to
+     * be called after [getTargetObjectLocation] because [mTempRect] needs to be populated.
      */
     private fun copyIconToDragLayer(insets: Rect) {
-        iconView = IconView(context).apply {
-            layoutParams = FrameLayout.LayoutParams(
-                taskContainer.iconView.width,
-                taskContainer.iconView.height
-            )
-            x = mTempRect.left.toFloat() - insets.left
-            y = mTempRect.top.toFloat() - insets.top
-            drawable = taskContainer.iconView.drawable
-            setDrawableSize(
-                taskContainer.iconView.drawableWidth,
-                taskContainer.iconView.drawableHeight
-            )
-        }
+        iconView =
+            IconView(context).apply {
+                layoutParams =
+                    FrameLayout.LayoutParams(
+                        taskContainer.iconView.width,
+                        taskContainer.iconView.height
+                    )
+                x = mTempRect.left.toFloat() - insets.left
+                y = mTempRect.top.toFloat() - insets.top
+                drawable = taskContainer.iconView.drawable
+                setDrawableSize(
+                    taskContainer.iconView.drawableWidth,
+                    taskContainer.iconView.drawableHeight
+                )
+            }
 
         popupContainer.addView(iconView)
     }
@@ -281,12 +285,13 @@
         // which means the arrow is left aligned with the menu
         val rightAlignedMenuStartX = mTempRect.left - widthWithArrow
         val leftAlignedMenuStartX = mTempRect.right + extraHorizontalSpace
-        mIsLeftAligned = if (mIsRtl) {
-            rightAlignedMenuStartX + insets.left < 0
-        } else {
-            leftAlignedMenuStartX + (widthWithArrow - extraHorizontalSpace) + insets.left <
+        mIsLeftAligned =
+            if (mIsRtl) {
+                rightAlignedMenuStartX + insets.left < 0
+            } else {
+                leftAlignedMenuStartX + (widthWithArrow - extraHorizontalSpace) + insets.left <
                     dragLayer.width - insets.right
-        }
+            }
 
         var menuStartX = if (mIsLeftAligned) leftAlignedMenuStartX else rightAlignedMenuStartX
 
@@ -311,8 +316,8 @@
     override fun addArrow() {
         popupContainer.addView(mArrow)
         mArrow.x = getArrowX()
-        mArrow.y = y + (optionMeasuredHeight / 2) - (mArrowHeight / 2) +
-                extraSpaceForSecondRowAlignment
+        mArrow.y =
+            y + (optionMeasuredHeight / 2) - (mArrowHeight / 2) + extraSpaceForSecondRowAlignment
 
         updateArrowColor()
 
@@ -322,22 +327,19 @@
     }
 
     private fun getArrowX(): Float {
-        return if (mIsLeftAligned)
-            x - mArrowHeight
-        else
-            x + measuredWidth + mArrowOffsetVertical
+        return if (mIsLeftAligned) x - mArrowHeight else x + measuredWidth + mArrowOffsetVertical
     }
 
     override fun updateArrowColor() {
-        mArrow.background = RoundedArrowDrawable(
-            mArrowWidth.toFloat(),
-            mArrowHeight.toFloat(),
-            mArrowPointRadius.toFloat(),
-            mIsLeftAligned,
-            mArrowColor
-        )
+        mArrow.background =
+            RoundedArrowDrawable(
+                mArrowWidth.toFloat(),
+                mArrowHeight.toFloat(),
+                mArrowPointRadius.toFloat(),
+                mIsLeftAligned,
+                mArrowColor
+            )
         elevation = mElevation
         mArrow.elevation = mElevation
     }
-
-}
\ No newline at end of file
+}
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index f6e172a..c71a74e 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -377,6 +377,8 @@
 
     private void updateSplashView(Drawable icon) {
         if (icon == null || icon.getConstantState() == null) {
+            mSplashViewDrawable = null;
+            mSplashView = null;
             return;
         }
         mSplashViewDrawable = icon.getConstantState().newDrawable().mutate();
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 1d9e05f..aa37fdd 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -561,10 +561,12 @@
      */
     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.setVisibility(GONE);
+            filterView.setAlpha(0);
         } else {
-            filterView.setVisibility(VISIBLE);
+            filterView.setAlpha(1);
         }
 
         filterView.setOnClickListener(callback);
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
new file mode 100644
index 0000000..8a78d8c
--- /dev/null
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
@@ -0,0 +1,95 @@
+/*
+ * 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
+
+import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController
+import com.android.launcher3.taskbar.overlay.TaskbarOverlayController
+import com.android.systemui.shared.rotation.RotationButtonController
+import org.junit.Before
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+/**
+ * Helper class to extend to get access to all controllers. Gotta be careful of your relationship
+ * with this class though, it can be quite... controlling.
+ */
+abstract class TaskbarBaseTestCase {
+
+    @Mock lateinit var taskbarActivityContext: TaskbarActivityContext
+    @Mock lateinit var taskbarDragController: TaskbarDragController
+    @Mock lateinit var navButtonController: TaskbarNavButtonController
+    @Mock lateinit var navbarButtonsViewController: NavbarButtonsViewController
+    @Mock lateinit var rotationButtonController: RotationButtonController
+    @Mock lateinit var taskbarDragLayerController: TaskbarDragLayerController
+    @Mock lateinit var taskbarScrimViewController: TaskbarScrimViewController
+    @Mock lateinit var taskbarViewController: TaskbarViewController
+    @Mock lateinit var taskbarUnfoldAnimationController: TaskbarUnfoldAnimationController
+    @Mock lateinit var taskbarKeyguardController: TaskbarKeyguardController
+    @Mock lateinit var stashedHandleViewController: StashedHandleViewController
+    @Mock lateinit var taskbarStashController: TaskbarStashController
+    @Mock lateinit var taskbarEduController: TaskbarEduController
+    @Mock lateinit var taskbarAutohideSuspendController: TaskbarAutohideSuspendController
+    @Mock lateinit var taskbarPopupController: TaskbarPopupController
+    @Mock
+    lateinit var taskbarForceVisibleImmersiveController: TaskbarForceVisibleImmersiveController
+    @Mock lateinit var taskbarAllAppsController: TaskbarAllAppsController
+    @Mock lateinit var taskbarInsetsController: TaskbarInsetsController
+    @Mock lateinit var voiceInteractionWindowController: VoiceInteractionWindowController
+    @Mock lateinit var taskbarRecentAppsController: TaskbarRecentAppsController
+    @Mock lateinit var taskbarTranslationController: TaskbarTranslationController
+    @Mock lateinit var taskbarOverlayController: TaskbarOverlayController
+    @Mock lateinit var taskbarEduTooltipController: TaskbarEduTooltipController
+
+    lateinit var mTaskbarControllers: TaskbarControllers
+
+    @Before
+    open fun setup() {
+        /*
+         * NOTE: Mocking of controllers that are written in Kotlin won't work since their methods
+         * are final by default (and should not be changed only for tests), meaning unmockable.
+         * Womp, womp woooommmmppp.
+         * If you want to mock one of those methods, you need to make a parent interface that
+         * includes that method to allow mocking it.
+         */
+        MockitoAnnotations.initMocks(this)
+        mTaskbarControllers =
+            TaskbarControllers(
+                taskbarActivityContext,
+                taskbarDragController,
+                navButtonController,
+                navbarButtonsViewController,
+                rotationButtonController,
+                taskbarDragLayerController,
+                taskbarViewController,
+                taskbarScrimViewController,
+                taskbarUnfoldAnimationController,
+                taskbarKeyguardController,
+                stashedHandleViewController,
+                taskbarStashController,
+                taskbarEduController,
+                taskbarAutohideSuspendController,
+                taskbarPopupController,
+                taskbarForceVisibleImmersiveController,
+                taskbarOverlayController,
+                taskbarAllAppsController,
+                taskbarInsetsController,
+                voiceInteractionWindowController,
+                taskbarTranslationController,
+                taskbarRecentAppsController,
+                taskbarEduTooltipController,
+            )
+    }
+}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarKeyguardControllerTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarKeyguardControllerTest.kt
new file mode 100644
index 0000000..59db8c8
--- /dev/null
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarKeyguardControllerTest.kt
@@ -0,0 +1,150 @@
+/*
+ * 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
+
+import android.app.KeyguardManager
+import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISABLED
+import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING
+import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DOZING
+import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED
+import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED
+import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
+import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+
+class TaskbarKeyguardControllerTest : TaskbarBaseTestCase() {
+
+    @Mock
+    lateinit var baseDragLayer: TaskbarDragLayer
+    @Mock
+    lateinit var keyguardManager: KeyguardManager
+
+    @Before
+    override fun setup() {
+        super.setup()
+        whenever(taskbarActivityContext.getSystemService(KeyguardManager::class.java))
+                .thenReturn(keyguardManager)
+        whenever(baseDragLayer.childCount).thenReturn(0)
+        whenever(taskbarActivityContext.dragLayer).thenReturn(baseDragLayer)
+
+        taskbarKeyguardController = TaskbarKeyguardController(taskbarActivityContext)
+        taskbarKeyguardController.init(navbarButtonsViewController)
+    }
+
+    @Test
+    fun uninterestingFlags_noActions() {
+        setFlags(0)
+        verify(navbarButtonsViewController, never()).setKeyguardVisible(anyBoolean(), anyBoolean())
+    }
+
+    @Test
+    fun keyguardShowing() {
+        setFlags(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING)
+        verify(navbarButtonsViewController, times(1)).setKeyguardVisible(
+                true /*isKeyguardVisible*/,
+                false /*isKeyguardOccluded*/)
+    }
+
+    @Test
+    fun dozingShowing() {
+        setFlags(SYSUI_STATE_DEVICE_DOZING)
+        verify(navbarButtonsViewController, times(1)).setKeyguardVisible(
+                true /*isKeyguardVisible*/,
+                false /*isKeyguardOccluded*/)
+    }
+
+    @Test
+    fun keyguardOccluded() {
+        setFlags(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED)
+        verify(navbarButtonsViewController, times(1)).setKeyguardVisible(
+                false /*isKeyguardVisible*/,
+                true /*isKeyguardOccluded*/)
+    }
+
+    @Test
+    fun keyguardOccludedAndDozing() {
+        setFlags(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED.or(SYSUI_STATE_DEVICE_DOZING))
+        verify(navbarButtonsViewController, times(1)).setKeyguardVisible(
+                true /*isKeyguardVisible*/,
+                true /*isKeyguardOccluded*/)
+    }
+
+    @Test
+    fun deviceInsecure_hideBackForBouncer() {
+        whenever(keyguardManager.isDeviceSecure).thenReturn(false)
+        setFlags(SYSUI_STATE_OVERVIEW_DISABLED
+                .or(SYSUI_STATE_HOME_DISABLED)
+                .or(SYSUI_STATE_BOUNCER_SHOWING))
+
+        verify(navbarButtonsViewController, times(1)).setBackForBouncer(false)
+    }
+
+    @Test
+    fun deviceSecure_showBackForBouncer() {
+        whenever(keyguardManager.isDeviceSecure).thenReturn(true)
+        setFlags(SYSUI_STATE_OVERVIEW_DISABLED
+                .or(SYSUI_STATE_HOME_DISABLED)
+                .or(SYSUI_STATE_BOUNCER_SHOWING))
+
+        verify(navbarButtonsViewController, times(1)).setBackForBouncer(true)
+    }
+
+    @Test
+    fun homeShowing_hideBackForBouncer() {
+        whenever(keyguardManager.isDeviceSecure).thenReturn(true)
+        setFlags(SYSUI_STATE_OVERVIEW_DISABLED
+                .or(SYSUI_STATE_BOUNCER_SHOWING))
+
+        verify(navbarButtonsViewController, times(1)).setBackForBouncer(false)
+    }
+
+    @Test
+    fun overviewShowing_hideBackForBouncer() {
+        whenever(keyguardManager.isDeviceSecure).thenReturn(true)
+        setFlags(SYSUI_STATE_HOME_DISABLED
+                .or(SYSUI_STATE_BOUNCER_SHOWING))
+
+        verify(navbarButtonsViewController, times(1)).setBackForBouncer(false)
+    }
+
+    @Test
+    fun backDisabled_hideBackForBouncer() {
+        whenever(keyguardManager.isDeviceSecure).thenReturn(true)
+        setFlags(SYSUI_STATE_BACK_DISABLED
+                .or(SYSUI_STATE_BOUNCER_SHOWING))
+
+        verify(navbarButtonsViewController, times(1)).setBackForBouncer(false)
+
+        // back disabled along with home and overview
+        setFlags(SYSUI_STATE_BACK_DISABLED
+                .or(SYSUI_STATE_HOME_DISABLED)
+                .or(SYSUI_STATE_OVERVIEW_DISABLED)
+                .or(SYSUI_STATE_BOUNCER_SHOWING))
+
+        verify(navbarButtonsViewController, times(2)).setBackForBouncer(false)
+    }
+
+    private fun setFlags(flags: Int) {
+        taskbarKeyguardController.updateStateForSysuiFlags(flags)
+    }
+}
\ No newline at end of file
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
index 4eec319..9622619 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
@@ -18,6 +18,7 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -103,12 +104,20 @@
     }
 
     @Test
-    public void testLongPressHome() {
+    public void testLongPressHome_enabled() {
+        mNavButtonController.setAssistantLongPressEnabled(true /*assistantLongPressEnabled*/);
         mNavButtonController.onButtonLongClick(BUTTON_HOME, mockView);
         verify(mockSystemUiProxy, times(1)).startAssistant(any());
     }
 
     @Test
+    public void testLongPressHome_disabled() {
+        mNavButtonController.setAssistantLongPressEnabled(false /*assistantLongPressEnabled*/);
+        mNavButtonController.onButtonLongClick(BUTTON_HOME, mockView);
+        verify(mockSystemUiProxy, never()).startAssistant(any());
+    }
+
+    @Test
     public void testPressHome() {
         mNavButtonController.onButtonClick(BUTTON_HOME, mockView);
         verify(mockCommandHelper, times(1)).addCommand(TYPE_HOME);
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
index 58f0949..236b5db 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
@@ -8,38 +8,29 @@
 import android.widget.LinearLayout
 import androidx.test.runner.AndroidJUnit4
 import com.android.launcher3.DeviceProfile
+import com.android.launcher3.R
 import com.android.launcher3.taskbar.TaskbarManager
+import java.lang.IllegalStateException
+import org.junit.Assume.assumeTrue
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
-import com.android.launcher3.R
-import org.junit.Assume.assumeTrue
 import org.mockito.Mockito.`when` as whenever
 import org.mockito.MockitoAnnotations
-import java.lang.IllegalStateException
 
 @RunWith(AndroidJUnit4::class)
 class NavButtonLayoutFactoryTest {
 
-    @Mock
-    lateinit var mockDeviceProfile: DeviceProfile
-    @Mock
-    lateinit var mockParentButtonContainer: FrameLayout
-    @Mock
-    lateinit var mockNavLayout: LinearLayout
-    @Mock
-    lateinit var mockStartContextualLayout: ViewGroup
-    @Mock
-    lateinit var mockEndContextualLayout: ViewGroup
-    @Mock
-    lateinit var mockResources: Resources
-    @Mock
-    lateinit var mockBackButton: ImageView
-    @Mock
-    lateinit var mockRecentsButton: ImageView
-    @Mock
-    lateinit var mockHomeButton: ImageView
+    @Mock lateinit var mockDeviceProfile: DeviceProfile
+    @Mock lateinit var mockParentButtonContainer: FrameLayout
+    @Mock lateinit var mockNavLayout: LinearLayout
+    @Mock lateinit var mockStartContextualLayout: ViewGroup
+    @Mock lateinit var mockEndContextualLayout: ViewGroup
+    @Mock lateinit var mockResources: Resources
+    @Mock lateinit var mockBackButton: ImageView
+    @Mock lateinit var mockRecentsButton: ImageView
+    @Mock lateinit var mockHomeButton: ImageView
 
     @Before
     fun setup() {
@@ -53,11 +44,11 @@
 
         // Init top level layout
         whenever(mockParentButtonContainer.findViewById<LinearLayout>(R.id.end_nav_buttons))
-                .thenReturn(mockNavLayout)
+            .thenReturn(mockNavLayout)
         whenever(mockParentButtonContainer.findViewById<ViewGroup>(R.id.end_contextual_buttons))
-                .thenReturn(mockEndContextualLayout)
+            .thenReturn(mockEndContextualLayout)
         whenever(mockParentButtonContainer.findViewById<ViewGroup>(R.id.start_contextual_buttons))
-                .thenReturn(mockStartContextualLayout)
+            .thenReturn(mockStartContextualLayout)
     }
 
     @Test
@@ -65,8 +56,12 @@
         assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
         mockDeviceProfile.isTaskbarPresent = true
         val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
-                getLayoutter(isKidsMode = true, isInSetup = false, isThreeButtonNav = false,
-                        phoneMode = false)
+            getLayoutter(
+                isKidsMode = true,
+                isInSetup = false,
+                isThreeButtonNav = false,
+                phoneMode = false
+            )
         assert(layoutter is KidsNavLayoutter)
     }
 
@@ -75,8 +70,12 @@
         assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
         mockDeviceProfile.isTaskbarPresent = true
         val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
-                getLayoutter(isKidsMode = false, isInSetup = true, isThreeButtonNav = false,
-                        phoneMode = false)
+            getLayoutter(
+                isKidsMode = false,
+                isInSetup = true,
+                isThreeButtonNav = false,
+                phoneMode = false
+            )
         assert(layoutter is SetupNavLayoutter)
     }
 
@@ -85,8 +84,12 @@
         assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
         mockDeviceProfile.isTaskbarPresent = true
         val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
-                getLayoutter(isKidsMode = false, isInSetup = false, isThreeButtonNav = false,
-                        phoneMode = false)
+            getLayoutter(
+                isKidsMode = false,
+                isInSetup = false,
+                isThreeButtonNav = false,
+                phoneMode = false
+            )
         assert(layoutter is TaskbarNavLayoutter)
     }
 
@@ -94,8 +97,12 @@
     fun noValidLayoutForLargeScreenTaskbarNotPresent() {
         assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
         mockDeviceProfile.isTaskbarPresent = false
-        getLayoutter(isKidsMode = false, isInSetup = false, isThreeButtonNav = false,
-                        phoneMode = false)
+        getLayoutter(
+            isKidsMode = false,
+            isInSetup = false,
+            isThreeButtonNav = false,
+            phoneMode = false
+        )
     }
 
     @Test
@@ -103,8 +110,12 @@
         assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
         mockDeviceProfile.isTaskbarPresent = false
         val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
-                getLayoutter(isKidsMode = false, isInSetup = false, isThreeButtonNav = true,
-                        phoneMode = true)
+            getLayoutter(
+                isKidsMode = false,
+                isInSetup = false,
+                isThreeButtonNav = true,
+                phoneMode = true
+            )
         assert(layoutter is PhonePortraitNavLayoutter)
     }
 
@@ -114,8 +125,12 @@
         mockDeviceProfile.isTaskbarPresent = false
         setDeviceProfileLandscape()
         val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
-                getLayoutter(isKidsMode = false, isInSetup = false, isThreeButtonNav = true,
-                        phoneMode = true)
+            getLayoutter(
+                isKidsMode = false,
+                isInSetup = false,
+                isThreeButtonNav = true,
+                phoneMode = true
+            )
         assert(layoutter is PhoneLandscapeNavLayoutter)
     }
 
@@ -123,8 +138,12 @@
     fun noValidLayoutForPhoneGestureNav() {
         assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
         mockDeviceProfile.isTaskbarPresent = false
-        getLayoutter(isKidsMode = false, isInSetup = false, isThreeButtonNav = false,
-                phoneMode = true)
+        getLayoutter(
+            isKidsMode = false,
+            isInSetup = false,
+            isThreeButtonNav = false,
+            phoneMode = true
+        )
     }
 
     private fun setDeviceProfileLandscape() {
@@ -134,15 +153,20 @@
         landscapeField.set(mockDeviceProfile, true)
     }
 
-    private fun getLayoutter(isKidsMode: Boolean, isInSetup: Boolean,
-                             isThreeButtonNav: Boolean, phoneMode: Boolean):
-            NavButtonLayoutFactory.NavButtonLayoutter {
+    private fun getLayoutter(
+        isKidsMode: Boolean,
+        isInSetup: Boolean,
+        isThreeButtonNav: Boolean,
+        phoneMode: Boolean
+    ): NavButtonLayoutFactory.NavButtonLayoutter {
         return NavButtonLayoutFactory.getUiLayoutter(
-                deviceProfile = mockDeviceProfile,
-                navButtonsView = mockParentButtonContainer,
-                resources = mockResources,
-                isKidsMode = isKidsMode, isInSetup = isInSetup,
-                isThreeButtonNav = isThreeButtonNav, phoneMode = phoneMode
+            deviceProfile = mockDeviceProfile,
+            navButtonsView = mockParentButtonContainer,
+            resources = mockResources,
+            isKidsMode = isKidsMode,
+            isInSetup = isInSetup,
+            isThreeButtonNav = isThreeButtonNav,
+            phoneMode = phoneMode
         )
     }
-}
\ No newline at end of file
+}
diff --git a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java
index 5c2e14f..1129a33 100644
--- a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java
+++ b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java
@@ -46,7 +46,8 @@
             runWithShellPermission(() ->
                     usageStatsManager.registerAppUsageLimitObserver(observerId, packages,
                             Duration.ofSeconds(600), Duration.ofSeconds(300),
-                            PendingIntent.getActivity(mTargetContext, -1, new Intent(),
+                            PendingIntent.getActivity(mTargetContext, -1, new Intent()
+                                            .setPackage(mTargetContext.getPackageName()),
                                     PendingIntent.FLAG_MUTABLE)));
 
             mLauncher.goHome();
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index 47bef7b..62d46d3 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -32,6 +32,8 @@
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.rule.ShellCommandRule.disableHeadsUpNotification;
 import static com.android.launcher3.util.rule.ShellCommandRule.getLauncherCommand;
+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;
@@ -59,6 +61,7 @@
 import com.android.launcher3.util.rule.FailureWatcher;
 import com.android.launcher3.util.rule.SamplerRule;
 import com.android.launcher3.util.rule.ScreenRecordRule;
+import com.android.launcher3.util.rule.TestStabilityRule;
 import com.android.quickstep.views.RecentsView;
 
 import org.junit.After;
@@ -168,7 +171,7 @@
 
     // b/143488140
     //@NavigationModeSwitch
-    @Ignore
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/266606727
     @Test
     public void goToOverviewFromHome() {
         mDevice.pressHome();
@@ -216,7 +219,7 @@
 
     // b/143488140
     //@NavigationModeSwitch
-    @Ignore
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/266606727
     @Test
     public void testOverview() {
         startAppFast(getAppPackageName());
diff --git a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt b/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
index 5ec935f..9afd893 100644
--- a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
@@ -27,15 +27,13 @@
 import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
 import com.android.wm.shell.util.SplitBounds
 import com.google.common.truth.Truth.assertThat
+import kotlin.math.roundToInt
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mockito.mock
-import kotlin.math.roundToInt
 
-/**
- * Test for FullscreenDrawParams class.
- */
+/** Test for FullscreenDrawParams class. */
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class FullscreenDrawParamsTest : DeviceProfileBaseTest() {
@@ -61,15 +59,29 @@
         val currentRotation = 0
         val isRtl = false
 
-        mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
-                canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
-                isRtl)
-        params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
-                /* taskViewScale= */ 1.0f,  /* previewWidth= */ 0, dp, mPreviewPositionHelper)
+        mPreviewPositionHelper.updateThumbnailMatrix(
+            previewRect,
+            mThumbnailData,
+            canvasWidth,
+            canvasHeight,
+            dp.widthPx,
+            dp.heightPx,
+            dp.taskbarSize,
+            dp.isTablet,
+            currentRotation,
+            isRtl
+        )
+        params.setProgress(
+            /* fullscreenProgress= */ 1.0f,
+            /* parentScale= */ 1.0f,
+            /* taskViewScale= */ 1.0f,
+            /* previewWidth= */ 0,
+            dp,
+            mPreviewPositionHelper
+        )
 
         val expectedClippedInsets = RectF(0f, 0f, 0f, dp.taskbarSize * TASK_SCALE)
-        assertThat(params.mCurrentDrawnInsets)
-                .isEqualTo(expectedClippedInsets)
+        assertThat(params.mCurrentDrawnInsets).isEqualTo(expectedClippedInsets)
     }
 
     @Test
@@ -83,25 +95,42 @@
         val isRtl = false
         // portrait/vertical split apps
         val dividerSize = 10
-        val splitBounds = SplitBounds(
+        val splitBounds =
+            SplitBounds(
                 Rect(0, 0, dp.widthPx, (dp.heightPx - dividerSize) / 2),
                 Rect(0, (dp.heightPx + dividerSize) / 2, dp.widthPx, dp.heightPx),
-                0 /*lefTopTaskId*/, 0 /*rightBottomTaskId*/)
+                0 /*lefTopTaskId*/,
+                0 /*rightBottomTaskId*/
+            )
         mPreviewPositionHelper.setSplitBounds(splitBounds, STAGE_POSITION_BOTTOM_OR_RIGHT)
 
-        mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
-                canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
-                isRtl)
-        params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
-                /* taskViewScale= */ 1.0f,  /* previewWidth= */ 0, dp, mPreviewPositionHelper)
+        mPreviewPositionHelper.updateThumbnailMatrix(
+            previewRect,
+            mThumbnailData,
+            canvasWidth,
+            canvasHeight,
+            dp.widthPx,
+            dp.heightPx,
+            dp.taskbarSize,
+            dp.isTablet,
+            currentRotation,
+            isRtl
+        )
+        params.setProgress(
+            /* fullscreenProgress= */ 1.0f,
+            /* parentScale= */ 1.0f,
+            /* taskViewScale= */ 1.0f,
+            /* previewWidth= */ 0,
+            dp,
+            mPreviewPositionHelper
+        )
 
         // Probably unhelpful, but also unclear how to test otherwise ¯\_(ツ)_/¯
-        val fullscreenTaskHeight = dp.heightPx *
-                (1 - (splitBounds.topTaskPercent + splitBounds.dividerHeightPercent))
+        val fullscreenTaskHeight =
+            dp.heightPx * (1 - (splitBounds.topTaskPercent + splitBounds.dividerHeightPercent))
         val canvasScreenRatio = canvasHeight / fullscreenTaskHeight
         val expectedBottomHint = dp.taskbarSize * canvasScreenRatio
-        assertThat(params.mCurrentDrawnInsets.bottom)
-                .isWithin(1f).of(expectedBottomHint)
+        assertThat(params.mCurrentDrawnInsets.bottom).isWithin(1f).of(expectedBottomHint)
     }
 
     @Test
@@ -115,20 +144,37 @@
         val isRtl = false
         // portrait/vertical split apps
         val dividerSize = 10
-        val splitBounds = SplitBounds(
+        val splitBounds =
+            SplitBounds(
                 Rect(0, 0, dp.widthPx, (dp.heightPx - dividerSize) / 2),
                 Rect(0, (dp.heightPx + dividerSize) / 2, dp.widthPx, dp.heightPx),
-                0 /*lefTopTaskId*/, 0 /*rightBottomTaskId*/)
+                0 /*lefTopTaskId*/,
+                0 /*rightBottomTaskId*/
+            )
         mPreviewPositionHelper.setSplitBounds(splitBounds, STAGE_POSITION_TOP_OR_LEFT)
 
-        mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
-                canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
-                isRtl)
-        params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
-                /* taskViewScale= */ 1.0f,  /* previewWidth= */ 0, dp, mPreviewPositionHelper)
+        mPreviewPositionHelper.updateThumbnailMatrix(
+            previewRect,
+            mThumbnailData,
+            canvasWidth,
+            canvasHeight,
+            dp.widthPx,
+            dp.heightPx,
+            dp.taskbarSize,
+            dp.isTablet,
+            currentRotation,
+            isRtl
+        )
+        params.setProgress(
+            /* fullscreenProgress= */ 1.0f,
+            /* parentScale= */ 1.0f,
+            /* taskViewScale= */ 1.0f,
+            /* previewWidth= */ 0,
+            dp,
+            mPreviewPositionHelper
+        )
 
-        assertThat(params.mCurrentDrawnInsets.bottom)
-                .isWithin(1f).of((0f))
+        assertThat(params.mCurrentDrawnInsets.bottom).isWithin(1f).of((0f))
     }
 
     @Test
@@ -142,20 +188,37 @@
         val isRtl = false
         // portrait/vertical split apps
         val dividerSize = 10
-        val splitBounds = SplitBounds(
+        val splitBounds =
+            SplitBounds(
                 Rect(0, 0, (dp.widthPx - dividerSize) / 2, dp.heightPx),
                 Rect((dp.widthPx + dividerSize) / 2, 0, dp.widthPx, dp.heightPx),
-                0 /*lefTopTaskId*/, 0 /*rightBottomTaskId*/)
+                0 /*lefTopTaskId*/,
+                0 /*rightBottomTaskId*/
+            )
         mPreviewPositionHelper.setSplitBounds(splitBounds, STAGE_POSITION_BOTTOM_OR_RIGHT)
 
-        mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
-                canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
-                isRtl)
-        params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
-                /* taskViewScale= */ 1.0f,  /* previewWidth= */ 0, dp, mPreviewPositionHelper)
+        mPreviewPositionHelper.updateThumbnailMatrix(
+            previewRect,
+            mThumbnailData,
+            canvasWidth,
+            canvasHeight,
+            dp.widthPx,
+            dp.heightPx,
+            dp.taskbarSize,
+            dp.isTablet,
+            currentRotation,
+            isRtl
+        )
+        params.setProgress(
+            /* fullscreenProgress= */ 1.0f,
+            /* parentScale= */ 1.0f,
+            /* taskViewScale= */ 1.0f,
+            /* previewWidth= */ 0,
+            dp,
+            mPreviewPositionHelper
+        )
 
-        assertThat(params.mCurrentDrawnInsets.bottom)
-                .isWithin(1f).of((dp.taskbarSize * TASK_SCALE))
+        assertThat(params.mCurrentDrawnInsets.bottom).isWithin(1f).of((dp.taskbarSize * TASK_SCALE))
     }
 
     @Test
@@ -168,14 +231,28 @@
         val currentRotation = 0
         val isRtl = false
 
-        mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
-                canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
-                isRtl)
-        params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
-                /* taskViewScale= */ 1.0f,  /* previewWidth= */ 0, dp, mPreviewPositionHelper)
+        mPreviewPositionHelper.updateThumbnailMatrix(
+            previewRect,
+            mThumbnailData,
+            canvasWidth,
+            canvasHeight,
+            dp.widthPx,
+            dp.heightPx,
+            dp.taskbarSize,
+            dp.isTablet,
+            currentRotation,
+            isRtl
+        )
+        params.setProgress(
+            /* fullscreenProgress= */ 1.0f,
+            /* parentScale= */ 1.0f,
+            /* taskViewScale= */ 1.0f,
+            /* previewWidth= */ 0,
+            dp,
+            mPreviewPositionHelper
+        )
 
         val expectedClippedInsets = RectF(0f, 0f, 0f, 0f)
-        assertThat(params.mCurrentDrawnInsets)
-                .isEqualTo(expectedClippedInsets)
+        assertThat(params.mCurrentDrawnInsets).isEqualTo(expectedClippedInsets)
     }
-}
\ No newline at end of file
+}
diff --git a/quickstep/tests/src/com/android/quickstep/HotseatWidthCalculationTest.kt b/quickstep/tests/src/com/android/quickstep/HotseatWidthCalculationTest.kt
index 4837c6c..adbca32 100644
--- a/quickstep/tests/src/com/android/quickstep/HotseatWidthCalculationTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/HotseatWidthCalculationTest.kt
@@ -29,8 +29,8 @@
 class HotseatWidthCalculationTest : DeviceProfileBaseTest() {
 
     /**
-     * This is a case when after setting the hotseat, the space needs to be recalculated
-     * but it doesn't need to change QSB width or remove icons
+     * This is a case when after setting the hotseat, the space needs to be recalculated but it
+     * doesn't need to change QSB width or remove icons
      */
     @Test
     fun distribute_border_space_when_space_is_enough_portrait() {
@@ -51,8 +51,8 @@
     }
 
     /**
-     * This is a case when after setting the hotseat, and recalculating spaces
-     * it still needs to remove icons for everything to fit
+     * This is a case when after setting the hotseat, and recalculating spaces it still needs to
+     * remove icons for everything to fit
      */
     @Test
     fun decrease_num_of_icons_when_not_enough_space_portrait() {
@@ -73,8 +73,8 @@
     }
 
     /**
-     * This is a case when after setting the hotseat, the space needs to be recalculated
-     * but it doesn't need to change QSB width or remove icons
+     * This is a case when after setting the hotseat, the space needs to be recalculated but it
+     * doesn't need to change QSB width or remove icons
      */
     @Test
     fun distribute_border_space_when_space_is_enough_landscape() {
@@ -94,8 +94,8 @@
     }
 
     /**
-     * This is a case when the hotseat spans a certain amount of columns
-     * and the nav buttons push the hotseat to the side, but not enough to change the border space.
+     * This is a case when the hotseat spans a certain amount of columns and the nav buttons push
+     * the hotseat to the side, but not enough to change the border space.
      */
     @Test
     fun nav_buttons_dont_interfere_with_required_hotseat_width() {
@@ -118,9 +118,7 @@
         assertThat(dp.hotseatQsbWidth).isEqualTo(1233)
     }
 
-    /**
-     * This is a case when after setting the hotseat, the QSB width needs to be changed to fit
-     */
+    /** This is a case when after setting the hotseat, the QSB width needs to be changed to fit */
     @Test
     fun decrease_qsb_when_not_enough_space_landscape() {
         initializeVarsForTablet(isGestureMode = false, isLandscape = true)
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 9a2fcc0..9f34775 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -262,6 +262,19 @@
         return launchedAppState;
     }
 
+    private void quickSwitchToPreviousAppAndAssert(boolean toRight) {
+        final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
+        if (toRight) {
+            launchedAppState.quickSwitchToPreviousApp();
+        } else {
+            launchedAppState.quickSwitchToPreviousAppSwipeLeft();
+        }
+
+        // While enable shell transition, Launcher can be resumed due to transient launch.
+        waitForLauncherCondition("Launcher shouldn't stay in resume forever",
+                this::isInLaunchedApp, 3000 /* timeout */);
+    }
+
     @Test
     @PortraitLandscape
     public void testAllAppsFromHome() throws Exception {
@@ -288,13 +301,11 @@
         startTestActivity(3);
         startTestActivity(4);
 
-        LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
-        launchedAppState.quickSwitchToPreviousApp();
+        quickSwitchToPreviousAppAndAssert(true /* toRight */);
         assertTrue("The first app we should have quick switched to is not running",
                 isTestActivityRunning(3));
 
-        launchedAppState = getAndAssertLaunchedApp();
-        launchedAppState.quickSwitchToPreviousApp();
+        quickSwitchToPreviousAppAndAssert(true /* toRight */);
         if (mLauncher.getNavigationModel() == NavigationModel.THREE_BUTTON) {
             // 3-button mode toggles between 2 apps, rather than going back further.
             assertTrue("Second quick switch should have returned to the first app.",
@@ -303,12 +314,12 @@
             assertTrue("The second app we should have quick switched to is not running",
                     isTestActivityRunning(2));
         }
-        launchedAppState = getAndAssertLaunchedApp();
-        launchedAppState.quickSwitchToPreviousAppSwipeLeft();
+
+        quickSwitchToPreviousAppAndAssert(false /* toRight */);
         assertTrue("The 2nd app we should have quick switched to is not running",
                 isTestActivityRunning(3));
 
-        launchedAppState = getAndAssertLaunchedApp();
+        final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
         launchedAppState.switchToOverview();
     }
 
@@ -327,8 +338,10 @@
         launchedAppState.assertTaskbarHidden();
 
         // Quick-switch to the test app with swiping to right.
-        launchedAppState.quickSwitchToPreviousApp();
+        quickSwitchToPreviousAppAndAssert(true /* toRight */);
 
+        assertTrue("The first app we should have quick switched to is not running",
+                isTestActivityRunning(2));
         // Expect task bar visible when the launched app was the test activity.
         launchedAppState = getAndAssertLaunchedApp();
         launchedAppState.assertTaskbarVisible();
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
index 0b8bc10..aed26d3 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
@@ -18,6 +18,7 @@
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
 import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
+import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
 
 import static junit.framework.TestCase.assertEquals;
 
@@ -82,19 +83,31 @@
     }
 
     @Test
-    @TaskbarModeSwitch
+    @TaskbarModeSwitch(mode = PERSISTENT)
     public void testLaunchApp() throws Exception {
         getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
     }
 
     @Test
-    @TaskbarModeSwitch
+    @TaskbarModeSwitch(mode = TRANSIENT)
+    public void testTransientLaunchApp() throws Exception {
+        getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+    }
+
+    @Test
+    @TaskbarModeSwitch(mode = PERSISTENT)
     public void testOpenMenu() throws Exception {
         getTaskbar().getAppIcon(TEST_APP_NAME).openMenu();
     }
 
     @Test
-    @TaskbarModeSwitch
+    @TaskbarModeSwitch(mode = TRANSIENT)
+    public void testTransientOpenMenu() throws Exception {
+        getTaskbar().getAppIcon(TEST_APP_NAME).openMenu();
+    }
+
+    @Test
+    @TaskbarModeSwitch(mode = PERSISTENT)
     public void testLaunchShortcut() throws Exception {
         getTaskbar().getAppIcon(TEST_APP_NAME)
                 .openDeepShortcutMenu()
@@ -103,9 +116,18 @@
     }
 
     @Test
+    @TaskbarModeSwitch(mode = TRANSIENT)
+    public void testTransientLaunchShortcut() throws Exception {
+        getTaskbar().getAppIcon(TEST_APP_NAME)
+                .openDeepShortcutMenu()
+                .getMenuItem("Shortcut 1")
+                .launch(TEST_APP_PACKAGE);
+    }
+
+    @Test
     @ScreenRecord // b/231615831
     @PortraitLandscape
-    @TaskbarModeSwitch
+    @TaskbarModeSwitch(mode = PERSISTENT)
     public void testLaunchAppInSplitscreen() throws Exception {
         getTaskbar().getAppIcon(TEST_APP_NAME).dragToSplitscreen(
                 TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
@@ -114,7 +136,16 @@
     @Test
     @ScreenRecord // b/231615831
     @PortraitLandscape
-    @TaskbarModeSwitch
+    @TaskbarModeSwitch(mode = TRANSIENT)
+    public void testTransientLaunchAppInSplitscreen() throws Exception {
+        getTaskbar().getAppIcon(TEST_APP_NAME).dragToSplitscreen(
+                TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+    }
+
+    @Test
+    @ScreenRecord // b/231615831
+    @PortraitLandscape
+    @TaskbarModeSwitch(mode = PERSISTENT)
     public void testLaunchShortcutInSplitscreen() throws Exception {
         getTaskbar().getAppIcon(TEST_APP_NAME)
                 .openDeepShortcutMenu()
@@ -123,19 +154,42 @@
     }
 
     @Test
-    @TaskbarModeSwitch
+    @ScreenRecord // b/231615831
+    @PortraitLandscape
+    @TaskbarModeSwitch(mode = TRANSIENT)
+    public void testTransientLaunchShortcutInSplitscreen() throws Exception {
+        getTaskbar().getAppIcon(TEST_APP_NAME)
+                .openDeepShortcutMenu()
+                .getMenuItem("Shortcut 1")
+                .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+    }
+
+    @Test
+    @TaskbarModeSwitch(mode = PERSISTENT)
     public void testLaunchApp_FromTaskbarAllApps() throws Exception {
         getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
     }
 
     @Test
-    @TaskbarModeSwitch
+    @TaskbarModeSwitch(mode = TRANSIENT)
+    public void testTransientLaunchApp_FromTaskbarAllApps() throws Exception {
+        getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+    }
+
+    @Test
+    @TaskbarModeSwitch(mode = PERSISTENT)
     public void testOpenMenu_FromTaskbarAllApps() throws Exception {
         getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).openMenu();
     }
 
     @Test
-    @TaskbarModeSwitch
+    @TaskbarModeSwitch(mode = TRANSIENT)
+    public void testTransientOpenMenu_FromTaskbarAllApps() throws Exception {
+        getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).openMenu();
+    }
+
+    @Test
+    @TaskbarModeSwitch(mode = PERSISTENT)
     public void testLaunchShortcut_FromTaskbarAllApps() throws Exception {
         getTaskbar().openAllApps()
                 .getAppIcon(TEST_APP_NAME)
@@ -145,9 +199,19 @@
     }
 
     @Test
+    @TaskbarModeSwitch(mode = TRANSIENT)
+    public void testTransientLaunchShortcut_FromTaskbarAllApps() throws Exception {
+        getTaskbar().openAllApps()
+                .getAppIcon(TEST_APP_NAME)
+                .openDeepShortcutMenu()
+                .getMenuItem("Shortcut 1")
+                .launch(TEST_APP_PACKAGE);
+    }
+
+    @Test
     @ScreenRecord // b/231615831
     @PortraitLandscape
-    @TaskbarModeSwitch
+    @TaskbarModeSwitch(mode = PERSISTENT)
     public void testLaunchAppInSplitscreen_FromTaskbarAllApps() throws Exception {
         getTaskbar().openAllApps()
                 .getAppIcon(TEST_APP_NAME)
@@ -157,7 +221,17 @@
     @Test
     @ScreenRecord // b/231615831
     @PortraitLandscape
-    @TaskbarModeSwitch
+    @TaskbarModeSwitch(mode = TRANSIENT)
+    public void testTransientLaunchAppInSplitscreen_FromTaskbarAllApps() throws Exception {
+        getTaskbar().openAllApps()
+                .getAppIcon(TEST_APP_NAME)
+                .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+    }
+
+    @Test
+    @ScreenRecord // b/231615831
+    @PortraitLandscape
+    @TaskbarModeSwitch(mode = PERSISTENT)
     public void testLaunchShortcutInSplitscreen_FromTaskbarAllApps() throws Exception {
         getTaskbar().openAllApps()
                 .getAppIcon(TEST_APP_NAME)
@@ -166,6 +240,18 @@
                 .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
     }
 
+    @Test
+    @ScreenRecord // b/231615831
+    @PortraitLandscape
+    @TaskbarModeSwitch(mode = TRANSIENT)
+    public void testTransientLaunchShortcutInSplitscreen_FromTaskbarAllApps() throws Exception {
+        getTaskbar().openAllApps()
+                .getAppIcon(TEST_APP_NAME)
+                .openDeepShortcutMenu()
+                .getMenuItem("Shortcut 1")
+                .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+    }
+
     private Taskbar getTaskbar() {
         Taskbar taskbar = mLauncher.getLaunchedAppState().getTaskbar();
         List<String> taskbarIconNames = taskbar.getIconNames();
diff --git a/res/layout/taskbar_divider.xml b/res/layout/taskbar_divider.xml
new file mode 100644
index 0000000..e25e7a3
--- /dev/null
+++ b/res/layout/taskbar_divider.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/taskbar_divider_container"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+    <View
+        android:id="@+id/taskbar_divider_bar"
+        android:layout_height="32dp"
+        android:layout_width="2dp"
+        android:layout_gravity="center"
+        android:background="@drawable/bg_rounded_corner_bottom_sheet_handle" />
+    <!-- TODO(b/265347148): Create separate drawable -->
+</FrameLayout>
diff --git a/res/layout/widget_cell_content.xml b/res/layout/widget_cell_content.xml
index feebfe1..3f61aaa 100644
--- a/res/layout/widget_cell_content.xml
+++ b/res/layout/widget_cell_content.xml
@@ -23,6 +23,7 @@
         android:layout_height="0dp"
         android:layout_weight="1"
         android:importantForAccessibility="noHideDescendants"
+        android:hapticFeedbackEnabled="false"
         android:layout_marginVertical="8dp">
         <!-- The image of the widget. This view does not support padding. Any placement adjustment
              should be done using margins. Width & height are set at runtime after scaling the
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 3a58b85..46358cd 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -53,9 +53,9 @@
     <string name="widget_category_conversations" msgid="8894438636213590446">"Сүйлөшүүлөр"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Керектүү маалымат манжаңыздын учунда"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Бир нерсе билүү үчүн колдонмолорду улам ачып убара болбостон, башкы экранга виджеттерди кошуп коюңуз."</string>
-    <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Виджеттин жөндөөлөрүн өзгөртүү үчүн таптап коюңуз"</string>
+    <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Виджеттин параметрлерин өзгөртүү үчүн таптап коюңуз"</string>
     <string name="widget_education_close_button" msgid="8676165703104836580">"Түшүндүм"</string>
-    <string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Виджеттин жөндөөлөрүн өзгөртүү"</string>
+    <string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Виджеттин параметрлерин өзгөртүү"</string>
     <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"Колдонмолорду издөө"</string>
     <string name="all_apps_loading_message" msgid="5813968043155271636">"Колдонмолор жүктөлүүдө…"</string>
     <string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" сурамына дал келген колдонмолор табылган жок"</string>
@@ -78,13 +78,13 @@
     <string name="pin_prediction" msgid="4196423321649756498">"Божомолдонгон колдонмону кадап коюу"</string>
     <string name="permlab_install_shortcut" msgid="5632423390354674437">"тез чакырмаларды орнотуу"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"Колдонмого колдонуучуга кайрылбастан тез чакырма кошууга уруксат берет."</string>
-    <string name="permlab_read_settings" msgid="5136500343007704955">"үйдүн жөндөөлөрүн жана ыкчам баскычтарын окуу"</string>
-    <string name="permdesc_read_settings" msgid="4208061150510996676">"Колдонмого үйдүн жөндөөлөрүн жана ыкчам баскычтарын окууга уруксат берет."</string>
-    <string name="permlab_write_settings" msgid="4820028712156303762">"үйдүн жөндөөлөрүн жана ыкчам баскычтарын жазуу"</string>
-    <string name="permdesc_write_settings" msgid="726859348127868466">"Колдонмого үйдүн жөндөөлөрүн жана ыкчам баскычтарын өзгөртүүгө уруксат берет."</string>
+    <string name="permlab_read_settings" msgid="5136500343007704955">"үйдүн параметрлерин жана ыкчам баскычтарын окуу"</string>
+    <string name="permdesc_read_settings" msgid="4208061150510996676">"Колдонмого үйдүн параметрлерин жана ыкчам баскычтарын окууга уруксат берет."</string>
+    <string name="permlab_write_settings" msgid="4820028712156303762">"үйдүн параметрлерин жана ыкчам баскычтарын жазуу"</string>
+    <string name="permdesc_write_settings" msgid="726859348127868466">"Колдонмого үйдүн параметрлерин жана ыкчам баскычтарын өзгөртүүгө уруксат берет."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> телефон чалууларды аткарууга уруксаты жок"</string>
     <string name="gadget_error_text" msgid="740356548025791839">"Виджет жүктөлбөй жатат"</string>
-    <string name="gadget_setup_text" msgid="8348374825537681407">"Виджеттин жөндөөлөрү"</string>
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Виджеттин параметрлери"</string>
     <string name="gadget_complete_setup_text" msgid="309040266978007925">"Аягына чейин тууралоо үчүн басып коюңуз"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Бул системдик колдонмо жана аны чечкенге болбойт."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Аталышын түзөтүү"</string>
@@ -102,7 +102,7 @@
     <string name="folder_name_format_overflow" msgid="4270108890534995199">"<xliff:g id="NAME">%1$s</xliff:g> папкасындагы объекттер: <xliff:g id="SIZE">%2$d</xliff:g> же андан көбүрөөк"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"Тушкагаздар"</string>
     <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Тушкагаз жана стиль"</string>
-    <string name="settings_button_text" msgid="8873672322605444408">"Башкы бет жөндөөлөрү"</string>
+    <string name="settings_button_text" msgid="8873672322605444408">"Башкы бет параметрлери"</string>
     <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Администраторуңуз өчүрүп койгон"</string>
     <string name="allow_rotation_title" msgid="7222049633713050106">"Башкы экранды бурууга уруксат берүү"</string>
     <string name="allow_rotation_desc" msgid="8662546029078692509">"Телефон бурулганда"</string>
diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml
new file mode 100644
index 0000000..52474da
--- /dev/null
+++ b/res/values-land/styles.xml
@@ -0,0 +1,21 @@
+<?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.
+  -->
+
+<resources>
+    <style name="CellStyleDefault">
+        <item name="iconDrawablePadding">4dp</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index bb1fb36..4dda225 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -162,7 +162,7 @@
     <string name="work_profile_toggle_label" msgid="3081029915775481146">"Perfil de trabalho"</string>
     <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"As apps de trabalho têm um emblema e estão visíveis para o seu administrador de TI"</string>
     <string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
-    <string name="work_apps_paused_title" msgid="3040901117349444598">"As apps de trabalho estão em pausa"</string>
+    <string name="work_apps_paused_title" msgid="3040901117349444598">"As apps de trabalho estão suspensas."</string>
     <string name="work_apps_paused_body" msgid="261634750995824906">"As apps de trabalho não podem enviar-lhe notificações, utilizar a bateria ou aceder à sua localização"</string>
     <string name="work_apps_paused_content_description" msgid="5149623040804051095">"As apps de trabalho estão desativadas. As apps de trabalho não podem enviar-lhe notificações, utilizar a bateria ou aceder à sua localização"</string>
     <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"As apps de trabalho têm um emblema e estão visíveis para o seu administrador de TI"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 98e8607..d97ba0f 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -32,7 +32,7 @@
     <string name="split_screen_position_left" msgid="7537793098851830883">"Dividir para a esquerda"</string>
     <string name="split_screen_position_right" msgid="1569377524925193369">"Dividir para a direita"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Informações do app %1$s"</string>
-    <string name="long_press_widget_to_add" msgid="3587712543577675817">"Toque e mantenha pressionado para mover um widget."</string>
+    <string name="long_press_widget_to_add" msgid="3587712543577675817">"Toque e pressione para mover um widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toque duas vezes e mantenha a tela pressionada para mover um widget ou usar ações personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largura por %2$d de altura"</string>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 40e49f1..09b2d6f 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -46,7 +46,4 @@
 
     <!--  Folder spaces  -->
     <dimen name="folder_footer_horiz_padding">24dp</dimen>
-
-    <!-- Transient taskbar -->
-    <dimen name="transient_taskbar_icon_size">57dp</dimen>
 </resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 08561d5..e6f285c 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -142,9 +142,13 @@
         <!--  numSearchContainerColumns defaults to numColumns, if not specified -->
         <attr name="numSearchContainerColumns" format="integer" />
 
+        <!-- Support attributes in CellStyle. defaults to CellStyleDefault -->
+        <attr name="cellStyle" format="reference" />
+
         <!-- numFolderRows & numFolderColumns defaults to numRows & numColumns, if not specified -->
         <attr name="numFolderRows" format="integer" />
         <attr name="numFolderColumns" format="integer" />
+        <!-- Support attributes in FolderStyle -->
         <attr name="folderStyle" format="reference" />
 
         <!-- numAllAppsColumns defaults to numColumns, if not specified -->
@@ -387,7 +391,7 @@
 
     </declare-styleable>
 
-    <declare-styleable name="FolderDisplayStyle">
+    <declare-styleable name="FolderStyle">
         <!-- defaults to minCellHeight if not specified
         when GridDisplayOption#isScalable is true. -->
         <attr name="folderCellHeight" format="dimension" />
@@ -402,7 +406,6 @@
         <attr name="folderTopPadding" format="dimension" />
     </declare-styleable>
 
-
     <declare-styleable name="CellLayout">
         <attr name="containerType" format="integer">
             <enum name="workspace" value="0" />
@@ -411,6 +414,10 @@
         </attr>
     </declare-styleable>
 
+    <declare-styleable name="CellStyle">
+        <attr name="iconDrawablePadding" format="dimension" />
+    </declare-styleable>
+
     <declare-styleable name="ShadowDrawable">
         <attr name="android:src" />
         <attr name="android:shadowColor" />
diff --git a/res/values/config.xml b/res/values/config.xml
index 016420b..1206dd8 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -203,4 +203,7 @@
     <!-- The max scale for the wallpaper when it's zoomed in -->
     <item name="config_wallpaperMaxScale" format="float" type="dimen">0</item>
 
+    <!-- Whether the floating rotation button should be on the left/right in the device's natural
+         orientation -->
+    <bool name="floating_rotation_button_position_left">true</bool>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b57eb02..321aef5 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -93,6 +93,8 @@
     -->
     <dimen name="fastscroll_width">58dp</dimen>
     <dimen name="fastscroll_end_margin">-26dp</dimen>
+    <!-- Extra margin between bottom of the scrollbar and the search bar protection layer. -->
+    <dimen name="fastscroll_bottom_margin_floating_search">4dp</dimen>
 
     <!-- PagedView -->
     <dimen name="fling_threshold_velocity">500dp</dimen>
@@ -139,11 +141,6 @@
     <dimen name="arrow_toast_elevation">2dp</dimen>
     <dimen name="arrow_toast_arrow_width">10dp</dimen>
 
-    <!-- Search bar in All Apps -->
-    <dimen name="all_apps_header_max_elevation">3dp</dimen>
-    <dimen name="all_apps_header_scroll_to_elevation">16dp</dimen>
-    <dimen name="all_apps_header_shadow_height">6dp</dimen>
-
     <dimen name="all_apps_divider_margin_vertical">8dp</dimen>
 
     <!-- Floating action button inside work tab to toggle work profile -->
@@ -252,6 +249,7 @@
 
     <!-- Folders -->
     <dimen name="page_indicator_dot_size">8dp</dimen>
+    <dimen name="page_indicator_dot_size_v2">6dp</dimen>
     <dimen name="page_indicator_size">10dp</dimen>
 
 
@@ -365,8 +363,8 @@
     <dimen name="min_hotseat_icon_space">18dp</dimen>
     <dimen name="max_hotseat_icon_space">50dp</dimen>
     <dimen name="min_hotseat_qsb_width">0dp</dimen>
-    <dimen name="taskbar_icon_size">44dp</dimen>
-    <dimen name="transient_taskbar_icon_size">50dp</dimen>
+    <dimen name="taskbar_icon_size">0dp</dimen>
+    <dimen name="transient_taskbar_icon_size">0dp</dimen>
     <!-- Transient taskbar (placeholders to compile in Launcher3 without Quickstep) -->
     <dimen name="transient_taskbar_size">0dp</dimen>
     <dimen name="transient_taskbar_margin">0dp</dimen>
@@ -374,10 +372,7 @@
     <dimen name="transient_taskbar_key_shadow_distance">0dp</dimen>
     <dimen name="transient_taskbar_stashed_size">0dp</dimen>
     <dimen name="transient_taskbar_clamped_offset_bound">0dp</dimen>
-    <!-- Note that this applies to both sides of all icons, so visible space is double this. -->
-    <dimen name="transient_taskbar_icon_spacing">0dp</dimen>
-    <!-- Note that this applies to both sides of all icons, so visible space is double this. -->
-    <dimen name="taskbar_icon_spacing">8dp</dimen>
+    <dimen name="taskbar_icon_spacing">0dp</dimen>
     <dimen name="taskbar_nav_buttons_size">0dp</dimen>
     <dimen name="taskbar_contextual_button_margin">0dp</dimen>
     <dimen name="taskbar_hotseat_nav_spacing">0dp</dimen>
diff --git a/res/values/id.xml b/res/values/id.xml
index 9fc0ff8..52a7e98 100644
--- a/res/values/id.xml
+++ b/res/values/id.xml
@@ -37,4 +37,6 @@
     <item type="id" name="quick_settings_button" />
     <item type="id" name="notifications_button" />
     <item type="id" name="cache_entry_tag_id" />
+
+    <item type="id" name="saved_clip_children_tag_id" />
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 7582a30..6b57532 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -54,7 +54,7 @@
         <item name="folderPreviewColor">@color/folder_preview_light</item>
         <item name="folderBackgroundColor">@color/folder_background_light</item>
         <item name="folderIconBorderColor">?android:attr/colorPrimary</item>
-        <item name="folderTextColor">@color/workspace_text_color_dark</item>
+        <item name="folderTextColor">?android:attr/textColorPrimary</item>
         <item name="isFolderDarkText">true</item>
         <item name="folderHintColor">@color/folder_hint_text_color_dark</item>
         <item name="loadingIconColor">#CCFFFFFF</item>
@@ -109,7 +109,6 @@
         <item name="folderPreviewColor">@color/folder_preview_dark</item>
         <item name="folderBackgroundColor">@color/folder_background_dark</item>
         <item name="folderIconBorderColor">?android:attr/colorPrimary</item>
-        <item name="folderTextColor">@color/workspace_text_color_light</item>
         <item name="isFolderDarkText">false</item>
         <item name="folderHintColor">@color/folder_hint_text_color_light</item>
         <item name="isMainColorDark">true</item>
@@ -293,7 +292,7 @@
         <item name="android:windowTranslucentStatus">true</item>
     </style>
 
-    <style name="FolderDefaultStyle">
+    <style name="FolderStyleDefault">
         <item name="folderTopPadding">24dp</item>
         <item name="folderCellHeight">94dp</item>
         <item name="folderCellWidth">80dp</item>
@@ -301,4 +300,8 @@
         <item name="folderFooterHeight">56dp</item>
     </style>
 
+    <style name="CellStyleDefault">
+        <item name="iconDrawablePadding">7dp</item>
+    </style>
+
 </resources>
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 28d4a9f..796fa80 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -46,7 +46,8 @@
 /**
  * Base class for a View which shows a floating UI on top of the launcher UI.
  */
-public abstract class AbstractFloatingView extends LinearLayout implements TouchController {
+public abstract class AbstractFloatingView extends LinearLayout implements TouchController,
+        OnBackPressedHandler {
 
     @IntDef(flag = true, value = {
             TYPE_FOLDER,
@@ -63,11 +64,13 @@
             TYPE_TASK_MENU,
             TYPE_OPTIONS_POPUP,
             TYPE_ICON_SURFACE,
+            TYPE_OPTIONS_POPUP_DIALOG,
             TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP,
             TYPE_WIDGETS_EDUCATION_DIALOG,
             TYPE_TASKBAR_EDUCATION_DIALOG,
             TYPE_TASKBAR_ALL_APPS,
-            TYPE_OPTIONS_POPUP_DIALOG
+            TYPE_ADD_TO_HOME_CONFIRMATION,
+            TYPE_TASKBAR_OVERLAY_PROXY
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface FloatingViewType {}
@@ -87,14 +90,14 @@
     public static final int TYPE_TASK_MENU = 1 << 11;
     public static final int TYPE_OPTIONS_POPUP = 1 << 12;
     public static final int TYPE_ICON_SURFACE = 1 << 13;
-    public static final int TYPE_OPTIONS_POPUP_DIALOG = 1 << 18;
+    public static final int TYPE_OPTIONS_POPUP_DIALOG = 1 << 14;
 
-    public static final int TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP = 1 << 14;
-    public static final int TYPE_WIDGETS_EDUCATION_DIALOG = 1 << 15;
-    public static final int TYPE_TASKBAR_EDUCATION_DIALOG = 1 << 16;
-    public static final int TYPE_TASKBAR_ALL_APPS = 1 << 17;
-    public static final int TYPE_ADD_TO_HOME_CONFIRMATION = 1 << 18;
-    public static final int TYPE_TASKBAR_OVERLAY_PROXY = 1 << 19;
+    public static final int TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP = 1 << 15;
+    public static final int TYPE_WIDGETS_EDUCATION_DIALOG = 1 << 16;
+    public static final int TYPE_TASKBAR_EDUCATION_DIALOG = 1 << 17;
+    public static final int TYPE_TASKBAR_ALL_APPS = 1 << 18;
+    public static final int TYPE_ADD_TO_HOME_CONFIRMATION = 1 << 19;
+    public static final int TYPE_TASKBAR_OVERLAY_PROXY = 1 << 20;
 
     public static final int TYPE_ALL = TYPE_FOLDER | TYPE_ACTION_POPUP
             | TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGET_RESIZE_FRAME | TYPE_WIDGETS_FULL_SHEET
@@ -163,13 +166,17 @@
 
     protected abstract boolean isOfType(@FloatingViewType int type);
 
-    /** @return Whether the back is consumed. If false, Launcher will handle the back as well. */
-    public boolean onBackPressed() {
-        close(true);
+    /** Return true if this view can consume back press. */
+    public boolean canHandleBack() {
         return true;
     }
 
     @Override
+    public void onBackInvoked() {
+        close(true);
+    }
+
+    @Override
     public boolean onControllerTouchEvent(MotionEvent ev) {
         return false;
     }
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 76a91c0..85bd2d3 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -268,8 +268,10 @@
 
         CellLayoutLayoutParams lp = (CellLayoutLayoutParams) mWidgetView.getLayoutParams();
         ItemInfo widgetInfo = (ItemInfo) mWidgetView.getTag();
-        lp.cellX = lp.tmpCellX = widgetInfo.cellX;
-        lp.cellY = lp.tmpCellY = widgetInfo.cellY;
+        lp.setCellX(widgetInfo.cellX);
+        lp.setTmpCellX(widgetInfo.cellX);
+        lp.setCellY(widgetInfo.cellY);
+        lp.setTmpCellY(widgetInfo.cellY);
         lp.cellHSpan = widgetInfo.spanX;
         lp.cellVSpan = widgetInfo.spanY;
         lp.isLockedToGrid = true;
@@ -425,8 +427,8 @@
 
         int spanX = lp.cellHSpan;
         int spanY = lp.cellVSpan;
-        int cellX = lp.useTmpCoords ? lp.tmpCellX : lp.cellX;
-        int cellY = lp.useTmpCoords ? lp.tmpCellY : lp.cellY;
+        int cellX = lp.useTmpCoords ? lp.getTmpCellX() : lp.getCellX();
+        int cellY = lp.useTmpCoords ? lp.getTmpCellY() : lp.getCellY();
 
         // For each border, we bound the resizing based on the minimum width, and the maximum
         // expandability.
@@ -467,8 +469,8 @@
                         mLauncher.getString(R.string.widget_resized, spanX, spanY));
             }
 
-            lp.tmpCellX = cellX;
-            lp.tmpCellY = cellY;
+            lp.setTmpCellX(cellX);
+            lp.setTmpCellY(cellY);
             lp.cellHSpan = spanX;
             lp.cellVSpan = spanY;
             mRunningVInc += vSpanDelta;
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index 61707df..e71391f 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -176,14 +176,7 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        if (Utilities.ATLEAST_T) {
-            getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
-                    OnBackInvokedDispatcher.PRIORITY_DEFAULT,
-                    () -> {
-                        onBackPressed();
-                        TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onBackInvoked");
-                    });
-        }
+        registerBackDispatcher();
     }
 
     @Override
@@ -246,6 +239,17 @@
 
     }
 
+    protected void registerBackDispatcher() {
+        if (Utilities.ATLEAST_T) {
+            getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
+                    OnBackInvokedDispatcher.PRIORITY_DEFAULT,
+                    () -> {
+                        onBackPressed();
+                        TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onBackInvoked");
+                    });
+        }
+    }
+
     public boolean isStarted() {
         return (mActivityFlags & ACTIVITY_STATE_STARTED) != 0;
     }
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index ca1fe40..6f3e948 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -125,9 +125,13 @@
         mCurrentActionMode = null;
     }
 
+    protected boolean isInAutoCancelActionMode() {
+        return mCurrentActionMode != null && AUTO_CANCEL_ACTION_MODE == mCurrentActionMode.getTag();
+    }
+
     @Override
     public boolean finishAutoCancelActionMode() {
-        if (mCurrentActionMode != null && AUTO_CANCEL_ACTION_MODE == mCurrentActionMode.getTag()) {
+        if (isInAutoCancelActionMode()) {
             mCurrentActionMode.finish();
             return true;
         }
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 9f54f09..edbce10 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -16,11 +16,14 @@
 
 package com.android.launcher3;
 
+import static com.android.launcher3.config.FeatureFlags.ENABLE_DOWNLOAD_APP_UX_V2;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_ICON_LABEL_AUTO_SCALING;
 import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
 import static com.android.launcher3.icons.BitmapInfo.FLAG_NO_BADGE;
 import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
 import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
+import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INCREMENTAL_DOWNLOAD_ACTIVE;
+import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -291,7 +294,7 @@
 
     @UiThread
     public void applyFromWorkspaceItem(WorkspaceItemInfo info, boolean animate, int staggerIndex) {
-        applyFromWorkspaceItem(info, false);
+        applyFromWorkspaceItem(info, null);
     }
 
     /**
@@ -320,10 +323,10 @@
     }
 
     @UiThread
-    public void applyFromWorkspaceItem(WorkspaceItemInfo info, boolean promiseStateChanged) {
+    public void applyFromWorkspaceItem(WorkspaceItemInfo info, PreloadIconDrawable icon) {
         applyIconAndLabel(info);
         setItemInfo(info);
-        applyLoadingState(promiseStateChanged);
+        applyLoadingState(icon);
         applyDotState(info, false /* animate */);
         setDownloadStateContentDescription(info, info.getProgressLevel());
     }
@@ -710,23 +713,23 @@
      * If this app is installed and downloading incrementally, the progress bar will be updated
      * with the total download progress.
      */
-    public void applyLoadingState(boolean promiseStateChanged) {
+    public void applyLoadingState(PreloadIconDrawable icon) {
         if (getTag() instanceof ItemInfoWithIcon) {
             WorkspaceItemInfo info = (WorkspaceItemInfo) getTag();
-            if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_INCREMENTAL_DOWNLOAD_ACTIVE)
-                    != 0) {
-                updateProgressBarUi(info.getProgressLevel() == 100);
-            } else if (info.hasPromiseIconUi() || (info.runtimeStatusFlags
-                        & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {
-                updateProgressBarUi(promiseStateChanged);
+            if ((info.runtimeStatusFlags & FLAG_INCREMENTAL_DOWNLOAD_ACTIVE) != 0
+                    || info.hasPromiseIconUi()
+                    || (info.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0
+                    || (ENABLE_DOWNLOAD_APP_UX_V2.get() && icon != null)) {
+                updateProgressBarUi(icon);
             }
         }
     }
 
-    private void updateProgressBarUi(boolean maybePerformFinishedAnimation) {
+    private void updateProgressBarUi(PreloadIconDrawable oldIcon) {
+        FastBitmapDrawable originalIcon = mIcon;
         PreloadIconDrawable preloadDrawable = applyProgressLevel();
-        if (preloadDrawable != null && maybePerformFinishedAnimation) {
-            preloadDrawable.maybePerformFinishedAnimation();
+        if (preloadDrawable != null && oldIcon != null) {
+            preloadDrawable.maybePerformFinishedAnimation(oldIcon, () -> setIcon(originalIcon));
         }
     }
 
@@ -824,12 +827,12 @@
                 != 0) {
             String percentageString = NumberFormat.getPercentInstance()
                     .format(progressLevel * 0.01);
-            if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {
+            if ((info.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0) {
                 setContentDescription(getContext()
                         .getString(
                             R.string.app_installing_title, info.title, percentageString));
             } else if ((info.runtimeStatusFlags
-                    & ItemInfoWithIcon.FLAG_INCREMENTAL_DOWNLOAD_ACTIVE) != 0) {
+                    & FLAG_INCREMENTAL_DOWNLOAD_ACTIVE) != 0) {
                 setContentDescription(getContext()
                         .getString(
                             R.string.app_downloading_title, info.title, percentageString));
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index ecfd230..05b225c 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -623,8 +623,8 @@
                 if (alpha <= 0) continue;
 
                 mVisualizeGridPaint.setAlpha(255);
-                int x = mDragOutlines[i].cellX;
-                int y = mDragOutlines[i].cellY;
+                int x = mDragOutlines[i].getCellX();
+                int y = mDragOutlines[i].getCellY();
                 int spanX = mDragOutlines[i].cellHSpan;
                 int spanY = mDragOutlines[i].cellVSpan;
 
@@ -764,7 +764,8 @@
 
         // Generate an id for each view, this assumes we have at most 256x256 cells
         // per workspace screen
-        if (lp.cellX >= 0 && lp.cellX <= mCountX - 1 && lp.cellY >= 0 && lp.cellY <= mCountY - 1) {
+        if (lp.getCellX() >= 0 && lp.getCellX() <= mCountX - 1
+                && lp.getCellY() >= 0 && lp.getCellY() <= mCountY - 1) {
             // If the horizontal or vertical span is set to -1, it is taken to
             // mean that it spans the extent of the CellLayout
             if (lp.cellHSpan < 0) lp.cellHSpan = mCountX;
@@ -1072,7 +1073,7 @@
 
             if (adjustOccupied) {
                 GridOccupancy occupied = permanent ? mOccupied : mTmpOccupied;
-                occupied.markCells(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, false);
+                occupied.markCells(lp.getCellX(), lp.getCellY(), lp.cellHSpan, lp.cellVSpan, false);
                 occupied.markCells(cellX, cellY, lp.cellHSpan, lp.cellVSpan, true);
             }
 
@@ -1083,11 +1084,11 @@
             final int oldY = lp.y;
             lp.isLockedToGrid = true;
             if (permanent) {
-                lp.cellX = info.cellX = cellX;
-                lp.cellY = info.cellY = cellY;
+                lp.setCellX(info.cellX = cellX);
+                lp.setCellY(info.cellY = cellY);
             } else {
-                lp.tmpCellX = cellX;
-                lp.tmpCellY = cellY;
+                lp.setTmpCellX(cellX);
+                lp.setTmpCellY(cellY);
             }
             clc.setupLp(child);
             final int newX = lp.x;
@@ -1167,8 +1168,8 @@
             mDragOutlineCurrent = (oldIndex + 1) % mDragOutlines.length;
 
             CellLayoutLayoutParams cell = mDragOutlines[mDragOutlineCurrent];
-            cell.cellX = cellX;
-            cell.cellY = cellY;
+            cell.setCellX(cellX);
+            cell.setCellY(cellY);
             cell.cellHSpan = spanX;
             cell.cellVSpan = spanY;
 
@@ -1385,8 +1386,8 @@
             CellLayoutLayoutParams lp = (CellLayoutLayoutParams) child.getLayoutParams();
             CellAndSpan c = solution.map.get(child);
             if (c != null) {
-                lp.tmpCellX = c.cellX;
-                lp.tmpCellY = c.cellY;
+                lp.setTmpCellX(c.cellX);
+                lp.setTmpCellY(c.cellY);
                 lp.cellHSpan = c.spanX;
                 lp.cellVSpan = c.spanY;
                 mTmpOccupied.markCells(c, true);
@@ -1433,7 +1434,7 @@
             CellLayoutLayoutParams lp = (CellLayoutLayoutParams) child.getLayoutParams();
             if (c != null && !skip && (child instanceof Reorderable)) {
                 ReorderPreviewAnimation rha = new ReorderPreviewAnimation((Reorderable) child,
-                        mode, lp.cellX, lp.cellY, c.cellX, c.cellY, c.spanX, c.spanY);
+                        mode, lp.getCellX(), lp.getCellY(), c.cellX, c.cellY, c.spanX, c.spanY);
                 rha.animate();
             }
         }
@@ -1626,12 +1627,14 @@
             // We do a null check here because the item info can be null in the case of the
             // AllApps button in the hotseat.
             if (info != null && child != dragView) {
-                final boolean requiresDbUpdate = (info.cellX != lp.tmpCellX
-                        || info.cellY != lp.tmpCellY || info.spanX != lp.cellHSpan
+                final boolean requiresDbUpdate = (info.cellX != lp.getTmpCellX()
+                        || info.cellY != lp.getTmpCellY() || info.spanX != lp.cellHSpan
                         || info.spanY != lp.cellVSpan);
 
-                info.cellX = lp.cellX = lp.tmpCellX;
-                info.cellY = lp.cellY = lp.tmpCellY;
+                lp.setCellX(lp.getTmpCellX());
+                info.cellX = lp.getTmpCellX();
+                info.cellY = lp.getTmpCellY();
+                lp.setCellY(lp.getTmpCellY());
                 info.spanX = lp.cellHSpan;
                 info.spanY = lp.cellVSpan;
 
@@ -1697,7 +1700,8 @@
             if (child == dragView) continue;
             CellLayoutLayoutParams
                     lp = (CellLayoutLayoutParams) child.getLayoutParams();
-            r1.set(lp.cellX, lp.cellY, lp.cellX + lp.cellHSpan, lp.cellY + lp.cellVSpan);
+            r1.set(lp.getCellX(), lp.getCellY(), lp.getCellX() + lp.cellHSpan,
+                    lp.getCellY() + lp.cellVSpan);
             if (Rect.intersects(r0, r1)) {
                 mIntersectingViews.add(child);
                 if (boundingRect != null) {
@@ -1723,11 +1727,11 @@
                 View child = mShortcutsAndWidgets.getChildAt(i);
                 CellLayoutLayoutParams
                         lp = (CellLayoutLayoutParams) child.getLayoutParams();
-                if (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.cellY) {
-                    lp.tmpCellX = lp.cellX;
-                    lp.tmpCellY = lp.cellY;
-                    animateChildToPosition(child, lp.cellX, lp.cellY, REORDER_ANIMATION_DURATION,
-                            0, false, false);
+                if (lp.getTmpCellX() != lp.getCellX() || lp.getTmpCellY() != lp.getCellY()) {
+                    lp.setTmpCellX(lp.getCellX());
+                    lp.setTmpCellY(lp.getCellY());
+                    animateChildToPosition(child, lp.getCellX(), lp.getCellY(),
+                            REORDER_ANIMATION_DURATION, 0, false, false);
                 }
             }
             setItemPlacementDirty(false);
@@ -2449,9 +2453,9 @@
             CellLayoutLayoutParams lp = (CellLayoutLayoutParams) child.getLayoutParams();
             CellAndSpan c;
             if (temp) {
-                c = new CellAndSpan(lp.tmpCellX, lp.tmpCellY, lp.cellHSpan, lp.cellVSpan);
+                c = new CellAndSpan(lp.getTmpCellX(), lp.getTmpCellY(), lp.cellHSpan, lp.cellVSpan);
             } else {
-                c = new CellAndSpan(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan);
+                c = new CellAndSpan(lp.getCellX(), lp.getCellY(), lp.cellHSpan, lp.cellVSpan);
             }
             solution.add(child, c);
         }
@@ -2794,7 +2798,7 @@
         if (view == null || view.getParent() != mShortcutsAndWidgets) return;
         CellLayoutLayoutParams
                 lp = (CellLayoutLayoutParams) view.getLayoutParams();
-        mOccupied.markCells(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, true);
+        mOccupied.markCells(lp.getCellX(), lp.getCellY(), lp.cellHSpan, lp.cellVSpan, true);
     }
 
     public void markCellsAsUnoccupiedForView(View view) {
@@ -2807,7 +2811,7 @@
         if (view == null || view.getParent() != mShortcutsAndWidgets) return;
         CellLayoutLayoutParams
                 lp = (CellLayoutLayoutParams) view.getLayoutParams();
-        mOccupied.markCells(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, false);
+        mOccupied.markCells(lp.getCellX(), lp.getCellY(), lp.cellHSpan, lp.cellVSpan, false);
     }
 
     public int getDesiredWidth() {
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 25520e1..9f9c6f9 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -260,6 +260,7 @@
     // Whether Taskbar will inset the bottom of apps by taskbarSize.
     public boolean isTaskbarPresentInApps;
     public int taskbarSize;
+    public int transientTaskbarSize;
     public int stashedTaskbarSize;
     public int transientTaskbarMargin;
 
@@ -324,12 +325,12 @@
         }
 
         if (isTaskbarPresent) {
+            transientTaskbarSize = res.getDimensionPixelSize(R.dimen.transient_taskbar_size);
+            transientTaskbarMargin = res.getDimensionPixelSize(R.dimen.transient_taskbar_margin);
             if (DisplayController.isTransientTaskbar(context)) {
-                taskbarSize = res.getDimensionPixelSize(R.dimen.transient_taskbar_size);
+                taskbarSize = transientTaskbarSize;
                 stashedTaskbarSize =
                         res.getDimensionPixelSize(R.dimen.transient_taskbar_stashed_size);
-                transientTaskbarMargin =
-                        res.getDimensionPixelSize(R.dimen.transient_taskbar_margin);
             } else {
                 taskbarSize = res.getDimensionPixelSize(R.dimen.taskbar_size);
                 stashedTaskbarSize = res.getDimensionPixelSize(R.dimen.taskbar_stashed_size);
@@ -375,19 +376,19 @@
 
         if (inv.folderStyle != INVALID_RESOURCE_HANDLE) {
             TypedArray folderStyle = context.obtainStyledAttributes(inv.folderStyle,
-                    R.styleable.FolderDisplayStyle);
+                    R.styleable.FolderStyle);
             // These are re-set in #updateFolderCellSize if the grid is not scalable
             folderCellHeightPx = folderStyle.getDimensionPixelSize(
-                    R.styleable.FolderDisplayStyle_folderCellHeight, 0);
+                    R.styleable.FolderStyle_folderCellHeight, 0);
             folderCellWidthPx = folderStyle.getDimensionPixelSize(
-                    R.styleable.FolderDisplayStyle_folderCellWidth, 0);
+                    R.styleable.FolderStyle_folderCellWidth, 0);
 
             folderContentPaddingTop = folderStyle.getDimensionPixelSize(
-                    R.styleable.FolderDisplayStyle_folderTopPadding, 0);
+                    R.styleable.FolderStyle_folderTopPadding, 0);
             folderCellLayoutBorderSpacePx = folderStyle.getDimensionPixelSize(
-                    R.styleable.FolderDisplayStyle_folderBorderSpace, 0);
+                    R.styleable.FolderStyle_folderBorderSpace, 0);
             folderFooterHeightPx = folderStyle.getDimensionPixelSize(
-                    R.styleable.FolderDisplayStyle_folderFooterHeight, 0);
+                    R.styleable.FolderStyle_folderFooterHeight, 0);
             folderStyle.recycle();
         } else {
             folderCellLayoutBorderSpacePx = 0;
@@ -406,8 +407,17 @@
         mWorkspacePageIndicatorOverlapWorkspace =
                 res.getDimensionPixelSize(R.dimen.workspace_page_indicator_overlap_workspace);
 
-        iconDrawablePaddingOriginalPx =
-                res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
+        TypedArray cellStyle;
+        if (inv.cellStyle != INVALID_RESOURCE_HANDLE) {
+            cellStyle = context.obtainStyledAttributes(inv.cellStyle,
+                    R.styleable.CellStyle);
+        } else {
+            cellStyle = context.obtainStyledAttributes(R.style.CellStyleDefault,
+                    R.styleable.CellStyle);
+        }
+        iconDrawablePaddingOriginalPx = cellStyle.getDimensionPixelSize(
+                R.styleable.CellStyle_iconDrawablePadding, 0);
+        cellStyle.recycle();
 
         dropTargetBarSizePx = res.getDimensionPixelSize(R.dimen.dynamic_grid_drop_target_size);
         dropTargetBarTopMarginPx = res.getDimensionPixelSize(R.dimen.drop_target_top_margin);
@@ -910,12 +920,24 @@
                     cellHeightPx = cellContentHeight;
                     cellLayoutBorderSpacePx.y -= extraHeightRequired / numBorders;
                 } else {
-                    // If it still doesn't fit, set borderSpace to 0 and distribute the space for
-                    // cellHeight, and reduce iconSize.
+                    // If it still doesn't fit, set borderSpace to 0 to recover space.
                     cellHeightPx = (cellHeightPx * inv.numRows
                             + cellLayoutBorderSpacePx.y * numBorders) / inv.numRows;
-                    iconSizePx = Math.min(iconSizePx, cellHeightPx - cellTextAndPaddingHeight);
                     cellLayoutBorderSpacePx.y = 0;
+                    // Reduce iconDrawablePaddingPx to make cellContentHeight smaller.
+                    int cellContentWithoutPadding = cellContentHeight - iconDrawablePaddingPx;
+                    if (cellContentWithoutPadding <= cellHeightPx) {
+                        iconDrawablePaddingPx = cellContentHeight - cellHeightPx;
+                    } else {
+                        // If it still doesn't fit, set iconDrawablePaddingPx to 0 to recover space,
+                        // then proportional reduce iconSizePx and iconTextSizePx to fit.
+                        iconDrawablePaddingPx = 0;
+                        float ratio = cellHeightPx / (float) cellContentWithoutPadding;
+                        iconSizePx = (int) (iconSizePx * ratio);
+                        iconTextSizePx = (int) (iconTextSizePx * ratio);
+                    }
+                    cellTextAndPaddingHeight =
+                            iconDrawablePaddingPx + Utilities.calculateTextHeight(iconTextSizePx);
                 }
                 cellContentHeight = iconSizePx + cellTextAndPaddingHeight;
             }
@@ -1371,7 +1393,7 @@
     public int getOverviewActionsClaimedSpaceBelow() {
         if (isTaskbarPresent) {
             if (FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get()) {
-                return taskbarSize + transientTaskbarMargin * 2;
+                return transientTaskbarSize + transientTaskbarMargin * 2;
             }
 
             return isGestureMode
@@ -1667,6 +1689,16 @@
         writer.println(prefix + pxToDpStr("getCellLayoutWidth()", getCellLayoutWidth()));
     }
 
+    /** Returns a reduced representation of this DeviceProfile. */
+    public String toSmallString() {
+        return "isTablet:" + isTablet + ", "
+                + "isMultiDisplay:" + isMultiDisplay + ", "
+                + "widthPx:" + widthPx + ", "
+                + "heightPx:" + heightPx + ", "
+                + "insets:" + mInsets + ", "
+                + "rotationHint:" + rotationHint;
+    }
+
     private static Context getContext(Context c, Info info, int orientation, WindowBounds bounds) {
         Configuration config = new Configuration(c.getResources().getConfiguration());
         config.orientation = orientation;
diff --git a/src/com/android/launcher3/FastScrollRecyclerView.java b/src/com/android/launcher3/FastScrollRecyclerView.java
index 2f927d3..3504b24 100644
--- a/src/com/android/launcher3/FastScrollRecyclerView.java
+++ b/src/com/android/launcher3/FastScrollRecyclerView.java
@@ -77,11 +77,15 @@
         return getPaddingTop();
     }
 
+    public int getScrollBarMarginBottom() {
+        return getPaddingBottom();
+    }
+
     /**
      * Returns the height of the fast scroll bar
      */
     public int getScrollbarTrackHeight() {
-        return mScrollbar.getHeight() - getScrollBarTop() - getPaddingBottom();
+        return mScrollbar.getHeight() - getScrollBarTop() - getScrollBarMarginBottom();
     }
 
     /**
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index a4020f9..d97eac9 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -143,6 +143,8 @@
 
     public @StyleRes int folderStyle;
 
+    public @StyleRes int cellStyle;
+
     public float[] horizontalMargin;
 
     public PointF[] allAppsCellSize;
@@ -206,8 +208,6 @@
         if (!newGridName.equals(gridName)) {
             LauncherPrefs.getPrefs(context).edit().putString(KEY_IDP_GRID_NAME, newGridName)
                     .apply();
-            Log.d("b/258560494", "InvariantDeviceProfile - setting newGridName: " + newGridName
-                    + ", gridName: " + gridName);
         }
         new DeviceGridState(this).writeToPrefs(context);
 
@@ -351,6 +351,8 @@
         numFolderColumns = closestProfile.numFolderColumns;
         folderStyle = closestProfile.folderStyle;
 
+        cellStyle = closestProfile.cellStyle;
+
         isScalable = closestProfile.isScalable;
         devicePaddingId = closestProfile.devicePaddingId;
         this.deviceType = deviceType;
@@ -455,7 +457,6 @@
     public void setCurrentGrid(Context context, String gridName) {
         Context appContext = context.getApplicationContext();
         LauncherPrefs.getPrefs(appContext).edit().putString(KEY_IDP_GRID_NAME, gridName).apply();
-        Log.d("b/258560494", "setCurrentGrid: " + gridName);
         MAIN_EXECUTOR.execute(() -> onConfigChanged(appContext));
     }
 
@@ -520,10 +521,6 @@
             }
         }
         if (filteredProfiles.isEmpty()) {
-            if (gridName != null) {
-                Log.d("b/258560494", "No matching grid from for gridName: " + gridName
-                        + ", deviceType: " + deviceType);
-            }
             // No grid found, use the default options
             for (DisplayOption option : profiles) {
                 if (option.canBeDefault) {
@@ -790,6 +787,7 @@
         private final int numFolderRows;
         private final int numFolderColumns;
         private final @StyleRes int folderStyle;
+        private final @StyleRes int cellStyle;
 
         private final int numAllAppsColumns;
         private final int numDatabaseAllAppsColumns;
@@ -859,6 +857,9 @@
             folderStyle = a.getResourceId(R.styleable.GridDisplayOption_folderStyle,
                     INVALID_RESOURCE_HANDLE);
 
+            cellStyle = a.getResourceId(R.styleable.GridDisplayOption_cellStyle,
+                    R.style.CellStyleDefault);
+
             isScalable = a.getBoolean(
                     R.styleable.GridDisplayOption_isScalable, false);
             devicePaddingId = a.getResourceId(
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 43772e4..e9b9f31 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -76,17 +76,16 @@
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
 import android.content.ActivityNotFoundException;
-import android.content.BroadcastReceiver;
 import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.database.sqlite.SQLiteDatabase;
 import android.graphics.Bitmap;
+import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.Build;
@@ -120,6 +119,7 @@
 import android.widget.Toast;
 
 import androidx.annotation.CallSuper;
+import androidx.annotation.FloatRange;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
@@ -132,7 +132,6 @@
 import com.android.launcher3.allapps.AllAppsRecyclerView;
 import com.android.launcher3.allapps.AllAppsStore;
 import com.android.launcher3.allapps.AllAppsTransitionController;
-import com.android.launcher3.allapps.BaseAllAppsContainerView;
 import com.android.launcher3.allapps.BaseSearchConfig;
 import com.android.launcher3.allapps.DiscoveryBounce;
 import com.android.launcher3.anim.PropertyListBuilder;
@@ -196,6 +195,8 @@
 import com.android.launcher3.util.PendingRequestArgs;
 import com.android.launcher3.util.RunnableList;
 import com.android.launcher3.util.SafeCloseable;
+import com.android.launcher3.util.ScreenOnTracker;
+import com.android.launcher3.util.ScreenOnTracker.ScreenOnListener;
 import com.android.launcher3.util.SystemUiController;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.Thunk;
@@ -534,9 +535,8 @@
         }
         getRootView().dispatchInsets();
 
-        // Listen for broadcasts
-        registerReceiver(mScreenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
-
+        // Listen for screen turning off
+        ScreenOnTracker.INSTANCE.get(this).addListener(mScreenOnListener);
         getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
                 Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
 
@@ -559,6 +559,61 @@
         setTitle(R.string.home_screen);
     }
 
+    /**
+     * Provide {@link OnBackPressedHandler} in below order:
+     * <ol>
+     *  <li> auto cancel action mode handler
+     *  <li> drag handler
+     *  <li> view handler
+     *  <li> state handler
+     * </ol>
+     *
+     * A back gesture (a single click on back button, or a swipe back gesture that contains a series
+     * of swipe events) should be handled by the same handler from above list. For a new back
+     * gesture, a new handler should be regenerated.
+     *
+     * Note that state handler will always be handling the back press event if the previous 3 don't.
+     */
+    @NonNull
+    protected OnBackPressedHandler getOnBackPressedHandler() {
+        // #1 auto cancel action mode handler
+        if (isInAutoCancelActionMode()) {
+            return this::finishAutoCancelActionMode;
+        }
+
+        // #2 drag handler
+        if (mDragController.isDragging()) {
+            return mDragController::cancelDrag;
+        }
+
+        // #3 view handler
+        AbstractFloatingView topView =
+                AbstractFloatingView.getTopOpenView(Launcher.this);
+        if (topView != null && topView.canHandleBack()) {
+            return topView;
+        }
+
+        // #4 state handler
+        return new OnBackPressedHandler() {
+            @Override
+            public void onBackInvoked() {
+                onStateBack();
+            }
+
+            @Override
+            public void onBackProgressed(
+                    @FloatRange(from = 0.0, to = 1.0) float backProgress) {
+                mStateManager.getState().onBackProgressed(
+                        Launcher.this, backProgress);
+            }
+
+            @Override
+            public void onBackCancelled() {
+                mStateManager.getState().onBackCancelled(Launcher.this);
+            }
+        };
+    }
+
     protected LauncherOverlayManager getDefaultOverlay() {
         return new LauncherOverlayManager() { };
     }
@@ -1275,11 +1330,19 @@
         // Setup the drag controller (drop targets have to be added in reverse order in priority)
         mDropTargetBar.setup(mDragController);
         mAllAppsController.setupViews(mScrimView, mAppsView);
+
+        if (SHOW_DOT_PAGINATION.get()) {
+            mWorkspace.getPageIndicator().setShouldAutoHide(true);
+            mWorkspace.getPageIndicator().setPaintColor(
+                    Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)
+                            ? Color.BLACK
+                            : Color.WHITE);
+        }
     }
 
     @Override
     public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
-        if ((SHOW_DOT_PAGINATION.get()) && WorkspacePageIndicator.class.getName().equals(name)) {
+        if (SHOW_DOT_PAGINATION.get() && WorkspacePageIndicator.class.getName().equals(name)) {
             return LayoutInflater.from(context).inflate(R.layout.page_indicator_dots,
                     (ViewGroup) parent, false);
         }
@@ -1466,12 +1529,7 @@
         hostView.setOnFocusChangeListener(mFocusHandler);
     }
 
-    private final BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            onScreenOff();
-        }
-    };
+    private final ScreenOnListener mScreenOnListener = this::onScreenOnChanged;
 
     private void updateNotificationDots(Predicate<PackageUserKey> updatedDots) {
         mWorkspace.updateNotificationDots(updatedDots);
@@ -1638,7 +1696,7 @@
 
     private void showAllAppsWorkTabFromIntent(boolean alreadyOnHome) {
         showAllAppsFromIntent(alreadyOnHome);
-        mAppsView.switchToTab(BaseAllAppsContainerView.AdapterHolder.WORK);
+        mAppsView.switchToTab(ActivityAllAppsContainerView.AdapterHolder.WORK);
     }
 
     /**
@@ -1705,7 +1763,7 @@
         super.onDestroy();
         ACTIVITY_TRACKER.onActivityDestroyed(this);
 
-        unregisterReceiver(mScreenOffReceiver);
+        ScreenOnTracker.INSTANCE.get(this).removeListener(mScreenOnListener);
         mWorkspace.removeFolderListeners();
         PluginManagerWrapper.INSTANCE.get(this).removePluginListener(this);
 
@@ -2043,32 +2101,17 @@
 
     @Override
     public void onBackPressed() {
-        if (finishAutoCancelActionMode()) {
-            return;
-        }
-
-        if (mDragController.isDragging()) {
-            mDragController.cancelDrag();
-            return;
-        }
-
-        // Note: There should be at most one log per method call. This is enforced implicitly
-        // by using if-else statements.
-        AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this);
-        if (topView == null || !topView.onBackPressed()) {
-            // Not handled by the floating view.
-            onStateBack();
-        }
+        getOnBackPressedHandler().onBackInvoked();
     }
 
     protected void onStateBack() {
         mStateManager.getState().onBackPressed(this);
     }
 
-    protected void onScreenOff() {
+    protected void onScreenOnChanged(boolean isOn) {
         // Reset AllApps to its initial state only if we are not in the middle of
         // processing a multi-step drop
-        if (mPendingRequestArgs == null) {
+        if (!isOn && mPendingRequestArgs == null) {
             if (!isInState(NORMAL)) {
                 onUiChangedWhileSleeping();
             }
@@ -3317,4 +3360,12 @@
             return false; // Return false to continue iterating through all the items.
         });
     }
+
+    /**
+     * Returns {@code true} if there are visible tasks with windowing mode set to
+     * {@link android.app.WindowConfiguration#WINDOWING_MODE_FREEFORM}
+     */
+    public boolean areFreeformTasksVisible() {
+        return false; // Base launcher does not track freeform tasks
+    }
 }
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 4965936..2b98d98 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -18,7 +18,8 @@
 
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
 
-import static com.android.launcher3.LauncherPrefs.getDevicePrefs;
+import static com.android.launcher3.LauncherPrefs.ICON_STATE;
+import static com.android.launcher3.LauncherPrefs.THEMED_ICONS;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI;
 
@@ -55,7 +56,7 @@
 public class LauncherAppState implements SafeCloseable {
 
     public static final String ACTION_FORCE_ROLOAD = "force-reload-launcher";
-    private static final String KEY_ICON_STATE = "pref_icon_shape_path";
+    public static final String KEY_ICON_STATE = "pref_icon_shape_path";
 
     // We do not need any synchronization for this variable as its only written on UI thread.
     public static final MainThreadInitializedObject<LauncherAppState> INSTANCE =
@@ -101,7 +102,7 @@
                 Intent.ACTION_MANAGED_PROFILE_UNLOCKED,
                 ACTION_DEVICE_POLICY_RESOURCE_UPDATED);
         if (FeatureFlags.IS_STUDIO_BUILD) {
-            modelChangeReceiver.register(mContext, Context.RECEIVER_EXPORTED, ACTION_FORCE_ROLOAD);
+            modelChangeReceiver.register(mContext, ACTION_FORCE_ROLOAD);
         }
         mOnTerminateCallback.add(() -> mContext.unregisterReceiver(modelChangeReceiver));
 
@@ -117,10 +118,9 @@
                 observer, MODEL_EXECUTOR.getHandler());
         mOnTerminateCallback.add(iconChangeTracker::close);
         MODEL_EXECUTOR.execute(observer::verifyIconChanged);
-        SharedPreferences prefs = LauncherPrefs.getPrefs(mContext);
-        prefs.registerOnSharedPreferenceChangeListener(observer);
+        LauncherPrefs.get(context).addListener(observer, THEMED_ICONS);
         mOnTerminateCallback.add(
-                () -> prefs.unregisterOnSharedPreferenceChangeListener(observer));
+                () -> LauncherPrefs.get(mContext).removeListener(observer, THEMED_ICONS));
 
         InstallSessionTracker installSessionTracker =
                 InstallSessionHelper.INSTANCE.get(context).registerInstallTracker(mModel);
@@ -207,12 +207,12 @@
         public void onSystemIconStateChanged(String iconState) {
             IconShape.init(mContext);
             refreshAndReloadLauncher();
-            getDevicePrefs(mContext).edit().putString(KEY_ICON_STATE, iconState).apply();
+            LauncherPrefs.get(mContext).put(ICON_STATE, iconState);
         }
 
         void verifyIconChanged() {
             String iconState = mIconProvider.getSystemIconState();
-            if (!iconState.equals(getDevicePrefs(mContext).getString(KEY_ICON_STATE, ""))) {
+            if (!iconState.equals(LauncherPrefs.get(mContext).get(ICON_STATE))) {
                 onSystemIconStateChanged(iconState);
             }
         }
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 20df897..2c6458b 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -47,7 +47,7 @@
 import com.android.launcher3.model.BgDataModel.Callbacks;
 import com.android.launcher3.model.CacheDataUpdatedTask;
 import com.android.launcher3.model.ItemInstallQueue;
-import com.android.launcher3.model.LoaderResults;
+import com.android.launcher3.model.LauncherBinder;
 import com.android.launcher3.model.LoaderTask;
 import com.android.launcher3.model.ModelDelegate;
 import com.android.launcher3.model.ModelWriter;
@@ -405,22 +405,22 @@
                     MAIN_EXECUTOR.execute(cb::clearPendingBinds);
                 }
 
-                LoaderResults loaderResults = new LoaderResults(
+                LauncherBinder launcherBinder = new LauncherBinder(
                         mApp, mBgDataModel, mBgAllAppsList, callbacksList);
                 if (bindDirectly) {
                     // Divide the set of loaded items into those that we are binding synchronously,
                     // and everything else that is to be bound normally (asynchronously).
-                    loaderResults.bindWorkspace(bindAllCallbacks);
+                    launcherBinder.bindWorkspace(bindAllCallbacks);
                     // For now, continue posting the binding of AllApps as there are other
                     // issues that arise from that.
-                    loaderResults.bindAllApps();
-                    loaderResults.bindDeepShortcuts();
-                    loaderResults.bindWidgets();
+                    launcherBinder.bindAllApps();
+                    launcherBinder.bindDeepShortcuts();
+                    launcherBinder.bindWidgets();
                     return true;
                 } else {
                     stopLoader();
                     mLoaderTask = new LoaderTask(
-                            mApp, mBgAllAppsList, mBgDataModel, mModelDelegate, loaderResults);
+                            mApp, mBgAllAppsList, mBgDataModel, mModelDelegate, launcherBinder);
 
                     // Always post the loader task, instead of running directly
                     // (even on same thread) so that we exit any nested synchronized blocks
diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt
index 23ff10a..1fb2dce 100644
--- a/src/com/android/launcher3/LauncherPrefs.kt
+++ b/src/com/android/launcher3/LauncherPrefs.kt
@@ -2,19 +2,255 @@
 
 import android.content.Context
 import android.content.SharedPreferences
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener
+import androidx.annotation.VisibleForTesting
+import com.android.launcher3.allapps.WorkProfileManager
+import com.android.launcher3.model.DeviceGridState
+import com.android.launcher3.pm.InstallSessionHelper
+import com.android.launcher3.provider.RestoreDbTask
+import com.android.launcher3.util.MainThreadInitializedObject
+import com.android.launcher3.util.Themes
 
-object LauncherPrefs {
+/**
+ * Use same context for shared preferences, so that we use a single cached instance
+ * TODO(b/262721340): Replace all direct SharedPreference refs with LauncherPrefs / Item methods.
+ */
+class LauncherPrefs(private val context: Context) {
 
-    @JvmStatic
-    fun getPrefs(context: Context): SharedPreferences {
-        // Use application context for shared preferences, so that we use a single cached instance
-        return context.applicationContext.getSharedPreferences(
-                LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
+    /**
+     * Retrieves the value for an [Item] from [SharedPreferences]. It handles method typing via the
+     * default value type, and will throw an error if the type of the item provided is not a
+     * `String`, `Boolean`, `Float`, `Int`, `Long`, or `Set<String>`.
+     */
+    @Suppress("IMPLICIT_CAST_TO_ANY", "UNCHECKED_CAST")
+    fun <T : Any> get(item: Item<T>): T {
+        val sp = context.getSharedPreferences(item.sharedPrefFile, Context.MODE_PRIVATE)
+
+        return when (item.defaultValue::class.java) {
+            String::class.java -> sp.getString(item.sharedPrefKey, item.defaultValue as String)
+            Boolean::class.java,
+            java.lang.Boolean::class.java ->
+                sp.getBoolean(item.sharedPrefKey, item.defaultValue as Boolean)
+            Int::class.java,
+            java.lang.Integer::class.java -> sp.getInt(item.sharedPrefKey, item.defaultValue as Int)
+            Float::class.java,
+            java.lang.Float::class.java ->
+                sp.getFloat(item.sharedPrefKey, item.defaultValue as Float)
+            Long::class.java,
+            java.lang.Long::class.java -> sp.getLong(item.sharedPrefKey, item.defaultValue as Long)
+            Set::class.java -> sp.getStringSet(item.sharedPrefKey, item.defaultValue as Set<String>)
+            else ->
+                throw IllegalArgumentException(
+                    "item type: ${item.defaultValue::class.java}" +
+                        " is not compatible with sharedPref methods"
+                )
+        }
+            as T
     }
 
-    @JvmStatic
-    fun getDevicePrefs(context: Context): SharedPreferences {
-        // Use application context for shared preferences, so that we use a single cached instance
-        return context.applicationContext.getSharedPreferences(
-                LauncherFiles.DEVICE_PREFERENCES_KEY, Context.MODE_PRIVATE)
-    }}
\ No newline at end of file
+    /**
+     * Stores each of the values provided in `SharedPreferences` according to the configuration
+     * contained within the associated items provided. Internally, it uses apply, so the caller
+     * cannot assume that the values that have been put are immediately available for use.
+     *
+     * The forEach loop is necessary here since there is 1 `SharedPreference.Editor` returned from
+     * prepareToPutValue(itemsToValues) for every distinct `SharedPreferences` file present in the
+     * provided item configurations.
+     */
+    fun put(vararg itemsToValues: Pair<Item<*>, Any>): Unit =
+        prepareToPutValues(itemsToValues).forEach { it.apply() }
+
+    /**
+     * Stores the value provided in `SharedPreferences` according to the item configuration provided
+     * It is asynchronous, so the caller can't assume that the value put is immediately available.
+     */
+    fun <T : Any> put(item: Item<T>, value: T): Unit =
+        context
+            .getSharedPreferences(item.sharedPrefFile, Context.MODE_PRIVATE)
+            .edit()
+            .putValue(item, value)
+            .apply()
+
+    /**
+     * Synchronously stores all the values provided according to their associated Item
+     * configuration.
+     */
+    fun putSync(vararg itemsToValues: Pair<Item<*>, Any>): Unit =
+        prepareToPutValues(itemsToValues).forEach { it.commit() }
+
+    /**
+     * Update each shared preference file with the item - value pairs provided. This method is
+     * optimized to avoid retrieving the same shared preference file multiple times.
+     *
+     * @return `List<SharedPreferences.Editor>` 1 for each distinct shared preference file among the
+     * items given as part of the itemsToValues parameter
+     */
+    private fun prepareToPutValues(
+        itemsToValues: Array<out Pair<Item<*>, Any>>
+    ): List<SharedPreferences.Editor> =
+        itemsToValues
+            .groupBy { it.first.sharedPrefFile }
+            .map { fileToItemValueList ->
+                context
+                    .getSharedPreferences(fileToItemValueList.key, Context.MODE_PRIVATE)
+                    .edit()
+                    .apply {
+                        fileToItemValueList.value.forEach { itemToValue ->
+                            putValue(itemToValue.first, itemToValue.second)
+                        }
+                    }
+            }
+
+    /**
+     * Handles adding values to `SharedPreferences` regardless of type. This method is especially
+     * helpful for updating `SharedPreferences` values for `List<<Item>Any>` that have multiple
+     * types of Item values.
+     */
+    @Suppress("UNCHECKED_CAST")
+    private fun SharedPreferences.Editor.putValue(
+        item: Item<*>,
+        value: Any
+    ): SharedPreferences.Editor =
+        when (value::class.java) {
+            String::class.java -> putString(item.sharedPrefKey, value as String)
+            Boolean::class.java,
+            java.lang.Boolean::class.java -> putBoolean(item.sharedPrefKey, value as Boolean)
+            Int::class.java,
+            java.lang.Integer::class.java -> putInt(item.sharedPrefKey, value as Int)
+            Float::class.java,
+            java.lang.Float::class.java -> putFloat(item.sharedPrefKey, value as Float)
+            Long::class.java,
+            java.lang.Long::class.java -> putLong(item.sharedPrefKey, value as Long)
+            Set::class.java -> putStringSet(item.sharedPrefKey, value as Set<String>)
+            else ->
+                throw IllegalArgumentException(
+                    "item type: " +
+                        "${item.defaultValue!!::class} is not compatible with sharedPref methods"
+                )
+        }
+
+    /**
+     * After calling this method, the listener will be notified of any future updates to the
+     * `SharedPreferences` files associated with the provided list of items. The listener will need
+     * to filter update notifications so they don't activate for non-relevant updates.
+     */
+    fun addListener(listener: OnSharedPreferenceChangeListener, vararg items: Item<*>) {
+        items
+            .map { it.sharedPrefFile }
+            .distinct()
+            .forEach {
+                context
+                    .getSharedPreferences(it, Context.MODE_PRIVATE)
+                    .registerOnSharedPreferenceChangeListener(listener)
+            }
+    }
+
+    /**
+     * Stops the listener from getting notified of any more updates to any of the
+     * `SharedPreferences` files associated with any of the provided list of [Item].
+     */
+    fun removeListener(listener: OnSharedPreferenceChangeListener, vararg items: Item<*>) {
+        // If a listener is not registered to a SharedPreference, unregistering it does nothing
+        items
+            .map { it.sharedPrefFile }
+            .distinct()
+            .forEach {
+                context
+                    .getSharedPreferences(it, Context.MODE_PRIVATE)
+                    .unregisterOnSharedPreferenceChangeListener(listener)
+            }
+    }
+
+    /**
+     * Checks if all the provided [Item] have values stored in their corresponding
+     * `SharedPreferences` files.
+     */
+    fun has(vararg items: Item<*>): Boolean {
+        items
+            .groupBy { it.sharedPrefFile }
+            .forEach { (file, itemsSublist) ->
+                val prefs: SharedPreferences =
+                    context.getSharedPreferences(file, Context.MODE_PRIVATE)
+                if (!itemsSublist.none { !prefs.contains(it.sharedPrefKey) }) return false
+            }
+        return true
+    }
+
+    /**
+     * Asynchronously removes the [Item]'s value from its corresponding `SharedPreferences` file.
+     */
+    fun remove(vararg items: Item<*>) = prepareToRemove(items).forEach { it.apply() }
+
+    /** Synchronously removes the [Item]'s value from its corresponding `SharedPreferences` file. */
+    fun removeSync(vararg items: Item<*>) = prepareToRemove(items).forEach { it.commit() }
+
+    /**
+     * Creates `SharedPreferences.Editor` transactions for removing all the provided [Item] values
+     * from their respective `SharedPreferences` files. These returned `Editors` can then be
+     * committed or applied for synchronous or async behavior.
+     */
+    private fun prepareToRemove(items: Array<out Item<*>>): List<SharedPreferences.Editor> =
+        items
+            .groupBy { it.sharedPrefFile }
+            .map { (file, items) ->
+                context.getSharedPreferences(file, Context.MODE_PRIVATE).edit().also { editor ->
+                    items.forEach { item -> editor.remove(item.sharedPrefKey) }
+                }
+            }
+
+    companion object {
+        @JvmField var INSTANCE = MainThreadInitializedObject { LauncherPrefs(it) }
+
+        @JvmStatic fun get(context: Context): LauncherPrefs = INSTANCE.get(context)
+
+        @JvmField val ICON_STATE = nonRestorableItem(LauncherAppState.KEY_ICON_STATE, "")
+        @JvmField val THEMED_ICONS = backedUpItem(Themes.KEY_THEMED_ICONS, false)
+        @JvmField val PROMISE_ICON_IDS = backedUpItem(InstallSessionHelper.PROMISE_ICON_IDS, "")
+        @JvmField val WORK_EDU_STEP = backedUpItem(WorkProfileManager.KEY_WORK_EDU_STEP, 0)
+        @JvmField val WORKSPACE_SIZE = backedUpItem(DeviceGridState.KEY_WORKSPACE_SIZE, "")
+        @JvmField val HOTSEAT_COUNT = backedUpItem(DeviceGridState.KEY_HOTSEAT_COUNT, -1)
+        @JvmField
+        val DEVICE_TYPE =
+            backedUpItem(DeviceGridState.KEY_DEVICE_TYPE, InvariantDeviceProfile.TYPE_PHONE)
+        @JvmField val DB_FILE = backedUpItem(DeviceGridState.KEY_DB_FILE, "")
+        @JvmField
+        val RESTORE_DEVICE =
+            backedUpItem(RestoreDbTask.RESTORED_DEVICE_TYPE, InvariantDeviceProfile.TYPE_PHONE)
+        @JvmField val APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_IDS, "")
+        @JvmField val OLD_APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_OLD_IDS, "")
+
+        @VisibleForTesting
+        @JvmStatic
+        fun <T> backedUpItem(sharedPrefKey: String, defaultValue: T): Item<T> =
+            Item(sharedPrefKey, LauncherFiles.SHARED_PREFERENCES_KEY, defaultValue)
+
+        @VisibleForTesting
+        @JvmStatic
+        fun <T> nonRestorableItem(sharedPrefKey: String, defaultValue: T): Item<T> =
+            Item(sharedPrefKey, LauncherFiles.DEVICE_PREFERENCES_KEY, defaultValue)
+
+        @Deprecated("Don't use shared preferences directly. Use other LauncherPref methods.")
+        @JvmStatic
+        fun getPrefs(context: Context): SharedPreferences {
+            // Use application context for shared preferences, so we use single cached instance
+            return context.applicationContext.getSharedPreferences(
+                LauncherFiles.SHARED_PREFERENCES_KEY,
+                Context.MODE_PRIVATE
+            )
+        }
+
+        @Deprecated("Don't use shared preferences directly. Use other LauncherPref methods.")
+        @JvmStatic
+        fun getDevicePrefs(context: Context): SharedPreferences {
+            // Use application context for shared preferences, so we use a single cached instance
+            return context.applicationContext.getSharedPreferences(
+                LauncherFiles.DEVICE_PREFERENCES_KEY,
+                Context.MODE_PRIVATE
+            )
+        }
+    }
+}
+
+data class Item<T>(val sharedPrefKey: String, val sharedPrefFile: String, val defaultValue: T) {
+    fun to(value: T): Pair<Item<T>, T> = Pair(this, value)
+}
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 6ea331d..66ea616 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -30,6 +30,20 @@
 public class LauncherSettings {
 
     /**
+     * Types of animations.
+     */
+    public static final class Animation {
+        /**
+         * The default animation for a given view/item info type.
+         */
+        public static final int DEFAULT = 0;
+        /**
+         * An animation using the view's background.
+         */
+        public static final int VIEW_BACKGROUND = 1;
+    }
+
+    /**
      * Favorites.
      */
     public static final class Favorites implements BaseColumns {
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 5dddc6f..b9e4c17 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -34,6 +34,8 @@
 import android.graphics.Color;
 import android.view.animation.Interpolator;
 
+import androidx.annotation.FloatRange;
+
 import com.android.launcher3.statemanager.BaseState;
 import com.android.launcher3.statemanager.StateManager;
 import com.android.launcher3.states.HintState;
@@ -342,6 +344,27 @@
         }
     }
 
+    /**
+     * Find {@link StateManager} and target {@link LauncherState} to handle back progress in
+     * predictive back gesture.
+     */
+    public void onBackProgressed(
+            Launcher launcher, @FloatRange(from = 0.0, to = 1.0) float backProgress) {
+        StateManager<LauncherState> lsm = launcher.getStateManager();
+        LauncherState toState = lsm.getLastState();
+        lsm.onBackProgressed(toState, backProgress);
+    }
+
+    /**
+     * Find {@link StateManager} and target {@link LauncherState} to handle backProgress in
+     * predictive back gesture.
+     */
+    public void onBackCancelled(Launcher launcher) {
+        StateManager<LauncherState> lsm = launcher.getStateManager();
+        LauncherState toState = lsm.getLastState();
+        lsm.onBackCancelled(toState);
+    }
+
     public static abstract class PageAlphaProvider {
 
         public final Interpolator interpolator;
diff --git a/src/com/android/launcher3/OnBackPressedHandler.java b/src/com/android/launcher3/OnBackPressedHandler.java
new file mode 100644
index 0000000..485aa0a
--- /dev/null
+++ b/src/com/android/launcher3/OnBackPressedHandler.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+import androidx.annotation.FloatRange;
+
+/**
+ * Interface that mimics {@link android.window.OnBackInvokedCallback} without dependencies on U's
+ * API such as {@link android.window.BackEvent}.
+ *
+ * <p> Impl can assume below order during a back gesture:
+ * <ol>
+ *  <li> [optional] one {@link #onBackStarted()} will be called to start the gesture
+ *  <li> zero or multiple {@link #onBackProgressed(float)} will be called during swipe gesture
+ *  <li> either one of {@link #onBackInvoked()} or {@link #onBackCancelled()} will be called to end
+ *  the gesture
+ */
+public interface OnBackPressedHandler {
+
+    /** Called when back has started. */
+    default void onBackStarted() {}
+
+    /** Called when back is committed. */
+    void onBackInvoked();
+
+    /** Called with back gesture's progress. */
+    default void onBackProgressed(@FloatRange(from = 0.0, to = 1.0) float backProgress) {}
+
+    /** Called when user drops the back gesture. */
+    default void onBackCancelled() {}
+}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index eb68adb..c3d8a53 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -699,7 +699,7 @@
     }
 
     /** Returns true iff this PagedView's scroll amounts are initialized to each page index. */
-    protected boolean pageScrollsInitialized() {
+    protected boolean isPageScrollsInitialized() {
         return mPageScrolls != null && mPageScrolls.length == getChildCount();
     }
 
@@ -708,12 +708,12 @@
      */
     public void runOnPageScrollsInitialized(Runnable callback) {
         mOnPageScrollsInitializedCallbacks.add(callback);
-        if (pageScrollsInitialized()) {
+        if (isPageScrollsInitialized()) {
             onPageScrollsInitialized();
         }
     }
 
-    private void onPageScrollsInitialized() {
+    protected void onPageScrollsInitialized() {
         for (Runnable callback : mOnPageScrollsInitializedCallbacks) {
             callback.run();
         }
@@ -727,7 +727,7 @@
         final int childCount = getChildCount();
         int[] pageScrolls = mPageScrolls;
         boolean pageScrollChanged = false;
-        if (!pageScrollsInitialized()) {
+        if (!isPageScrollsInitialized()) {
             pageScrolls = new int[childCount];
             pageScrollChanged = true;
         }
@@ -1199,7 +1199,7 @@
     }
 
     public int getScrollForPage(int index) {
-        if (!pageScrollsInitialized() || index >= mPageScrolls.length || index < 0) {
+        if (!isPageScrollsInitialized() || index >= mPageScrolls.length || index < 0) {
             return 0;
         } else {
             return mPageScrolls[index];
@@ -1209,7 +1209,7 @@
     // While layout transitions are occurring, a child's position may stray from its baseline
     // position. This method returns the magnitude of this stray at any given time.
     public int getLayoutTransitionOffsetForPage(int index) {
-        if (!pageScrollsInitialized() || index >= mPageScrolls.length || index < 0) {
+        if (!isPageScrollsInitialized() || index >= mPageScrolls.length || index < 0) {
             return 0;
         } else {
             View child = getChildAt(index);
@@ -1404,15 +1404,17 @@
                             (isFling && !isVelocityLeft)) && mCurrentPage > 0) {
                         finalPage = returnToOriginalPage
                                 ? mCurrentPage : mCurrentPage - getPanelCount();
-                        snapToPageWithVelocity(finalPage, velocity);
+                        runOnPageScrollsInitialized(
+                                () -> snapToPageWithVelocity(finalPage, velocity));
                     } else if (((isSignificantMove && isDeltaLeft && !isFling) ||
                             (isFling && isVelocityLeft)) &&
                             mCurrentPage < getChildCount() - 1) {
                         finalPage = returnToOriginalPage
                                 ? mCurrentPage : mCurrentPage + getPanelCount();
-                        snapToPageWithVelocity(finalPage, velocity);
+                        runOnPageScrollsInitialized(
+                                () -> snapToPageWithVelocity(finalPage, velocity));
                     } else {
-                        snapToDestination();
+                        runOnPageScrollsInitialized(this::snapToDestination);
                     }
                 } else {
                     if (!mScroller.isFinished()) {
@@ -1435,7 +1437,7 @@
 
                         int finalPos = mScroller.getFinalX();
                         mNextPage = getDestinationPage(finalPos);
-                        onNotSnappingToPageInFreeScroll();
+                        runOnPageScrollsInitialized(this::onNotSnappingToPageInFreeScroll);
                     }
                     invalidate();
                 }
@@ -1449,7 +1451,7 @@
 
         case MotionEvent.ACTION_CANCEL:
             if (mIsBeingDragged) {
-                snapToDestination();
+                runOnPageScrollsInitialized(this::snapToDestination);
             }
             mEdgeGlowLeft.onRelease();
             mEdgeGlowRight.onRelease();
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index 7a74d7e..5f39f7e 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -83,8 +83,8 @@
             View child = getChildAt(i);
             CellLayoutLayoutParams lp = (CellLayoutLayoutParams) child.getLayoutParams();
 
-            if ((lp.cellX <= cellX) && (cellX < lp.cellX + lp.cellHSpan)
-                    && (lp.cellY <= cellY) && (cellY < lp.cellY + lp.cellVSpan)) {
+            if ((lp.getCellX() <= cellX) && (cellX < lp.getCellX() + lp.cellHSpan)
+                    && (lp.getCellY() <= cellY) && (cellY < lp.getCellY() + lp.cellVSpan)) {
                 return child;
             }
         }
@@ -260,7 +260,7 @@
         lp.canReorder = false;
         if (mContainerType == HOTSEAT) {
             CellLayout cl = (CellLayout) getParent();
-            cl.setFolderLeaveBehindCell(lp.cellX, lp.cellY);
+            cl.setFolderLeaveBehindCell(lp.getCellX(), lp.getCellY());
         }
     }
 
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index b10256e..d7e84f0 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -723,4 +723,14 @@
         }
         return options;
     }
+
+    /** Logs the Scale and Translate properties of a matrix. Ignores skew and perspective. */
+    public static void logMatrix(String label, Matrix matrix) {
+        float[] matrixValues = new float[9];
+        matrix.getValues(matrixValues);
+        Log.d(label, String.format("%s: %s\nscale (x,y) = (%f, %f)\ntranslate (x,y) = (%f, %f)",
+                label, matrix, matrixValues[Matrix.MSCALE_X], matrixValues[Matrix.MSCALE_Y],
+                matrixValues[Matrix.MTRANS_X], matrixValues[Matrix.MTRANS_Y]
+        ));
+    }
 }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 483309d..460c658 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -62,6 +62,7 @@
 import android.widget.Toast;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 
 import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
 import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
@@ -161,7 +162,9 @@
 
     protected ShortcutAndWidgetContainer mDragSourceInternal;
 
-    @Thunk final IntSparseArrayMap<CellLayout> mWorkspaceScreens = new IntSparseArrayMap<>();
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    @Thunk public final IntSparseArrayMap<CellLayout> mWorkspaceScreens = new IntSparseArrayMap<>();
+
     @Thunk final IntArray mScreenOrder = new IntArray();
 
     @Thunk boolean mDeferRemoveExtraEmptyScreen = false;
@@ -1754,7 +1757,8 @@
     boolean willCreateUserFolder(ItemInfo info, View dropOverView, boolean considerTimeout) {
         if (dropOverView != null) {
             CellLayoutLayoutParams lp = (CellLayoutLayoutParams) dropOverView.getLayoutParams();
-            if (lp.useTmpCoords && (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.cellY)) {
+            if (lp.useTmpCoords && (lp.getTmpCellX() != lp.getCellX()
+                    || lp.getTmpCellY() != lp.getCellY())) {
                 return false;
             }
         }
@@ -1789,7 +1793,8 @@
     boolean willAddToExistingUserFolder(ItemInfo dragInfo, View dropOverView) {
         if (dropOverView != null) {
             CellLayoutLayoutParams lp = (CellLayoutLayoutParams) dropOverView.getLayoutParams();
-            if (lp.useTmpCoords && (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.cellY)) {
+            if (lp.useTmpCoords && (lp.getTmpCellX() != lp.getCellX()
+                    || lp.getTmpCellY() != lp.getCellY())) {
                 return false;
             }
         }
@@ -2006,8 +2011,10 @@
 
                     // update the item's position after drop
                     CellLayoutLayoutParams lp = (CellLayoutLayoutParams) cell.getLayoutParams();
-                    lp.cellX = lp.tmpCellX = mTargetCell[0];
-                    lp.cellY = lp.tmpCellY = mTargetCell[1];
+                    lp.setTmpCellX(mTargetCell[0]);
+                    lp.setCellX(mTargetCell[0]);
+                    lp.setTmpCellY(mTargetCell[1]);
+                    lp.setCellY(mTargetCell[1]);
                     lp.cellHSpan = item.spanX;
                     lp.cellVSpan = item.spanY;
                     lp.isLockedToGrid = true;
@@ -2021,7 +2028,7 @@
                                 (LauncherAppWidgetHostView) cell, dropTargetLayout);
                     }
                     mLauncher.getModelWriter().modifyItemInDatabase(info, container, screenId,
-                            lp.cellX, lp.cellY, item.spanX, item.spanY);
+                            lp.getCellX(), lp.getCellY(), item.spanX, item.spanY);
                 } else {
                     if (!returnToOriginalCellToPreventShuffling) {
                         onNoCellFound(dropTargetLayout, d.dragInfo, d.logInstanceId);
@@ -2032,8 +2039,8 @@
 
                     // If we can't find a drop location, we return the item to its original position
                     CellLayoutLayoutParams lp = (CellLayoutLayoutParams) cell.getLayoutParams();
-                    mTargetCell[0] = lp.cellX;
-                    mTargetCell[1] = lp.cellY;
+                    mTargetCell[0] = lp.getCellX();
+                    mTargetCell[1] = lp.getCellY();
                     CellLayout layout = (CellLayout) cell.getParent().getParent();
                     layout.markCellsAsOccupiedForView(cell);
                 }
diff --git a/src/com/android/launcher3/WorkspaceLayoutManager.java b/src/com/android/launcher3/WorkspaceLayoutManager.java
index 91e12fa..bf448c9 100644
--- a/src/com/android/launcher3/WorkspaceLayoutManager.java
+++ b/src/com/android/launcher3/WorkspaceLayoutManager.java
@@ -117,8 +117,8 @@
             lp = new CellLayoutLayoutParams(x, y, spanX, spanY, screenId);
         } else {
             lp = (CellLayoutLayoutParams) genericLp;
-            lp.cellX = x;
-            lp.cellY = y;
+            lp.setCellX(x);
+            lp.setCellY(y);
             lp.cellHSpan = spanX;
             lp.cellVSpan = spanY;
         }
@@ -136,7 +136,8 @@
             // TODO: This branch occurs when the workspace is adding views
             // outside of the defined grid
             // maybe we should be deleting these items from the LauncherModel?
-            Log.e(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
+            Log.e(TAG, "Failed to add to item at (" + lp.getCellX() + "," + lp.getCellY()
+                    + ") to CellLayout");
         }
 
         child.setHapticFeedbackEnabled(false);
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index 063b82e..3c316b8 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -259,7 +259,7 @@
             if (((host.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL)
                     && layout.isRegionVacant(info.cellX - 1, info.cellY, 1, info.spanY))
                     || !layout.isRegionVacant(info.cellX + info.spanX, info.cellY, 1, info.spanY)) {
-                lp.cellX --;
+                lp.setCellX(lp.getCellX() - 1);
                 info.cellX --;
             }
             lp.cellHSpan ++;
@@ -269,7 +269,7 @@
             info.spanX --;
         } else if (action == R.string.action_increase_height) {
             if (!layout.isRegionVacant(info.cellX, info.cellY + info.spanY, info.spanX, 1)) {
-                lp.cellY --;
+                lp.setCellY(lp.getCellY() - 1);
                 info.cellY --;
             }
             lp.cellVSpan ++;
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 2511cada..3bb8fb4 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -15,25 +15,74 @@
  */
 package com.android.launcher3.allapps;
 
-import static com.android.launcher3.allapps.BaseAllAppsContainerView.AdapterHolder.SEARCH;
+import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.SEARCH;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_COUNT;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
 import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Path.Direction;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.os.Process;
+import android.os.UserManager;
 import android.util.AttributeSet;
+import android.util.Log;
+import android.util.SparseArray;
+import android.util.TypedValue;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.WindowInsets;
+import android.widget.Button;
 import android.widget.RelativeLayout;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 import androidx.core.graphics.ColorUtils;
 import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
+import com.android.launcher3.DragSource;
+import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.Insettable;
+import com.android.launcher3.InsettableFrameLayout;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
+import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider;
+import com.android.launcher3.allapps.search.SearchAdapterProvider;
 import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.keyboard.FocusedItemDecorator;
+import com.android.launcher3.model.StringCache;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.ItemInfoMatcher;
+import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.BaseDragLayer;
+import com.android.launcher3.views.RecyclerViewFastScroller;
+import com.android.launcher3.views.ScrimView;
+import com.android.launcher3.views.SpringRelativeLayout;
+import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
 
 /**
  * All apps container view with search support for use in a dragging activity.
@@ -41,16 +90,67 @@
  * @param <T> Type of context inflating all apps.
  */
 public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
-        extends BaseAllAppsContainerView<T> {
+        extends SpringRelativeLayout implements DragSource, Insettable,
+        OnDeviceProfileChangeListener, PersonalWorkSlidingTabStrip.OnActivePageChangedListener,
+        ScrimView.ScrimDrawingController {
 
+    public static final float PULL_MULTIPLIER = .02f;
+    public static final float FLING_VELOCITY_MULTIPLIER = 1200f;
+    protected static final String BUNDLE_KEY_CURRENT_PAGE = "launcher.allapps.current_page";
     private static final long DEFAULT_SEARCH_TRANSITION_DURATION_MS = 300;
+    // Render the header protection at all times to debug clipping issues.
+    private static final boolean DEBUG_HEADER_PROTECTION = false;
+    /** Context of an activity or window that is inflating this container. */
+
+    protected final T mActivityContext;
+    protected final List<AdapterHolder> mAH;
+    protected final Predicate<ItemInfo> mPersonalMatcher = ItemInfoMatcher.ofUser(
+            Process.myUserHandle());
+    protected final WorkProfileManager mWorkManager;
+    protected final Point mFastScrollerOffset = new Point();
+    protected final int mScrimColor;
+    protected final float mHeaderThreshold;
 
     // Used to animate Search results out and A-Z apps in, or vice-versa.
     private final SearchTransitionController mSearchTransitionController;
+    private final Paint mHeaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+    private final Rect mInsets = new Rect();
+    private final AllAppsStore mAllAppsStore = new AllAppsStore();
+    private final RecyclerView.OnScrollListener mScrollListener =
+            new RecyclerView.OnScrollListener() {
+                @Override
+                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+                    updateHeaderScroll(recyclerView.computeVerticalScrollOffset());
+                }
+            };
+    private final Paint mNavBarScrimPaint;
+    private final int mHeaderProtectionColor;
+    private final Path mTmpPath = new Path();
+    private final RectF mTmpRectF = new RectF();
+    protected AllAppsPagedView mViewPager;
+    protected FloatingHeaderView mHeader;
+    protected View mBottomSheetBackground;
+    /**
+     * View that defines the search box. Result is rendered inside {@link #mSearchRecyclerView}.
+     */
+    protected View mSearchContainer;
+    protected SearchUiManager mSearchUiManager;
+    protected boolean mUsingTabs;
+    protected RecyclerViewFastScroller mTouchHandler;
 
     /** {@code true} when rendered view is in search state instead of the scroll state. */
     private boolean mIsSearching;
     private boolean mRebindAdaptersAfterSearchAnimation;
+    private int mNavBarScrimHeight = 0;
+    private SearchRecyclerView mSearchRecyclerView;
+    protected SearchAdapterProvider<?> mMainAdapterProvider;
+    private View mBottomSheetHandleArea;
+    private boolean mHasWorkApps;
+    private float[] mBottomSheetCornerRadii;
+    private ScrimView mScrimView;
+    private int mHeaderColor;
+    private int mBottomSheetBackgroundColor;
+    private int mTabsProtectionAlpha;
 
     public ActivityAllAppsContainerView(Context context) {
         this(context, null);
@@ -62,13 +162,87 @@
 
     public ActivityAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
+        mActivityContext = ActivityContext.lookupContext(context);
+
+        mScrimColor = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
+        mHeaderThreshold = getResources().getDimensionPixelSize(
+                R.dimen.dynamic_grid_cell_border_spacing);
+        mHeaderProtectionColor = Themes.getAttrColor(context, R.attr.allappsHeaderProtectionColor);
+
+        mWorkManager = new WorkProfileManager(
+                mActivityContext.getSystemService(UserManager.class),
+                this, mActivityContext.getStatsLogManager());
+        mAH = Arrays.asList(null, null, null);
+        mNavBarScrimPaint = new Paint();
+        mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
+
+        mAllAppsStore.addUpdateListener(this::onAppsUpdated);
+        mActivityContext.addOnDeviceProfileChangeListener(this);
+
+        // This is a focus listener that proxies focus from a view into the list view.  This is to
+        // work around the search box from getting first focus and showing the cursor.
+        setOnFocusChangeListener((v, hasFocus) -> {
+            if (hasFocus && getActiveRecyclerView() != null) {
+                getActiveRecyclerView().requestFocus();
+            }
+        });
+        initContent();
 
         mSearchTransitionController = new SearchTransitionController(this);
     }
 
+    /**
+     * Initializes the view hierarchy and internal variables. Any initialization which actually uses
+     * these members should be done in {@link #onFinishInflate()}.
+     * In terms of subclass initialization, the following would be parallel order for activity:
+     *   initContent -> onPreCreate
+     *   constructor/init -> onCreate
+     *   onFinishInflate -> onPostCreate
+     */
+    protected void initContent() {
+        mMainAdapterProvider = createMainAdapterProvider();
+
+        mAH.set(AdapterHolder.MAIN, new AdapterHolder(AdapterHolder.MAIN,
+                new AlphabeticalAppsList<>(mActivityContext, mAllAppsStore, null)));
+        mAH.set(AdapterHolder.WORK, new AdapterHolder(AdapterHolder.WORK,
+                new AlphabeticalAppsList<>(mActivityContext, mAllAppsStore, mWorkManager)));
+        mAH.set(SEARCH, new AdapterHolder(SEARCH,
+                new AlphabeticalAppsList<>(mActivityContext, null, null)));
+
+        getLayoutInflater().inflate(R.layout.all_apps_content, this);
+        mHeader = findViewById(R.id.all_apps_header);
+        mBottomSheetBackground = findViewById(R.id.bottom_sheet_background);
+        mBottomSheetHandleArea = findViewById(R.id.bottom_sheet_handle_area);
+        mSearchRecyclerView = findViewById(R.id.search_results_list_view);
+
+        // Add the search box above everything else.
+        mSearchContainer = inflateSearchBox();
+        addView(mSearchContainer);
+        mSearchUiManager = (SearchUiManager) mSearchContainer;
+    }
+
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
+
+        mAH.get(SEARCH).setup(mSearchRecyclerView,
+                /* Filter out A-Z apps */ itemInfo -> false);
+        rebindAdapters(true /* force */);
+        float cornerRadius = Themes.getDialogCornerRadius(getContext());
+        mBottomSheetCornerRadii = new float[]{
+                cornerRadius,
+                cornerRadius, // Top left radius in px
+                cornerRadius,
+                cornerRadius, // Top right radius in px
+                0,
+                0, // Bottom right
+                0,
+                0 // Bottom left
+        };
+        final TypedValue value = new TypedValue();
+        getContext().getTheme().resolveAttribute(android.R.attr.colorBackground, value, true);
+        mBottomSheetBackgroundColor = value.data;
+        updateBackground(mActivityContext.getDeviceProfile());
         mSearchUiManager.initializeSearch(this);
     }
 
@@ -141,19 +315,43 @@
                 });
     }
 
-    @Override
     public boolean shouldContainerScroll(MotionEvent ev) {
+        BaseDragLayer dragLayer = mActivityContext.getDragLayer();
         // IF the MotionEvent is inside the search box, and the container keeps on receiving
         // touch input, container should move down.
-        if (mActivityContext.getDragLayer().isEventOverView(mSearchContainer, ev)) {
+        if (dragLayer.isEventOverView(mSearchContainer, ev)) {
             return true;
         }
-        return super.shouldContainerScroll(ev);
+        // Scroll if not within the container view (e.g. over large-screen scrim).
+        if (!dragLayer.isEventOverView(getVisibleContainerView(), ev)) {
+            return true;
+        }
+        if (dragLayer.isEventOverView(mBottomSheetHandleArea, ev)) {
+            return true;
+        }
+        AllAppsRecyclerView rv = getActiveRecyclerView();
+        if (rv == null) {
+            return true;
+        }
+        if (rv.getScrollbar() != null
+                && rv.getScrollbar().getThumbOffsetY() >= 0
+                && dragLayer.isEventOverView(rv.getScrollbar(), ev)) {
+            return false;
+        }
+        return rv.shouldContainerScroll(ev, dragLayer);
     }
 
-    @Override
     public void reset(boolean animate) {
-        super.reset(animate);
+        for (int i = 0; i < mAH.size(); i++) {
+            if (mAH.get(i).mRecyclerView != null) {
+                mAH.get(i).mRecyclerView.scrollToTop();
+            }
+        }
+        if (mHeader != null && mHeader.getVisibility() == VISIBLE) {
+            mHeader.reset(animate);
+        }
+        // Reset the base recycler view after transitioning home.
+        updateHeaderScroll(0);
         // Reset the search bar after transitioning home.
         mSearchUiManager.resetSearch();
         // Animate to A-Z with 0 time to reset the animation with proper state management.
@@ -166,16 +364,26 @@
         return super.dispatchKeyEvent(event);
     }
 
-    @Override
     public String getDescription() {
         if (!mUsingTabs && isSearching()) {
             return getContext().getString(R.string.all_apps_search_results);
         } else {
-            return super.getDescription();
+            StringCache cache = mActivityContext.getStringCache();
+            if (mUsingTabs) {
+                if (cache != null) {
+                    return isPersonalTab()
+                            ? cache.allAppsPersonalTabAccessibility
+                            : cache.allAppsWorkTabAccessibility;
+                } else {
+                    return isPersonalTab()
+                            ? getContext().getString(R.string.all_apps_button_personal_label)
+                            : getContext().getString(R.string.all_apps_button_work_label);
+                }
+            }
+            return getContext().getString(R.string.all_apps_button_label);
         }
     }
 
-    @Override
     public boolean isSearching() {
         return mIsSearching;
     }
@@ -186,30 +394,122 @@
             // Will be called at the end of the animation.
             return;
         }
-        super.onActivePageChanged(currentActivePage);
+        if (mAH.get(currentActivePage).mRecyclerView != null) {
+            mAH.get(currentActivePage).mRecyclerView.bindFastScrollbar();
+        }
+        // Header keeps track of active recycler view to properly render header protection.
+        mHeader.setActiveRV(currentActivePage);
+        reset(true /* animate */);
+
+        mWorkManager.onActivePageChanged(currentActivePage);
     }
 
-    @Override
+    protected void rebindAdapters() {
+        rebindAdapters(false /* force */);
+    }
+
     protected void rebindAdapters(boolean force) {
         if (mSearchTransitionController.isRunning()) {
             mRebindAdaptersAfterSearchAnimation = true;
             return;
         }
-        super.rebindAdapters(force);
-        if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()
-                || getMainAdapterProvider().getDecorator() == null
-                || getSearchRecyclerView() == null) {
+        updateSearchResultsVisibility();
+
+        boolean showTabs = shouldShowTabs();
+        if (showTabs == mUsingTabs && !force) {
             return;
         }
 
-        RecyclerView.ItemDecoration decoration = getMainAdapterProvider().getDecorator();
-        getSearchRecyclerView().removeItemDecoration(decoration); // In case it is already added.
-        getSearchRecyclerView().addItemDecoration(decoration);
+        if (isSearching()) {
+            mUsingTabs = showTabs;
+            mWorkManager.detachWorkModeSwitch();
+            return;
+        }
+
+        // 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.
+        replaceAppsRVContainer(showTabs);
+        mUsingTabs = showTabs;
+
+        mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
+        mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
+        mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.SEARCH).mRecyclerView);
+
+        if (mUsingTabs) {
+            mAH.get(AdapterHolder.MAIN).setup(mViewPager.getChildAt(0), mPersonalMatcher);
+            mAH.get(AdapterHolder.WORK).setup(mViewPager.getChildAt(1), mWorkManager.getMatcher());
+            mAH.get(AdapterHolder.WORK).mRecyclerView.setId(R.id.apps_list_view_work);
+            if (FeatureFlags.ENABLE_EXPANDING_PAUSE_WORK_BUTTON.get()) {
+                mAH.get(AdapterHolder.WORK).mRecyclerView.addOnScrollListener(
+                        mWorkManager.newScrollListener());
+            }
+            mViewPager.getPageIndicator().setActiveMarker(AdapterHolder.MAIN);
+            findViewById(R.id.tab_personal)
+                    .setOnClickListener((View view) -> {
+                        if (mViewPager.snapToPage(AdapterHolder.MAIN)) {
+                            mActivityContext.getStatsLogManager().logger()
+                                    .log(LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB);
+                        }
+                        mActivityContext.hideKeyboard();
+                    });
+            findViewById(R.id.tab_work)
+                    .setOnClickListener((View view) -> {
+                        if (mViewPager.snapToPage(AdapterHolder.WORK)) {
+                            mActivityContext.getStatsLogManager().logger()
+                                    .log(LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB);
+                        }
+                        mActivityContext.hideKeyboard();
+                    });
+            setDeviceManagementResources();
+            onActivePageChanged(mViewPager.getNextPage());
+        } else {
+            mAH.get(AdapterHolder.MAIN).setup(findViewById(R.id.apps_list_view), null);
+            mAH.get(AdapterHolder.WORK).mRecyclerView = null;
+        }
+        setupHeader();
+
+        if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+            // Keep the scroller above the search bar.
+            RelativeLayout.LayoutParams scrollerLayoutParams =
+                    (LayoutParams) findViewById(R.id.fast_scroller).getLayoutParams();
+            scrollerLayoutParams.addRule(RelativeLayout.ABOVE, R.id.search_container_all_apps);
+            scrollerLayoutParams.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+            scrollerLayoutParams.bottomMargin = getResources().getDimensionPixelSize(
+                    R.dimen.fastscroll_bottom_margin_floating_search);
+        }
+
+        mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
+        mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
+        mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.SEARCH).mRecyclerView);
     }
 
-    @Override
     protected View replaceAppsRVContainer(boolean showTabs) {
-        View rvContainer = super.replaceAppsRVContainer(showTabs);
+        for (int i = AdapterHolder.MAIN; i <= AdapterHolder.WORK; i++) {
+            AdapterHolder adapterHolder = mAH.get(i);
+            if (adapterHolder.mRecyclerView != null) {
+                adapterHolder.mRecyclerView.setLayoutManager(null);
+                adapterHolder.mRecyclerView.setAdapter(null);
+            }
+        }
+        View oldView = getAppsRecyclerViewContainer();
+        int index = indexOfChild(oldView);
+        removeView(oldView);
+        int layout = showTabs ? R.layout.all_apps_tabs : R.layout.all_apps_rv_layout;
+        final View rvContainer = getLayoutInflater().inflate(layout, this, false);
+        addView(rvContainer, index);
+        if (showTabs) {
+            mViewPager = (AllAppsPagedView) rvContainer;
+            mViewPager.initParentViews(this);
+            mViewPager.getPageIndicator().setOnActivePageChangedListener(this);
+
+            mWorkManager.reset();
+            post(() -> mAH.get(AdapterHolder.WORK).applyPadding());
+
+        } else {
+            mWorkManager.detachWorkModeSwitch();
+            mViewPager = null;
+        }
 
         removeCustomRules(rvContainer);
         removeCustomRules(getSearchRecyclerView());
@@ -228,21 +528,47 @@
         return rvContainer;
     }
 
-    @Override
     void setupHeader() {
-        super.setupHeader();
+        mHeader.setVisibility(View.VISIBLE);
+        boolean tabsHidden = !mUsingTabs;
+        mHeader.setup(
+                mAH.get(AdapterHolder.MAIN).mRecyclerView,
+                mAH.get(AdapterHolder.WORK).mRecyclerView,
+                (SearchRecyclerView) mAH.get(SEARCH).mRecyclerView,
+                getCurrentPage(),
+                tabsHidden);
+
+        int padding = mHeader.getMaxTranslation();
+        mAH.forEach(adapterHolder -> {
+            adapterHolder.mPadding.top = padding;
+            adapterHolder.applyPadding();
+            if (adapterHolder.mRecyclerView != null) {
+                adapterHolder.mRecyclerView.scrollToTop();
+            }
+        });
 
         removeCustomRules(mHeader);
-        if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+        if (!isSearchSupported()) {
+            layoutWithoutSearchContainer(mHeader, false /* includeTabsMargin */);
+        } else if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
             alignParentTop(mHeader, false /* includeTabsMargin */);
         } else {
             layoutBelowSearchContainer(mHeader, false /* includeTabsMargin */);
         }
     }
 
-    @Override
     protected void updateHeaderScroll(int scrolledOffset) {
-        super.updateHeaderScroll(scrolledOffset);
+        float prog1 = Utilities.boundToRange((float) scrolledOffset / mHeaderThreshold, 0f, 1f);
+        int headerColor = getHeaderColor(prog1);
+        int tabsAlpha = mHeader.getPeripheralProtectionHeight() == 0 ? 0
+                : (int) (Utilities.boundToRange(
+                        (scrolledOffset + mHeader.mSnappedScrolledY) / mHeaderThreshold, 0f, 1f)
+                        * 255);
+        if (headerColor != mHeaderColor || mTabsProtectionAlpha != tabsAlpha) {
+            mHeaderColor = headerColor;
+            mTabsProtectionAlpha = tabsAlpha;
+            invalidateHeader();
+        }
         if (mSearchUiManager.getEditText() == null) {
             return;
         }
@@ -257,10 +583,9 @@
         mSearchUiManager.setBackgroundVisibility(bgVisible, 1 - prog);
     }
 
-    @Override
     protected int getHeaderColor(float blendRatio) {
         return ColorUtils.setAlphaComponent(
-                super.getHeaderColor(blendRatio),
+                ColorUtils.blendARGB(mScrimColor, mHeaderProtectionColor, blendRatio),
                 (int) (mSearchContainer.getAlpha() * 255));
     }
 
@@ -315,11 +640,9 @@
         layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
     }
 
-    @Override
-    protected BaseAllAppsAdapter<T> createAdapter(AlphabeticalAppsList<T> appsList,
-            BaseAdapterProvider[] adapterProviders) {
+    protected BaseAllAppsAdapter<T> createAdapter(AlphabeticalAppsList<T> appsList) {
         return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), appsList,
-                adapterProviders);
+                mMainAdapterProvider);
     }
 
     // TODO(b/216683257): Remove when Taskbar All Apps supports search.
@@ -339,9 +662,549 @@
                 : R.dimen.all_apps_header_top_margin);
     }
 
-    @Override
     public boolean isInAllApps() {
         // TODO: Make this abstract
         return true;
     }
+
+    /**
+     * Inflates the search box
+     */
+    protected View inflateSearchBox() {
+        return getLayoutInflater().inflate(R.layout.search_container_all_apps, this, false);
+    }
+
+    /** Creates the adapter provider for the main section. */
+    protected SearchAdapterProvider<?> createMainAdapterProvider() {
+        return new DefaultSearchAdapterProvider(mActivityContext);
+    }
+
+    /** The adapter provider for the main section. */
+    public final SearchAdapterProvider<?> getMainAdapterProvider() {
+        return mMainAdapterProvider;
+    }
+
+    @Override
+    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> sparseArray) {
+        try {
+            // Many slice view id is not properly assigned, and hence throws null
+            // pointer exception in the underneath method. Catching the exception
+            // simply doesn't restore these slice views. This doesn't have any
+            // user visible effect because because we query them again.
+            super.dispatchRestoreInstanceState(sparseArray);
+        } catch (Exception e) {
+            Log.e("AllAppsContainerView", "restoreInstanceState viewId = 0", e);
+        }
+
+        Bundle state = (Bundle) sparseArray.get(R.id.work_tab_state_id, null);
+        if (state != null) {
+            int currentPage = state.getInt(BUNDLE_KEY_CURRENT_PAGE, 0);
+            if (currentPage == AdapterHolder.WORK && mViewPager != null) {
+                mViewPager.setCurrentPage(currentPage);
+                rebindAdapters();
+            } else {
+                reset(true);
+            }
+        }
+    }
+
+    @Override
+    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
+        super.dispatchSaveInstanceState(container);
+        Bundle state = new Bundle();
+        state.putInt(BUNDLE_KEY_CURRENT_PAGE, getCurrentPage());
+        container.put(R.id.work_tab_state_id, state);
+    }
+
+    /**
+     * Sets the long click listener for icons
+     */
+    public void setOnIconLongClickListener(OnLongClickListener listener) {
+        for (AdapterHolder holder : mAH) {
+            holder.mAdapter.setOnIconLongClickListener(listener);
+        }
+    }
+
+    public AllAppsStore getAppsStore() {
+        return mAllAppsStore;
+    }
+
+    public WorkProfileManager getWorkManager() {
+        return mWorkManager;
+    }
+
+    @Override
+    public void onDeviceProfileChanged(DeviceProfile dp) {
+        for (AdapterHolder holder : mAH) {
+            holder.mAdapter.setAppsPerRow(dp.numShownAllAppsColumns);
+            if (holder.mRecyclerView != null) {
+                // Remove all views and clear the pool, while keeping the data same. After this
+                // call, all the viewHolders will be recreated.
+                holder.mRecyclerView.swapAdapter(holder.mRecyclerView.getAdapter(), true);
+                holder.mRecyclerView.getRecycledViewPool().clear();
+            }
+        }
+        updateBackground(dp);
+    }
+
+    protected void updateBackground(DeviceProfile deviceProfile) {
+        mBottomSheetBackground.setVisibility(deviceProfile.isTablet ? View.VISIBLE : View.GONE);
+        // Note: For tablets, the opaque background and header protection are added in drawOnScrim.
+        // For the taskbar entrypoint, the scrim is drawn differently, so a static background is
+        // added in TaskbarAllAppsContainerView and header protection is not yet supported.
+    }
+
+    private void onAppsUpdated() {
+        mHasWorkApps = Stream.of(mAllAppsStore.getApps()).anyMatch(mWorkManager.getMatcher());
+        if (!isSearching()) {
+            rebindAdapters();
+            if (mHasWorkApps) {
+                mWorkManager.reset();
+            }
+        }
+
+        mActivityContext.getStatsLogManager().logger()
+                .withCardinality(mAllAppsStore.getApps().length)
+                .log(LAUNCHER_ALLAPPS_COUNT);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        // The AllAppsContainerView houses the QSB and is hence visible from the Workspace
+        // Overview states. We shouldn't intercept for the scrubber in these cases.
+        if (!isInAllApps()) {
+            mTouchHandler = null;
+            return false;
+        }
+
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            AllAppsRecyclerView rv = getActiveRecyclerView();
+            if (rv != null && rv.getScrollbar() != null
+                    && rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(), mFastScrollerOffset)) {
+                mTouchHandler = rv.getScrollbar();
+            } else {
+                mTouchHandler = null;
+            }
+        }
+        if (mTouchHandler != null) {
+            return mTouchHandler.handleTouchEvent(ev, mFastScrollerOffset);
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (!isInAllApps()) {
+            return false;
+        }
+
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            AllAppsRecyclerView rv = getActiveRecyclerView();
+            if (rv != null && rv.getScrollbar() != null
+                    && rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(), mFastScrollerOffset)) {
+                mTouchHandler = rv.getScrollbar();
+            } else {
+                mTouchHandler = null;
+
+            }
+        }
+        if (mTouchHandler != null) {
+            mTouchHandler.handleTouchEvent(ev, mFastScrollerOffset);
+            return true;
+        }
+        if (isSearching()
+                && mActivityContext.getDragLayer().isEventOverView(getVisibleContainerView(), ev)) {
+            // if in search state, consume touch event.
+            return true;
+        }
+        return false;
+    }
+
+    /** The current active recycler view (A-Z list from one of the profiles, or search results). */
+    public AllAppsRecyclerView getActiveRecyclerView() {
+        if (isSearching()) {
+            return getSearchRecyclerView();
+        }
+        return getActiveAppsRecyclerView();
+    }
+
+    /** The current apps recycler view in the container. */
+    private AllAppsRecyclerView getActiveAppsRecyclerView() {
+        if (!mUsingTabs || isPersonalTab()) {
+            return mAH.get(AdapterHolder.MAIN).mRecyclerView;
+        } else {
+            return mAH.get(AdapterHolder.WORK).mRecyclerView;
+        }
+    }
+
+    /**
+     * The container for A-Z apps (the ViewPager for main+work tabs, or main RV). This is currently
+     * hidden while searching.
+     **/
+    protected View getAppsRecyclerViewContainer() {
+        return mViewPager != null ? mViewPager : findViewById(R.id.apps_list_view);
+    }
+
+    /** The RV for search results, which is hidden while A-Z apps are visible. */
+    public SearchRecyclerView getSearchRecyclerView() {
+        return mSearchRecyclerView;
+    }
+
+    protected boolean isPersonalTab() {
+        return mViewPager == null || mViewPager.getNextPage() == 0;
+    }
+
+    /**
+     * Switches the current page to the provided {@code tab} if tabs are supported, otherwise does
+     * nothing.
+     */
+    public void switchToTab(int tab) {
+        if (mUsingTabs) {
+            mViewPager.setCurrentPage(tab);
+        }
+    }
+
+    public LayoutInflater getLayoutInflater() {
+        return LayoutInflater.from(getContext());
+    }
+
+    @Override
+    public void onDropCompleted(View target, DragObject d, boolean success) {}
+
+    @Override
+    public void setInsets(Rect insets) {
+        mInsets.set(insets);
+        DeviceProfile grid = mActivityContext.getDeviceProfile();
+
+        applyAdapterSideAndBottomPaddings(grid);
+
+        MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
+        mlp.leftMargin = insets.left;
+        mlp.rightMargin = insets.right;
+        setLayoutParams(mlp);
+
+        if (grid.isVerticalBarLayout()) {
+            setPadding(grid.workspacePadding.left, 0, grid.workspacePadding.right, 0);
+        } else {
+            int topPadding = grid.allAppsTopPadding;
+            if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get() && !grid.isTablet) {
+                topPadding += getResources().getDimensionPixelSize(
+                        R.dimen.all_apps_additional_top_padding_floating_search);
+            }
+            setPadding(grid.allAppsLeftRightMargin, topPadding, grid.allAppsLeftRightMargin, 0);
+        }
+
+        InsettableFrameLayout.dispatchInsets(this, insets);
+    }
+
+    /**
+     * Returns a padding in case a scrim is shown on the bottom of the view and a padding is needed.
+     */
+    protected int computeNavBarScrimHeight(WindowInsets insets) {
+        return 0;
+    }
+
+    /**
+     * Returns the current height of nav bar scrim
+     */
+    public int getNavBarScrimHeight() {
+        return mNavBarScrimHeight;
+    }
+
+    @Override
+    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
+        mNavBarScrimHeight = computeNavBarScrimHeight(insets);
+        applyAdapterSideAndBottomPaddings(mActivityContext.getDeviceProfile());
+        return super.dispatchApplyWindowInsets(insets);
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+
+        if (mNavBarScrimHeight > 0) {
+            canvas.drawRect(0, getHeight() - mNavBarScrimHeight, getWidth(), getHeight(),
+                    mNavBarScrimPaint);
+        }
+    }
+
+    protected void updateSearchResultsVisibility() {
+        if (isSearching()) {
+            getSearchRecyclerView().setVisibility(VISIBLE);
+            getAppsRecyclerViewContainer().setVisibility(GONE);
+            mHeader.setVisibility(GONE);
+        } else {
+            getSearchRecyclerView().setVisibility(GONE);
+            getAppsRecyclerViewContainer().setVisibility(VISIBLE);
+            mHeader.setVisibility(VISIBLE);
+        }
+        if (mHeader.isSetUp()) {
+            mHeader.setActiveRV(getCurrentPage());
+        }
+    }
+
+    private void applyAdapterSideAndBottomPaddings(DeviceProfile grid) {
+        int bottomPadding = Math.max(mInsets.bottom, mNavBarScrimHeight);
+        mAH.forEach(adapterHolder -> {
+            adapterHolder.mPadding.bottom = bottomPadding;
+            adapterHolder.mPadding.left =
+                    adapterHolder.mPadding.right = grid.allAppsLeftRightPadding;
+            adapterHolder.applyPadding();
+        });
+    }
+
+    private void setDeviceManagementResources() {
+        if (mActivityContext.getStringCache() != null) {
+            Button personalTab = findViewById(R.id.tab_personal);
+            personalTab.setText(mActivityContext.getStringCache().allAppsPersonalTab);
+
+            Button workTab = findViewById(R.id.tab_work);
+            workTab.setText(mActivityContext.getStringCache().allAppsWorkTab);
+        }
+    }
+
+    protected boolean shouldShowTabs() {
+        return mHasWorkApps;
+    }
+
+    // Used by tests only
+    private boolean isDescendantViewVisible(int viewId) {
+        final View view = findViewById(viewId);
+        if (view == null) return false;
+
+        if (!view.isShown()) return false;
+
+        return view.getGlobalVisibleRect(new Rect());
+    }
+
+    @VisibleForTesting
+    public boolean isPersonalTabVisible() {
+        return isDescendantViewVisible(R.id.tab_personal);
+    }
+
+    @VisibleForTesting
+    public boolean isWorkTabVisible() {
+        return isDescendantViewVisible(R.id.tab_work);
+    }
+
+    public AlphabeticalAppsList<T> getSearchResultList() {
+        return mAH.get(SEARCH).mAppsList;
+    }
+
+    public FloatingHeaderView getFloatingHeaderView() {
+        return mHeader;
+    }
+
+    @VisibleForTesting
+    public View getContentView() {
+        return isSearching() ? getSearchRecyclerView() : getAppsRecyclerViewContainer();
+    }
+
+    /** The current page visible in all apps. */
+    public int getCurrentPage() {
+        return isSearching()
+                ? SEARCH
+                : mViewPager == null ? AdapterHolder.MAIN : mViewPager.getNextPage();
+    }
+
+    /** The scroll bar for the active apps recycler view. */
+    public RecyclerViewFastScroller getScrollBar() {
+        AllAppsRecyclerView rv = getActiveAppsRecyclerView();
+        return rv == null ? null : rv.getScrollbar();
+    }
+
+    /**
+     * Adds an update listener to animator that adds springs to the animation.
+     */
+    public void addSpringFromFlingUpdateListener(ValueAnimator animator,
+            float velocity /* release velocity */,
+            float progress /* portion of the distance to travel*/) {
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animator) {
+                float distance = (1 - progress) * getHeight(); // px
+                float settleVelocity = Math.min(0, distance
+                        / (AllAppsTransitionController.INTERP_COEFF * animator.getDuration())
+                        + velocity);
+                absorbSwipeUpVelocity(Math.max(1000, Math.abs(
+                        Math.round(settleVelocity * FLING_VELOCITY_MULTIPLIER))));
+            }
+        });
+    }
+
+    /** Invoked when the container is pulled. */
+    public void onPull(float deltaDistance, float displacement) {
+        absorbPullDeltaDistance(PULL_MULTIPLIER * deltaDistance, PULL_MULTIPLIER * displacement);
+        // Current motion spec is to actually push and not pull
+        // on this surface. However, until EdgeEffect.onPush (b/190612804) is
+        // implemented at view level, we will simply pull
+    }
+
+    @Override
+    public void getDrawingRect(Rect outRect) {
+        super.getDrawingRect(outRect);
+        outRect.offset(0, (int) getTranslationY());
+    }
+
+    @Override
+    public void setTranslationY(float translationY) {
+        super.setTranslationY(translationY);
+        invalidateHeader();
+    }
+
+    public void setScrimView(ScrimView scrimView) {
+        mScrimView = scrimView;
+    }
+
+    @Override
+    public void drawOnScrimWithScale(Canvas canvas, float scale) {
+        boolean isTablet = mActivityContext.getDeviceProfile().isTablet;
+
+        // Draw full background panel for tablets.
+        if (isTablet) {
+            mHeaderPaint.setColor(mBottomSheetBackgroundColor);
+            View panel = (View) mBottomSheetBackground;
+            float translationY = ((View) panel.getParent()).getTranslationY();
+            mTmpRectF.set(panel.getLeft(), panel.getTop() + translationY,
+                    panel.getRight(), panel.getBottom());
+            mTmpPath.reset();
+            mTmpPath.addRoundRect(mTmpRectF, mBottomSheetCornerRadii, Direction.CW);
+            canvas.drawPath(mTmpPath, mHeaderPaint);
+        }
+
+        if (DEBUG_HEADER_PROTECTION) {
+            mHeaderPaint.setColor(Color.MAGENTA);
+            mHeaderPaint.setAlpha(255);
+        } else {
+            mHeaderPaint.setColor(mHeaderColor);
+            mHeaderPaint.setAlpha((int) (getAlpha() * Color.alpha(mHeaderColor)));
+        }
+        if (mHeaderPaint.getColor() == mScrimColor || mHeaderPaint.getColor() == 0) {
+            return;
+        }
+        final float offset = (getVisibleContainerView().getHeight() * (1 - scale) / 2);
+        final float bottom =
+                scale * (getHeaderBottom() + getVisibleContainerView().getPaddingTop()) + offset;
+        FloatingHeaderView headerView = getFloatingHeaderView();
+        if (isTablet) {
+            // Start adding header protection if search bar or tabs will attach to the top.
+            if (!FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get() || mUsingTabs) {
+                View panel = (View) mBottomSheetBackground;
+                float translationY = ((View) panel.getParent()).getTranslationY();
+                mTmpRectF.set(panel.getLeft(), panel.getTop() + translationY, panel.getRight(),
+                        bottom);
+                mTmpPath.reset();
+                mTmpPath.addRoundRect(mTmpRectF, mBottomSheetCornerRadii, Direction.CW);
+                canvas.drawPath(mTmpPath, mHeaderPaint);
+            }
+        } else {
+            canvas.drawRect(0, 0, canvas.getWidth(), bottom, mHeaderPaint);
+        }
+        int tabsHeight = headerView.getPeripheralProtectionHeight();
+        if (mTabsProtectionAlpha > 0 && tabsHeight != 0) {
+            if (DEBUG_HEADER_PROTECTION) {
+                mHeaderPaint.setColor(Color.BLUE);
+                mHeaderPaint.setAlpha(255);
+            } else {
+                mHeaderPaint.setAlpha((int) (getAlpha() * mTabsProtectionAlpha));
+            }
+            int left = 0;
+            int right = canvas.getWidth();
+            if (isTablet) {
+                left = mBottomSheetBackground.getLeft();
+                right = mBottomSheetBackground.getRight();
+            }
+            canvas.drawRect(left, bottom, right, bottom + tabsHeight, mHeaderPaint);
+        }
+    }
+
+    /**
+     * redraws header protection
+     */
+    public void invalidateHeader() {
+        if (mScrimView != null) {
+            mScrimView.invalidate();
+        }
+    }
+
+    /** Returns the position of the bottom edge of the header */
+    public int getHeaderBottom() {
+        int bottom = (int) getTranslationY() + mHeader.getClipTop();
+        if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+            if (mActivityContext.getDeviceProfile().isTablet) {
+                return bottom + mBottomSheetBackground.getTop();
+            }
+            return bottom;
+        }
+        return bottom + mHeader.getTop();
+    }
+
+    /**
+     * Returns a view that denotes the visible part of all apps container view.
+     */
+    public View getVisibleContainerView() {
+        return mActivityContext.getDeviceProfile().isTablet ? mBottomSheetBackground : this;
+    }
+
+    protected void onInitializeRecyclerView(RecyclerView rv) {
+        rv.addOnScrollListener(mScrollListener);
+    }
+
+    /** Holds a {@link BaseAllAppsAdapter} and related fields. */
+    public class AdapterHolder {
+        public static final int MAIN = 0;
+        public static final int WORK = 1;
+        public static final int SEARCH = 2;
+
+        private final int mType;
+        public final BaseAllAppsAdapter<T> mAdapter;
+        final RecyclerView.LayoutManager mLayoutManager;
+        final AlphabeticalAppsList<T> mAppsList;
+        final Rect mPadding = new Rect();
+        AllAppsRecyclerView mRecyclerView;
+
+        AdapterHolder(int type, AlphabeticalAppsList<T> appsList) {
+            mType = type;
+            mAppsList = appsList;
+            mAdapter = createAdapter(mAppsList);
+            mAppsList.setAdapter(mAdapter);
+            mLayoutManager = mAdapter.getLayoutManager();
+        }
+
+        void setup(@NonNull View rv, @Nullable Predicate<ItemInfo> matcher) {
+            mAppsList.updateItemFilter(matcher);
+            mRecyclerView = (AllAppsRecyclerView) rv;
+            mRecyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
+            mRecyclerView.setApps(mAppsList);
+            mRecyclerView.setLayoutManager(mLayoutManager);
+            mRecyclerView.setAdapter(mAdapter);
+            mRecyclerView.setHasFixedSize(true);
+            // No animations will occur when changes occur to the items in this RecyclerView.
+            mRecyclerView.setItemAnimator(null);
+            onInitializeRecyclerView(mRecyclerView);
+            FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(mRecyclerView);
+            mRecyclerView.addItemDecoration(focusedItemDecorator);
+            mAdapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
+            applyPadding();
+        }
+
+        void applyPadding() {
+            if (mRecyclerView != null) {
+                int bottomOffset = 0;
+                if (isWork() && mWorkManager.getWorkModeSwitch() != null) {
+                    bottomOffset = mInsets.bottom + mWorkManager.getWorkModeSwitch().getHeight();
+                }
+                mRecyclerView.setPadding(mPadding.left, mPadding.top, mPadding.right,
+                        mPadding.bottom + bottomOffset);
+            }
+        }
+
+        private boolean isWork() {
+            return mType == WORK;
+        }
+
+        private boolean isSearch() {
+            return mType == SEARCH;
+        }
+    }
 }
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 63e6d13..866932a 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -21,6 +21,7 @@
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 
+import androidx.annotation.Px;
 import androidx.core.view.accessibility.AccessibilityEventCompat;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
 import androidx.core.view.accessibility.AccessibilityRecordCompat;
@@ -28,6 +29,7 @@
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.recyclerview.widget.RecyclerView.Adapter;
 
+import com.android.launcher3.allapps.search.SearchAdapterProvider;
 import com.android.launcher3.util.ScrollableLayoutManager;
 import com.android.launcher3.views.ActivityContext;
 
@@ -72,8 +74,8 @@
 
 
     public AllAppsGridAdapter(T activityContext, LayoutInflater inflater,
-            AlphabeticalAppsList apps, BaseAdapterProvider[] adapterProviders) {
-        super(activityContext, inflater, apps, adapterProviders);
+            AlphabeticalAppsList apps, SearchAdapterProvider<?> adapterProvider) {
+        super(activityContext, inflater, apps, adapterProvider);
         mGridLayoutMgr = new AppsGridLayoutManager(mActivityContext);
         mGridLayoutMgr.setSpanSizeLookup(new GridSpanSizer());
         setAppsPerRow(activityContext.getDeviceProfile().numShownAllAppsColumns);
@@ -144,6 +146,19 @@
         }
 
         /**
+         * We need to extend all apps' RecyclerView's bottom by 5% of view height to ensure extra
+         * roll(s) of app icons is rendered at the bottom, so that they can fill the bottom gap
+         * created during predictive back's scale animation from all apps to home.
+         */
+        @Override
+        protected void calculateExtraLayoutSpace(RecyclerView.State state, int[] extraLayoutSpace) {
+            super.calculateExtraLayoutSpace(state, extraLayoutSpace);
+            @Px int extraSpacePx = (int) (getHeight()
+                    * (1 - AllAppsTransitionController.SWIPE_ALL_APPS_TO_HOME_MIN_SCALE) / 2);
+            extraLayoutSpace[1] = Math.max(extraLayoutSpace[1], extraSpacePx);
+        }
+
+        /**
          * Returns the number of rows before {@param adapterPosition}, including this position
          * which should not be counted towards the collection info.
          */
@@ -181,11 +196,9 @@
     public void setAppsPerRow(int appsPerRow) {
         mAppsPerRow = appsPerRow;
         int totalSpans = mAppsPerRow;
-        for (BaseAdapterProvider adapterProvider : mAdapterProviders) {
-            for (int itemPerRow : adapterProvider.getSupportedItemsPerRowArray()) {
-                if (totalSpans % itemPerRow != 0) {
-                    totalSpans *= itemPerRow;
-                }
+        for (int itemPerRow : mAdapterProvider.getSupportedItemsPerRowArray()) {
+            if (totalSpans % itemPerRow != 0) {
+                totalSpans *= itemPerRow;
             }
         }
         mGridLayoutMgr.setSpanCount(totalSpans);
@@ -212,9 +225,8 @@
             if (isIconViewType(viewType)) {
                 return totalSpans / mAppsPerRow;
             } else {
-                BaseAdapterProvider adapterProvider = getAdapterProvider(viewType);
-                if (adapterProvider != null) {
-                    return totalSpans / adapterProvider.getItemsPerRow(viewType, mAppsPerRow);
+                if (mAdapterProvider.isViewSupported(viewType)) {
+                    return totalSpans / mAdapterProvider.getItemsPerRow(viewType, mAppsPerRow);
                 }
 
                 // Section breaks span the full width
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index d308fcb..6b45fe6 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -17,11 +17,15 @@
 
 import static com.android.launcher3.logger.LauncherAtom.ContainerInfo;
 import static com.android.launcher3.logger.LauncherAtom.SearchResultContainer;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_SCROLLED_DOWN;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_PERSONAL_SCROLLED_DOWN;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_PERSONAL_SCROLLED_UP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_SCROLLED_UNKNOWN_DIRECTION;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_SCROLLED_UP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_SEARCH_SCROLLED_DOWN;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_SEARCH_SCROLLED_UP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_VERTICAL_SWIPE_END;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORK_FAB_BUTTON_COLLAPSE;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORK_FAB_BUTTON_EXTEND;
 import static com.android.launcher3.util.LogConfig.SEARCH_LOGGING;
 
 import android.content.Context;
@@ -257,12 +261,19 @@
         }
     }
 
+    @Override
     public int getScrollBarTop() {
         return ActivityContext.lookupContext(getContext()).getAppsView().isSearchSupported()
                 ? getResources().getDimensionPixelOffset(R.dimen.all_apps_header_top_padding)
                 : 0;
     }
 
+    @Override
+    public int getScrollBarMarginBottom() {
+        return getRootWindowInsets() == null ? 0
+                : getRootWindowInsets().getSystemWindowInsetBottom();
+    }
+
     public RecyclerViewFastScroller getScrollbar() {
         return mScrollbar;
     }
@@ -275,17 +286,37 @@
     private void logCumulativeVerticalScroll() {
         ActivityContext context = ActivityContext.lookupContext(getContext());
         StatsLogManager mgr = context.getStatsLogManager();
-        ExtendedEditText editText = context.getAppsView().getSearchUiManager().getEditText();
+        ActivityAllAppsContainerView<?> appsView = context.getAppsView();
+        ExtendedEditText editText = appsView.getSearchUiManager().getEditText();
         ContainerInfo containerInfo = ContainerInfo.newBuilder().setSearchResultContainer(
                 SearchResultContainer
                         .newBuilder()
                         .setQueryLength((editText == null) ? -1 : editText.length())).build();
-
-        // mCumulativeVerticalScroll == 0 when user comes back to original position, we don't
-        // know the direction of scrolling.
-        mgr.logger().withContainerInfo(containerInfo).log(
-                mCumulativeVerticalScroll == 0 ? LAUNCHER_ALLAPPS_SCROLLED_UNKNOWN_DIRECTION
-                        : (mCumulativeVerticalScroll > 0) ? LAUNCHER_ALLAPPS_SCROLLED_DOWN
-                                : LAUNCHER_ALLAPPS_SCROLLED_UP);
+        if (mCumulativeVerticalScroll == 0) {
+            // mCumulativeVerticalScroll == 0 when user comes back to original position, we
+            // don't know the direction of scrolling.
+            mgr.logger().withContainerInfo(containerInfo).log(
+                    LAUNCHER_ALLAPPS_SCROLLED_UNKNOWN_DIRECTION);
+            return;
+        } else if (appsView.isSearching()) {
+            // In search results page
+            mgr.logger().withContainerInfo(containerInfo).log((mCumulativeVerticalScroll > 0)
+                    ? LAUNCHER_ALLAPPS_SEARCH_SCROLLED_DOWN
+                    : LAUNCHER_ALLAPPS_SEARCH_SCROLLED_UP);
+            return;
+        } else if (appsView.mViewPager != null) {
+            int currentPage = appsView.mViewPager.getCurrentPage();
+            if (currentPage == ActivityAllAppsContainerView.AdapterHolder.WORK) {
+                // In work A-Z list
+                mgr.logger().withContainerInfo(containerInfo).log((mCumulativeVerticalScroll > 0)
+                        ? LAUNCHER_WORK_FAB_BUTTON_COLLAPSE
+                        : LAUNCHER_WORK_FAB_BUTTON_EXTEND);
+                return;
+            }
+        }
+        // In personal A-Z list
+        mgr.logger().withContainerInfo(containerInfo).log((mCumulativeVerticalScroll > 0)
+                ? LAUNCHER_ALLAPPS_PERSONAL_SCROLLED_DOWN
+                : LAUNCHER_ALLAPPS_PERSONAL_SCROLLED_UP);
     }
 }
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 9930abe..f7b0d96 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.allapps;
 
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.ALL_APPS_CONTENT;
@@ -24,6 +25,9 @@
 import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
+import static com.android.launcher3.util.SystemUiController.FLAG_DARK_NAV;
+import static com.android.launcher3.util.SystemUiController.FLAG_LIGHT_NAV;
+import static com.android.launcher3.util.SystemUiController.UI_STATE_ALL_APPS;
 
 import android.animation.Animator;
 import android.animation.Animator.AnimatorListener;
@@ -31,13 +35,21 @@
 import android.util.FloatProperty;
 import android.view.HapticFeedbackConstants;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
 import android.view.animation.Interpolator;
 
+import androidx.annotation.FloatRange;
+import androidx.annotation.Nullable;
+
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
+import com.android.launcher3.R;
+import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.AnimatorListeners;
+import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.anim.PropertySetter;
 import com.android.launcher3.statemanager.StateManager.StateHandler;
@@ -45,6 +57,7 @@
 import com.android.launcher3.util.MultiPropertyFactory;
 import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
 import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.ScrimView;
 
 /**
@@ -61,6 +74,10 @@
         implements StateHandler<LauncherState>, OnDeviceProfileChangeListener {
     // This constant should match the second derivative of the animator interpolator.
     public static final float INTERP_COEFF = 1.7f;
+    public static final float SWIPE_ALL_APPS_TO_HOME_MIN_SCALE = 0.9f;
+    private static final int REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS = 200;
+
+    private static final float NAV_BAR_COLOR_FORCE_UPDATE_THRESHOLD = 0.1f;
 
     public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PROGRESS =
             new FloatProperty<AllAppsTransitionController>("allAppsProgress") {
@@ -139,6 +156,9 @@
     private ActivityAllAppsContainerView<Launcher> mAppsView;
 
     private final Launcher mLauncher;
+    private final AnimatedFloat mAllAppScale = new AnimatedFloat(this::onScaleProgressChanged);
+    private final int mNavScrimFlag;
+
     private boolean mIsVerticalLayout;
 
     // Whether this class should take care of closing the keyboard.
@@ -160,13 +180,18 @@
 
     private boolean mIsTablet;
 
+    private boolean mHasScaleEffect;
+
     public AllAppsTransitionController(Launcher l) {
         mLauncher = l;
         DeviceProfile dp = mLauncher.getDeviceProfile();
-        setShiftRange(dp.allAppsShiftRange);
         mProgress = 1f;
         mIsVerticalLayout = dp.isVerticalBarLayout();
         mIsTablet = dp.isTablet;
+        mNavScrimFlag = Themes.getAttrBoolean(l, R.attr.isMainColorDark)
+                ? FLAG_DARK_NAV : FLAG_LIGHT_NAV;
+
+        setShiftRange(dp.allAppsShiftRange);
         mLauncher.addOnDeviceProfileChangeListener(this);
     }
 
@@ -199,6 +224,11 @@
         mProgress = progress;
         getAppsViewProgressTranslationY().setValue(mProgress * mShiftRange);
         mLauncher.onAllAppsTransition(1 - progress);
+
+        boolean hasScrim = progress < NAV_BAR_COLOR_FORCE_UPDATE_THRESHOLD
+                && mLauncher.getAppsView().getNavBarScrimHeight() > 0;
+        mLauncher.getSystemUiController().updateUiState(
+                UI_STATE_ALL_APPS, hasScrim ? mNavScrimFlag : 0);
     }
 
     public float getProgress() {
@@ -232,6 +262,62 @@
         onProgressAnimationEnd();
     }
 
+    @Override
+    public void onBackProgressed(
+            LauncherState toState, @FloatRange(from = 0.0, to = 1.0) float backProgress) {
+        if (!mLauncher.isInState(ALL_APPS) || !NORMAL.equals(toState)) {
+            return;
+        }
+
+        float deceleratedProgress =
+                Interpolators.PREDICTIVE_BACK_DECELERATED_EASE.getInterpolation(backProgress);
+        float scaleProgress = SWIPE_ALL_APPS_TO_HOME_MIN_SCALE
+                + (1 - SWIPE_ALL_APPS_TO_HOME_MIN_SCALE) * (1 - deceleratedProgress);
+
+        mAllAppScale.updateValue(scaleProgress);
+    }
+
+    @Override
+    public void onBackCancelled(LauncherState toState) {
+        if (!mLauncher.isInState(ALL_APPS) || !NORMAL.equals(toState)) {
+            return;
+        }
+
+        // TODO: once ag/20649618 is picked into tm-qpr, we don't need to animate back on cancel
+        // swipe because framework will do that for us in {@link #onBackProgressed}.
+        animateAllAppsToNoScale();
+    }
+
+    private void onScaleProgressChanged() {
+        final float scaleProgress = mAllAppScale.value;
+        SCALE_PROPERTY.set(mLauncher.getAppsView(), scaleProgress);
+        mLauncher.getScrimView().setScrimHeaderScale(scaleProgress);
+
+        AllAppsRecyclerView rv = mLauncher.getAppsView().getActiveRecyclerView();
+        if (rv != null && rv.getScrollbar() != null) {
+            rv.getScrollbar().setVisibility(scaleProgress < 1f ? View.INVISIBLE : View.VISIBLE);
+        }
+
+        // Disable view clipping from all apps' RecyclerView up to all apps view during scale
+        // animation, and vice versa. The goal is to display extra roll(s) app icons (rendered in
+        // {@link AppsGridLayoutManager#calculateExtraLayoutSpace}) during scale animation.
+        boolean hasScaleEffect = scaleProgress < 1f;
+        if (hasScaleEffect != mHasScaleEffect) {
+            mHasScaleEffect = hasScaleEffect;
+            if (mHasScaleEffect) {
+                setClipChildrenOnViewTree(rv, mLauncher.getAppsView(), false);
+            } else {
+                restoreClipChildrenOnViewTree(rv, mLauncher.getAppsView());
+            }
+        }
+    }
+
+    private void animateAllAppsToNoScale() {
+        mAllAppScale.animateToValue(1f)
+                .setDuration(REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS)
+                .start();
+    }
+
     /**
      * Creates an animation which updates the vertical transition progress and updates all the
      * dependent UI using various animation events
@@ -258,6 +344,8 @@
                 if (config.userControlled && success && mShouldControlKeyboard) {
                     mLauncher.getAppsView().getSearchUiManager().getEditText().hideKeyboard();
                 }
+
+                mAllAppScale.updateValue(1f);
             });
         }
 
@@ -325,6 +413,79 @@
     }
 
     /**
+     * Recursively call {@link ViewGroup#setClipChildren(boolean)} from {@link View} to ts parent
+     * (direct or indirect) inclusive. This method will also save the old clipChildren value on each
+     * view with {@link View#setTag(int, Object)}, which can be restored in
+     * {@link #restoreClipChildrenOnViewTree(View, ViewParent)}.
+     *
+     * Note that if parent is null or not a parent of the view, this method will be applied all the
+     * way to root view.
+     *
+     * @param v child view
+     * @param parent direct or indirect parent of child view
+     * @param clipChildren whether we should clip children
+     */
+    private static void setClipChildrenOnViewTree(
+            @Nullable View v,
+            @Nullable ViewParent parent,
+            boolean clipChildren) {
+        if (v == null) {
+            return;
+        }
+
+        if (v instanceof ViewGroup) {
+            ViewGroup viewGroup = (ViewGroup) v;
+            boolean oldClipChildren = viewGroup.getClipChildren();
+            if (oldClipChildren != clipChildren) {
+                v.setTag(R.id.saved_clip_children_tag_id, oldClipChildren);
+                viewGroup.setClipChildren(clipChildren);
+            }
+        }
+
+        if (v == parent) {
+            return;
+        }
+
+        if (v.getParent() instanceof View) {
+            setClipChildrenOnViewTree((View) v.getParent(), parent, clipChildren);
+        }
+    }
+
+    /**
+     * Recursively call {@link ViewGroup#setClipChildren(boolean)} to restore clip children value
+     * set in {@link #setClipChildrenOnViewTree(View, ViewParent, boolean)} on view to its parent
+     * (direct or indirect) inclusive.
+     *
+     * Note that if parent is null or not a parent of the view, this method will be applied all the
+     * way to root view.
+     *
+     * @param v child view
+     * @param parent direct or indirect parent of child view
+     */
+    private static void restoreClipChildrenOnViewTree(
+            @Nullable View v, @Nullable ViewParent parent) {
+        if (v == null) {
+            return;
+        }
+        if (v instanceof ViewGroup) {
+            ViewGroup viewGroup = (ViewGroup) v;
+            Object viewTag = viewGroup.getTag(R.id.saved_clip_children_tag_id);
+            if (viewTag instanceof Boolean) {
+                viewGroup.setClipChildren((boolean) viewTag);
+                viewGroup.setTag(R.id.saved_clip_children_tag_id, null);
+            }
+        }
+
+        if (v == parent) {
+            return;
+        }
+
+        if (v.getParent() instanceof View) {
+            restoreClipChildrenOnViewTree((View) v.getParent(), parent);
+        }
+    }
+
+    /**
      * Updates the total scroll range but does not update the UI.
      */
     public void setShiftRange(float shiftRange) {
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index fc1b830..29767bf 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -239,23 +239,24 @@
             mAdapterItems.addAll(mSearchResults);
         } else {
             int position = 0;
+            boolean addApps = true;
             if (mWorkProviderManager != null) {
                 position += mWorkProviderManager.addWorkItems(mAdapterItems);
-                if (!mWorkProviderManager.shouldShowWorkApps()) {
-                    return;
-                }
+                addApps = mWorkProviderManager.shouldShowWorkApps();
             }
-            String lastSectionName = null;
-            for (AppInfo info : mApps) {
-                mAdapterItems.add(AdapterItem.asApp(info));
+            if (addApps) {
+                String lastSectionName = null;
+                for (AppInfo info : mApps) {
+                    mAdapterItems.add(AdapterItem.asApp(info));
 
-                String sectionName = info.sectionName;
-                // Create a new section if the section names do not match
-                if (!sectionName.equals(lastSectionName)) {
-                    lastSectionName = sectionName;
-                    mFastScrollerSections.add(new FastScrollSectionInfo(sectionName, position));
+                    String sectionName = info.sectionName;
+                    // Create a new section if the section names do not match
+                    if (!sectionName.equals(lastSectionName)) {
+                        lastSectionName = sectionName;
+                        mFastScrollerSections.add(new FastScrollSectionInfo(sectionName, position));
+                    }
+                    position++;
                 }
-                position++;
             }
         }
         mAccessibilityResultsCount = (int) mAdapterItems.stream()
diff --git a/src/com/android/launcher3/allapps/BaseAdapterProvider.java b/src/com/android/launcher3/allapps/BaseAdapterProvider.java
deleted file mode 100644
index 308294c..0000000
--- a/src/com/android/launcher3/allapps/BaseAdapterProvider.java
+++ /dev/null
@@ -1,56 +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.allapps;
-
-import android.view.LayoutInflater;
-import android.view.ViewGroup;
-
-/**
- * A UI expansion wrapper providing for providing dynamic recyclerview items
- */
-public abstract class BaseAdapterProvider {
-
-    /**
-     * Returns whether or not viewType can be handled by searchProvider
-     */
-    public abstract boolean isViewSupported(int viewType);
-
-    /**
-     * Called from RecyclerView.Adapter#onBindViewHolder
-     */
-    public abstract void onBindView(AllAppsGridAdapter.ViewHolder holder, int position);
-
-    /**
-     * Called from RecyclerView.Adapter#onCreateViewHolder
-     */
-    public abstract AllAppsGridAdapter.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater,
-            ViewGroup parent, int viewType);
-
-    /**
-     * Returns supported item per row combinations supported
-     */
-    public int[] getSupportedItemsPerRowArray() {
-        return new int[]{};
-    }
-
-    /**
-     * Returns how many cells a view should span
-     */
-    public int getItemsPerRow(int viewType, int appsPerRow) {
-        return appsPerRow;
-    }
-
-}
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
index 42f8b0c..7040de5 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
@@ -27,18 +27,16 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 
-import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.R;
+import com.android.launcher3.allapps.search.SearchAdapterProvider;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.views.ActivityContext;
 
-import java.util.Arrays;
-
 /**
  * Adapter for all the apps.
  *
@@ -65,8 +63,7 @@
     public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
     public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON;
 
-
-    protected final BaseAdapterProvider[] mAdapterProviders;
+    protected final SearchAdapterProvider<?> mAdapterProvider;
 
     /**
      * ViewHolder for each icon.
@@ -146,7 +143,7 @@
     private final int mExtraHeight;
 
     public BaseAllAppsAdapter(T activityContext, LayoutInflater inflater,
-            AlphabeticalAppsList<T> apps, BaseAdapterProvider[] adapterProviders) {
+            AlphabeticalAppsList<T> apps, SearchAdapterProvider<?> adapterProvider) {
         Resources res = activityContext.getResources();
         mActivityContext = activityContext;
         mApps = apps;
@@ -154,7 +151,7 @@
 
         mOnIconClickListener = mActivityContext.getItemOnClickListener();
 
-        mAdapterProviders = adapterProviders;
+        mAdapterProvider = adapterProvider;
         mExtraHeight = res.getDimensionPixelSize(R.dimen.all_apps_height_extra);
     }
 
@@ -216,9 +213,8 @@
                 return new ViewHolder(mLayoutInflater.inflate(
                         R.layout.work_apps_paused, parent, false));
             default:
-                BaseAdapterProvider adapterProvider = getAdapterProvider(viewType);
-                if (adapterProvider != null) {
-                    return adapterProvider.onCreateViewHolder(mLayoutInflater, parent, viewType);
+                if (mAdapterProvider.isViewSupported(viewType)) {
+                    return mAdapterProvider.onCreateViewHolder(mLayoutInflater, parent, viewType);
                 }
                 throw new RuntimeException("Unexpected view type" + viewType);
         }
@@ -250,19 +246,13 @@
                 ((WorkEduCard) holder.itemView).setPosition(position);
                 break;
             default:
-                BaseAdapterProvider adapterProvider = getAdapterProvider(holder.getItemViewType());
-                if (adapterProvider != null) {
-                    adapterProvider.onBindView(holder, position);
+                if (mAdapterProvider.isViewSupported(holder.getItemViewType())) {
+                    mAdapterProvider.onBindView(holder, position);
                 }
         }
     }
 
     @Override
-    public void onViewRecycled(@NonNull ViewHolder holder) {
-        super.onViewRecycled(holder);
-    }
-
-    @Override
     public boolean onFailedToRecycleView(ViewHolder holder) {
         // Always recycle and we will reset the view when it is bound
         return true;
@@ -283,10 +273,4 @@
         return (viewType & viewTypeMask) != 0;
     }
 
-    @Nullable
-    protected BaseAdapterProvider getAdapterProvider(int viewType) {
-        return Arrays.stream(mAdapterProviders).filter(
-                adapterProvider -> adapterProvider.isViewSupported(viewType)).findFirst().orElse(
-                null);
-    }
 }
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
deleted file mode 100644
index ca08164..0000000
--- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
+++ /dev/null
@@ -1,989 +0,0 @@
-/*
- * Copyright (C) 2015 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 static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_COUNT;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Path.Direction;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.os.Process;
-import android.os.UserManager;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.SparseArray;
-import android.util.TypedValue;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.WindowInsets;
-import android.widget.Button;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import androidx.core.graphics.ColorUtils;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
-import com.android.launcher3.DragSource;
-import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.Insettable;
-import com.android.launcher3.InsettableFrameLayout;
-import com.android.launcher3.LauncherPrefs;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider;
-import com.android.launcher3.allapps.search.SearchAdapterProvider;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.keyboard.FocusedItemDecorator;
-import com.android.launcher3.model.StringCache;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.Themes;
-import com.android.launcher3.views.ActivityContext;
-import com.android.launcher3.views.BaseDragLayer;
-import com.android.launcher3.views.RecyclerViewFastScroller;
-import com.android.launcher3.views.ScrimView;
-import com.android.launcher3.views.SpringRelativeLayout;
-import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePageChangedListener;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Predicate;
-import java.util.stream.Stream;
-
-/**
- * Base all apps view container.
- *
- * @param <T> Type of context inflating all apps.
- */
-public abstract class BaseAllAppsContainerView<T extends Context & ActivityContext>
-        extends SpringRelativeLayout implements DragSource, Insettable,
-        OnDeviceProfileChangeListener, OnActivePageChangedListener,
-        ScrimView.ScrimDrawingController {
-
-    protected static final String BUNDLE_KEY_CURRENT_PAGE = "launcher.allapps.current_page";
-
-    public static final float PULL_MULTIPLIER = .02f;
-    public static final float FLING_VELOCITY_MULTIPLIER = 1200f;
-
-    // Render the header protection at all times to debug clipping issues.
-    private static final boolean DEBUG_HEADER_PROTECTION = false;
-
-    private final Paint mHeaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-    private final Rect mInsets = new Rect();
-
-    /** Context of an activity or window that is inflating this container. */
-    protected final T mActivityContext;
-    protected final List<AdapterHolder> mAH;
-    protected final Predicate<ItemInfo> mPersonalMatcher = ItemInfoMatcher.ofUser(
-            Process.myUserHandle());
-    private final AllAppsStore mAllAppsStore = new AllAppsStore();
-
-    private final RecyclerView.OnScrollListener mScrollListener =
-            new RecyclerView.OnScrollListener() {
-                @Override
-                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
-                    updateHeaderScroll(recyclerView.computeVerticalScrollOffset());
-                }
-            };
-
-    protected final WorkProfileManager mWorkManager;
-
-    private final Paint mNavBarScrimPaint;
-    private int mNavBarScrimHeight = 0;
-
-    protected AllAppsPagedView mViewPager;
-    private SearchRecyclerView mSearchRecyclerView;
-    private SearchAdapterProvider<?> mMainAdapterProvider;
-
-    protected FloatingHeaderView mHeader;
-    protected View mBottomSheetBackground;
-    private View mBottomSheetHandleArea;
-
-    /**
-     * View that defines the search box. Result is rendered inside {@link #mSearchRecyclerView}.
-     */
-    protected View mSearchContainer;
-    protected SearchUiManager mSearchUiManager;
-
-    protected boolean mUsingTabs;
-    private boolean mHasWorkApps;
-
-    protected RecyclerViewFastScroller mTouchHandler;
-    protected final Point mFastScrollerOffset = new Point();
-
-    protected final int mScrimColor;
-    private final int mHeaderProtectionColor;
-    protected final float mHeaderThreshold;
-    private final Path mTmpPath = new Path();
-    private final RectF mTmpRectF = new RectF();
-    private float[] mBottomSheetCornerRadii;
-    private ScrimView mScrimView;
-    private int mHeaderColor;
-    private int mBottomSheetBackgroundColor;
-    private int mTabsProtectionAlpha;
-
-    protected BaseAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        mActivityContext = ActivityContext.lookupContext(context);
-
-        mScrimColor = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
-        mHeaderThreshold = getResources().getDimensionPixelSize(
-                R.dimen.dynamic_grid_cell_border_spacing);
-        mHeaderProtectionColor = Themes.getAttrColor(context, R.attr.allappsHeaderProtectionColor);
-
-        mWorkManager = new WorkProfileManager(
-                mActivityContext.getSystemService(UserManager.class),
-                this, LauncherPrefs.getPrefs(mActivityContext));
-        mAH = Arrays.asList(null, null, null);
-        mNavBarScrimPaint = new Paint();
-        mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
-
-        mAllAppsStore.addUpdateListener(this::onAppsUpdated);
-        mActivityContext.addOnDeviceProfileChangeListener(this);
-
-        // This is a focus listener that proxies focus from a view into the list view.  This is to
-        // work around the search box from getting first focus and showing the cursor.
-        setOnFocusChangeListener((v, hasFocus) -> {
-            if (hasFocus && getActiveRecyclerView() != null) {
-                getActiveRecyclerView().requestFocus();
-            }
-        });
-        initContent();
-    }
-
-    /**
-     * Initializes the view hierarchy and internal variables. Any initialization which actually uses
-     * these members should be done in {@link #onFinishInflate()}.
-     * In terms of subclass initialization, the following would be parallel order for activity:
-     *   initContent -> onPreCreate
-     *   constructor/init -> onCreate
-     *   onFinishInflate -> onPostCreate
-     */
-    protected void initContent() {
-        mMainAdapterProvider = createMainAdapterProvider();
-
-        mAH.set(AdapterHolder.MAIN, new AdapterHolder(AdapterHolder.MAIN));
-        mAH.set(AdapterHolder.WORK, new AdapterHolder(AdapterHolder.WORK));
-        mAH.set(AdapterHolder.SEARCH, new AdapterHolder(AdapterHolder.SEARCH));
-
-        getLayoutInflater().inflate(R.layout.all_apps_content, this);
-        mHeader = findViewById(R.id.all_apps_header);
-        mBottomSheetBackground = findViewById(R.id.bottom_sheet_background);
-        mBottomSheetHandleArea = findViewById(R.id.bottom_sheet_handle_area);
-        mSearchRecyclerView = findViewById(R.id.search_results_list_view);
-
-        // Add the search box next to the header
-        mSearchContainer = inflateSearchBox();
-        addView(mSearchContainer, indexOfChild(mHeader) + 1);
-        mSearchUiManager = (SearchUiManager) mSearchContainer;
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-
-        mAH.get(AdapterHolder.SEARCH).setup(mSearchRecyclerView,
-                /* Filter out A-Z apps */ itemInfo -> false);
-        rebindAdapters(true /* force */);
-        float cornerRadius = Themes.getDialogCornerRadius(getContext());
-        mBottomSheetCornerRadii = new float[]{
-                cornerRadius,
-                cornerRadius, // Top left radius in px
-                cornerRadius,
-                cornerRadius, // Top right radius in px
-                0,
-                0, // Bottom right
-                0,
-                0 // Bottom left
-        };
-        final TypedValue value = new TypedValue();
-        getContext().getTheme().resolveAttribute(android.R.attr.colorBackground, value, true);
-        mBottomSheetBackgroundColor = value.data;
-        updateBackground(mActivityContext.getDeviceProfile());
-    }
-
-    /**
-     * Inflates the search box
-     */
-    protected View inflateSearchBox() {
-        return getLayoutInflater().inflate(R.layout.search_container_all_apps, this, false);
-    }
-
-    /** Creates the adapter provider for the main section. */
-    protected SearchAdapterProvider<?> createMainAdapterProvider() {
-        return new DefaultSearchAdapterProvider(mActivityContext);
-    }
-
-    /** The adapter provider for the main section. */
-    public final SearchAdapterProvider<?> getMainAdapterProvider() {
-        return mMainAdapterProvider;
-    }
-
-    @Override
-    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> sparseArray) {
-        try {
-            // Many slice view id is not properly assigned, and hence throws null
-            // pointer exception in the underneath method. Catching the exception
-            // simply doesn't restore these slice views. This doesn't have any
-            // user visible effect because because we query them again.
-            super.dispatchRestoreInstanceState(sparseArray);
-        } catch (Exception e) {
-            Log.e("AllAppsContainerView", "restoreInstanceState viewId = 0", e);
-        }
-
-        Bundle state = (Bundle) sparseArray.get(R.id.work_tab_state_id, null);
-        if (state != null) {
-            int currentPage = state.getInt(BUNDLE_KEY_CURRENT_PAGE, 0);
-            if (currentPage == AdapterHolder.WORK && mViewPager != null) {
-                mViewPager.setCurrentPage(currentPage);
-                rebindAdapters();
-            } else {
-                reset(true);
-            }
-        }
-    }
-
-    @Override
-    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
-        super.dispatchSaveInstanceState(container);
-        Bundle state = new Bundle();
-        state.putInt(BUNDLE_KEY_CURRENT_PAGE, getCurrentPage());
-        container.put(R.id.work_tab_state_id, state);
-    }
-
-    /**
-     * Sets the long click listener for icons
-     */
-    public void setOnIconLongClickListener(OnLongClickListener listener) {
-        for (AdapterHolder holder : mAH) {
-            holder.mAdapter.setOnIconLongClickListener(listener);
-        }
-    }
-
-    public AllAppsStore getAppsStore() {
-        return mAllAppsStore;
-    }
-
-    public WorkProfileManager getWorkManager() {
-        return mWorkManager;
-    }
-
-    @Override
-    public void onDeviceProfileChanged(DeviceProfile dp) {
-        for (AdapterHolder holder : mAH) {
-            holder.mAdapter.setAppsPerRow(dp.numShownAllAppsColumns);
-            if (holder.mRecyclerView != null) {
-                // Remove all views and clear the pool, while keeping the data same. After this
-                // call, all the viewHolders will be recreated.
-                holder.mRecyclerView.swapAdapter(holder.mRecyclerView.getAdapter(), true);
-                holder.mRecyclerView.getRecycledViewPool().clear();
-            }
-        }
-        updateBackground(dp);
-    }
-
-    protected void updateBackground(DeviceProfile deviceProfile) {
-        mBottomSheetBackground.setVisibility(deviceProfile.isTablet ? View.VISIBLE : View.GONE);
-        // Note: For tablets, the opaque background and header protection are added in drawOnScrim.
-        // For the taskbar entrypoint, the scrim is drawn differently, so a static background is
-        // added in TaskbarAllAppsContainerView and header protection is not yet supported.
-    }
-
-    private void onAppsUpdated() {
-        mHasWorkApps = Stream.of(mAllAppsStore.getApps()).anyMatch(mWorkManager.getMatcher());
-        if (!isSearching()) {
-            rebindAdapters();
-            if (mHasWorkApps) {
-                mWorkManager.reset();
-            }
-        }
-
-        mActivityContext.getStatsLogManager().logger()
-                .withCardinality(mAllAppsStore.getApps().length)
-                .log(LAUNCHER_ALLAPPS_COUNT);
-    }
-
-    /**
-     * Returns whether the view itself will handle the touch event or not.
-     */
-    public boolean shouldContainerScroll(MotionEvent ev) {
-        BaseDragLayer dragLayer = mActivityContext.getDragLayer();
-        // Scroll if not within the container view (e.g. over large-screen scrim).
-        if (!dragLayer.isEventOverView(getVisibleContainerView(), ev)) {
-            return true;
-        }
-        if (dragLayer.isEventOverView(mBottomSheetHandleArea, ev)) {
-            return true;
-        }
-        AllAppsRecyclerView rv = getActiveRecyclerView();
-        if (rv == null) {
-            return true;
-        }
-        if (rv.getScrollbar() != null
-                && rv.getScrollbar().getThumbOffsetY() >= 0
-                && dragLayer.isEventOverView(rv.getScrollbar(), ev)) {
-            return false;
-        }
-        return rv.shouldContainerScroll(ev, dragLayer);
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        // The AllAppsContainerView houses the QSB and is hence visible from the Workspace
-        // Overview states. We shouldn't intercept for the scrubber in these cases.
-        if (!isInAllApps()) {
-            mTouchHandler = null;
-            return false;
-        }
-
-        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            AllAppsRecyclerView rv = getActiveRecyclerView();
-            if (rv != null && rv.getScrollbar() != null
-                    && rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(), mFastScrollerOffset)) {
-                mTouchHandler = rv.getScrollbar();
-            } else {
-                mTouchHandler = null;
-            }
-        }
-        if (mTouchHandler != null) {
-            return mTouchHandler.handleTouchEvent(ev, mFastScrollerOffset);
-        }
-        return false;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        if (!isInAllApps()) {
-            return false;
-        }
-
-        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            AllAppsRecyclerView rv = getActiveRecyclerView();
-            if (rv != null && rv.getScrollbar() != null
-                    && rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(), mFastScrollerOffset)) {
-                mTouchHandler = rv.getScrollbar();
-            } else {
-                mTouchHandler = null;
-
-            }
-        }
-        if (mTouchHandler != null) {
-            mTouchHandler.handleTouchEvent(ev, mFastScrollerOffset);
-            return true;
-        }
-        if (isSearching()
-                && mActivityContext.getDragLayer().isEventOverView(getVisibleContainerView(), ev)) {
-            // if in search state, consume touch event.
-            return true;
-        }
-        return false;
-    }
-
-    /** Description of the container view based on its current state. */
-    public String getDescription() {
-        StringCache cache = mActivityContext.getStringCache();
-        if (mUsingTabs) {
-            if (cache != null) {
-                return isPersonalTab()
-                        ? cache.allAppsPersonalTabAccessibility
-                        : cache.allAppsWorkTabAccessibility;
-            } else {
-                return isPersonalTab()
-                        ? getContext().getString(R.string.all_apps_button_personal_label)
-                        : getContext().getString(R.string.all_apps_button_work_label);
-            }
-        }
-        return getContext().getString(R.string.all_apps_button_label);
-    }
-
-    /** The current active recycler view (A-Z list from one of the profiles, or search results). */
-    public AllAppsRecyclerView getActiveRecyclerView() {
-        if (isSearching()) {
-            return getSearchRecyclerView();
-        }
-        return getActiveAppsRecyclerView();
-    }
-
-    /** The current apps recycler view in the container. */
-    private AllAppsRecyclerView getActiveAppsRecyclerView() {
-        if (!mUsingTabs || isPersonalTab()) {
-            return mAH.get(AdapterHolder.MAIN).mRecyclerView;
-        } else {
-            return mAH.get(AdapterHolder.WORK).mRecyclerView;
-        }
-    }
-
-    /**
-     * The container for A-Z apps (the ViewPager for main+work tabs, or main RV). This is currently
-     * hidden while searching.
-     **/
-    protected View getAppsRecyclerViewContainer() {
-        return mViewPager != null ? mViewPager : findViewById(R.id.apps_list_view);
-    }
-
-    /** The RV for search results, which is hidden while A-Z apps are visible. */
-    public SearchRecyclerView getSearchRecyclerView() {
-        return mSearchRecyclerView;
-    }
-
-    protected boolean isPersonalTab() {
-        return mViewPager == null || mViewPager.getNextPage() == 0;
-    }
-
-    /**
-     * Switches the current page to the provided {@code tab} if tabs are supported, otherwise does
-     * nothing.
-     */
-    public void switchToTab(int tab) {
-        if (mUsingTabs) {
-            mViewPager.setCurrentPage(tab);
-        }
-    }
-
-    public LayoutInflater getLayoutInflater() {
-        return LayoutInflater.from(getContext());
-    }
-
-    /**
-     * Resets the state of AllApps.
-     */
-    public void reset(boolean animate) {
-        for (int i = 0; i < mAH.size(); i++) {
-            if (mAH.get(i).mRecyclerView != null) {
-                mAH.get(i).mRecyclerView.scrollToTop();
-            }
-        }
-        if (isHeaderVisible()) {
-            mHeader.reset(animate);
-        }
-        // Reset the base recycler view after transitioning home.
-        updateHeaderScroll(0);
-    }
-
-    @Override
-    public void onDropCompleted(View target, DragObject d, boolean success) {}
-
-    @Override
-    public void setInsets(Rect insets) {
-        mInsets.set(insets);
-        DeviceProfile grid = mActivityContext.getDeviceProfile();
-
-        applyAdapterSideAndBottomPaddings(grid);
-
-        MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
-        mlp.leftMargin = insets.left;
-        mlp.rightMargin = insets.right;
-        setLayoutParams(mlp);
-
-        if (grid.isVerticalBarLayout()) {
-            setPadding(grid.workspacePadding.left, 0, grid.workspacePadding.right, 0);
-        } else {
-            int topPadding = grid.allAppsTopPadding;
-            if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get() && !grid.isTablet) {
-                topPadding += getResources().getDimensionPixelSize(
-                        R.dimen.all_apps_additional_top_padding_floating_search);
-            }
-            setPadding(grid.allAppsLeftRightMargin, topPadding, grid.allAppsLeftRightMargin, 0);
-        }
-
-        InsettableFrameLayout.dispatchInsets(this, insets);
-    }
-
-    /**
-     * Returns a padding in case a scrim is shown on the bottom of the view and a padding is needed.
-     */
-    protected int getNavBarScrimHeight(WindowInsets insets) {
-        return 0;
-    }
-
-    @Override
-    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
-        mNavBarScrimHeight = getNavBarScrimHeight(insets);
-        applyAdapterSideAndBottomPaddings(mActivityContext.getDeviceProfile());
-        return super.dispatchApplyWindowInsets(insets);
-    }
-
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        super.dispatchDraw(canvas);
-
-        if (mNavBarScrimHeight > 0) {
-            canvas.drawRect(0, getHeight() - mNavBarScrimHeight, getWidth(), getHeight(),
-                    mNavBarScrimPaint);
-        }
-    }
-
-    protected void rebindAdapters() {
-        rebindAdapters(false /* force */);
-    }
-
-    protected void rebindAdapters(boolean force) {
-        updateSearchResultsVisibility();
-
-        boolean showTabs = shouldShowTabs();
-        if (showTabs == mUsingTabs && !force) {
-            return;
-        }
-
-        if (isSearching()) {
-            mUsingTabs = showTabs;
-            mWorkManager.detachWorkModeSwitch();
-            return;
-        }
-
-        // 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.
-        replaceAppsRVContainer(showTabs);
-        mUsingTabs = showTabs;
-
-        mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
-        mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
-        mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.SEARCH).mRecyclerView);
-
-        if (mUsingTabs) {
-            mAH.get(AdapterHolder.MAIN).setup(mViewPager.getChildAt(0), mPersonalMatcher);
-            mAH.get(AdapterHolder.WORK).setup(mViewPager.getChildAt(1), mWorkManager.getMatcher());
-            mAH.get(AdapterHolder.WORK).mRecyclerView.setId(R.id.apps_list_view_work);
-            if (FeatureFlags.ENABLE_EXPANDING_PAUSE_WORK_BUTTON.get()) {
-                mAH.get(AdapterHolder.WORK).mRecyclerView.addOnScrollListener(
-                        mWorkManager.newScrollListener());
-            }
-            mViewPager.getPageIndicator().setActiveMarker(AdapterHolder.MAIN);
-            findViewById(R.id.tab_personal)
-                    .setOnClickListener((View view) -> {
-                        if (mViewPager.snapToPage(AdapterHolder.MAIN)) {
-                            mActivityContext.getStatsLogManager().logger()
-                                    .log(LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB);
-                        }
-                        mActivityContext.hideKeyboard();
-                    });
-            findViewById(R.id.tab_work)
-                    .setOnClickListener((View view) -> {
-                        if (mViewPager.snapToPage(AdapterHolder.WORK)) {
-                            mActivityContext.getStatsLogManager().logger()
-                                    .log(LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB);
-                        }
-                        mActivityContext.hideKeyboard();
-                    });
-            setDeviceManagementResources();
-            onActivePageChanged(mViewPager.getNextPage());
-        } else {
-            mAH.get(AdapterHolder.MAIN).setup(findViewById(R.id.apps_list_view), null);
-            mAH.get(AdapterHolder.WORK).mRecyclerView = null;
-        }
-        setupHeader();
-
-        mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
-        mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
-        mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.SEARCH).mRecyclerView);
-    }
-
-    protected void updateSearchResultsVisibility() {
-        if (isSearching()) {
-            getSearchRecyclerView().setVisibility(VISIBLE);
-            getAppsRecyclerViewContainer().setVisibility(GONE);
-            mHeader.setVisibility(GONE);
-        } else {
-            getSearchRecyclerView().setVisibility(GONE);
-            getAppsRecyclerViewContainer().setVisibility(VISIBLE);
-            mHeader.setVisibility(VISIBLE);
-        }
-        if (mHeader.isSetUp()) {
-            mHeader.setActiveRV(getCurrentPage());
-        }
-    }
-
-    private void applyAdapterSideAndBottomPaddings(DeviceProfile grid) {
-        int bottomPadding = Math.max(mInsets.bottom, mNavBarScrimHeight);
-        mAH.forEach(adapterHolder -> {
-            adapterHolder.mPadding.bottom = bottomPadding;
-            adapterHolder.mPadding.left =
-                    adapterHolder.mPadding.right = grid.allAppsLeftRightPadding;
-            adapterHolder.applyPadding();
-        });
-    }
-
-    private void setDeviceManagementResources() {
-        if (mActivityContext.getStringCache() != null) {
-            Button personalTab = findViewById(R.id.tab_personal);
-            personalTab.setText(mActivityContext.getStringCache().allAppsPersonalTab);
-
-            Button workTab = findViewById(R.id.tab_work);
-            workTab.setText(mActivityContext.getStringCache().allAppsWorkTab);
-        }
-    }
-
-    protected boolean shouldShowTabs() {
-        return mHasWorkApps;
-    }
-
-    protected boolean isSearching() {
-        return false;
-    }
-
-    protected View replaceAppsRVContainer(boolean showTabs) {
-        for (int i = AdapterHolder.MAIN; i <= AdapterHolder.WORK; i++) {
-            AdapterHolder adapterHolder = mAH.get(i);
-            if (adapterHolder.mRecyclerView != null) {
-                adapterHolder.mRecyclerView.setLayoutManager(null);
-                adapterHolder.mRecyclerView.setAdapter(null);
-            }
-        }
-        View oldView = getAppsRecyclerViewContainer();
-        int index = indexOfChild(oldView);
-        removeView(oldView);
-        int layout = showTabs ? R.layout.all_apps_tabs : R.layout.all_apps_rv_layout;
-        View newView = getLayoutInflater().inflate(layout, this, false);
-        addView(newView, index);
-        if (showTabs) {
-            mViewPager = (AllAppsPagedView) newView;
-            mViewPager.initParentViews(this);
-            mViewPager.getPageIndicator().setOnActivePageChangedListener(this);
-
-            mWorkManager.reset();
-            post(() -> mAH.get(AdapterHolder.WORK).applyPadding());
-
-        } else {
-            mWorkManager.detachWorkModeSwitch();
-            mViewPager = null;
-        }
-        return newView;
-    }
-
-    @Override
-    public void onActivePageChanged(int currentActivePage) {
-        if (mAH.get(currentActivePage).mRecyclerView != null) {
-            mAH.get(currentActivePage).mRecyclerView.bindFastScrollbar();
-        }
-        // Header keeps track of active recycler view to properly render header protection.
-        mHeader.setActiveRV(currentActivePage);
-        reset(true /* animate */);
-
-        mWorkManager.onActivePageChanged(currentActivePage);
-    }
-
-    // Used by tests only
-    private boolean isDescendantViewVisible(int viewId) {
-        final View view = findViewById(viewId);
-        if (view == null) return false;
-
-        if (!view.isShown()) return false;
-
-        return view.getGlobalVisibleRect(new Rect());
-    }
-
-    @VisibleForTesting
-    public boolean isPersonalTabVisible() {
-        return isDescendantViewVisible(R.id.tab_personal);
-    }
-
-    @VisibleForTesting
-    public boolean isWorkTabVisible() {
-        return isDescendantViewVisible(R.id.tab_work);
-    }
-
-    public AlphabeticalAppsList<T> getSearchResultList() {
-        return mAH.get(AdapterHolder.SEARCH).mAppsList;
-    }
-
-    public FloatingHeaderView getFloatingHeaderView() {
-        return mHeader;
-    }
-
-    @VisibleForTesting
-    public View getContentView() {
-        return isSearching() ? getSearchRecyclerView() : getAppsRecyclerViewContainer();
-    }
-
-    /** The current page visible in all apps. */
-    public int getCurrentPage() {
-        return isSearching()
-                ? AdapterHolder.SEARCH
-                : mViewPager == null ? AdapterHolder.MAIN : mViewPager.getNextPage();
-    }
-
-    /** The scroll bar for the active apps recycler view. */
-    public RecyclerViewFastScroller getScrollBar() {
-        AllAppsRecyclerView rv = getActiveAppsRecyclerView();
-        return rv == null ? null : rv.getScrollbar();
-    }
-
-    void setupHeader() {
-        mHeader.setVisibility(View.VISIBLE);
-        boolean tabsHidden = !mUsingTabs;
-        mHeader.setup(
-                mAH.get(AdapterHolder.MAIN).mRecyclerView,
-                mAH.get(AdapterHolder.WORK).mRecyclerView,
-                (SearchRecyclerView) mAH.get(AdapterHolder.SEARCH).mRecyclerView,
-                getCurrentPage(),
-                tabsHidden);
-
-        int padding = mHeader.getMaxTranslation();
-        mAH.forEach(adapterHolder -> {
-            adapterHolder.mPadding.top = padding;
-            adapterHolder.applyPadding();
-            if (adapterHolder.mRecyclerView != null) {
-                adapterHolder.mRecyclerView.scrollToTop();
-            }
-        });
-    }
-
-    public boolean isHeaderVisible() {
-        return mHeader != null && mHeader.getVisibility() == View.VISIBLE;
-    }
-
-    /**
-     * Adds an update listener to animator that adds springs to the animation.
-     */
-    public void addSpringFromFlingUpdateListener(ValueAnimator animator,
-            float velocity /* release velocity */,
-            float progress /* portion of the distance to travel*/) {
-        animator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationStart(Animator animator) {
-                float distance = (1 - progress) * getHeight(); // px
-                float settleVelocity = Math.min(0, distance
-                        / (AllAppsTransitionController.INTERP_COEFF * animator.getDuration())
-                        + velocity);
-                absorbSwipeUpVelocity(Math.max(1000, Math.abs(
-                        Math.round(settleVelocity * FLING_VELOCITY_MULTIPLIER))));
-            }
-        });
-    }
-
-    /** Invoked when the container is pulled. */
-    public void onPull(float deltaDistance, float displacement) {
-        absorbPullDeltaDistance(PULL_MULTIPLIER * deltaDistance, PULL_MULTIPLIER * displacement);
-        // Current motion spec is to actually push and not pull
-        // on this surface. However, until EdgeEffect.onPush (b/190612804) is
-        // implemented at view level, we will simply pull
-    }
-
-    @Override
-    public void getDrawingRect(Rect outRect) {
-        super.getDrawingRect(outRect);
-        outRect.offset(0, (int) getTranslationY());
-    }
-
-    @Override
-    public void setTranslationY(float translationY) {
-        super.setTranslationY(translationY);
-        invalidateHeader();
-    }
-
-    public void setScrimView(ScrimView scrimView) {
-        mScrimView = scrimView;
-    }
-
-    @Override
-    public void drawOnScrim(Canvas canvas) {
-        boolean isTablet = mActivityContext.getDeviceProfile().isTablet;
-
-        // Draw full background panel for tablets.
-        if (isTablet) {
-            mHeaderPaint.setColor(mBottomSheetBackgroundColor);
-            View panel = (View) mBottomSheetBackground;
-            float translationY = ((View) panel.getParent()).getTranslationY();
-            mTmpRectF.set(panel.getLeft(), panel.getTop() + translationY,
-                    panel.getRight(), panel.getBottom());
-            mTmpPath.reset();
-            mTmpPath.addRoundRect(mTmpRectF, mBottomSheetCornerRadii, Direction.CW);
-            canvas.drawPath(mTmpPath, mHeaderPaint);
-        }
-
-        if (DEBUG_HEADER_PROTECTION) {
-            mHeaderPaint.setColor(Color.MAGENTA);
-            mHeaderPaint.setAlpha(255);
-        } else {
-            mHeaderPaint.setColor(mHeaderColor);
-            mHeaderPaint.setAlpha((int) (getAlpha() * Color.alpha(mHeaderColor)));
-        }
-        if (mHeaderPaint.getColor() == mScrimColor || mHeaderPaint.getColor() == 0) {
-            return;
-        }
-        int bottom = getHeaderBottom() + getVisibleContainerView().getPaddingTop();
-        FloatingHeaderView headerView = getFloatingHeaderView();
-        if (isTablet) {
-            // Start adding header protection if search bar or tabs will attach to the top.
-            if (!FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get() || mUsingTabs) {
-                View panel = (View) mBottomSheetBackground;
-                float translationY = ((View) panel.getParent()).getTranslationY();
-                mTmpRectF.set(panel.getLeft(), panel.getTop() + translationY, panel.getRight(),
-                        bottom);
-                mTmpPath.reset();
-                mTmpPath.addRoundRect(mTmpRectF, mBottomSheetCornerRadii, Direction.CW);
-                canvas.drawPath(mTmpPath, mHeaderPaint);
-            }
-        } else {
-            canvas.drawRect(0, 0, canvas.getWidth(), bottom, mHeaderPaint);
-        }
-        int tabsHeight = headerView.getPeripheralProtectionHeight();
-        if (mTabsProtectionAlpha > 0 && tabsHeight != 0) {
-            if (DEBUG_HEADER_PROTECTION) {
-                mHeaderPaint.setColor(Color.BLUE);
-                mHeaderPaint.setAlpha(255);
-            } else {
-                mHeaderPaint.setAlpha((int) (getAlpha() * mTabsProtectionAlpha));
-            }
-            int left = 0;
-            int right = canvas.getWidth();
-            if (isTablet) {
-                left = mBottomSheetBackground.getLeft();
-                right = mBottomSheetBackground.getRight();
-            }
-            canvas.drawRect(left, bottom, right, bottom + tabsHeight, mHeaderPaint);
-        }
-    }
-
-    /**
-     * redraws header protection
-     */
-    public void invalidateHeader() {
-        if (mScrimView != null) {
-            mScrimView.invalidate();
-        }
-    }
-
-    protected void updateHeaderScroll(int scrolledOffset) {
-        float prog = Utilities.boundToRange((float) scrolledOffset / mHeaderThreshold, 0f, 1f);
-        int headerColor = getHeaderColor(prog);
-        int tabsAlpha = mHeader.getPeripheralProtectionHeight() == 0 ? 0
-                : (int) (Utilities.boundToRange(
-                        (scrolledOffset + mHeader.mSnappedScrolledY) / mHeaderThreshold, 0f, 1f)
-                        * 255);
-        if (headerColor != mHeaderColor || mTabsProtectionAlpha != tabsAlpha) {
-            mHeaderColor = headerColor;
-            mTabsProtectionAlpha = tabsAlpha;
-            invalidateHeader();
-        }
-    }
-
-    protected int getHeaderColor(float blendRatio) {
-        return ColorUtils.blendARGB(mScrimColor, mHeaderProtectionColor, blendRatio);
-    }
-
-    protected abstract BaseAllAppsAdapter<T> createAdapter(AlphabeticalAppsList<T> mAppsList,
-            BaseAdapterProvider[] adapterProviders);
-
-    public int getHeaderBottom() {
-        int bottom = (int) getTranslationY() + mHeader.getClipTop();
-        if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
-            if (mActivityContext.getDeviceProfile().isTablet) {
-                return bottom + mBottomSheetBackground.getTop();
-            }
-            return bottom;
-        }
-        return bottom + mHeader.getTop();
-    }
-
-    /**
-     * Returns a view that denotes the visible part of all apps container view.
-     */
-    public View getVisibleContainerView() {
-        return mActivityContext.getDeviceProfile().isTablet ? mBottomSheetBackground : this;
-    }
-
-    protected void onInitializeRecyclerView(RecyclerView rv) {
-        rv.addOnScrollListener(mScrollListener);
-    }
-
-    /**
-     * Returns {@code true} the All Apps UI is currently being displayed on the target surface and
-     * is interactive.
-     */
-    public abstract boolean isInAllApps();
-
-    /** Holds a {@link BaseAllAppsAdapter} and related fields. */
-    public class AdapterHolder {
-        public static final int MAIN = 0;
-        public static final int WORK = 1;
-        public static final int SEARCH = 2;
-
-        private final int mType;
-        public final BaseAllAppsAdapter<T> mAdapter;
-        final RecyclerView.LayoutManager mLayoutManager;
-        final AlphabeticalAppsList<T> mAppsList;
-        final Rect mPadding = new Rect();
-        AllAppsRecyclerView mRecyclerView;
-
-        AdapterHolder(int type) {
-            mType = type;
-            mAppsList = new AlphabeticalAppsList<>(mActivityContext,
-                    isSearch() ? null : mAllAppsStore,
-                    isWork() ? mWorkManager : null);
-            BaseAdapterProvider[] adapterProviders =
-                    new BaseAdapterProvider[]{mMainAdapterProvider};
-
-            mAdapter = createAdapter(mAppsList, adapterProviders);
-            mAppsList.setAdapter(mAdapter);
-            mLayoutManager = mAdapter.getLayoutManager();
-        }
-
-        void setup(@NonNull View rv, @Nullable Predicate<ItemInfo> matcher) {
-            mAppsList.updateItemFilter(matcher);
-            mRecyclerView = (AllAppsRecyclerView) rv;
-            mRecyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
-            mRecyclerView.setApps(mAppsList);
-            mRecyclerView.setLayoutManager(mLayoutManager);
-            mRecyclerView.setAdapter(mAdapter);
-            mRecyclerView.setHasFixedSize(true);
-            // No animations will occur when changes occur to the items in this RecyclerView.
-            mRecyclerView.setItemAnimator(null);
-            onInitializeRecyclerView(mRecyclerView);
-            FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(mRecyclerView);
-            mRecyclerView.addItemDecoration(focusedItemDecorator);
-            mAdapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
-            applyPadding();
-        }
-
-        void applyPadding() {
-            if (mRecyclerView != null) {
-                int bottomOffset = 0;
-                if (isWork() && mWorkManager.getWorkModeSwitch() != null) {
-                    bottomOffset = mInsets.bottom + mWorkManager.getWorkModeSwitch().getHeight();
-                }
-                mRecyclerView.setPadding(mPadding.left, mPadding.top, mPadding.right,
-                        mPadding.bottom + bottomOffset);
-            }
-        }
-
-        private boolean isWork() {
-            return mType == WORK;
-        }
-
-        private boolean isSearch() {
-            return mType == SEARCH;
-        }
-    }
-}
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
index be261f7..0188a47 100644
--- a/src/com/android/launcher3/allapps/DiscoveryBounce.java
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -81,10 +81,10 @@
     }
 
     @Override
-    public boolean onBackPressed() {
-        super.onBackPressed();
-        // Go back to the previous state (from a user's perspective this floating view isn't
-        // something to go back from).
+    public boolean canHandleBack() {
+        // Since DiscoveryBounce doesn't handle back, onBackInvoked() won't be called and we should
+        // close it without animation.
+        close(false);
         return false;
     }
 
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index c18f9e1..b3ea3ab 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -32,7 +32,7 @@
 
 import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
-import com.android.launcher3.allapps.BaseAllAppsContainerView.AdapterHolder;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
 import com.android.launcher3.views.ActivityContext;
@@ -72,8 +72,8 @@
                     moved(current);
                     applyVerticalMove();
                     if (headerCollapsed != mHeaderCollapsed) {
-                        BaseAllAppsContainerView<?> parent =
-                                (BaseAllAppsContainerView<?>) getParent();
+                        ActivityAllAppsContainerView<?> parent =
+                                (ActivityAllAppsContainerView<?>) getParent();
                         parent.invalidateHeader();
                     }
                 }
@@ -191,7 +191,7 @@
         updateExpectedHeight();
 
         if (mMaxTranslation != oldMaxHeight || mFloatingRowsCollapsed) {
-            BaseAllAppsContainerView<?> parent = (BaseAllAppsContainerView<?>) getParent();
+            ActivityAllAppsContainerView parent = (ActivityAllAppsContainerView) getParent();
             if (parent != null) {
                 parent.setupHeader();
             }
diff --git a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
index 5a5ba2b..aefedae 100644
--- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
@@ -41,7 +41,7 @@
     }
 
     @Override
-    protected int getNavBarScrimHeight(WindowInsets insets) {
+    protected int computeNavBarScrimHeight(WindowInsets insets) {
         if (Utilities.ATLEAST_Q) {
             return insets.getTappableElementInsets().bottom;
         } else {
diff --git a/src/com/android/launcher3/allapps/WorkEduCard.java b/src/com/android/launcher3/allapps/WorkEduCard.java
index b3245ee..b4cdc96 100644
--- a/src/com/android/launcher3/allapps/WorkEduCard.java
+++ b/src/com/android/launcher3/allapps/WorkEduCard.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.allapps;
 
+import static com.android.launcher3.LauncherPrefs.WORK_EDU_STEP;
 import static com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.getTabWidth;
 
 import android.content.Context;
@@ -85,8 +86,7 @@
     @Override
     public void onClick(View view) {
         startAnimation(mDismissAnim);
-        LauncherPrefs.getPrefs(getContext()).edit().putInt(WorkProfileManager.KEY_WORK_EDU_STEP,
-                1).apply();
+        LauncherPrefs.get(getContext()).put(WORK_EDU_STEP, 1);
     }
 
     @Override
diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java
index c9466a8..3f2f21d 100644
--- a/src/com/android/launcher3/allapps/WorkModeSwitch.java
+++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java
@@ -15,6 +15,8 @@
  */
 package com.android.launcher3.allapps;
 
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORK_FAB_BUTTON_COLLAPSE;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORK_FAB_BUTTON_EXTEND;
 import static com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.getTabWidth;
 
 import android.animation.LayoutTransition;
@@ -37,6 +39,7 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.KeyboardInsetAnimationCallback;
 import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.model.StringCache;
 import com.android.launcher3.views.ActivityContext;
 /**
@@ -59,6 +62,8 @@
     private final int mScrollThreshold;
     private ImageView mIcon;
     private TextView mTextView;
+    private final StatsLogManager mStatsLogManager;
+
 
     public WorkModeSwitch(@NonNull Context context) {
         this(context, null, 0);
@@ -72,6 +77,7 @@
         super(context, attrs, defStyleAttr);
         mScrollThreshold = Utilities.dpToPx(SCROLL_THRESHOLD_DP);
         mActivityContext = ActivityContext.lookupContext(getContext());
+        mStatsLogManager = mActivityContext.getStatsLogManager();
     }
 
     @Override
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index 547b74c..f66ea34 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -15,18 +15,18 @@
  */
 package com.android.launcher3.allapps;
 
+import static com.android.launcher3.LauncherPrefs.WORK_EDU_STEP;
+import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.MAIN;
+import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.SEARCH;
+import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.WORK;
 import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_DISABLED_CARD;
 import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_EDU_CARD;
-import static com.android.launcher3.allapps.BaseAllAppsContainerView.AdapterHolder.MAIN;
-import static com.android.launcher3.allapps.BaseAllAppsContainerView.AdapterHolder.SEARCH;
-import static com.android.launcher3.allapps.BaseAllAppsContainerView.AdapterHolder.WORK;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TURN_OFF_WORK_APPS_TAP;
 import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
 import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION;
 import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 
-import android.content.SharedPreferences;
 import android.os.Build;
 import android.os.Process;
 import android.os.UserHandle;
@@ -40,11 +40,12 @@
 import androidx.annotation.RequiresApi;
 import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
+import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
 
 import java.lang.annotation.Retention;
@@ -53,7 +54,7 @@
 import java.util.function.Predicate;
 
 /**
- * Companion class for {@link BaseAllAppsContainerView} to manage work tab and personal tab
+ * Companion class for {@link ActivityAllAppsContainerView} to manage work tab and personal tab
  * related
  * logic based on {@link WorkProfileState}?
  */
@@ -78,21 +79,22 @@
     public @interface WorkProfileState { }
 
     private final UserManager mUserManager;
-    private final BaseAllAppsContainerView<?> mAllApps;
+    private final ActivityAllAppsContainerView<?> mAllApps;
     private final Predicate<ItemInfo> mMatcher;
+    private final StatsLogManager mStatsLogManager;
 
     private WorkModeSwitch mWorkModeSwitch;
 
     @WorkProfileState
     private int mCurrentState;
-    private SharedPreferences mPreferences;
 
     public WorkProfileManager(
-            UserManager userManager, BaseAllAppsContainerView<?> allApps, SharedPreferences prefs) {
+            UserManager userManager, ActivityAllAppsContainerView allApps,
+            StatsLogManager statsLogManager) {
         mUserManager = userManager;
         mAllApps = allApps;
-        mPreferences = prefs;
         mMatcher = mAllApps.mPersonalMatcher.negate();
+        mStatsLogManager = statsLogManager;
     }
 
     /**
@@ -150,7 +152,7 @@
     }
 
     /**
-     * Creates and attaches for profile toggle button to {@link BaseAllAppsContainerView}
+     * Creates and attaches for profile toggle button to {@link ActivityAllAppsContainerView}
      */
     public boolean attachWorkModeSwitch() {
         if (!mAllApps.getAppsStore().hasModelFlag(
@@ -175,7 +177,7 @@
         return true;
     }
     /**
-     * Removes work profile toggle button from {@link BaseAllAppsContainerView}
+     * Removes work profile toggle button from {@link ActivityAllAppsContainerView}
      */
     public void detachWorkModeSwitch() {
         if (mWorkModeSwitch != null && mWorkModeSwitch.getParent() == mAllApps) {
@@ -193,7 +195,7 @@
         return mWorkModeSwitch;
     }
 
-    private BaseAllAppsContainerView<?>.AdapterHolder getAH() {
+    private ActivityAllAppsContainerView.AdapterHolder getAH() {
         return mAllApps.mAH.get(WORK);
     }
 
@@ -222,14 +224,12 @@
     }
 
     private boolean isEduSeen() {
-        return mPreferences.getInt(KEY_WORK_EDU_STEP, 0) != 0;
+        return LauncherPrefs.get(mAllApps.getContext()).get(WORK_EDU_STEP) != 0;
     }
 
     private void onWorkFabClicked(View view) {
         if (Utilities.ATLEAST_P && mCurrentState == STATE_ENABLED && mWorkModeSwitch.isEnabled()) {
-            ActivityContext activityContext = ActivityContext.lookupContext(
-                    mWorkModeSwitch.getContext());
-            activityContext.getStatsLogManager().logger().log(LAUNCHER_TURN_OFF_WORK_APPS_TAP);
+            mStatsLogManager.logger().log(LAUNCHER_TURN_OFF_WORK_APPS_TAP);
             setWorkProfileEnabled(false);
         }
     }
diff --git a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
index 20edf8a..714304b 100644
--- a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
@@ -15,12 +15,10 @@
  */
 package com.android.launcher3.allapps.search;
 
-import android.graphics.Canvas;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.launcher3.BubbleTextView;
@@ -38,13 +36,7 @@
 
     public DefaultSearchAdapterProvider(ActivityContext launcher) {
         super(launcher);
-        mDecoration = new RecyclerView.ItemDecoration() {
-            @Override
-            public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent,
-                    @NonNull RecyclerView.State state) {
-                super.onDraw(c, parent, state);
-            }
-        };
+        mDecoration = new RecyclerView.ItemDecoration() { };
     }
 
     @Override
diff --git a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
index 3890741..15756f5 100644
--- a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
@@ -16,12 +16,13 @@
 
 package com.android.launcher3.allapps.search;
 
-import android.net.Uri;
+import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.launcher3.allapps.BaseAdapterProvider;
+import com.android.launcher3.allapps.AllAppsGridAdapter;
 import com.android.launcher3.views.ActivityContext;
 
 /**
@@ -29,7 +30,7 @@
  *
  * @param <T> Context for this adapter provider.
  */
-public abstract class SearchAdapterProvider<T extends ActivityContext> extends BaseAdapterProvider {
+public abstract class SearchAdapterProvider<T extends ActivityContext> {
 
     protected final T mLauncher;
 
@@ -38,12 +39,6 @@
     }
 
     /**
-     * Called from LiveSearchManager to notify slice status updates.
-     */
-    public void onSliceStatusUpdate(Uri sliceUri) {
-    }
-
-    /**
      * Handles selection event on search adapter item. Returns false if provider can not handle
      * event
      */
@@ -63,4 +58,34 @@
      * Clear the highlighted view.
      */
     public abstract void clearHighlightedItem();
+
+    /**
+     * Returns whether or not viewType can be handled by searchProvider
+     */
+    public abstract boolean isViewSupported(int viewType);
+
+    /**
+     * Called from RecyclerView.Adapter#onBindViewHolder
+     */
+    public abstract void onBindView(AllAppsGridAdapter.ViewHolder holder, int position);
+
+    /**
+     * Called from RecyclerView.Adapter#onCreateViewHolder
+     */
+    public abstract AllAppsGridAdapter.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater,
+            ViewGroup parent, int viewType);
+
+    /**
+     * Returns supported item per row combinations supported
+     */
+    public int[] getSupportedItemsPerRowArray() {
+        return new int[]{};
+    }
+
+    /**
+     * Returns how many cells a view should span
+     */
+    public int getItemsPerRow(int viewType, int appsPerRow) {
+        return appsPerRow;
+    }
 }
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index b55a1e4..e886543 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -56,6 +56,8 @@
 
     public static final Interpolator DECELERATED_EASE = new PathInterpolator(0, 0, .2f, 1f);
     public static final Interpolator ACCELERATED_EASE = new PathInterpolator(0.4f, 0, 1f, 1f);
+    public static final Interpolator PREDICTIVE_BACK_DECELERATED_EASE =
+            new PathInterpolator(0, 0, 0, 1f);
 
     /**
      * The default emphasized interpolator. Used for hero / emphasized movement of content.
diff --git a/src/com/android/launcher3/celllayout/CellLayoutLayoutParams.java b/src/com/android/launcher3/celllayout/CellLayoutLayoutParams.java
index abd4682..726ef05 100644
--- a/src/com/android/launcher3/celllayout/CellLayoutLayoutParams.java
+++ b/src/com/android/launcher3/celllayout/CellLayoutLayoutParams.java
@@ -29,29 +29,17 @@
  */
 public class CellLayoutLayoutParams extends ViewGroup.MarginLayoutParams {
 
-    public int screenId = -1;
+    private int mScreenId = -1;
 
-    /**
-     * Horizontal location of the item in the grid.
-     */
     @ViewDebug.ExportedProperty
-    public int cellX;
+    private int mCellX;
 
-    /**
-     * Vertical location of the item in the grid.
-     */
     @ViewDebug.ExportedProperty
-    public int cellY;
+    private int mCellY;
 
-    /**
-     * Temporary horizontal location of the item in the grid during reorder
-     */
-    public int tmpCellX;
+    private int mTmpCellX;
 
-    /**
-     * Temporary vertical location of the item in the grid during reorder
-     */
-    public int tmpCellY;
+    private int mTmpCellY;
 
     /**
      * Indicates that the temporary coordinates should be used to layout the items
@@ -105,24 +93,24 @@
 
     public CellLayoutLayoutParams(CellLayoutLayoutParams source) {
         super(source);
-        this.cellX = source.cellX;
-        this.cellY = source.cellY;
+        this.mCellX = source.getCellX();
+        this.mCellY = source.getCellY();
         this.cellHSpan = source.cellHSpan;
         this.cellVSpan = source.cellVSpan;
-        this.screenId = source.screenId;
-        this.tmpCellX = source.tmpCellX;
-        this.tmpCellY = source.tmpCellY;
+        this.mScreenId = source.getScreenId();
+        this.mTmpCellX = source.getTmpCellX();
+        this.mTmpCellY = source.getTmpCellY();
         this.useTmpCoords = source.useTmpCoords;
     }
 
     public CellLayoutLayoutParams(int cellX, int cellY, int cellHSpan, int cellVSpan,
             int screenId) {
         super(CellLayoutLayoutParams.MATCH_PARENT, CellLayoutLayoutParams.MATCH_PARENT);
-        this.cellX = cellX;
-        this.cellY = cellY;
+        this.mCellX = cellX;
+        this.mCellY = cellY;
         this.cellHSpan = cellHSpan;
         this.cellVSpan = cellVSpan;
-        this.screenId = screenId;
+        this.mScreenId = screenId;
     }
 
     /**
@@ -148,8 +136,8 @@
         if (isLockedToGrid) {
             final int myCellHSpan = cellHSpan;
             final int myCellVSpan = cellVSpan;
-            int myCellX = useTmpCoords ? tmpCellX : cellX;
-            int myCellY = useTmpCoords ? tmpCellY : cellY;
+            int myCellX = useTmpCoords ? getTmpCellX() : getCellX();
+            int myCellY = useTmpCoords ? getTmpCellY() : getCellY();
 
             if (invertHorizontally) {
                 myCellX = colCount - myCellX - cellHSpan;
@@ -179,14 +167,66 @@
      * Sets the position to the provided point
      */
     public void setCellXY(Point point) {
-        cellX = point.x;
-        cellY = point.y;
+        setCellX(point.x);
+        setCellY(point.y);
     }
 
     /**
      * @return the string representation of the position of the {@link CellLayoutLayoutParams}
      */
     public String toString() {
-        return "(" + this.cellX + ", " + this.cellY + ")";
+        return "(" + this.getCellX() + ", " + this.getCellY() + ")";
+    }
+
+    public int getScreenId() {
+        return mScreenId;
+    }
+
+    public void setScreenId(int screenId) {
+        this.mScreenId = screenId;
+    }
+
+    /**
+     * Horizontal location of the item in the grid.
+     */
+    public int getCellX() {
+        return mCellX;
+    }
+
+    public void setCellX(int cellX) {
+        this.mCellX = cellX;
+    }
+
+    /**
+     * Vertical location of the item in the grid.
+     */
+    public int getCellY() {
+        return mCellY;
+    }
+
+    public void setCellY(int cellY) {
+        this.mCellY = cellY;
+    }
+
+    /**
+     * Temporary horizontal location of the item in the grid during reorder
+     */
+    public int getTmpCellX() {
+        return mTmpCellX;
+    }
+
+    public void setTmpCellX(int tmpCellX) {
+        this.mTmpCellX = tmpCellX;
+    }
+
+    /**
+     * Temporary vertical location of the item in the grid during reorder
+     */
+    public int getTmpCellY() {
+        return mTmpCellY;
+    }
+
+    public void setTmpCellY(int tmpCellY) {
+        this.mTmpCellY = tmpCellY;
     }
 }
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 082f6a1..2841129 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -96,9 +96,6 @@
             "ENABLE_EXPANDING_PAUSE_WORK_BUTTON", false,
             "Expand and collapse pause work button while scrolling");
 
-    public static final BooleanFlag ENABLE_HIDE_HEADER_STATIC = new DeviceFlag(
-            "ENABLE_HIDE_HEADER_STATIC", false, "Hide keyboard suggestion strip");
-
     public static final BooleanFlag COLLECT_SEARCH_HISTORY = new DeviceFlag(
             "COLLECT_SEARCH_HISTORY", false, "Allow launcher to collect search history for log");
 
@@ -273,6 +270,10 @@
             "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", false,
             "Enable option to replace decorator-based search result backgrounds with drawables");
 
+    public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = new DeviceFlag(
+            "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", false,
+            "Enable option to launch search results using the new view container transitions");
+
     public static final BooleanFlag TWO_PREDICTED_ROWS_ALL_APPS_SEARCH = new DeviceFlag(
             "TWO_PREDICTED_ROWS_ALL_APPS_SEARCH", false,
             "Use 2 rows of app predictions in All Apps search zero-state");
@@ -326,8 +327,8 @@
             "HOME_GARDENING_WORKSPACE_BUTTONS", false,
             "Change workspace edit buttons to reflect home gardening");
 
-    public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V2 = getDebugFlag(
-            "ENABLE_DOWNLOAD_APP_UX_V2", false, "Updates the download app UX"
+    public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V2 = new DeviceFlag(
+            "ENABLE_DOWNLOAD_APP_UX_V2", true, "Updates the download app UX"
                     + " to have better visuals");
 
     public static final BooleanFlag ENABLE_TASKBAR_REVISED_THRESHOLDS = getDebugFlag(
@@ -364,7 +365,7 @@
             "ENABLE_DEVICE_PROFILE_LOGGING", false, "Allows DeviceProfile logging");
 
     public static final BooleanFlag ENABLE_LAUNCH_FROM_STAGED_APP = getDebugFlag(
-            "ENABLE_LAUNCH_FROM_STAGED_APP", false,
+            "ENABLE_LAUNCH_FROM_STAGED_APP", true,
             "Enable the ability to tap a staged app during split select to launch it in full screen"
     );
 
@@ -381,6 +382,11 @@
             "ENABLE_MULTI_INSTANCE", false,
             "Enables creation and filtering of multiple task instances in overview");
 
+    public static final BooleanFlag ENABLE_TASKBAR_PINNING = getDebugFlag(
+            "ENABLE_TASKBAR_PINNING", false,
+            "Enables taskbar pinning to allow user to switch between transient and persistent "
+                    + "taskbar flavors");
+
     public static void initialize(Context context) {
         synchronized (sDebugFlags) {
             for (DebugFlag flag : sDebugFlags) {
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 09fe740..f54d05d 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -568,7 +568,8 @@
                     .setSpring(new SpringForce(0)
                             .setDampingRatio(DAMPENING_RATIO)
                             .setStiffness(STIFFNESS));
-            mDelta = view.getResources().getDisplayMetrics().density * PARALLAX_MAX_IN_DP;
+            mDelta = Math.min(
+                    range, view.getResources().getDisplayMetrics().density * PARALLAX_MAX_IN_DP);
         }
 
         public void animateToPos(float value) {
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 94eea35..9a5d77e 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -1579,17 +1579,14 @@
         return getOpenView(activityContext, TYPE_FOLDER);
     }
 
-    /**
-     * Navigation bar back key or hardware input back key has been issued.
-     */
+    /** Navigation bar back key or hardware input back key has been issued. */
     @Override
-    public boolean onBackPressed() {
+    public void onBackInvoked() {
         if (isEditingName()) {
             mFolderName.dispatchBackKey();
         } else {
-            super.onBackPressed();
+            super.onBackInvoked();
         }
-        return true;
     }
 
     @Override
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index dd00f07..e69f781 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -41,6 +41,7 @@
 import android.widget.FrameLayout;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import com.android.launcher3.Alarm;
 import com.android.launcher3.BubbleTextView;
@@ -181,8 +182,11 @@
         return icon;
     }
 
-    public static FolderIcon inflateIcon(int resId, ActivityContext activity, ViewGroup group,
-            FolderInfo folderInfo) {
+    /**
+     * Builds a FolderIcon to be added to the Launcher
+     */
+    public static FolderIcon inflateIcon(int resId, ActivityContext activity,
+            @Nullable ViewGroup group, FolderInfo folderInfo) {
         @SuppressWarnings("all") // suppress dead code warning
         final boolean error = INITIAL_ITEM_ANIMATION_DURATION >= DROP_IN_ANIMATION_DURATION;
         if (error) {
@@ -192,8 +196,10 @@
         }
 
         DeviceProfile grid = activity.getDeviceProfile();
-        FolderIcon icon = (FolderIcon) LayoutInflater.from(group.getContext())
-                .inflate(resId, group, false);
+        LayoutInflater inflater = (group != null)
+                ? LayoutInflater.from(group.getContext())
+                : activity.getLayoutInflater();
+        FolderIcon icon = (FolderIcon) inflater.inflate(resId, group, false);
 
         icon.setClipToPadding(false);
         icon.mFolderName = icon.findViewById(R.id.folder_icon_name);
@@ -281,7 +287,7 @@
         CellLayoutLayoutParams lp = (CellLayoutLayoutParams) getLayoutParams();
         CellLayout cl = (CellLayout) getParent().getParent();
 
-        mBackground.animateToAccept(cl, lp.cellX, lp.cellY);
+        mBackground.animateToAccept(cl, lp.getCellX(), lp.getCellY());
         mOpenAlarm.setOnAlarmListener(mOnOpenListener);
         if (SPRING_LOADING_ENABLED &&
                 ((dragInfo instanceof WorkspaceItemFactory)
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index 141388f..10a2637 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -113,7 +113,6 @@
     public void setFolder(Folder folder) {
         mFolder = folder;
         mPageIndicator = folder.findViewById(R.id.folder_page_indicator);
-        mPageIndicator.setShouldAutoHide(false);
         initParentViews(folder);
     }
 
@@ -225,8 +224,8 @@
             textView.setLayoutParams(new CellLayoutLayoutParams(
                     item.cellX, item.cellY, item.spanX, item.spanY, item.screenId));
         } else {
-            lp.cellX = item.cellX;
-            lp.cellY = item.cellY;
+            lp.setCellX(item.cellX);
+            lp.setCellY(item.cellY);
             lp.cellHSpan = lp.cellVSpan = 1;
         }
         return textView;
diff --git a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
index feadafa..9426c22 100644
--- a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
+++ b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
@@ -1,8 +1,7 @@
 package com.android.launcher3.graphics;
 
-import static com.android.launcher3.LauncherPrefs.getPrefs;
+import static com.android.launcher3.LauncherPrefs.THEMED_ICONS;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-import static com.android.launcher3.util.Themes.KEY_THEMED_ICONS;
 import static com.android.launcher3.util.Themes.isThemedIconEnabled;
 
 import android.annotation.TargetApi;
@@ -25,6 +24,7 @@
 
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.InvariantDeviceProfile.GridOption;
+import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.util.Executors;
 
@@ -142,9 +142,8 @@
             }
             case ICON_THEMED:
             case SET_ICON_THEMED: {
-                getPrefs(getContext()).edit()
-                        .putBoolean(KEY_THEMED_ICONS, values.getAsBoolean(BOOLEAN_VALUE))
-                        .apply();
+                LauncherPrefs.get(getContext())
+                        .put(THEMED_ICONS, values.getAsBoolean(BOOLEAN_VALUE));
                 return 1;
             }
             default:
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index e7b0446..4810b15 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -68,6 +68,7 @@
 import com.android.launcher3.InsettableFrameLayout;
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
@@ -137,7 +138,7 @@
                 new ConcurrentLinkedQueue<>();
 
         public PreviewContext(Context base, InvariantDeviceProfile idp) {
-            super(base, UserCache.INSTANCE, InstallSessionHelper.INSTANCE,
+            super(base, UserCache.INSTANCE, InstallSessionHelper.INSTANCE, LauncherPrefs.INSTANCE,
                     LauncherAppState.INSTANCE, InvariantDeviceProfile.INSTANCE,
                     CustomWidgetManager.INSTANCE, PluginManagerWrapper.INSTANCE,
                     WindowManagerProxy.INSTANCE, DisplayController.INSTANCE);
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index 9a961ca..f2fde0e 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -17,6 +17,7 @@
 
 package com.android.launcher3.graphics;
 
+import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_DOWNLOAD_APP_UX_V2;
 
@@ -27,6 +28,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.ColorFilter;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Path;
@@ -39,6 +41,8 @@
 
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AnimatedFloat;
+import com.android.launcher3.anim.AnimatorListeners;
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.launcher3.icons.GraphicsUtils;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
@@ -51,7 +55,7 @@
 /**
  * Extension of {@link FastBitmapDrawable} which shows a progress bar around the icon.
  */
-public class PreloadIconDrawable extends FastBitmapDrawable implements Runnable {
+public class PreloadIconDrawable extends FastBitmapDrawable {
 
     private static final Property<PreloadIconDrawable, Float> INTERNAL_STATE =
             new Property<PreloadIconDrawable, Float>(Float.TYPE, "internalStateProgress") {
@@ -72,19 +76,23 @@
     private static final int DISABLED_ICON_ALPHA = (int) (0.6f * MAX_PAINT_ALPHA);
 
     private static final long DURATION_SCALE = 500;
+    private static final long SCALE_AND_ALPHA_ANIM_DURATION = 500;
 
     // The smaller the number, the faster the animation would be.
     // Duration = COMPLETE_ANIM_FRACTION * DURATION_SCALE
-    private static final float COMPLETE_ANIM_FRACTION = 0.3f;
+    private static final float COMPLETE_ANIM_FRACTION = 1f;
 
-    private static final float SMALL_SCALE = ENABLE_DOWNLOAD_APP_UX_V2.get() ? 0.85f : 0.7f;
-    private static final float PROGRESS_STROKE_SCALE = 0.075f;
+    private static final float SMALL_SCALE = 0.7f;
+    private static final float PROGRESS_STROKE_SCALE = ENABLE_DOWNLOAD_APP_UX_V2.get()
+            ? 0.0655f
+            : 0.075f;
+    private static final float PROGRESS_BOUNDS_SCALE = 0.075f;
 
     private static final int PRELOAD_ACCENT_COLOR_INDEX = 0;
     private static final int PRELOAD_BACKGROUND_COLOR_INDEX = 1;
 
     private static final int ALPHA_DURATION_MILLIS = 3000;
-    private static final float OVERLAY_ALPHA_RANGE = 127.5f;
+    private static final int OVERLAY_ALPHA_RANGE = 127;
     private static final long WAVE_MOTION_DELAY_FACTOR_MILLIS = 100;
     private static final WeakHashMap<Integer, PorterDuffColorFilter> COLOR_FILTER_MAP =
             new WeakHashMap<>();
@@ -108,18 +116,17 @@
     private final int mSystemBackgroundColor;
     private final boolean mIsDarkMode;
 
-    private int mTrackAlpha;
     private float mTrackLength;
-    private float mIconScale;
 
     private boolean mRanFinishAnimation;
-
-    private int mOverlayAlpha = 127;
-    private int mRefreshRateMillis;
+    private final int mRefreshRateMillis;
 
     // Progress of the internal state. [0, 1] indicates the fraction of completed progress,
     // [1, (1 + COMPLETE_ANIM_FRACTION)] indicates the progress of zoom animation.
     private float mInternalStateProgress;
+    // This multiplier is used to animate scale when going from 0 to non-zero and expanding
+    private final Runnable mInvalidateRunnable = this::invalidateSelf;
+    private final AnimatedFloat mIconScaleMultiplier = new AnimatedFloat(mInvalidateRunnable);
 
     private ObjectAnimator mCurrentAnim;
 
@@ -155,6 +162,9 @@
         mIsDarkMode = isDarkMode;
         mRefreshRateMillis = refreshRateMillis;
 
+        // If it's a pending app we will animate scale and alpha when it's no longer pending.
+        mIconScaleMultiplier.updateValue(info.getProgressLevel() == 0 ? 0 : 1);
+
         setLevel(info.getProgressLevel());
         setIsStartable(info.isAppStartable());
     }
@@ -163,14 +173,17 @@
     protected void onBoundsChange(Rect bounds) {
         super.onBoundsChange(bounds);
 
-        float progressWidth = PROGRESS_STROKE_SCALE * bounds.width();
+
+        float progressWidth = bounds.width() * (ENABLE_DOWNLOAD_APP_UX_V2.get()
+                ? PROGRESS_BOUNDS_SCALE
+                : PROGRESS_STROKE_SCALE);
         mTmpMatrix.setScale(
                 (bounds.width() - 2 * progressWidth) / DEFAULT_PATH_SIZE,
                 (bounds.height() - 2 * progressWidth) / DEFAULT_PATH_SIZE);
         mTmpMatrix.postTranslate(bounds.left + progressWidth, bounds.top + progressWidth);
 
         mShapePath.transform(mTmpMatrix, mScaledTrackPath);
-        mProgressPaint.setStrokeWidth(progressWidth);
+        mProgressPaint.setStrokeWidth(PROGRESS_STROKE_SCALE * bounds.width());
 
         mPathMeasure.setPath(mScaledTrackPath, true);
         mTrackLength = mPathMeasure.getLength();
@@ -185,25 +198,35 @@
             return;
         }
 
-        // Draw background.
-        mProgressPaint.setStyle(Paint.Style.FILL_AND_STROKE);
-        mProgressPaint.setColor(mSystemBackgroundColor);
-        canvas.drawPath(mScaledTrackPath, mProgressPaint);
+        if (!ENABLE_DOWNLOAD_APP_UX_V2.get() && mInternalStateProgress > 0) {
+            // Draw background.
+            mProgressPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+            mProgressPaint.setColor(mSystemBackgroundColor);
+            canvas.drawPath(mScaledTrackPath, mProgressPaint);
+        }
 
-        // Draw track and progress.
-        mProgressPaint.setStyle(Paint.Style.STROKE);
-        mProgressPaint.setColor(mIsStartable ? mIndicatorColor : mSystemAccentColor);
-        mProgressPaint.setAlpha(TRACK_ALPHA);
-        canvas.drawPath(mScaledTrackPath, mProgressPaint);
-        mProgressPaint.setAlpha(mTrackAlpha);
-        canvas.drawPath(mScaledProgressPath, mProgressPaint);
+        if (!ENABLE_DOWNLOAD_APP_UX_V2.get() || mInternalStateProgress > 0) {
+            // Draw track and progress.
+            mProgressPaint.setStyle(Paint.Style.STROKE);
+            mProgressPaint.setColor(mSystemAccentColor);
+            mProgressPaint.setAlpha(TRACK_ALPHA);
+            canvas.drawPath(mScaledTrackPath, mProgressPaint);
+            mProgressPaint.setAlpha(MAX_PAINT_ALPHA);
+            canvas.drawPath(mScaledProgressPath, mProgressPaint);
+        }
 
         int saveCount = canvas.save();
-        canvas.scale(mIconScale, mIconScale, bounds.exactCenterX(), bounds.exactCenterY());
+        float scale = ENABLE_DOWNLOAD_APP_UX_V2.get()
+                ? 1 - mIconScaleMultiplier.value * (1 - SMALL_SCALE)
+                : SMALL_SCALE;
+        canvas.scale(scale, scale, bounds.exactCenterX(), bounds.exactCenterY());
+
+        ColorFilter filter = getOverlayFilter();
+        mPaint.setColorFilter(filter);
         super.drawInternal(canvas, bounds);
         canvas.restoreToCount(saveCount);
 
-        if (ENABLE_DOWNLOAD_APP_UX_V2.get() && mInternalStateProgress == 0) {
+        if (ENABLE_DOWNLOAD_APP_UX_V2.get() && filter != null) {
             reschedule();
         }
     }
@@ -221,7 +244,7 @@
     @Override
     protected boolean onLevelChange(int level) {
         // Run the animation if we have already been bound.
-        updateInternalState(level * 0.01f,  getBounds().width() > 0, false);
+        updateInternalState(level * 0.01f, false, null);
         return true;
     }
 
@@ -229,12 +252,18 @@
      * Runs the finish animation if it is has not been run after last call to
      * {@link #onLevelChange}
      */
-    public void maybePerformFinishedAnimation() {
+    public void maybePerformFinishedAnimation(
+            PreloadIconDrawable oldIcon, Runnable onFinishCallback) {
+
+        if (oldIcon.mInternalStateProgress >= 1) {
+            mInternalStateProgress = oldIcon.mInternalStateProgress;
+        }
+
         // If the drawable was recently initialized, skip the progress animation.
         if (mInternalStateProgress == 0) {
             mInternalStateProgress = 1;
         }
-        updateInternalState(1 + COMPLETE_ANIM_FRACTION, true, true);
+        updateInternalState(1 + COMPLETE_ANIM_FRACTION, true, onFinishCallback);
     }
 
     public boolean hasNotCompleted() {
@@ -249,26 +278,29 @@
         }
     }
 
-    private void updateInternalState(float finalProgress, boolean shouldAnimate, boolean isFinish) {
+    private void updateInternalState(
+            float finalProgress, boolean isFinish, Runnable onFinishCallback) {
         if (mCurrentAnim != null) {
             mCurrentAnim.cancel();
             mCurrentAnim = null;
         }
 
-        if (Float.compare(finalProgress, mInternalStateProgress) == 0) {
-            return;
-        }
-        if (finalProgress < mInternalStateProgress) {
-            shouldAnimate = false;
-        }
-        if (!shouldAnimate || mRanFinishAnimation) {
+        boolean animateProgress =
+                finalProgress >= mInternalStateProgress && getBounds().width() > 0;
+        if (!animateProgress || mRanFinishAnimation) {
             setInternalProgress(finalProgress);
+            if (isFinish && onFinishCallback != null) {
+                onFinishCallback.run();
+            }
         } else {
             mCurrentAnim = ObjectAnimator.ofFloat(this, INTERNAL_STATE, finalProgress);
             mCurrentAnim.setDuration(
                     (long) ((finalProgress - mInternalStateProgress) * DURATION_SCALE));
             mCurrentAnim.setInterpolator(LINEAR);
             if (isFinish) {
+                if (onFinishCallback != null) {
+                    mCurrentAnim.addListener(AnimatorListeners.forEndCallback(onFinishCallback));
+                }
                 mCurrentAnim.addListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationEnd(Animator animation) {
@@ -286,46 +318,38 @@
      *     - icon with pending motion
      *     - progress track is not visible
      *     - progress bar is not visible
-     *   for progress < 1
+     *   for progress < 1:
      *     - icon without pending motion
      *     - progress track is visible
      *     - progress bar is visible. Progress bar is drawn as a fraction of
      *       {@link #mScaledTrackPath}.
      *       @see PathMeasure#getSegment(float, float, Path, boolean)
-     *   for 1 <= progress < (1 + COMPLETE_ANIM_FRACTION)
-     *     - we calculate fraction of progress in the above range
-     *     - progress track is drawn with alpha based on fraction
-     *     - progress bar is drawn at 100% with alpha based on fraction
-     *     - icon is scaled up based on fraction and is drawn in enabled state
-     *   for progress >= (1 + COMPLETE_ANIM_FRACTION)
-     *     - only icon is drawn in normal state
+     *   for progress > 1:
+     *     - scale the icon back to full size
      */
     private void setInternalProgress(float progress) {
+        // Animate scale and alpha from pending to downloading state.
+        if (ENABLE_DOWNLOAD_APP_UX_V2.get() && progress > 0 && mInternalStateProgress == 0) {
+            // Progress is changing for the first time, animate the icon scale
+            Animator iconScaleAnimator = mIconScaleMultiplier.animateToValue(1);
+            iconScaleAnimator.setDuration(SCALE_AND_ALPHA_ANIM_DURATION);
+            iconScaleAnimator.setInterpolator(EMPHASIZED);
+            iconScaleAnimator.start();
+        }
+
         mInternalStateProgress = progress;
         if (progress <= 0) {
-            mIconScale = ENABLE_DOWNLOAD_APP_UX_V2.get() ? 1 : SMALL_SCALE;
-            mScaledTrackPath.reset();
-            mTrackAlpha = MAX_PAINT_ALPHA;
-        } else if (progress < 1) {
-            mPathMeasure.getSegment(0, progress * mTrackLength, mScaledProgressPath, true);
-            if (ENABLE_DOWNLOAD_APP_UX_V2.get()) {
-                mPaint.setColorFilter(null);
-                mPathMeasure.getSegment(0, mTrackLength, mScaledTrackPath, true);
+            if (!ENABLE_DOWNLOAD_APP_UX_V2.get()) {
+                mScaledTrackPath.reset();
             }
-            mIconScale = SMALL_SCALE;
-            mTrackAlpha = MAX_PAINT_ALPHA;
+            mIconScaleMultiplier.updateValue(0);
         } else {
-            setIsDisabled(mItem.isDisabled());
-            mScaledTrackPath.set(mScaledProgressPath);
-            float fraction = (progress - 1) / COMPLETE_ANIM_FRACTION;
-
-            if (fraction >= 1) {
-                // Animation has completed
-                mIconScale = 1;
-                mTrackAlpha = 0;
-            } else {
-                mTrackAlpha = Math.round((1 - fraction) * MAX_PAINT_ALPHA);
-                mIconScale = SMALL_SCALE + (1 - SMALL_SCALE) * fraction;
+            mPathMeasure.getSegment(
+                    0, Math.min(progress, 1) * mTrackLength, mScaledProgressPath, true);
+            if (progress > 1 && ENABLE_DOWNLOAD_APP_UX_V2.get()) {
+                // map the scale back to original value
+                mIconScaleMultiplier.updateValue(Utilities.mapBoundToRange(
+                        progress - 1, 0, COMPLETE_ANIM_FRACTION, 1, 0, EMPHASIZED));
             }
         }
         invalidateSelf();
@@ -366,70 +390,48 @@
     }
 
     @Override
-    public void run() {
-        if (!ENABLE_DOWNLOAD_APP_UX_V2.get() || mInternalStateProgress > 0) {
-            return;
-        }
-        if (applyPendingIconOverlay()) {
-            invalidateSelf();
-        } else {
-            reschedule();
-        }
-    }
-
-    @Override
     public boolean setVisible(boolean visible, boolean restart) {
-        boolean result = super.setVisible(visible, restart);
-        if (visible) {
-            reschedule();
-        } else {
-            unscheduleSelf(this);
+        if (!visible) {
+            unscheduleSelf(mInvalidateRunnable);
         }
-        return result;
+        return super.setVisible(visible, restart);
     }
 
     private void reschedule() {
-        unscheduleSelf(this);
-
+        unscheduleSelf(mInvalidateRunnable);
         if (!isVisible()) {
             return;
         }
-
         final long upTime = SystemClock.uptimeMillis();
-        scheduleSelf(this, upTime - ((upTime % mRefreshRateMillis)) + mRefreshRateMillis);
+        scheduleSelf(mInvalidateRunnable,
+                upTime - ((upTime % mRefreshRateMillis)) + mRefreshRateMillis);
     }
 
-
     /**
-     * Apply an overlay on the pending icon with cascading motion based on its position.
-     * Returns {@code true} if the icon alpha is updated, so that we re-draw.
+     * Returns a color filter to be used as an overlay on the pending icon with cascading motion
+     * based on its position.
      */
-    private boolean applyPendingIconOverlay() {
+    private ColorFilter getOverlayFilter() {
+        if (!ENABLE_DOWNLOAD_APP_UX_V2.get() || mInternalStateProgress > 0) {
+            // If the download has started, we do no need to animate
+            return null;
+        }
         long waveMotionDelay = (mItem.cellX * WAVE_MOTION_DELAY_FACTOR_MILLIS)
                 + (mItem.cellY * WAVE_MOTION_DELAY_FACTOR_MILLIS);
         long time = SystemClock.uptimeMillis();
-        int newAlpha = (int) Utilities.mapBoundToRange(
-                (float) (time + waveMotionDelay) % ALPHA_DURATION_MILLIS,
+        int alpha = (int) Utilities.mapBoundToRange(
+                (int) ((time + waveMotionDelay) % ALPHA_DURATION_MILLIS),
                 0,
                 ALPHA_DURATION_MILLIS,
                 0,
-                MAX_PAINT_ALPHA,
+                OVERLAY_ALPHA_RANGE * 2,
                 LINEAR);
-        if (newAlpha > OVERLAY_ALPHA_RANGE) {
-            newAlpha = (int) (OVERLAY_ALPHA_RANGE - (newAlpha % OVERLAY_ALPHA_RANGE));
+        if (alpha > OVERLAY_ALPHA_RANGE) {
+            alpha = (OVERLAY_ALPHA_RANGE - (alpha % OVERLAY_ALPHA_RANGE));
         }
-
-        boolean invalidate = false;
-        if (mOverlayAlpha != newAlpha) {
-            mOverlayAlpha = newAlpha;
-            int overlayColor = mIsDarkMode ? 0 : 255;
-            int currArgb = Color.argb(mOverlayAlpha, overlayColor, overlayColor, overlayColor);
-            mPaint.setColorFilter(COLOR_FILTER_MAP.computeIfAbsent(
-                    currArgb,
-                    FILTER_FACTORY));
-            invalidate = true;
-        }
-        return invalidate;
+        int overlayColor = mIsDarkMode ? 0 : 255;
+        int currArgb = Color.argb(alpha, overlayColor, overlayColor, overlayColor);
+        return COLOR_FILTER_MAP.computeIfAbsent(currArgb, FILTER_FACTORY);
     }
 
     protected static class PreloadIconConstantState extends FastBitmapConstantState {
diff --git a/src/com/android/launcher3/graphics/SysUiScrim.java b/src/com/android/launcher3/graphics/SysUiScrim.java
index 185b8d3..11e7dc8 100644
--- a/src/com/android/launcher3/graphics/SysUiScrim.java
+++ b/src/com/android/launcher3/graphics/SysUiScrim.java
@@ -16,17 +16,10 @@
 
 package com.android.launcher3.graphics;
 
-import static android.content.Intent.ACTION_SCREEN_OFF;
-import static android.content.Intent.ACTION_USER_PRESENT;
-
 import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION;
 import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
 
 import android.animation.ObjectAnimator;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -43,10 +36,12 @@
 
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.R;
-import com.android.launcher3.testing.shared.ResourceUtils;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.testing.shared.ResourceUtils;
 import com.android.launcher3.util.DynamicResource;
+import com.android.launcher3.util.ScreenOnTracker;
+import com.android.launcher3.util.ScreenOnTracker.ScreenOnListener;
 import com.android.launcher3.util.Themes;
 import com.android.systemui.plugins.ResourceProvider;
 
@@ -85,18 +80,20 @@
     /**
      * Receiver used to get a signal that the user unlocked their device.
      */
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+    private final ScreenOnListener mScreenOnListener = new ScreenOnListener() {
         @Override
-        public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            if (ACTION_SCREEN_OFF.equals(action)) {
+        public void onScreenOnChanged(boolean isOn) {
+            if (!isOn) {
                 mAnimateScrimOnNextDraw = true;
-            } else if (ACTION_USER_PRESENT.equals(action)) {
-                // ACTION_USER_PRESENT is sent after onStart/onResume. This covers the case where
-                // the user unlocked and the Launcher is not in the foreground.
-                mAnimateScrimOnNextDraw = false;
             }
         }
+
+        @Override
+        public void onUserPresent() {
+            // ACTION_USER_PRESENT is sent after onStart/onResume. This covers the case where
+            // the user unlocked and the Launcher is not in the foreground.
+            mAnimateScrimOnNextDraw = false;
+        }
     };
 
     private static final int MAX_HOTSEAT_SCRIM_ALPHA = 100;
@@ -208,16 +205,14 @@
     @Override
     public void onViewAttachedToWindow(View view) {
         if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) {
-            IntentFilter filter = new IntentFilter(ACTION_SCREEN_OFF);
-            filter.addAction(ACTION_USER_PRESENT); // When the device wakes up + keyguard is gone
-            mRoot.getContext().registerReceiver(mReceiver, filter);
+            ScreenOnTracker.INSTANCE.get(mActivity).addListener(mScreenOnListener);
         }
     }
 
     @Override
     public void onViewDetachedFromWindow(View view) {
         if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) {
-            mRoot.getContext().unregisterReceiver(mReceiver);
+            ScreenOnTracker.INSTANCE.get(mActivity).removeListener(mScreenOnListener);
         }
     }
 
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 24d8c9d..5f6df27 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -558,14 +558,11 @@
                 + "result page etc.")
         LAUNCHER_ALLAPPS_SCROLLED(985),
 
-        @UiEvent(doc = "User scrolled up on one of the all apps surfaces such as A-Z list, search "
-                + "result page etc.")
-        LAUNCHER_ALLAPPS_SCROLLED_UP(1229),
+        @UiEvent(doc = "User scrolled up on the all apps personal A-Z list.")
+        LAUNCHER_ALLAPPS_PERSONAL_SCROLLED_UP(1287),
 
-        @UiEvent(doc =
-                "User scrolled down on one of the all apps surfaces such as A-Z list, search "
-                        + "result page etc.")
-        LAUNCHER_ALLAPPS_SCROLLED_DOWN(1230),
+        @UiEvent(doc = "User scrolled down on the all apps personal A-Z list.")
+        LAUNCHER_ALLAPPS_PERSONAL_SCROLLED_DOWN(1288),
 
         @UiEvent(doc = "User scrolled on one of the all apps surfaces such as A-Z list, search "
                 + "result page etc and we don't know the direction since user came back to "
@@ -624,7 +621,21 @@
         LAUNCHER_KEYBOARD_SHORTCUT_SPLIT_RIGHT_BOTTOM(1232),
 
         @UiEvent(doc = "User has invoked split to left half with a keyboard shortcut.")
-        LAUNCHER_KEYBOARD_SHORTCUT_SPLIT_LEFT_TOP(1233)
+        LAUNCHER_KEYBOARD_SHORTCUT_SPLIT_LEFT_TOP(1233),
+
+        @UiEvent(doc = "User has collapsed the work FAB button by scrolling down in the all apps"
+                + " work A-Z list.")
+        LAUNCHER_WORK_FAB_BUTTON_COLLAPSE(1276),
+
+        @UiEvent(doc = "User has collapsed the work FAB button by scrolling up in the all apps"
+                + " work A-Z list.")
+        LAUNCHER_WORK_FAB_BUTTON_EXTEND(1277),
+
+        @UiEvent(doc = "User scrolled down on the search result page.")
+        LAUNCHER_ALLAPPS_SEARCH_SCROLLED_DOWN(1285),
+
+        @UiEvent(doc = "User scrolled up on the search result page.")
+        LAUNCHER_ALLAPPS_SEARCH_SCROLLED_UP(1286),
         ;
 
         // ADD MORE
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java
index 6da948c..8f85bfb 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -18,7 +18,6 @@
 
 import static com.android.launcher3.model.data.AppInfo.COMPONENT_KEY_COMPARATOR;
 import static com.android.launcher3.model.data.AppInfo.EMPTY_ARRAY;
-import static com.android.launcher3.testing.shared.TestProtocol.INCORRECT_INFO_UPDATED;
 
 import android.content.ComponentName;
 import android.content.Context;
@@ -39,7 +38,6 @@
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.pm.PackageInstallInfo;
-import com.android.launcher3.testing.shared.TestProtocol;
 import com.android.launcher3.util.FlagOp;
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.SafeCloseable;
@@ -275,14 +273,8 @@
     }
 
     public void updateIconsAndLabels(HashSet<String> packages, UserHandle user) {
-        if (TestProtocol.sDebugTracing) {
-            Log.i(INCORRECT_INFO_UPDATED, "updateIconsAndLabels: packages=" + packages);
-        }
         for (AppInfo info : data) {
             if (info.user.equals(user) && packages.contains(info.componentName.getPackageName())) {
-                if (TestProtocol.sDebugTracing) {
-                    Log.i(INCORRECT_INFO_UPDATED, "updateIconsAndLabels: updating info=" + info);
-                }
                 mIconCache.updateTitleAndIcon(info);
                 info.sectionName = mIndex.computeSectionName(info.title);
                 mDataChanged = true;
diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLauncherBinder.java
similarity index 95%
rename from src/com/android/launcher3/model/BaseLoaderResults.java
rename to src/com/android/launcher3/model/BaseLauncherBinder.java
index 8c6428b..9f8db51 100644
--- a/src/com/android/launcher3/model/BaseLoaderResults.java
+++ b/src/com/android/launcher3/model/BaseLauncherBinder.java
@@ -47,12 +47,11 @@
 import java.util.concurrent.Executor;
 
 /**
- * Base Helper class to handle results of {@link com.android.launcher3.model.LoaderTask}.
+ * Binds the results of {@link com.android.launcher3.model.LoaderTask} to the Callbacks objects.
  */
-public abstract class BaseLoaderResults {
+public abstract class BaseLauncherBinder {
 
-    protected static final String TAG = "LoaderResults";
-    protected static final int INVALID_SCREEN_ID = -1;
+    protected static final String TAG = "LauncherBinder";
     private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
 
     protected final LooperExecutor mUiExecutor;
@@ -65,7 +64,7 @@
 
     private int mMyBindingId;
 
-    public BaseLoaderResults(LauncherAppState app, BgDataModel dataModel,
+    public BaseLauncherBinder(LauncherAppState app, BgDataModel dataModel,
             AllAppsList allAppsList, Callbacks[] callbacksList, LooperExecutor uiExecutor) {
         mUiExecutor = uiExecutor;
         mApp = app;
@@ -101,8 +100,14 @@
         }
     }
 
+    /**
+     * BindDeepShortcuts is abstract because it is a no-op for the go launcher.
+     */
     public abstract void bindDeepShortcuts();
 
+    /**
+     * Binds the all apps results from LoaderTask to the callbacks UX.
+     */
     public void bindAllApps() {
         // shallow copy
         AppInfo[] apps = mBgAllAppsList.copyData();
@@ -110,6 +115,9 @@
         executeCallbacksTask(c -> c.bindAllApplications(apps, flags), mUiExecutor);
     }
 
+    /**
+     * bindWidgets is abstract because it is a no-op for the go launcher.
+     */
     public abstract void bindWidgets();
 
     /**
@@ -160,6 +168,9 @@
         });
     }
 
+    /**
+     * Only used in LoaderTask.
+     */
     public LooperIdleLock newIdleLock(Object lock) {
         LooperIdleLock idleLock = new LooperIdleLock(lock, mUiExecutor.getLooper());
         // If we are not binding or if the main looper is already idle, there is no reason to wait
diff --git a/src/com/android/launcher3/model/DeviceGridState.java b/src/com/android/launcher3/model/DeviceGridState.java
index 85d54c0..edc8c1b 100644
--- a/src/com/android/launcher3/model/DeviceGridState.java
+++ b/src/com/android/launcher3/model/DeviceGridState.java
@@ -17,7 +17,10 @@
 package com.android.launcher3.model;
 
 import static com.android.launcher3.InvariantDeviceProfile.DeviceType;
-import static com.android.launcher3.InvariantDeviceProfile.TYPE_PHONE;
+import static com.android.launcher3.LauncherPrefs.DB_FILE;
+import static com.android.launcher3.LauncherPrefs.DEVICE_TYPE;
+import static com.android.launcher3.LauncherPrefs.HOTSEAT_COUNT;
+import static com.android.launcher3.LauncherPrefs.WORKSPACE_SIZE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_2;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_3;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_4;
@@ -25,7 +28,6 @@
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_6;
 
 import android.content.Context;
-import android.content.SharedPreferences;
 import android.text.TextUtils;
 
 import com.android.launcher3.InvariantDeviceProfile;
@@ -58,11 +60,11 @@
     }
 
     public DeviceGridState(Context context) {
-        SharedPreferences prefs = LauncherPrefs.getPrefs(context);
-        mGridSizeString = prefs.getString(KEY_WORKSPACE_SIZE, "");
-        mNumHotseat = prefs.getInt(KEY_HOTSEAT_COUNT, -1);
-        mDeviceType = prefs.getInt(KEY_DEVICE_TYPE, TYPE_PHONE);
-        mDbFile = prefs.getString(KEY_DB_FILE, "");
+        LauncherPrefs lp = LauncherPrefs.get(context);
+        mGridSizeString = lp.get(WORKSPACE_SIZE);
+        mNumHotseat = lp.get(HOTSEAT_COUNT);
+        mDeviceType = lp.get(DEVICE_TYPE);
+        mDbFile = lp.get(DB_FILE);
     }
 
     /**
@@ -90,12 +92,11 @@
      * Stores the device state to shared preferences
      */
     public void writeToPrefs(Context context) {
-        LauncherPrefs.getPrefs(context).edit()
-                .putString(KEY_WORKSPACE_SIZE, mGridSizeString)
-                .putInt(KEY_HOTSEAT_COUNT, mNumHotseat)
-                .putInt(KEY_DEVICE_TYPE, mDeviceType)
-                .putString(KEY_DB_FILE, mDbFile)
-                .apply();
+        LauncherPrefs.get(context).put(
+                WORKSPACE_SIZE.to(mGridSizeString),
+                HOTSEAT_COUNT.to(mNumHotseat),
+                DEVICE_TYPE.to(mDeviceType),
+                DB_FILE.to(mDbFile));
     }
 
     /**
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 1d6971e..46a6a66 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -125,7 +125,7 @@
 
     private FirstScreenBroadcast mFirstScreenBroadcast;
 
-    private final LoaderResults mResults;
+    private final LauncherBinder mLauncherBinder;
 
     private final LauncherApps mLauncherApps;
     private final UserManager mUserManager;
@@ -145,12 +145,12 @@
     private String mDbName;
 
     public LoaderTask(LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel dataModel,
-            ModelDelegate modelDelegate, LoaderResults results) {
+            ModelDelegate modelDelegate, LauncherBinder launcherBinder) {
         mApp = app;
         mBgAllAppsList = bgAllAppsList;
         mBgDataModel = dataModel;
         mModelDelegate = modelDelegate;
-        mResults = results;
+        mLauncherBinder = launcherBinder;
 
         mLauncherApps = mApp.getContext().getSystemService(LauncherApps.class);
         mUserManager = mApp.getContext().getSystemService(UserManager.class);
@@ -163,7 +163,7 @@
         // Wait until the either we're stopped or the other threads are done.
         // This way we don't start loading all apps until the workspace has settled
         // down.
-        LooperIdleLock idleLock = mResults.newIdleLock(this);
+        LooperIdleLock idleLock = mLauncherBinder.newIdleLock(this);
         // Just in case mFlushingWorkerThread changes but we aren't woken up,
         // wait no longer than 1sec at a time
         while (!mStopped && idleLock.awaitLocked(1000));
@@ -221,7 +221,7 @@
             }
 
             verifyNotStopped();
-            mResults.bindWorkspace(true /* incrementBindId */);
+            mLauncherBinder.bindWorkspace(true /* incrementBindId */);
             logASplit(logger, "bindWorkspace");
 
             mModelDelegate.workspaceLoadComplete();
@@ -245,7 +245,7 @@
             logASplit(logger, "loadAllApps");
 
             verifyNotStopped();
-            mResults.bindAllApps();
+            mLauncherBinder.bindAllApps();
             logASplit(logger, "bindAllApps");
 
             verifyNotStopped();
@@ -271,7 +271,7 @@
             logASplit(logger, "loadDeepShortcuts");
 
             verifyNotStopped();
-            mResults.bindDeepShortcuts();
+            mLauncherBinder.bindDeepShortcuts();
             logASplit(logger, "bindDeepShortcuts");
 
             verifyNotStopped();
@@ -290,7 +290,7 @@
             logASplit(logger, "load widgets");
 
             verifyNotStopped();
-            mResults.bindWidgets();
+            mLauncherBinder.bindWidgets();
             logASplit(logger, "bindWidgets");
             verifyNotStopped();
 
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index 2dd44a4..4eb2e9e 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -47,8 +47,10 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.LauncherSettings.Animation;
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.Workspace;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logger.LauncherAtom;
 import com.android.launcher3.logger.LauncherAtom.AllAppsContainer;
 import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
@@ -94,6 +96,12 @@
     public int itemType;
 
     /**
+     * One of {@link Animation#DEFAULT},
+     * {@link Animation#VIEW_BACKGROUND}.
+     */
+    public int animationType = Animation.DEFAULT;
+
+    /**
      * The id of the container that holds this item. For the desktop, this will be
      * {@link Favorites#CONTAINER_DESKTOP}. For the all applications folder it
      * will be {@link #NO_ID} (since it is not stored in the settings DB). For user folders
@@ -185,6 +193,7 @@
         rank = info.rank;
         screenId = info.screenId;
         itemType = info.itemType;
+        animationType = info.animationType;
         container = info.container;
         user = info.user;
         contentDescription = info.contentDescription;
@@ -298,6 +307,15 @@
     }
 
     /**
+     * Returns whether this item should use the background animation.
+     */
+    public boolean shouldUseBackgroundAnimation() {
+        return animationType == LauncherSettings.Animation.VIEW_BACKGROUND
+                && FeatureFlags.ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES.get()
+                && FeatureFlags.ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION.get();
+    }
+
+    /**
      * Creates {@link LauncherAtom.ItemInfo} with important fields and parent container info.
      */
     @NonNull
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index ec69193..570d6ff 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -46,4 +46,11 @@
     default void skipAnimationsToEnd() {
         // No-op by default
     }
+
+    /**
+     * Sets the paint color.
+     */
+    default void setPaintColor(int color) {
+        // No-op by default
+    }
 }
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index c324ce3..b2c64b3 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -35,6 +35,7 @@
 import android.os.Looper;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
+import android.util.IntProperty;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewOutlineProvider;
@@ -58,7 +59,8 @@
     private static final float SHIFT_THRESHOLD = 0.1f;
     private static final long ANIMATION_DURATION = 150;
     private static final int PAGINATION_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay();
-    private static final int ALPHA_ANIMATE_DURATION = ViewConfiguration.getScrollBarFadeDuration();
+    private static final int PAGINATION_FADE_IN_DURATION = 83;
+    private static final int PAGINATION_FADE_OUT_DURATION = 167;
 
     private static final int ENTER_ANIMATION_START_DELAY = 300;
     private static final int ENTER_ANIMATION_STAGGERED_DELAY = 150;
@@ -66,8 +68,9 @@
 
     private static final int PAGE_INDICATOR_ALPHA = 255;
     private static final int DOT_ALPHA = 128;
-    private static final int DOT_GAP_FACTOR = 3;
-    private static final int VISIBLE_ALPHA = 1;
+    private static final float DOT_ALPHA_FRACTION = 0.5f;
+    private static final int DOT_GAP_FACTOR = SHOW_DOT_PAGINATION.get() ? 4 : 3;
+    private static final int VISIBLE_ALPHA = 255;
     private static final int INVISIBLE_ALPHA = 0;
     private Paint mPaginationPaint;
 
@@ -89,21 +92,21 @@
                     obj.invalidate();
                     obj.invalidateOutline();
                 }
-            };
+    };
 
-    private static final FloatProperty<PageIndicatorDots> PAGINATION_ALPHA =
-            new FloatProperty<PageIndicatorDots>("pagination_alpha") {
-                @Override
-                public Float get(PageIndicatorDots obj) {
-                    return obj.getAlpha();
-                }
+    private static final IntProperty<PageIndicatorDots> PAGINATION_ALPHA =
+            new IntProperty<PageIndicatorDots>("pagination_alpha") {
+        @Override
+        public Integer get(PageIndicatorDots obj) {
+            return obj.mPaginationPaint.getAlpha();
+        }
 
-                @Override
-                public void setValue(PageIndicatorDots obj, float alpha) {
-                    obj.setAlpha(alpha);
-                    obj.invalidate();
-                }
-            };
+        @Override
+        public void setValue(PageIndicatorDots obj, int alpha) {
+            obj.mPaginationPaint.setAlpha(alpha);
+            obj.invalidate();
+        }
+    };
 
     private final Handler mDelayedPaginationFadeHandler = new Handler(Looper.getMainLooper());
     private final float mDotRadius;
@@ -112,9 +115,8 @@
 
     private int mNumPages;
     private int mActivePage;
-    private int mCurrentScroll;
     private int mTotalScroll;
-    private boolean mShouldAutoHide = true;
+    private boolean mShouldAutoHide;
     private int mToAlpha;
 
     /**
@@ -133,7 +135,8 @@
 
     private float[] mEntryAnimationRadiusFactors;
 
-    private Runnable mHidePaginationRunnable = () -> animatePaginationToAlpha(INVISIBLE_ALPHA);
+    private final Runnable mHidePaginationRunnable =
+            () -> animatePaginationToAlpha(INVISIBLE_ALPHA);
 
     public PageIndicatorDots(Context context) {
         this(context, null);
@@ -149,7 +152,10 @@
         mPaginationPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mPaginationPaint.setStyle(Style.FILL);
         mPaginationPaint.setColor(Themes.getAttrColor(context, R.attr.folderPaginationColor));
-        mDotRadius = getResources().getDimension(R.dimen.page_indicator_dot_size) / 2;
+        mDotRadius = (SHOW_DOT_PAGINATION.get()
+                ? getResources().getDimension(R.dimen.page_indicator_dot_size_v2)
+                : getResources().getDimension(R.dimen.page_indicator_dot_size))
+                / 2;
         mCircleGap = DOT_GAP_FACTOR * mDotRadius;
         setOutlineProvider(new MyOutlineProver());
         mIsRtl = Utilities.isRtl(getResources());
@@ -157,15 +163,19 @@
 
     @Override
     public void setScroll(int currentScroll, int totalScroll) {
-        if (SHOW_DOT_PAGINATION.get()) {
-            animatePaginationToAlpha(VISIBLE_ALPHA);
+        if (SHOW_DOT_PAGINATION.get() && mActivePage != 0 && currentScroll == 0) {
+            CURRENT_POSITION.set(this, (float) mActivePage);
+            return;
         }
 
         if (mNumPages <= 1) {
-            mCurrentScroll = 0;
             return;
         }
 
+        if (mShouldAutoHide) {
+            animatePaginationToAlpha(VISIBLE_ALPHA);
+        }
+
         if (mIsRtl) {
             currentScroll = totalScroll - currentScroll;
         }
@@ -173,7 +183,7 @@
         mTotalScroll = totalScroll;
 
         int scrollPerPage = totalScroll / (mNumPages - 1);
-        int pageToLeft = currentScroll / scrollPerPage;
+        int pageToLeft = scrollPerPage == 0 ? 0 : currentScroll / scrollPerPage;
         int pageToLeftScroll = pageToLeft * scrollPerPage;
         int pageToRightScroll = pageToLeftScroll + scrollPerPage;
 
@@ -181,31 +191,39 @@
         if (currentScroll < pageToLeftScroll + scrollThreshold) {
             // scroll is within the left page's threshold
             animateToPosition(pageToLeft);
-            if (SHOW_DOT_PAGINATION.get()) {
+            if (mShouldAutoHide) {
                 hideAfterDelay();
             }
         } else if (currentScroll > pageToRightScroll - scrollThreshold) {
             // scroll is far enough from left page to go to the right page
             animateToPosition(pageToLeft + 1);
-            if (SHOW_DOT_PAGINATION.get()) {
+            if (mShouldAutoHide) {
                 hideAfterDelay();
             }
         } else {
             // scroll is between left and right page
             animateToPosition(pageToLeft + SHIFT_PER_ANIMATION);
+            if (mShouldAutoHide) {
+                mDelayedPaginationFadeHandler.removeCallbacksAndMessages(null);
+            }
         }
     }
 
     @Override
     public void setShouldAutoHide(boolean shouldAutoHide) {
-        mShouldAutoHide = shouldAutoHide;
-        if (shouldAutoHide && this.getAlpha() > INVISIBLE_ALPHA) {
+        mShouldAutoHide = shouldAutoHide && SHOW_DOT_PAGINATION.get();
+        if (shouldAutoHide && mPaginationPaint.getAlpha() > INVISIBLE_ALPHA) {
             hideAfterDelay();
         } else if (!shouldAutoHide) {
             mDelayedPaginationFadeHandler.removeCallbacksAndMessages(null);
         }
     }
 
+    @Override
+    public void setPaintColor(int color) {
+        mPaginationPaint.setColor(color);
+    }
+
     private void hideAfterDelay() {
         mDelayedPaginationFadeHandler.removeCallbacksAndMessages(null);
         mDelayedPaginationFadeHandler.postDelayed(mHidePaginationRunnable, PAGINATION_FADE_DELAY);
@@ -216,14 +234,17 @@
             // Ignore the new animation if it is going to the same alpha as the current animation.
             return;
         }
-        mToAlpha = alpha;
 
         if (mAlphaAnimator != null) {
             mAlphaAnimator.cancel();
         }
-        mAlphaAnimator = ObjectAnimator.ofFloat(this, PAGINATION_ALPHA,
+        mAlphaAnimator = ObjectAnimator.ofInt(this, PAGINATION_ALPHA,
                 alpha);
-        mAlphaAnimator.setDuration(ALPHA_ANIMATE_DURATION);
+        // If we are animating to decrease the alpha, then it's a fade out animation
+        // whereas if we are animating to increase the alpha, it's a fade in animation.
+        mAlphaAnimator.setDuration(alpha < mToAlpha
+                ? PAGINATION_FADE_OUT_DURATION
+                : PAGINATION_FADE_IN_DURATION);
         mAlphaAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
@@ -231,7 +252,7 @@
             }
         });
         mAlphaAnimator.start();
-
+        mToAlpha = alpha;
     }
 
     /**
@@ -349,7 +370,12 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
-        if ((mShouldAutoHide && mTotalScroll == 0) || mNumPages < 2) {
+        if (mNumPages < 2) {
+            return;
+        }
+
+        if (mShouldAutoHide && mTotalScroll == 0) {
+            mPaginationPaint.setAlpha(INVISIBLE_ALPHA);
             return;
         }
 
@@ -373,15 +399,19 @@
                 x += circleGap;
             }
         } else {
+            int alpha = mPaginationPaint.getAlpha();
+
             // Here we draw the dots
-            mPaginationPaint.setAlpha(DOT_ALPHA);
+            mPaginationPaint.setAlpha(SHOW_DOT_PAGINATION.get()
+                    ? ((int) (alpha * DOT_ALPHA_FRACTION))
+                    : DOT_ALPHA);
             for (int i = 0; i < mNumPages; i++) {
                 canvas.drawCircle(x, y, mDotRadius, mPaginationPaint);
                 x += circleGap;
             }
 
             // Here we draw the current page indicator
-            mPaginationPaint.setAlpha(PAGE_INDICATOR_ALPHA);
+            mPaginationPaint.setAlpha(SHOW_DOT_PAGINATION.get() ? alpha : PAGE_INDICATOR_ALPHA);
             canvas.drawRoundRect(getActiveRect(), mDotRadius, mDotRadius, mPaginationPaint);
         }
     }
@@ -450,6 +480,9 @@
         @Override
         public void onAnimationEnd(Animator animation) {
             if (!mCancelled) {
+                if (mShouldAutoHide && SHOW_DOT_PAGINATION.get()) {
+                    hideAfterDelay();
+                }
                 mAnimator = null;
                 animateToPosition(mFinalPosition);
             }
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index 150bca4..db23566 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -16,8 +16,6 @@
 
 package com.android.launcher3.pm;
 
-import static com.android.launcher3.LauncherPrefs.getPrefs;
-
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.LauncherApps;
@@ -34,6 +32,7 @@
 import androidx.annotation.RequiresApi;
 import androidx.annotation.WorkerThread;
 
+import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.SessionCommitReceiver;
 import com.android.launcher3.Utilities;
@@ -65,7 +64,7 @@
     // Set<String> of session ids of promise icons that have been added to the home screen
     // as FLAG_PROMISE_NEW_INSTALLS.
     @NonNull
-    protected static final String PROMISE_ICON_IDS = "promise_icon_ids";
+    public static final String PROMISE_ICON_IDS = "promise_icon_ids";
 
     private static final boolean DEBUG = false;
 
@@ -102,7 +101,7 @@
             return mPromiseIconIds;
         }
         mPromiseIconIds = IntSet.wrap(IntArray.fromConcatString(
-                getPrefs(mAppContext).getString(PROMISE_ICON_IDS, "")));
+                LauncherPrefs.get(mAppContext).get(LauncherPrefs.PROMISE_ICON_IDS)));
 
         IntArray existingIds = new IntArray();
         for (SessionInfo info : getActiveSessions().values()) {
@@ -146,9 +145,8 @@
     }
 
     private void updatePromiseIconPrefs() {
-        getPrefs(mAppContext).edit()
-                .putString(PROMISE_ICON_IDS, getPromiseIconIds().getArray().toConcatString())
-                .apply();
+        LauncherPrefs.get(mAppContext).put(LauncherPrefs.PROMISE_ICON_IDS,
+                getPromiseIconIds().getArray().toConcatString());
     }
 
     @Nullable
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 0e25984c..69bba69 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -40,6 +40,7 @@
 public abstract class SystemShortcut<T extends Context & ActivityContext> extends ItemInfo
         implements View.OnClickListener {
 
+    private static final String TAG = SystemShortcut.class.getSimpleName();
     private final int mIconResId;
     protected final int mLabelResId;
     protected int mAccessibilityActionId;
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index 5e97b2d..2a452be 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -17,13 +17,14 @@
 package com.android.launcher3.provider;
 
 import static com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY;
-import static com.android.launcher3.InvariantDeviceProfile.TYPE_PHONE;
+import static com.android.launcher3.LauncherPrefs.APP_WIDGET_IDS;
+import static com.android.launcher3.LauncherPrefs.OLD_APP_WIDGET_IDS;
+import static com.android.launcher3.LauncherPrefs.RESTORE_DEVICE;
 import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
 
 import android.app.backup.BackupManager;
 import android.content.ContentValues;
 import android.content.Context;
-import android.content.SharedPreferences;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.os.UserHandle;
@@ -62,13 +63,13 @@
 public class RestoreDbTask {
 
     private static final String TAG = "RestoreDbTask";
-    private static final String RESTORED_DEVICE_TYPE = "restored_task_pending";
+    public static final String RESTORED_DEVICE_TYPE = "restored_task_pending";
 
     private static final String INFO_COLUMN_NAME = "name";
     private static final String INFO_COLUMN_DEFAULT_VALUE = "dflt_value";
 
-    private static final String APPWIDGET_OLD_IDS = "appwidget_old_ids";
-    private static final String APPWIDGET_IDS = "appwidget_ids";
+    public static final String APPWIDGET_OLD_IDS = "appwidget_old_ids";
+    public static final String APPWIDGET_IDS = "appwidget_ids";
 
     /**
      * Tries to restore the backup DB if needed
@@ -87,7 +88,7 @@
 
         // Set is pending to false irrespective of the result, so that it doesn't get
         // executed again.
-        LauncherPrefs.getPrefs(context).edit().remove(RESTORED_DEVICE_TYPE).commit();
+        LauncherPrefs.get(context).removeSync(RESTORE_DEVICE);
 
         idp.reinitializeAfterRestore(context);
     }
@@ -240,8 +241,7 @@
         }
 
         // If restored from a single display backup, remove gaps between screenIds
-        if (LauncherPrefs.getPrefs(context).getInt(RESTORED_DEVICE_TYPE, TYPE_PHONE)
-                != TYPE_MULTI_DISPLAY) {
+        if (LauncherPrefs.get(context).get(RESTORE_DEVICE) != TYPE_MULTI_DISPLAY) {
             removeScreenIdGaps(db);
         }
 
@@ -339,7 +339,7 @@
     }
 
     public static boolean isPending(Context context) {
-        return LauncherPrefs.getPrefs(context).contains(RESTORED_DEVICE_TYPE);
+        return LauncherPrefs.get(context).has(RESTORE_DEVICE);
     }
 
     /**
@@ -347,34 +347,31 @@
      */
     public static void setPending(Context context) {
         FileLog.d(TAG, "Restore data received through full backup ");
-        LauncherPrefs.getPrefs(context).edit()
-                .putInt(RESTORED_DEVICE_TYPE, new DeviceGridState(context).getDeviceType())
-                .commit();
+        LauncherPrefs.get(context)
+                .putSync(RESTORE_DEVICE.to(new DeviceGridState(context).getDeviceType()));
     }
 
     private void restoreAppWidgetIdsIfExists(Context context) {
-        SharedPreferences prefs = LauncherPrefs.getPrefs(context);
-        if (prefs.contains(APPWIDGET_OLD_IDS) && prefs.contains(APPWIDGET_IDS)) {
+        LauncherPrefs lp = LauncherPrefs.get(context);
+        if (lp.has(APP_WIDGET_IDS, OLD_APP_WIDGET_IDS)) {
             LauncherWidgetHolder holder = LauncherWidgetHolder.newInstance(context);
             AppWidgetsRestoredReceiver.restoreAppWidgetIds(context,
-                    IntArray.fromConcatString(prefs.getString(APPWIDGET_OLD_IDS, "")).toArray(),
-                    IntArray.fromConcatString(prefs.getString(APPWIDGET_IDS, "")).toArray(),
+                    IntArray.fromConcatString(lp.get(OLD_APP_WIDGET_IDS)).toArray(),
+                    IntArray.fromConcatString(lp.get(APP_WIDGET_IDS)).toArray(),
                     holder);
             holder.destroy();
         } else {
             FileLog.d(TAG, "No app widget ids to restore.");
         }
 
-        prefs.edit().remove(APPWIDGET_OLD_IDS)
-                .remove(APPWIDGET_IDS).apply();
+        lp.remove(APP_WIDGET_IDS, OLD_APP_WIDGET_IDS);
     }
 
     public static void setRestoredAppWidgetIds(Context context, @NonNull int[] oldIds,
             @NonNull int[] newIds) {
-        LauncherPrefs.getPrefs(context).edit()
-                .putString(APPWIDGET_OLD_IDS, IntArray.wrap(oldIds).toConcatString())
-                .putString(APPWIDGET_IDS, IntArray.wrap(newIds).toConcatString())
-                .commit();
+        LauncherPrefs.get(context).putSync(
+                OLD_APP_WIDGET_IDS.to(IntArray.wrap(oldIds).toConcatString()),
+                APP_WIDGET_IDS.to(IntArray.wrap(newIds).toConcatString()));
     }
 
 }
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
index a2353d8..56dffa9 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
@@ -175,8 +175,9 @@
         // Note: There should be at most one log per method call. This is enforced implicitly
         // by using if-else statements.
         AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this);
-        if (topView != null && topView.onBackPressed()) {
+        if (topView != null && topView.canHandleBack()) {
             // Handled by the floating view.
+            topView.onBackInvoked();
         } else {
             showAppDrawer(false);
         }
diff --git a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
index c81214e..40fc16e 100644
--- a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
+++ b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
@@ -15,6 +15,9 @@
  */
 package com.android.launcher3.settings;
 
+import static android.content.Intent.ACTION_PACKAGE_ADDED;
+import static android.content.Intent.ACTION_PACKAGE_CHANGED;
+import static android.content.Intent.ACTION_PACKAGE_REMOVED;
 import static android.content.pm.PackageManager.GET_RESOLVED_FILTER;
 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
 import static android.view.View.GONE;
@@ -25,11 +28,9 @@
 import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.pluginEnabledKey;
 
 import android.annotation.TargetApi;
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
@@ -66,6 +67,7 @@
 import com.android.launcher3.secondarydisplay.SecondaryDisplayLauncher;
 import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
 import com.android.launcher3.util.OnboardingPrefs;
+import com.android.launcher3.util.SimpleBroadcastReceiver;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -83,12 +85,8 @@
     private static final String ACTION_PLUGIN_SETTINGS = "com.android.systemui.action.PLUGIN_SETTINGS";
     private static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN";
 
-    private final BroadcastReceiver mPluginReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            loadPluginPrefs();
-        }
-    };
+    private final SimpleBroadcastReceiver mPluginReceiver =
+            new SimpleBroadcastReceiver(i -> loadPluginPrefs());
 
     private PreferenceScreen mPreferenceScreen;
 
@@ -97,13 +95,9 @@
 
     @Override
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
-        IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
-        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
-        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        filter.addDataScheme("package");
-        getContext().registerReceiver(mPluginReceiver, filter);
-        getContext().registerReceiver(mPluginReceiver,
-                new IntentFilter(Intent.ACTION_USER_UNLOCKED));
+        mPluginReceiver.registerPkgActions(getContext(), null,
+                ACTION_PACKAGE_ADDED, ACTION_PACKAGE_CHANGED, ACTION_PACKAGE_REMOVED);
+        mPluginReceiver.register(getContext(), Intent.ACTION_USER_UNLOCKED);
 
         mPreferenceScreen = getPreferenceManager().createPreferenceScreen(getContext());
         setPreferenceScreen(mPreferenceScreen);
@@ -185,7 +179,7 @@
     @Override
     public void onDestroy() {
         super.onDestroy();
-        getContext().unregisterReceiver(mPluginReceiver);
+        mPluginReceiver.unregisterReceiverSafely(getContext());
     }
 
     private PreferenceCategory newCategory(String title) {
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index 3e2d051..8d6a5cb 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -93,7 +93,8 @@
         WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
 
         Intent intent = getIntent();
-        if (intent.hasExtra(EXTRA_FRAGMENT) || intent.hasExtra(EXTRA_FRAGMENT_ARGS)) {
+        if (intent.hasExtra(EXTRA_FRAGMENT) || intent.hasExtra(EXTRA_FRAGMENT_ARGS)
+                || intent.hasExtra(EXTRA_FRAGMENT_ARG_KEY)) {
             getActionBar().setDisplayHomeAsUpEnabled(true);
         }
 
@@ -225,9 +226,10 @@
                         getResources().getString(R.string.search_pref_screen_title))){
                     DeviceProfile mDeviceProfile = InvariantDeviceProfile.INSTANCE.get(
                             getContext()).getDeviceProfile(getContext());
-                    getPreferenceScreen().setTitle(mDeviceProfile.isTablet ?
-                            R.string.search_pref_screen_title_tablet
-                            : R.string.search_pref_screen_title);
+                    getPreferenceScreen().setTitle(mDeviceProfile.isMultiDisplay
+                            || mDeviceProfile.isPhone ?
+                            R.string.search_pref_screen_title :
+                            R.string.search_pref_screen_title_tablet);
                 }
                 getActivity().setTitle(getPreferenceScreen().getTitle());
             }
@@ -268,8 +270,8 @@
                     return !WidgetsModel.GO_DISABLE_NOTIFICATION_DOTS;
 
                 case ALLOW_ROTATION_PREFERENCE_KEY:
-                    DisplayController.Info info = InvariantDeviceProfile.INSTANCE.get(
-                            getContext()).getDeviceProfile(getContext()).getDisplayInfo();
+                    DisplayController.Info info =
+                            DisplayController.INSTANCE.get(getContext()).getInfo();
                     if (info.isTablet(info.realBounds)) {
                         // Launcher supports rotation by default. No need to show this setting.
                         return false;
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index ad1e7f0..34ac8c2 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -28,6 +28,8 @@
 import android.os.Handler;
 import android.os.Looper;
 
+import androidx.annotation.FloatRange;
+
 import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.PendingAnimation;
@@ -195,6 +197,21 @@
         }
     }
 
+    /** Handles backProgress in predictive back gesture by passing it to state handlers. */
+    public void onBackProgressed(
+            STATE_TYPE toState, @FloatRange(from = 0.0, to = 1.0) float backProgress) {
+        for (StateHandler handler : getStateHandlers()) {
+            handler.onBackProgressed(toState, backProgress);
+        }
+    }
+
+    /** Handles back cancelled event in predictive back gesture by passing it to state handlers. */
+    public void onBackCancelled(STATE_TYPE toState) {
+        for (StateHandler handler : getStateHandlers()) {
+            handler.onBackCancelled(toState);
+        }
+    }
+
     private void goToState(
             STATE_TYPE state, boolean animated, long delay, AnimatorListener listener) {
         animated &= areAnimatorsEnabled();
@@ -586,6 +603,13 @@
          */
         void setStateWithAnimation(
                 STATE_TYPE toState, StateAnimationConfig config, PendingAnimation animation);
+
+        /** Handles backProgress in predictive back gesture for target state. */
+        default void onBackProgressed(
+                STATE_TYPE toState, @FloatRange(from = 0.0, to = 1.0) float backProgress) {};
+
+        /** Handles back cancelled event in predictive back gesture for target state.  */
+        default void onBackCancelled(STATE_TYPE toState) {};
     }
 
     public interface StateListener<STATE_TYPE> {
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index acb7eb3..9a34478 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -201,6 +201,13 @@
                 });
             }
 
+            case TestProtocol.REQUEST_WORKSPACE_COLUMNS_ROWS: {
+                return getLauncherUIProperty(Bundle::putParcelable, launcher -> new Point(
+                        InvariantDeviceProfile.INSTANCE.get(mContext).numColumns,
+                        InvariantDeviceProfile.INSTANCE.get(mContext).numRows)
+                );
+            }
+
             case TestProtocol.REQUEST_HOTSEAT_CELL_CENTER: {
                 final HotseatCellCenterRequest request = extra.getParcelable(
                         TestProtocol.TEST_INFO_REQUEST_FIELD);
diff --git a/src/com/android/launcher3/testing/shared/TestProtocol.java b/src/com/android/launcher3/testing/shared/TestProtocol.java
index 1deb23d..9b2ce9a 100644
--- a/src/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/src/com/android/launcher3/testing/shared/TestProtocol.java
@@ -123,6 +123,7 @@
 
     public static final String REQUEST_WORKSPACE_CELL_LAYOUT_SIZE = "workspace-cell-layout-size";
     public static final String REQUEST_WORKSPACE_CELL_CENTER = "workspace-cell-center";
+    public static final String REQUEST_WORKSPACE_COLUMNS_ROWS = "workspace-columns-rows";
 
     public static final String REQUEST_HOTSEAT_CELL_CENTER = "hotseat-cell-center";
 
@@ -148,7 +149,6 @@
     public static final String NULL_INT_SET = "b/200572078";
     public static final String MISSING_PROMISE_ICON = "b/202985412";
     public static final String TASKBAR_IN_APP_STATE = "b/227657604";
-    public static final String INCORRECT_INFO_UPDATED = "b/239465630";
     public static final String NPE_TRANSIENT_TASKBAR = "b/257549303";
 
     public static final String REQUEST_EMULATE_DISPLAY = "emulate-display";
diff --git a/src/com/android/launcher3/testing/shared/WorkspaceCellCenterRequest.java b/src/com/android/launcher3/testing/shared/WorkspaceCellCenterRequest.java
index 80dbef8..e2cd8ea 100644
--- a/src/com/android/launcher3/testing/shared/WorkspaceCellCenterRequest.java
+++ b/src/com/android/launcher3/testing/shared/WorkspaceCellCenterRequest.java
@@ -124,7 +124,7 @@
          * Set span Height in cells
          */
         public WorkspaceCellCenterRequest.Builder setSpanY(int y) {
-            this.mCellY = y;
+            this.mSpanY = y;
             return this;
         }
 
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 8f7a4ec..c499e35 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -32,7 +32,6 @@
 
 import android.animation.Animator.AnimatorListener;
 import android.animation.ValueAnimator;
-import android.util.Log;
 import android.view.MotionEvent;
 
 import com.android.launcher3.Launcher;
@@ -292,11 +291,18 @@
                             ? mToState : mFromState;
             // snap to top or bottom using the release velocity
         } else {
-            float successTransitionProgress =
-                    mLauncher.getDeviceProfile().isTablet
-                            && (mToState == ALL_APPS || mFromState == ALL_APPS)
-                            ? TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS
-                            : SUCCESS_TRANSITION_PROGRESS;
+            float successTransitionProgress = SUCCESS_TRANSITION_PROGRESS;
+            if (mLauncher.getDeviceProfile().isTablet
+                    && (mToState == ALL_APPS || mFromState == ALL_APPS)) {
+                successTransitionProgress = TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS;
+            } else if (!mLauncher.getDeviceProfile().isTablet
+                    && mToState == ALL_APPS && mFromState == NORMAL) {
+                successTransitionProgress = AllAppsSwipeController.ALL_APPS_STATE_TRANSITION_MANUAL;
+            } else if (!mLauncher.getDeviceProfile().isTablet
+                    && mToState == NORMAL && mFromState == ALL_APPS) {
+                successTransitionProgress =
+                        1 - AllAppsSwipeController.ALL_APPS_STATE_TRANSITION_MANUAL;
+            }
             targetState =
                     (interpolatedProgress > successTransitionProgress) ? mToState : mFromState;
         }
diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
index 5279dec..bfd0e1b 100644
--- a/src/com/android/launcher3/touch/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -17,7 +17,6 @@
 
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.anim.Interpolators.DECELERATED_EASE;
 import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
 import static com.android.launcher3.anim.Interpolators.EMPHASIZED_ACCELERATE;
 import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE;
@@ -64,11 +63,14 @@
 
     // ---- Custom interpolators for NORMAL -> ALL_APPS on phones only. ----
 
-    private static final float WORKSPACE_MOTION_START_ATOMIC = 0.1667f;
-    private static final float ALL_APPS_STATE_TRANSITION_ATOMIC = 0.305f;
-    private static final float ALL_APPS_STATE_TRANSITION_MANUAL = 0.4f;
-    private static final float ALL_APPS_FADE_END_ATOMIC = 0.4717f;
+    public static final float ALL_APPS_STATE_TRANSITION_ATOMIC = 0.3333f;
+    public static final float ALL_APPS_STATE_TRANSITION_MANUAL = 0.4f;
+    private static final float ALL_APPS_FADE_END_ATOMIC = 0.8333f;
+    private static final float ALL_APPS_FADE_END_MANUAL = 0.8f;
     private static final float ALL_APPS_FULL_DEPTH_PROGRESS = 0.5f;
+    private static final float SCRIM_FADE_START_ATOMIC = 0.2642f;
+    private static final float SCRIM_FADE_START_MANUAL = 0.117f;
+    private static final float WORKSPACE_MOTION_START_ATOMIC = 0.1667f;
 
     private static final Interpolator LINEAR_EARLY_MANUAL =
             Interpolators.clampToProgress(LINEAR, 0f, ALL_APPS_STATE_TRANSITION_MANUAL);
@@ -98,27 +100,30 @@
     public static final Interpolator HOTSEAT_FADE_ATOMIC = STEP_TRANSITION_ATOMIC;
     public static final Interpolator HOTSEAT_FADE_MANUAL = STEP_TRANSITION_MANUAL;
 
-    public static final Interpolator HOTSEAT_SCALE_ATOMIC = STEP_TRANSITION_ATOMIC;
-    public static final Interpolator HOTSEAT_SCALE_MANUAL = LINEAR_EARLY_MANUAL;
-
-    public static final Interpolator HOTSEAT_TRANSLATE_ATOMIC =
+    public static final Interpolator HOTSEAT_SCALE_ATOMIC =
             Interpolators.clampToProgress(
                     EMPHASIZED_ACCELERATE, WORKSPACE_MOTION_START_ATOMIC,
                     ALL_APPS_STATE_TRANSITION_ATOMIC);
+    public static final Interpolator HOTSEAT_SCALE_MANUAL = LINEAR_EARLY_MANUAL;
+
+    public static final Interpolator HOTSEAT_TRANSLATE_ATOMIC = STEP_TRANSITION_ATOMIC;
     public static final Interpolator HOTSEAT_TRANSLATE_MANUAL = STEP_TRANSITION_MANUAL;
 
     public static final Interpolator SCRIM_FADE_ATOMIC =
             Interpolators.clampToProgress(
                     Interpolators.mapToProgress(LINEAR, 0f, 0.8f),
-                    WORKSPACE_MOTION_START_ATOMIC, ALL_APPS_STATE_TRANSITION_ATOMIC);
-    public static final Interpolator SCRIM_FADE_MANUAL = LINEAR_EARLY_MANUAL;
+                    SCRIM_FADE_START_ATOMIC, ALL_APPS_STATE_TRANSITION_ATOMIC);
+    public static final Interpolator SCRIM_FADE_MANUAL =
+            Interpolators.clampToProgress(
+                    LINEAR, SCRIM_FADE_START_MANUAL, ALL_APPS_STATE_TRANSITION_MANUAL);
 
     public static final Interpolator ALL_APPS_FADE_ATOMIC =
             Interpolators.clampToProgress(
-                    Interpolators.mapToProgress(DECELERATED_EASE, 0.2f, 1f),
+                    Interpolators.mapToProgress(EMPHASIZED_DECELERATE, 0.2f, 1f),
                     ALL_APPS_STATE_TRANSITION_ATOMIC, ALL_APPS_FADE_END_ATOMIC);
     public static final Interpolator ALL_APPS_FADE_MANUAL =
-            Interpolators.clampToProgress(LINEAR, ALL_APPS_STATE_TRANSITION_MANUAL, 1f);
+            Interpolators.clampToProgress(
+                    LINEAR, ALL_APPS_STATE_TRANSITION_MANUAL, ALL_APPS_FADE_END_MANUAL);
 
     public static final Interpolator ALL_APPS_VERTICAL_PROGRESS_ATOMIC =
             Interpolators.clampToProgress(
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index b7e0105..790c226 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -23,14 +23,14 @@
 import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_QUIET_USER;
 import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE;
 import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageInstaller.SessionInfo;
-import android.os.Process;
-import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
@@ -66,6 +66,8 @@
 import com.android.launcher3.widget.WidgetManagerHelper;
 
 import java.util.Collections;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
 
 /**
  * Class for handling clicks on workspace and all-apps items
@@ -156,32 +158,18 @@
 
     private static void onClickPendingAppItem(View v, Launcher launcher, String packageName,
             boolean downloadStarted) {
-        if (downloadStarted) {
-            // If the download has started, simply direct to the market app.
-            startMarketIntentForPackage(v, launcher, packageName);
-            return;
-        }
-        UserHandle user = v.getTag() instanceof ItemInfo
-                ? ((ItemInfo) v.getTag()).user : Process.myUserHandle();
-        new AlertDialog.Builder(launcher)
-                .setTitle(R.string.abandoned_promises_title)
-                .setMessage(R.string.abandoned_promise_explanation)
-                .setPositiveButton(R.string.abandoned_search,
-                        (d, i) -> startMarketIntentForPackage(v, launcher, packageName))
-                .setNeutralButton(R.string.abandoned_clean_this,
-                        (d, i) -> launcher.getWorkspace()
-                                .persistRemoveItemsByMatcher(ItemInfoMatcher.ofPackages(
-                                        Collections.singleton(packageName), user),
-                                        "user explicitly removes the promise app icon"))
-                .create().show();
-    }
-
-    private static void startMarketIntentForPackage(View v, Launcher launcher, String packageName) {
         ItemInfo item = (ItemInfo) v.getTag();
+        CompletableFuture<SessionInfo> siFuture;
         if (Utilities.ATLEAST_Q) {
-            SessionInfo sessionInfo = InstallSessionHelper.INSTANCE.get(launcher)
-                    .getActiveSessionInfo(item.user, packageName);
-            if (sessionInfo != null) {
+            siFuture = CompletableFuture.supplyAsync(() ->
+                    InstallSessionHelper.INSTANCE.get(launcher)
+                            .getActiveSessionInfo(item.user, packageName),
+                    UI_HELPER_EXECUTOR);
+        } else {
+            siFuture = CompletableFuture.completedFuture(null);
+        }
+        Consumer<SessionInfo> marketLaunchAction = sessionInfo -> {
+            if (sessionInfo != null && Utilities.ATLEAST_Q) {
                 LauncherApps launcherApps = launcher.getSystemService(LauncherApps.class);
                 try {
                     launcherApps.startPackageInstallerSessionDetailsActivity(sessionInfo, null,
@@ -191,11 +179,27 @@
                     Log.e(TAG, "Unable to launch market intent for package=" + packageName, e);
                 }
             }
-        }
+            // Fallback to using custom market intent.
+            Intent intent = new PackageManagerHelper(launcher).getMarketIntent(packageName);
+            launcher.startActivitySafely(v, intent, item);
+        };
 
-        // Fallback to using custom market intent.
-        Intent intent = new PackageManagerHelper(launcher).getMarketIntent(packageName);
-        launcher.startActivitySafely(v, intent, item);
+        if (downloadStarted) {
+            // If the download has started, simply direct to the market app.
+            siFuture.thenAcceptAsync(marketLaunchAction, MAIN_EXECUTOR);
+            return;
+        }
+        new AlertDialog.Builder(launcher)
+                .setTitle(R.string.abandoned_promises_title)
+                .setMessage(R.string.abandoned_promise_explanation)
+                .setPositiveButton(R.string.abandoned_search,
+                        (d, i) -> siFuture.thenAcceptAsync(marketLaunchAction, MAIN_EXECUTOR))
+                .setNeutralButton(R.string.abandoned_clean_this,
+                        (d, i) -> launcher.getWorkspace()
+                                .persistRemoveItemsByMatcher(ItemInfoMatcher.ofPackages(
+                                        Collections.singleton(packageName), item.user),
+                                        "user explicitly removes the promise app icon"))
+                .create().show();
     }
 
     /**
@@ -339,7 +343,8 @@
                 return;
             }
         }
-        if (v != null && launcher.supportsAdaptiveIconAnimation(v)) {
+        if (v != null && launcher.supportsAdaptiveIconAnimation(v)
+                && !item.shouldUseBackgroundAnimation()) {
             // Preload the icon to reduce latency b/w swapping the floating view with the original.
             FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */);
         }
diff --git a/src/com/android/launcher3/util/DimensionUtils.kt b/src/com/android/launcher3/util/DimensionUtils.kt
index 758b3a9..1922310 100644
--- a/src/com/android/launcher3/util/DimensionUtils.kt
+++ b/src/com/android/launcher3/util/DimensionUtils.kt
@@ -24,12 +24,15 @@
 
 object DimensionUtils {
     /**
-     * Point where x is width, and y is height of taskbar based on provided [deviceProfile]
-     * x or y could also be -1 to indicate there is no dimension specified
+     * Point where x is width, and y is height of taskbar based on provided [deviceProfile] x or y
+     * could also be -1 to indicate there is no dimension specified
      */
     @JvmStatic
-    fun getTaskbarPhoneDimensions(deviceProfile: DeviceProfile, res: Resources,
-                                  isPhoneMode: Boolean): Point {
+    fun getTaskbarPhoneDimensions(
+        deviceProfile: DeviceProfile,
+        res: Resources,
+        isPhoneMode: Boolean
+    ): Point {
         val p = Point()
         // Taskbar for large screen
         if (!isPhoneMode) {
@@ -57,4 +60,4 @@
         p.y = ViewGroup.LayoutParams.MATCH_PARENT
         return p
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index c52890f..9ed6700 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -23,7 +23,6 @@
 import static com.android.launcher3.config.FeatureFlags.ENABLE_TRANSIENT_TASKBAR;
 import static com.android.launcher3.config.FeatureFlags.FORCE_PERSISTENT_TASKBAR;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;
 import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH;
 
 import android.annotation.SuppressLint;
@@ -111,8 +110,7 @@
         }
 
         // Initialize navigation mode change listener
-        mContext.registerReceiver(mReceiver,
-                getPackageFilter(TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED));
+        mReceiver.registerPkgActions(mContext, TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED);
 
         WindowManagerProxy wmProxy = WindowManagerProxy.INSTANCE.get(context);
         Context displayInfoContext = getDisplayInfoContext(display);
diff --git a/src/com/android/launcher3/util/LauncherBindableItemsContainer.java b/src/com/android/launcher3/util/LauncherBindableItemsContainer.java
index a4cb30a..f73940b 100644
--- a/src/com/android/launcher3/util/LauncherBindableItemsContainer.java
+++ b/src/com/android/launcher3/util/LauncherBindableItemsContainer.java
@@ -50,7 +50,12 @@
                 Drawable oldIcon = shortcut.getIcon();
                 boolean oldPromiseState = (oldIcon instanceof PreloadIconDrawable)
                         && ((PreloadIconDrawable) oldIcon).hasNotCompleted();
-                shortcut.applyFromWorkspaceItem(si, si.isPromise() != oldPromiseState);
+                shortcut.applyFromWorkspaceItem(
+                        si,
+                        si.isPromise() != oldPromiseState
+                                && oldIcon instanceof PreloadIconDrawable
+                                ? (PreloadIconDrawable) oldIcon
+                                : null);
             } else if (info instanceof FolderInfo && v instanceof FolderIcon) {
                 ((FolderIcon) v).updatePreviewItems(updates::contains);
             }
@@ -74,7 +79,7 @@
         ItemOperator op = (info, v) -> {
             if (info instanceof WorkspaceItemInfo && v instanceof BubbleTextView
                     && updates.contains(info)) {
-                ((BubbleTextView) v).applyLoadingState(false /* promiseStateChanged */);
+                ((BubbleTextView) v).applyLoadingState(null);
             } else if (v instanceof PendingAppWidgetHostView
                     && info instanceof LauncherAppWidgetInfo
                     && updates.contains(info)) {
diff --git a/src/com/android/launcher3/util/LockedUserState.kt b/src/com/android/launcher3/util/LockedUserState.kt
new file mode 100644
index 0000000..7b49583
--- /dev/null
+++ b/src/com/android/launcher3/util/LockedUserState.kt
@@ -0,0 +1,57 @@
+package com.android.launcher3.util
+
+import android.content.Context
+import android.content.Intent
+import android.os.Process
+import android.os.UserManager
+import androidx.annotation.VisibleForTesting
+
+class LockedUserState(private val mContext: Context) : SafeCloseable {
+    var isUserUnlocked: Boolean
+        private set
+    private val mUserUnlockedActions: RunnableList = RunnableList()
+
+    @VisibleForTesting
+    val mUserUnlockedReceiver = SimpleBroadcastReceiver {
+        if (Intent.ACTION_USER_UNLOCKED == it.action) {
+            isUserUnlocked = true
+            notifyUserUnlocked()
+        }
+    }
+
+    init {
+        isUserUnlocked =
+            mContext
+                .getSystemService(UserManager::class.java)!!
+                .isUserUnlocked(Process.myUserHandle())
+        if (isUserUnlocked) {
+            notifyUserUnlocked()
+        } else {
+            mUserUnlockedReceiver.register(mContext, Intent.ACTION_USER_UNLOCKED)
+        }
+    }
+
+    private fun notifyUserUnlocked() {
+        mUserUnlockedActions.executeAllAndDestroy()
+        mUserUnlockedReceiver.unregisterReceiverSafely(mContext)
+    }
+
+    /** Stops the receiver from listening for ACTION_USER_UNLOCK broadcasts. */
+    override fun close() {
+        mUserUnlockedReceiver.unregisterReceiverSafely(mContext)
+    }
+
+    /**
+     * Adds a `Runnable` to be executed when a user is unlocked. If the user is already unlocked,
+     * this runnable will run immediately because RunnableList will already have been destroyed.
+     */
+    fun runOnUserUnlocked(action: Runnable) {
+        mUserUnlockedActions.add(action)
+    }
+
+    companion object {
+        @VisibleForTesting val INSTANCE = MainThreadInitializedObject { LockedUserState(it) }
+
+        @JvmStatic fun get(context: Context): LockedUserState = INSTANCE.get(context)
+    }
+}
diff --git a/src/com/android/launcher3/util/OnboardingPrefs.java b/src/com/android/launcher3/util/OnboardingPrefs.java
index f4893c7..c146216 100644
--- a/src/com/android/launcher3/util/OnboardingPrefs.java
+++ b/src/com/android/launcher3/util/OnboardingPrefs.java
@@ -44,6 +44,7 @@
     public static final String TASKBAR_EDU_SEEN = "launcher.taskbar_edu_seen2";
     public static final String ALL_APPS_VISITED_COUNT = "launcher.all_apps_visited_count";
     public static final String QSB_SEARCH_ONBOARDING_CARD_DISMISSED = "launcher.qsb_edu_dismiss";
+    public static final String TASKBAR_EDU_TOOLTIP_STEP = "launcher.taskbar_edu_tooltip_step";
     // When adding a new key, add it here as well, to be able to reset it from Developer Options.
     public static final Map<String, String[]> ALL_PREF_KEYS = Map.of(
             "All Apps Bounce", new String[] { HOME_BOUNCE_SEEN, HOME_BOUNCE_COUNT },
@@ -51,7 +52,7 @@
                     HOTSEAT_LONGPRESS_TIP_SEEN },
             "Search Education", new String[] { SEARCH_KEYBOARD_EDU_SEEN, SEARCH_SNACKBAR_COUNT,
                     SEARCH_ONBOARDING_COUNT, QSB_SEARCH_ONBOARDING_CARD_DISMISSED},
-            "Taskbar Education", new String[] { TASKBAR_EDU_SEEN },
+            "Taskbar Education", new String[] { TASKBAR_EDU_SEEN, TASKBAR_EDU_TOOLTIP_STEP },
             "All Apps Visited Count", new String[] {ALL_APPS_VISITED_COUNT}
     );
 
@@ -76,7 +77,8 @@
             HOTSEAT_DISCOVERY_TIP_COUNT,
             SEARCH_SNACKBAR_COUNT,
             SEARCH_ONBOARDING_COUNT,
-            ALL_APPS_VISITED_COUNT
+            ALL_APPS_VISITED_COUNT,
+            TASKBAR_EDU_TOOLTIP_STEP,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface EventCountKey {}
@@ -91,6 +93,7 @@
         // This is the sum of all onboarding cards. Currently there is only 1 card shown 3 times.
         maxCounts.put(SEARCH_ONBOARDING_COUNT, 3);
         maxCounts.put(ALL_APPS_VISITED_COUNT, 20);
+        maxCounts.put(TASKBAR_EDU_TOOLTIP_STEP, 2);
         MAX_COUNTS = Collections.unmodifiableMap(maxCounts);
     }
 
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 140440e..a6a2751 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -21,7 +21,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.LauncherActivityInfo;
 import android.content.pm.LauncherApps;
@@ -33,7 +32,6 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.PatternMatcher;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
@@ -249,19 +247,6 @@
         }
     }
 
-    /**
-     * Creates an intent filter to listen for actions with a specific package in the data field.
-     */
-    public static IntentFilter getPackageFilter(String pkg, String... actions) {
-        IntentFilter packageFilter = new IntentFilter();
-        for (String action : actions) {
-            packageFilter.addAction(action);
-        }
-        packageFilter.addDataScheme("package");
-        packageFilter.addDataSchemeSpecificPart(pkg, PatternMatcher.PATTERN_LITERAL);
-        return packageFilter;
-    }
-
     public static boolean isSystemApp(@NonNull final Context context,
             @NonNull final Intent intent) {
         PackageManager pm = context.getPackageManager();
diff --git a/src/com/android/launcher3/util/ScreenOnTracker.java b/src/com/android/launcher3/util/ScreenOnTracker.java
new file mode 100644
index 0000000..67530a6
--- /dev/null
+++ b/src/com/android/launcher3/util/ScreenOnTracker.java
@@ -0,0 +1,93 @@
+/*
+ * 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.util;
+
+import static android.content.Intent.ACTION_SCREEN_OFF;
+import static android.content.Intent.ACTION_SCREEN_ON;
+import static android.content.Intent.ACTION_USER_PRESENT;
+
+import android.content.Context;
+import android.content.Intent;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Utility class for tracking if the screen is currently on or off
+ */
+public class ScreenOnTracker {
+
+    public static final MainThreadInitializedObject<ScreenOnTracker> INSTANCE =
+            new MainThreadInitializedObject<>(ScreenOnTracker::new);
+
+    private final SimpleBroadcastReceiver mReceiver = new SimpleBroadcastReceiver(this::onReceive);
+    private final CopyOnWriteArrayList<ScreenOnListener> mListeners = new CopyOnWriteArrayList<>();
+
+    private boolean mIsScreenOn;
+
+    private ScreenOnTracker(Context context) {
+        // Assume that the screen is on to begin with
+        mIsScreenOn = true;
+        mReceiver.register(context, ACTION_SCREEN_ON, ACTION_SCREEN_OFF, ACTION_USER_PRESENT);
+    }
+
+    private void onReceive(Intent intent) {
+        String action = intent.getAction();
+        if (ACTION_SCREEN_ON.equals(action)) {
+            mIsScreenOn = true;
+            dispatchScreenOnChanged();
+        } else if (ACTION_SCREEN_OFF.equals(action)) {
+            mIsScreenOn = false;
+            dispatchScreenOnChanged();
+        } else if (ACTION_USER_PRESENT.equals(action)) {
+            mListeners.forEach(ScreenOnListener::onUserPresent);
+        }
+    }
+
+    private void dispatchScreenOnChanged() {
+        mListeners.forEach(l -> l.onScreenOnChanged(mIsScreenOn));
+    }
+
+    /** Returns if the screen is on or not */
+    public boolean isScreenOn() {
+        return mIsScreenOn;
+    }
+
+    /** Adds a listener for screen on changes */
+    public void addListener(ScreenOnListener listener) {
+        mListeners.add(listener);
+    }
+
+    /** Removes a previously added listener */
+    public void removeListener(ScreenOnListener listener) {
+        mListeners.remove(listener);
+    }
+
+    /**
+     * Interface to listen for screen on changes
+     */
+    public interface ScreenOnListener {
+
+        /**
+         * Called when the screen turns on/off
+         */
+        void onScreenOnChanged(boolean isOn);
+
+        /**
+         * Called when the keyguard goes away
+         */
+        default void onUserPresent() { }
+    }
+}
diff --git a/src/com/android/launcher3/util/SimpleBroadcastReceiver.java b/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
index 0a23506..064bcd0 100644
--- a/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
+++ b/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
@@ -19,6 +19,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.PatternMatcher;
+import android.text.TextUtils;
+
+import androidx.annotation.Nullable;
 
 import java.util.function.Consumer;
 
@@ -39,18 +43,34 @@
      * Helper method to register multiple actions
      */
     public void register(Context context, String... actions) {
-        register(context, 0, actions);
+        context.registerReceiver(this, getFilter(actions));
     }
 
     /**
-     * Helper method to register multiple actions with one or more {@code flags}.
+     * Helper method to register multiple actions associated with a paction
      */
-    public void register(Context context, int flags, String... actions) {
+    public void registerPkgActions(Context context, @Nullable String pkg, String... actions) {
+        context.registerReceiver(this, getPackageFilter(pkg, actions));
+    }
+
+    /**
+     * Creates an intent filter to listen for actions with a specific package in the data field.
+     */
+    public static IntentFilter getPackageFilter(String pkg, String... actions) {
+        IntentFilter filter = getFilter(actions);
+        filter.addDataScheme("package");
+        if (!TextUtils.isEmpty(pkg)) {
+            filter.addDataSchemeSpecificPart(pkg, PatternMatcher.PATTERN_LITERAL);
+        }
+        return filter;
+    }
+
+    private static IntentFilter getFilter(String... actions) {
         IntentFilter filter = new IntentFilter();
         for (String action : actions) {
             filter.addAction(action);
         }
-        context.registerReceiver(this, filter, flags);
+        return filter;
     }
 
     /**
diff --git a/src/com/android/launcher3/util/SplitConfigurationOptions.java b/src/com/android/launcher3/util/SplitConfigurationOptions.java
index 19a3948..8c5e782 100644
--- a/src/com/android/launcher3/util/SplitConfigurationOptions.java
+++ b/src/com/android/launcher3/util/SplitConfigurationOptions.java
@@ -21,11 +21,15 @@
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
+import android.content.Intent;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.View;
 
 import androidx.annotation.IntDef;
 
 import com.android.launcher3.logging.StatsLogManager;
+import com.android.launcher3.model.data.ItemInfo;
 
 import java.lang.annotation.Retention;
 
@@ -190,4 +194,35 @@
         return position == STAGE_POSITION_TOP_OR_LEFT ? STAGE_POSITION_BOTTOM_OR_RIGHT
                 : STAGE_POSITION_TOP_OR_LEFT;
     }
+
+    public static class SplitSelectSource {
+
+        /** Keep in sync w/ ActivityTaskManager#INVALID_TASK_ID (unreference-able) */
+        private static final int INVALID_TASK_ID = -1;
+
+        public final View view;
+        public final Drawable drawable;
+        public final Intent intent;
+        public final SplitPositionOption position;
+        public final ItemInfo itemInfo;
+        public final StatsLogManager.EventEnum splitEvent;
+        /** Represents the taskId of the first app to start in split screen */
+        public int alreadyRunningTaskId = INVALID_TASK_ID;
+        /**
+         * If {@code true}, animates the view represented by {@link #alreadyRunningTaskId} into the
+         * split placeholder view
+         */
+        public boolean animateCurrentTaskDismissal;
+
+        public SplitSelectSource(View view, Drawable drawable, Intent intent,
+                SplitPositionOption position, ItemInfo itemInfo,
+                StatsLogManager.EventEnum splitEvent) {
+            this.view = view;
+            this.drawable = drawable;
+            this.intent = intent;
+            this.position = position;
+            this.itemInfo = itemInfo;
+            this.splitEvent = splitEvent;
+        }
+    }
 }
diff --git a/src/com/android/launcher3/util/SystemUiController.java b/src/com/android/launcher3/util/SystemUiController.java
index 6945983..df54fd7 100644
--- a/src/com/android/launcher3/util/SystemUiController.java
+++ b/src/com/android/launcher3/util/SystemUiController.java
@@ -35,6 +35,7 @@
     public static final int UI_STATE_SCRIM_VIEW = 1;
     public static final int UI_STATE_WIDGET_BOTTOM_SHEET = 2;
     public static final int UI_STATE_FULLSCREEN_TASK = 3;
+    public static final int UI_STATE_ALL_APPS = 4;
 
     public static final int FLAG_LIGHT_NAV = 1 << 0;
     public static final int FLAG_DARK_NAV = 1 << 1;
@@ -54,7 +55,7 @@
     public @interface SystemUiControllerFlags {}
 
     private final Window mWindow;
-    private final int[] mStates = new int[4];
+    private final int[] mStates = new int[5];
 
     public SystemUiController(Window window) {
         mWindow = window;
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
index 585bea9..5526839 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -19,6 +19,8 @@
 import static android.app.WallpaperColors.HINT_SUPPORTS_DARK_TEXT;
 import static android.app.WallpaperColors.HINT_SUPPORTS_DARK_THEME;
 
+import static com.android.launcher3.LauncherPrefs.THEMED_ICONS;
+
 import android.app.WallpaperColors;
 import android.app.WallpaperManager;
 import android.content.Context;
@@ -74,7 +76,7 @@
      * Returns true if workspace icon theming is enabled
      */
     public static boolean isThemedIconEnabled(Context context) {
-        return LauncherPrefs.getPrefs(context).getBoolean(KEY_THEMED_ICONS, false);
+        return LauncherPrefs.get(context).get(THEMED_ICONS);
     }
 
     public static String getDefaultBodyFont(Context context) {
diff --git a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
index 43e9820..4ac6bc4 100644
--- a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
+++ b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
@@ -1,12 +1,11 @@
 package com.android.launcher3.util;
 
+import static android.content.Intent.ACTION_WALLPAPER_CHANGED;
+
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 
 import android.app.WallpaperManager;
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -23,7 +22,7 @@
 /**
  * Utility class to handle wallpaper scrolling along with workspace.
  */
-public class WallpaperOffsetInterpolator extends BroadcastReceiver {
+public class WallpaperOffsetInterpolator {
 
     private static final int[] sTempInt = new int[2];
     private static final String TAG = "WPOffsetInterpolator";
@@ -32,6 +31,8 @@
     // Don't use all the wallpaper for parallax until you have at least this many pages
     private static final int MIN_PARALLAX_PAGE_SPAN = 4;
 
+    private final SimpleBroadcastReceiver mWallpaperChangeReceiver =
+            new SimpleBroadcastReceiver(i -> onWallpaperChanged());
     private final Workspace<?> mWorkspace;
     private final boolean mIsRtl;
     private final Handler mHandler;
@@ -197,22 +198,20 @@
     public void setWindowToken(IBinder token) {
         mWindowToken = token;
         if (mWindowToken == null && mRegistered) {
-            mWorkspace.getContext().unregisterReceiver(this);
+            mWallpaperChangeReceiver.unregisterReceiverSafely(mWorkspace.getContext());
             mRegistered = false;
         } else if (mWindowToken != null && !mRegistered) {
-            mWorkspace.getContext()
-                    .registerReceiver(this, new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED));
-            onReceive(mWorkspace.getContext(), null);
+            mWallpaperChangeReceiver.register(mWorkspace.getContext(), ACTION_WALLPAPER_CHANGED);
+            onWallpaperChanged();
             mRegistered = true;
         }
     }
 
-    @Override
-    public void onReceive(Context context, Intent intent) {
+    private void onWallpaperChanged() {
         UI_HELPER_EXECUTOR.execute(() -> {
             // Updating the boolean on a background thread is fine as the assignments are atomic
-            mWallpaperIsLiveWallpaper =
-                    WallpaperManager.getInstance(context).getWallpaperInfo() != null;
+            mWallpaperIsLiveWallpaper = WallpaperManager.getInstance(mWorkspace.getContext())
+                    .getWallpaperInfo() != null;
             updateOffset();
         });
     }
diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java
index fb2ae73..4093bc9 100644
--- a/src/com/android/launcher3/util/window/WindowManagerProxy.java
+++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java
@@ -161,12 +161,10 @@
         insetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.navigationBars(), newNavInsets);
 
         Insets statusBarInsets = oldInsets.getInsets(WindowInsets.Type.statusBars());
-        int statusBarHeight = getDimenByName(systemRes,
-                (isPortrait) ? STATUS_BAR_HEIGHT_PORTRAIT : STATUS_BAR_HEIGHT_LANDSCAPE,
-                STATUS_BAR_HEIGHT);
+
         Insets newStatusBarInsets = Insets.of(
                 statusBarInsets.left,
-                Math.max(statusBarInsets.top, statusBarHeight),
+                getStatusBarHeight(context, isPortrait, statusBarInsets.top),
                 statusBarInsets.right,
                 statusBarInsets.bottom);
         insetsBuilder.setInsets(WindowInsets.Type.statusBars(), newStatusBarInsets);
@@ -190,6 +188,15 @@
         return result;
     }
 
+    protected int getStatusBarHeight(Context context, boolean isPortrait, int statusBarInset) {
+        Resources systemRes = context.getResources();
+        int statusBarHeight = getDimenByName(systemRes,
+                isPortrait ? STATUS_BAR_HEIGHT_PORTRAIT : STATUS_BAR_HEIGHT_LANDSCAPE,
+                STATUS_BAR_HEIGHT);
+
+        return Math.max(statusBarInset, statusBarHeight);
+    }
+
     /**
      * Returns a list of possible WindowBounds for the display keyed on the 4 surface rotations
      */
@@ -212,6 +219,9 @@
         boolean isTabletOrGesture = isTablet
                 || (Utilities.ATLEAST_R && isGestureNav(context));
 
+        // Use the status bar height resources because current system API to get the status bar
+        // height doesn't allow to do this for an arbitrary display, it returns value only
+        // for the current active display (see com.android.internal.policy.StatusBarUtils)
         int statusBarHeightPortrait = getDimenByName(systemRes,
                 STATUS_BAR_HEIGHT_PORTRAIT, STATUS_BAR_HEIGHT);
         int statusBarHeightLandscape = getDimenByName(systemRes,
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index 79b4cb4..fe60eba 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -23,6 +23,7 @@
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 
 import android.app.ActivityOptions;
+import android.app.PendingIntent;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -45,6 +46,7 @@
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Toast;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.BubbleTextView;
@@ -70,6 +72,7 @@
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.Preconditions;
 import com.android.launcher3.util.RunnableList;
+import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.ViewCache;
 
 import java.util.List;
@@ -130,6 +133,12 @@
         return null;
     }
 
+    /** Called when the first app in split screen has been selected */
+    default void startSplitSelection(
+            SplitConfigurationOptions.SplitSelectSource splitSelectSource) {
+        // Overridden, intentionally empty
+    }
+
     /**
      * The root view to support drag-and-drop and popup support.
      */
@@ -270,6 +279,29 @@
         }
     }
 
+
+    /**
+     * Sends a pending intent animating from a view.
+     *
+     * @param v View to animate.
+     * @param intent The pending intent being launched.
+     * @param item Item associated with the view.
+     * @return {@code true} if the intent is sent successfully.
+     */
+    default boolean sendPendingIntentWithAnimation(
+            @NonNull View v, PendingIntent intent, @Nullable ItemInfo item) {
+        Bundle optsBundle = getActivityLaunchOptions(v, item).toBundle();
+        try {
+            intent.send(null, 0, null, null, null, null, optsBundle);
+            return true;
+        } catch (PendingIntent.CanceledException e) {
+            Toast.makeText(v.getContext(),
+                    v.getContext().getResources().getText(R.string.shortcut_not_available),
+                    Toast.LENGTH_SHORT).show();
+        }
+        return false;
+    }
+
     /**
      * Safely starts an activity.
      *
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index 4c0bfde..ca80c51 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -46,6 +46,7 @@
     private int mBackgroundColor;
     private boolean mIsVisible = true;
     private boolean mLastDispatchedOpaqueness;
+    private float mHeaderScale = 1f;
 
     public ScrimView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -76,6 +77,10 @@
         super.setBackgroundColor(color);
     }
 
+    public int getBackgroundColor() {
+        return mBackgroundColor;
+    }
+
     @Override
     public void onVisibilityAggregated(boolean isVisible) {
         super.onVisibilityAggregated(isVisible);
@@ -91,7 +96,16 @@
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
         if (mDrawingController != null) {
-            mDrawingController.drawOnScrim(canvas);
+            mDrawingController.drawOnScrimWithScale(canvas, mHeaderScale);
+        }
+    }
+
+    /** Set scrim header's scale and bottom offset. */
+    public void setScrimHeaderScale(float scale) {
+        boolean hasChanged = mHeaderScale != scale;
+        mHeaderScale = scale;
+        if (hasChanged) {
+            invalidate();
         }
     }
 
@@ -176,6 +190,6 @@
         /**
          * Called inside ScrimView#OnDraw
          */
-        void drawOnScrim(Canvas canvas);
+        void drawOnScrimWithScale(Canvas canvas, float scale);
     }
 }
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 220d1c1..c78ecf5 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -17,7 +17,9 @@
 
 import static android.view.View.MeasureSpec.makeMeasureSpec;
 
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
+import static com.android.launcher3.allapps.AllAppsTransitionController.SWIPE_ALL_APPS_TO_HOME_MIN_SCALE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGETSTRAY_SEARCHED;
 import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
 
@@ -45,6 +47,7 @@
 import android.widget.Button;
 import android.widget.TextView;
 
+import androidx.annotation.FloatRange;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.recyclerview.widget.DefaultItemAnimator;
@@ -54,6 +57,7 @@
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.model.UserManagerState;
@@ -169,6 +173,7 @@
     private View mSearchBarContainer;
     private WidgetsSearchBar mSearchBar;
     private TextView mHeaderTitle;
+    private @Nullable WidgetsRecyclerView mCurrentTouchEventRecyclerView;
 
     public WidgetsFullSheet(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
@@ -263,6 +268,15 @@
         attachScrollbarToRecyclerView(currentRecyclerView);
     }
 
+    @Override
+    public void onBackProgressed(@FloatRange(from = 0.0, to = 1.0) float progress) {
+        float deceleratedProgress =
+                Interpolators.PREDICTIVE_BACK_DECELERATED_EASE.getInterpolation(progress);
+        float scaleProgress = SWIPE_ALL_APPS_TO_HOME_MIN_SCALE
+                + (1 - SWIPE_ALL_APPS_TO_HOME_MIN_SCALE) * (1 - deceleratedProgress);
+        SCALE_PROPERTY.set(this, scaleProgress);
+    }
+
     private void attachScrollbarToRecyclerView(WidgetsRecyclerView recyclerView) {
         recyclerView.bindFastScrollbar();
         if (mCurrentWidgetsRecyclerView != recyclerView) {
@@ -642,6 +656,51 @@
         return sheet;
     }
 
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        return isTouchOnScrollbar(ev) || super.onInterceptTouchEvent(ev);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        return maybeHandleTouchEvent(ev) || super.onTouchEvent(ev);
+    }
+
+    private boolean maybeHandleTouchEvent(MotionEvent ev) {
+        boolean isEventHandled = false;
+
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            mCurrentTouchEventRecyclerView = isTouchOnScrollbar(ev) ? getRecyclerView() : null;
+        }
+
+        if (mCurrentTouchEventRecyclerView != null) {
+            final float offsetX = mContent.getX();
+            final float offsetY = mContent.getY();
+            ev.offsetLocation(-offsetX, -offsetY);
+            isEventHandled = mCurrentTouchEventRecyclerView.dispatchTouchEvent(ev);
+            ev.offsetLocation(offsetX, offsetY);
+        }
+
+        if (ev.getAction() == MotionEvent.ACTION_UP
+                || ev.getAction() == MotionEvent.ACTION_CANCEL) {
+            mCurrentTouchEventRecyclerView = null;
+        }
+
+        return isEventHandled;
+    }
+
+    private boolean isTouchOnScrollbar(MotionEvent ev) {
+        final float offsetX = mContent.getX();
+        final float offsetY = mContent.getY();
+        WidgetsRecyclerView rv = getRecyclerView();
+
+        ev.offsetLocation(-offsetX, -offsetY);
+        boolean isOnScrollBar = rv != null && rv.getScrollbar() != null && rv.isHitOnScrollBar(ev);
+        ev.offsetLocation(offsetX, offsetY);
+
+        return isOnScrollBar;
+    }
+
     /** Gets the {@link WidgetsRecyclerView} which shows all widgets in {@link WidgetsFullSheet}. */
     @VisibleForTesting
     public static WidgetsRecyclerView getWidgetsView(Launcher launcher) {
@@ -690,12 +749,12 @@
     }
 
     @Override
-    public boolean onBackPressed() {
+    public void onBackInvoked() {
         if (mIsInSearchMode) {
             mSearchBar.reset();
-            return true;
+        } else {
+            super.onBackInvoked();
         }
-        return super.onBackPressed();
     }
 
     @Override
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
index 5969e3e..698e764 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
@@ -127,8 +127,7 @@
     @Override
     public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
         if (e.getAction() == MotionEvent.ACTION_DOWN) {
-            mTouchDownOnScroller =
-                    mScrollbar.isHitInParent(e.getX(), e.getY(), mFastScrollerOffset);
+            mTouchDownOnScroller = isHitOnScrollBar(e);
         }
         if (mTouchDownOnScroller) {
             final boolean result = mScrollbar.handleTouchEvent(e, mFastScrollerOffset);
@@ -144,6 +143,15 @@
         }
     }
 
+    /**
+     * Detects whether a {@code MotionEvent} is on the scroll bar
+     * @param e The {@code MotionEvent} on the screen
+     * @return {@code true} if the motion is on the scroll bar
+     */
+    boolean isHitOnScrollBar(MotionEvent e) {
+        return mScrollbar.isHitInParent(e.getX(), e.getY(), mFastScrollerOffset);
+    }
+
     @Override
     public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
     }
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java b/src_shortcuts_overrides/com/android/launcher3/model/LauncherBinder.java
similarity index 88%
rename from src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java
rename to src_shortcuts_overrides/com/android/launcher3/model/LauncherBinder.java
index abce2a2..e1a5f24 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/LauncherBinder.java
@@ -27,11 +27,11 @@
 import java.util.List;
 
 /**
- * Helper class to handle results of {@link com.android.launcher3.model.LoaderTask}.
+ * Binds the results of {@link com.android.launcher3.model.LoaderTask} to the Callbacks objects.
  */
-public class LoaderResults extends BaseLoaderResults {
+public class LauncherBinder extends BaseLauncherBinder {
 
-    public LoaderResults(LauncherAppState app, BgDataModel dataModel,
+    public LauncherBinder(LauncherAppState app, BgDataModel dataModel,
             AllAppsList allAppsList, Callbacks[] callbacks) {
         super(app, dataModel, allAppsList, callbacks, MAIN_EXECUTOR);
     }
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index bedf277..b170061 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -280,7 +280,7 @@
             </intent-filter>
         </activity-alias>
         <activity-alias android:name="Activity15" android:exported="true"
-            android:label="ThemeIconTestActivity"
+            android:label="IconThemedActivity"
             android:icon="@drawable/test_theme_icon"
             android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
             <intent-filter>
diff --git a/tests/res/xml/shortcuts.xml b/tests/res/xml/shortcuts.xml
index fde0dbb..94e8edd 100644
--- a/tests/res/xml/shortcuts.xml
+++ b/tests/res/xml/shortcuts.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
     <shortcut
-        android:shortcutId="shortcut1"
+        android:shortcutId="shortcut1_themed"
         android:icon="@drawable/test_theme_icon"
         android:shortcutShortLabel="@string/shortcut1">
         <intent android:action="com.android.launcher3.intent.action.test_shortcut"/>
diff --git a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
index 13e56f3..b7d0f28 100644
--- a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
+++ b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
@@ -23,11 +23,11 @@
 import com.android.launcher3.DeviceProfile.DEFAULT_PROVIDER
 import com.android.launcher3.util.DisplayController.Info
 import com.android.launcher3.util.WindowBounds
+import java.io.PrintWriter
+import java.io.StringWriter
 import org.junit.Before
 import org.mockito.ArgumentMatchers.any
 import org.mockito.Mockito.mock
-import java.io.PrintWriter
-import java.io.StringWriter
 import org.mockito.Mockito.`when` as whenever
 
 abstract class DeviceProfileBaseTest {
@@ -49,31 +49,36 @@
         isGestureMode = true
     }
 
-    protected fun newDP(): DeviceProfile = DeviceProfile(
-        context,
-        inv,
-        info,
-        windowBounds,
-        SparseArray(),
-        isMultiWindowMode,
-        transposeLayoutWithOrientation,
-        useTwoPanels,
-        isGestureMode,
-        DEFAULT_PROVIDER
-    )
+    protected fun newDP(): DeviceProfile =
+        DeviceProfile(
+            context,
+            inv,
+            info,
+            windowBounds,
+            SparseArray(),
+            isMultiWindowMode,
+            transposeLayoutWithOrientation,
+            useTwoPanels,
+            isGestureMode,
+            DEFAULT_PROVIDER
+        )
 
-    protected fun initializeVarsForPhone(isGestureMode: Boolean = true,
-                                         isVerticalBar: Boolean = false) {
-        val (x, y) = if (isVerticalBar)
-            Pair(2400, 1080)
-        else
-            Pair(1080, 2400)
+    protected fun initializeVarsForPhone(
+        isGestureMode: Boolean = true,
+        isVerticalBar: Boolean = false
+    ) {
+        val (x, y) = if (isVerticalBar) Pair(2400, 1080) else Pair(1080, 2400)
 
-        windowBounds = WindowBounds(Rect(0, 0, x, y), Rect(
-                if (isVerticalBar) 118 else 0,
-                if (isVerticalBar) 74 else 118,
-                if (!isGestureMode && isVerticalBar) 126 else 0,
-                if (isGestureMode) 63 else if (isVerticalBar) 0 else 126))
+        windowBounds =
+            WindowBounds(
+                Rect(0, 0, x, y),
+                Rect(
+                    if (isVerticalBar) 118 else 0,
+                    if (isVerticalBar) 74 else 118,
+                    if (!isGestureMode && isVerticalBar) 126 else 0,
+                    if (isGestureMode) 63 else if (isVerticalBar) 0 else 126
+                )
+            )
 
         whenever(info.isTablet(any())).thenReturn(false)
         whenever(info.getDensityDpi()).thenReturn(420)
@@ -82,79 +87,76 @@
         this.isGestureMode = isGestureMode
         transposeLayoutWithOrientation = true
 
-        inv = InvariantDeviceProfile().apply {
-            numRows = 5
-            numColumns = 4
-            numSearchContainerColumns = 4
+        inv =
+            InvariantDeviceProfile().apply {
+                numRows = 5
+                numColumns = 4
+                numSearchContainerColumns = 4
 
-            iconSize = floatArrayOf(60f, 54f, 60f, 60f)
-            iconTextSize = FloatArray(4) { 14f }
-            deviceType = InvariantDeviceProfile.TYPE_PHONE
+                iconSize = floatArrayOf(60f, 54f, 60f, 60f)
+                iconTextSize = FloatArray(4) { 14f }
+                deviceType = InvariantDeviceProfile.TYPE_PHONE
 
-            minCellSize = listOf(
-                    PointF(80f, 104f),
-                    PointF(80f, 104f),
-                    PointF(80f, 104f),
-                    PointF(80f, 104f)
-            ).toTypedArray()
+                minCellSize =
+                    listOf(
+                            PointF(80f, 104f),
+                            PointF(80f, 104f),
+                            PointF(80f, 104f),
+                            PointF(80f, 104f)
+                        )
+                        .toTypedArray()
 
-            borderSpaces = listOf(
-                    PointF(16f, 16f),
-                    PointF(16f, 16f),
-                    PointF(16f, 16f),
-                    PointF(16f, 16f)
-            ).toTypedArray()
+                borderSpaces =
+                    listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f))
+                        .toTypedArray()
 
-            numFolderRows = 3
-            numFolderColumns = 3
-            folderStyle = R.style.FolderDefaultStyle
+                numFolderRows = 3
+                numFolderColumns = 3
+                folderStyle = R.style.FolderStyleDefault
 
-            inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_split
+                inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_split
 
-            horizontalMargin = FloatArray(4) { 22f }
+                horizontalMargin = FloatArray(4) { 22f }
 
-            allAppsCellSize = listOf(
-                    PointF(80f, 104f),
-                    PointF(80f, 104f),
-                    PointF(80f, 104f),
-                    PointF(80f, 104f)
-            ).toTypedArray()
-            allAppsIconSize = floatArrayOf(60f, 60f, 60f, 60f)
-            allAppsIconTextSize = FloatArray(4) { 14f }
-            allAppsBorderSpaces = listOf(
-                    PointF(16f, 16f),
-                    PointF(16f, 16f),
-                    PointF(16f, 16f),
-                    PointF(16f, 16f)
-            ).toTypedArray()
+                allAppsCellSize =
+                    listOf(
+                            PointF(80f, 104f),
+                            PointF(80f, 104f),
+                            PointF(80f, 104f),
+                            PointF(80f, 104f)
+                        )
+                        .toTypedArray()
+                allAppsIconSize = floatArrayOf(60f, 60f, 60f, 60f)
+                allAppsIconTextSize = FloatArray(4) { 14f }
+                allAppsBorderSpaces =
+                    listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f))
+                        .toTypedArray()
 
-            numShownHotseatIcons = 4
+                numShownHotseatIcons = 4
 
-            numDatabaseHotseatIcons = 4
+                numDatabaseHotseatIcons = 4
 
-            hotseatColumnSpan = IntArray(4) { 4 }
-            hotseatBarBottomSpace = FloatArray(4) { 48f }
-            hotseatQsbSpace = FloatArray(4) { 36f }
+                hotseatColumnSpan = IntArray(4) { 4 }
+                hotseatBarBottomSpace = FloatArray(4) { 48f }
+                hotseatQsbSpace = FloatArray(4) { 36f }
 
-            numAllAppsColumns = 4
+                numAllAppsColumns = 4
 
-            isScalable = true
+                isScalable = true
 
-            inlineQsb = BooleanArray(4) { false }
+                inlineQsb = BooleanArray(4) { false }
 
-            devicePaddingId = R.xml.paddings_handhelds
-        }
+                devicePaddingId = R.xml.paddings_handhelds
+            }
     }
 
-    protected fun initializeVarsForTablet(isLandscape: Boolean = false,
-                                          isGestureMode: Boolean = true) {
-        val (x, y) = if (isLandscape)
-            Pair(2560, 1600)
-        else
-            Pair(1600, 2560)
+    protected fun initializeVarsForTablet(
+        isLandscape: Boolean = false,
+        isGestureMode: Boolean = true
+    ) {
+        val (x, y) = if (isLandscape) Pair(2560, 1600) else Pair(1600, 2560)
 
-        windowBounds =
-                WindowBounds(Rect(0, 0, x, y), Rect(0, 104, 0, 0))
+        windowBounds = WindowBounds(Rect(0, 0, x, y), Rect(0, 104, 0, 0))
 
         whenever(info.isTablet(any())).thenReturn(true)
         whenever(info.getDensityDpi()).thenReturn(320)
@@ -163,85 +165,77 @@
         this.isGestureMode = isGestureMode
         useTwoPanels = false
 
-        inv = InvariantDeviceProfile().apply {
-            numRows = 5
-            numColumns = 6
-            numSearchContainerColumns = 3
+        inv =
+            InvariantDeviceProfile().apply {
+                numRows = 5
+                numColumns = 6
+                numSearchContainerColumns = 3
 
-            iconSize = FloatArray(4) { 60f }
-            iconTextSize = FloatArray(4) { 14f }
-            deviceType = InvariantDeviceProfile.TYPE_TABLET
+                iconSize = FloatArray(4) { 60f }
+                iconTextSize = FloatArray(4) { 14f }
+                deviceType = InvariantDeviceProfile.TYPE_TABLET
 
-            minCellSize = listOf(
-                    PointF(102f, 120f),
-                    PointF(120f, 104f),
-                    PointF(102f, 120f),
-                    PointF(102f, 120f)
-            ).toTypedArray()
+                minCellSize =
+                    listOf(
+                            PointF(102f, 120f),
+                            PointF(120f, 104f),
+                            PointF(102f, 120f),
+                            PointF(102f, 120f)
+                        )
+                        .toTypedArray()
 
-            borderSpaces = listOf(
-                    PointF(16f, 64f),
-                    PointF(64f, 16f),
-                    PointF(16f, 64f),
-                    PointF(16f, 64f)
-            ).toTypedArray()
+                borderSpaces =
+                    listOf(PointF(16f, 64f), PointF(64f, 16f), PointF(16f, 64f), PointF(16f, 64f))
+                        .toTypedArray()
 
-            numFolderRows = 3
-            numFolderColumns = 3
-            folderStyle = R.style.FolderDefaultStyle
+                numFolderRows = 3
+                numFolderColumns = 3
+                folderStyle = R.style.FolderStyleDefault
 
-            inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_6_5
+                inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_6_5
 
-            horizontalMargin = floatArrayOf(54f, 120f, 54f, 54f)
+                horizontalMargin = floatArrayOf(54f, 120f, 54f, 54f)
 
-            allAppsCellSize = listOf(
-                    PointF(96f, 142f),
-                    PointF(126f, 126f),
-                    PointF(96f, 142f),
-                    PointF(96f, 142f)
-            ).toTypedArray()
-            allAppsIconSize = FloatArray(4) { 60f }
-            allAppsIconTextSize = FloatArray(4) { 14f }
-            allAppsBorderSpaces = listOf(
-                    PointF(8f, 16f),
-                    PointF(16f, 16f),
-                    PointF(8f, 16f),
-                    PointF(8f, 16f)
-            ).toTypedArray()
+                allAppsCellSize =
+                    listOf(
+                            PointF(96f, 142f),
+                            PointF(126f, 126f),
+                            PointF(96f, 142f),
+                            PointF(96f, 142f)
+                        )
+                        .toTypedArray()
+                allAppsIconSize = FloatArray(4) { 60f }
+                allAppsIconTextSize = FloatArray(4) { 14f }
+                allAppsBorderSpaces =
+                    listOf(PointF(8f, 16f), PointF(16f, 16f), PointF(8f, 16f), PointF(8f, 16f))
+                        .toTypedArray()
 
-            numShownHotseatIcons = 6
+                numShownHotseatIcons = 6
 
-            numDatabaseHotseatIcons = 6
+                numDatabaseHotseatIcons = 6
 
-            hotseatColumnSpan = intArrayOf(6, 4, 6, 6)
-            hotseatBarBottomSpace = floatArrayOf(36f, 40f, 36f, 36f)
-            hotseatQsbSpace = FloatArray(4) { 32f }
+                hotseatColumnSpan = intArrayOf(6, 4, 6, 6)
+                hotseatBarBottomSpace = floatArrayOf(36f, 40f, 36f, 36f)
+                hotseatQsbSpace = FloatArray(4) { 32f }
 
-            numAllAppsColumns = 6
+                numAllAppsColumns = 6
 
-            isScalable = true
-            devicePaddingId = R.xml.paddings_6x5
+                isScalable = true
+                devicePaddingId = R.xml.paddings_6x5
 
-            inlineQsb = booleanArrayOf(
-                    false,
-                    true,
-                    false,
-                    false
-            )
+                inlineQsb = booleanArrayOf(false, true, false, false)
 
-            devicePaddingId = R.xml.paddings_handhelds
-        }
+                devicePaddingId = R.xml.paddings_handhelds
+            }
     }
 
-    protected fun initializeVarsForTwoPanel(isLandscape: Boolean = false,
-            isGestureMode: Boolean = true) {
-        val (x, y) = if (isLandscape)
-            Pair(2208, 1840)
-        else
-            Pair(1840, 2208)
+    protected fun initializeVarsForTwoPanel(
+        isLandscape: Boolean = false,
+        isGestureMode: Boolean = true
+    ) {
+        val (x, y) = if (isLandscape) Pair(2208, 1840) else Pair(1840, 2208)
 
-        windowBounds = WindowBounds(Rect(0, 0, x, y),
-                Rect(0, 110, 0, 0))
+        windowBounds = WindowBounds(Rect(0, 0, x, y), Rect(0, 110, 0, 0))
 
         whenever(info.isTablet(any())).thenReturn(true)
         whenever(info.getDensityDpi()).thenReturn(420)
@@ -250,74 +244,63 @@
         this.isGestureMode = isGestureMode
         useTwoPanels = true
 
-        inv = InvariantDeviceProfile().apply {
-            numRows = 4
-            numColumns = 4
-            numSearchContainerColumns = 4
+        inv =
+            InvariantDeviceProfile().apply {
+                numRows = 4
+                numColumns = 4
+                numSearchContainerColumns = 4
 
-            iconSize = floatArrayOf(60f, 52f, 52f, 60f)
-            iconTextSize = floatArrayOf(14f, 14f, 12f, 14f)
-            deviceType = InvariantDeviceProfile.TYPE_MULTI_DISPLAY
+                iconSize = floatArrayOf(60f, 52f, 52f, 60f)
+                iconTextSize = floatArrayOf(14f, 14f, 12f, 14f)
+                deviceType = InvariantDeviceProfile.TYPE_MULTI_DISPLAY
 
-            minCellSize = listOf(
-                    PointF(80f, 104f),
-                    PointF(80f, 104f),
-                    PointF(68f, 116f),
-                    PointF(80f, 102f)
-            ).toTypedArray()
+                minCellSize =
+                    listOf(
+                            PointF(80f, 104f),
+                            PointF(80f, 104f),
+                            PointF(68f, 116f),
+                            PointF(80f, 102f)
+                        )
+                        .toTypedArray()
 
-            borderSpaces = listOf(
-                    PointF(16f, 16f),
-                    PointF(16f, 16f),
-                    PointF(16f, 20f),
-                    PointF(20f, 20f)
-            ).toTypedArray()
+                borderSpaces =
+                    listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 20f), PointF(20f, 20f))
+                        .toTypedArray()
 
-            numFolderRows = 3
-            numFolderColumns = 3
-            folderStyle = R.style.FolderDefaultStyle
+                numFolderRows = 3
+                numFolderColumns = 3
+                folderStyle = R.style.FolderStyleDefault
 
-            inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_split
+                inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_split
 
-            horizontalMargin = floatArrayOf(21.5f, 21.5f, 22.5f, 30.5f)
+                horizontalMargin = floatArrayOf(21.5f, 21.5f, 22.5f, 30.5f)
 
-            allAppsCellSize = listOf(
-                    PointF(0f, 0f),
-                    PointF(0f, 0f),
-                    PointF(68f, 104f),
-                    PointF(80f, 104f)
-            ).toTypedArray()
-            allAppsIconSize = floatArrayOf(60f, 60f, 52f, 60f)
-            allAppsIconTextSize = floatArrayOf(14f, 14f, 12f, 14f)
-            allAppsBorderSpaces = listOf(
-                    PointF(16f, 16f),
-                    PointF(16f, 16f),
-                    PointF(16f, 28f),
-                    PointF(20f, 16f)
-            ).toTypedArray()
+                allAppsCellSize =
+                    listOf(PointF(0f, 0f), PointF(0f, 0f), PointF(68f, 104f), PointF(80f, 104f))
+                        .toTypedArray()
+                allAppsIconSize = floatArrayOf(60f, 60f, 52f, 60f)
+                allAppsIconTextSize = floatArrayOf(14f, 14f, 12f, 14f)
+                allAppsBorderSpaces =
+                    listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 28f), PointF(20f, 16f))
+                        .toTypedArray()
 
-            numShownHotseatIcons = 6
+                numShownHotseatIcons = 6
 
-            numDatabaseHotseatIcons = 6
+                numDatabaseHotseatIcons = 6
 
-            hotseatColumnSpan = IntArray(4) { 6 }
-            hotseatBarBottomSpace = floatArrayOf(48f, 48f, 36f, 20f)
-            hotseatQsbSpace = floatArrayOf(36f, 36f, 36f, 28f)
+                hotseatColumnSpan = IntArray(4) { 6 }
+                hotseatBarBottomSpace = floatArrayOf(48f, 48f, 36f, 20f)
+                hotseatQsbSpace = floatArrayOf(36f, 36f, 36f, 28f)
 
-            numAllAppsColumns = 6
-            numDatabaseAllAppsColumns = 6
+                numAllAppsColumns = 6
+                numDatabaseAllAppsColumns = 6
 
-            isScalable = true
+                isScalable = true
 
-            inlineQsb = booleanArrayOf(
-                    false,
-                    false,
-                    false,
-                    false
-            )
+                inlineQsb = booleanArrayOf(false, false, false, false)
 
-            devicePaddingId = R.xml.paddings_handhelds
-        }
+                devicePaddingId = R.xml.paddings_handhelds
+            }
     }
 
     fun dump(dp: DeviceProfile): String {
@@ -327,4 +310,4 @@
         printWriter.flush()
         return stringWriter.toString()
     }
-}
\ No newline at end of file
+}
diff --git a/tests/src/com/android/launcher3/LauncherPrefsTest.kt b/tests/src/com/android/launcher3/LauncherPrefsTest.kt
new file mode 100644
index 0000000..151abf1
--- /dev/null
+++ b/tests/src/com/android/launcher3/LauncherPrefsTest.kt
@@ -0,0 +1,148 @@
+package com.android.launcher3
+
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private val TEST_BOOLEAN_ITEM = LauncherPrefs.nonRestorableItem("1", false)
+private val TEST_STRING_ITEM = LauncherPrefs.nonRestorableItem("2", "( ͡❛ ͜ʖ ͡❛)")
+private val TEST_INT_ITEM = LauncherPrefs.nonRestorableItem("3", -1)
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class LauncherPrefsTest {
+
+    private val launcherPrefs by lazy {
+        LauncherPrefs.get(InstrumentationRegistry.getInstrumentation().targetContext).apply {
+            remove(TEST_BOOLEAN_ITEM, TEST_STRING_ITEM, TEST_INT_ITEM)
+        }
+    }
+
+    @Test
+    fun has_keyMissingFromLauncherPrefs_returnsFalse() {
+        assertThat(launcherPrefs.has(TEST_BOOLEAN_ITEM)).isFalse()
+    }
+
+    @Test
+    fun has_keyPresentInLauncherPrefs_returnsTrue() {
+        with(launcherPrefs) {
+            putSync(TEST_BOOLEAN_ITEM.to(TEST_BOOLEAN_ITEM.defaultValue))
+            assertThat(has(TEST_BOOLEAN_ITEM)).isTrue()
+            remove(TEST_BOOLEAN_ITEM)
+        }
+    }
+
+    @Test
+    fun addListener_listeningForStringItemUpdates_isCorrectlyNotifiedOfUpdates() {
+        val latch = CountDownLatch(1)
+        val listener = OnSharedPreferenceChangeListener { _, _ -> latch.countDown() }
+
+        with(launcherPrefs) {
+            putSync(TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue))
+            addListener(listener, TEST_STRING_ITEM)
+            putSync(TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue + "abc"))
+
+            assertThat(latch.await(2, TimeUnit.SECONDS)).isTrue()
+            remove(TEST_STRING_ITEM)
+        }
+    }
+
+    @Test
+    fun removeListener_previouslyListeningForStringItemUpdates_isNoLongerNotifiedOfUpdates() {
+        val latch = CountDownLatch(1)
+        val listener = OnSharedPreferenceChangeListener { _, _ -> latch.countDown() }
+
+        with(launcherPrefs) {
+            addListener(listener, TEST_STRING_ITEM)
+            removeListener(listener, TEST_STRING_ITEM)
+            putSync(TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue + "hello."))
+
+            // latch will be still be 1 (and await will return false) if the listener was not called
+            assertThat(latch.await(2, TimeUnit.SECONDS)).isFalse()
+            remove(TEST_STRING_ITEM)
+        }
+    }
+
+    @Test
+    fun addListenerAndRemoveListener_forMultipleItems_bothWorkProperly() {
+        var latch = CountDownLatch(3)
+        val listener = OnSharedPreferenceChangeListener { _, _ -> latch.countDown() }
+
+        with(launcherPrefs) {
+            addListener(listener, TEST_INT_ITEM, TEST_STRING_ITEM, TEST_BOOLEAN_ITEM)
+            putSync(
+                TEST_INT_ITEM.to(TEST_INT_ITEM.defaultValue + 123),
+                TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue + "abc"),
+                TEST_BOOLEAN_ITEM.to(!TEST_BOOLEAN_ITEM.defaultValue)
+            )
+            assertThat(latch.await(2, TimeUnit.SECONDS)).isTrue()
+
+            removeListener(listener, TEST_INT_ITEM, TEST_STRING_ITEM, TEST_BOOLEAN_ITEM)
+            latch = CountDownLatch(1)
+            putSync(
+                TEST_INT_ITEM.to(TEST_INT_ITEM.defaultValue),
+                TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue),
+                TEST_BOOLEAN_ITEM.to(TEST_BOOLEAN_ITEM.defaultValue)
+            )
+            remove(TEST_INT_ITEM, TEST_STRING_ITEM, TEST_BOOLEAN_ITEM)
+
+            assertThat(latch.await(2, TimeUnit.SECONDS)).isFalse()
+        }
+    }
+
+    @Test
+    fun get_booleanItemNotInLauncherprefs_returnsDefaultValue() {
+        assertThat(launcherPrefs.get(TEST_BOOLEAN_ITEM)).isEqualTo(TEST_BOOLEAN_ITEM.defaultValue)
+    }
+
+    @Test
+    fun get_stringItemNotInLauncherPrefs_returnsDefaultValue() {
+        assertThat(launcherPrefs.get(TEST_STRING_ITEM)).isEqualTo(TEST_STRING_ITEM.defaultValue)
+    }
+
+    @Test
+    fun get_intItemNotInLauncherprefs_returnsDefaultValue() {
+        assertThat(launcherPrefs.get(TEST_INT_ITEM)).isEqualTo(TEST_INT_ITEM.defaultValue)
+    }
+
+    @Test
+    fun put_storesItemInLauncherPrefs_successfully() {
+        val notDefaultValue = !TEST_BOOLEAN_ITEM.defaultValue
+
+        with(launcherPrefs) {
+            putSync(TEST_BOOLEAN_ITEM.to(notDefaultValue))
+            assertThat(get(TEST_BOOLEAN_ITEM)).isEqualTo(notDefaultValue)
+            remove(TEST_BOOLEAN_ITEM)
+        }
+    }
+
+    @Test
+    fun put_storesListOfItemsInLauncherPrefs_successfully() {
+        with(launcherPrefs) {
+            putSync(
+                TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue),
+                TEST_INT_ITEM.to(TEST_INT_ITEM.defaultValue),
+                TEST_BOOLEAN_ITEM.to(TEST_BOOLEAN_ITEM.defaultValue)
+            )
+            assertThat(has(TEST_BOOLEAN_ITEM, TEST_INT_ITEM, TEST_STRING_ITEM)).isTrue()
+            remove(TEST_STRING_ITEM, TEST_INT_ITEM, TEST_BOOLEAN_ITEM)
+        }
+    }
+
+    @Test
+    fun remove_deletesItemFromLauncherPrefs_successfully() {
+        val notDefaultValue = !TEST_BOOLEAN_ITEM.defaultValue
+
+        with(launcherPrefs) {
+            putSync(TEST_BOOLEAN_ITEM.to(notDefaultValue))
+            remove(TEST_BOOLEAN_ITEM)
+            assertThat(get(TEST_BOOLEAN_ITEM)).isEqualTo(TEST_BOOLEAN_ITEM.defaultValue)
+        }
+    }
+}
diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java
index a32ce3c..6d75180 100644
--- a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java
+++ b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java
@@ -26,9 +26,76 @@
 import java.util.Map;
 import java.util.Queue;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 
-public class CellLayoutBoard {
+public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
+
+    private boolean intersects(Rect r1, Rect r2) {
+        // If one rectangle is on left side of other
+        if (r1.left > r2.right || r2.left > r1.right) {
+            return false;
+        }
+
+        // If one rectangle is above other
+        if (r1.bottom > r2.top || r2.bottom > r1.top) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private boolean overlapsWithIgnored(Set<Rect> ignoredRectangles, Rect rect) {
+        for (Rect ignoredRect : ignoredRectangles) {
+            // Using the built in intersects doesn't work because it doesn't account for area 0
+            if (intersects(ignoredRect, rect)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int compareTo(CellLayoutBoard cellLayoutBoard) {
+        // to be equal they need to have the same number of widgets and the same dimensions
+        // their order can be different
+        Set<Rect> widgetsSet = new HashSet<>();
+        Set<Rect> ignoredRectangles = new HashSet<>();
+        for (WidgetRect rect : mWidgetsRects) {
+            if (rect.shouldIgnore()) {
+                ignoredRectangles.add(rect.mBounds);
+            } else {
+                widgetsSet.add(rect.mBounds);
+            }
+        }
+        for (WidgetRect rect : cellLayoutBoard.mWidgetsRects) {
+            // ignore rectangles overlapping with the area marked by x
+            if (overlapsWithIgnored(ignoredRectangles, rect.mBounds)) {
+                continue;
+            }
+            if (!widgetsSet.contains(rect.mBounds)) {
+                return -1;
+            }
+            widgetsSet.remove(rect.mBounds);
+        }
+        if (!widgetsSet.isEmpty()) {
+            return 1;
+        }
+
+        // to be equal they need to have the same number of icons their order can be different
+        Set<Point> iconsSet = new HashSet<>();
+        mIconPoints.forEach(icon -> iconsSet.add(icon.getCoord()));
+        for (IconPoint icon : cellLayoutBoard.mIconPoints) {
+            if (!iconsSet.contains(icon.getCoord())) {
+                return -1;
+            }
+            iconsSet.remove(icon.getCoord());
+        }
+        if (!iconsSet.isEmpty()) {
+            return 1;
+        }
+        return 0;
+    }
 
     public static class CellType {
         // The cells marked by this will be filled by 1x1 widgets and will be ignored when
@@ -114,7 +181,7 @@
     List<IconPoint> mIconPoints = new ArrayList<>();
     Map<Character, IconPoint> mIconsMap = new HashMap<>();
 
-    Point mMain = new Point();
+    WidgetRect mMain = null;
 
     CellLayoutBoard() {
         for (int x = 0; x < mWidget.length; x++) {
@@ -132,7 +199,7 @@
         return mIconPoints;
     }
 
-    public Point getMain() {
+    public WidgetRect getMain() {
         return mMain;
     }
 
@@ -140,6 +207,73 @@
         return mWidgetsMap.get(c);
     }
 
+    private void removeWidgetFromBoard(WidgetRect widget) {
+        for (int xi = widget.mBounds.left; xi < widget.mBounds.right; xi++) {
+            for (int yi = widget.mBounds.top; yi < widget.mBounds.bottom; yi++) {
+                mWidget[xi][yi] = '-';
+            }
+        }
+    }
+
+    private void removeOverlappingItems(Rect rect) {
+        // Remove overlapping widgets and remove them from the board
+        mWidgetsRects = mWidgetsRects.stream().filter(widget -> {
+            if (rect.intersect(widget.mBounds)) {
+                removeWidgetFromBoard(widget);
+                return false;
+            }
+            return true;
+        }).collect(Collectors.toList());
+        // Remove overlapping icons and remove them from the board
+        mIconPoints = mIconPoints.stream().filter(iconPoint -> {
+            int x = iconPoint.coord.x;
+            int y = iconPoint.coord.y;
+            if (rect.contains(x, y)) {
+                mWidget[x][y] = '-';
+                return false;
+            }
+            return true;
+        }).collect(Collectors.toList());
+    }
+
+    private void removeOverlappingItems(Point p) {
+        // Remove overlapping widgets and remove them from the board
+        mWidgetsRects = mWidgetsRects.stream().filter(widget -> {
+            if (widget.mBounds.contains(p.x, p.y)) {
+                removeWidgetFromBoard(widget);
+                return false;
+            }
+            return true;
+        }).collect(Collectors.toList());
+        // Remove overlapping icons and remove them from the board
+        mIconPoints = mIconPoints.stream().filter(iconPoint -> {
+            int x = iconPoint.coord.x;
+            int y = iconPoint.coord.y;
+            if (p.x == x && p.y == y) {
+                mWidget[x][y] = '-';
+                return false;
+            }
+            return true;
+        }).collect(Collectors.toList());
+    }
+
+    public void addWidget(int x, int y, int spanX, int spanY, char type) {
+        Rect rect = new Rect(x, y + spanY - 1, x + spanX - 1, y);
+        removeOverlappingItems(rect);
+        WidgetRect widgetRect = new WidgetRect(type, rect);
+        mWidgetsRects.add(widgetRect);
+        for (int xi = rect.left; xi < rect.right + 1; xi++) {
+            for (int yi = rect.bottom; yi < rect.top + 1; yi++) {
+                mWidget[xi][yi] = type;
+            }
+        }
+    }
+
+    public void addIcon(int x, int y) {
+        removeOverlappingItems(new Point(x, y));
+        mWidget[x][y] = 'i';
+    }
+
     public static WidgetRect getWidgetRect(int x, int y, Set<Point> used, char[][] board) {
         char type = board[x][y];
         Queue<Point> search = new ArrayDeque<Point>();
@@ -205,6 +339,16 @@
         return iconPoints;
     }
 
+    public static WidgetRect getMainFromList(List<CellLayoutBoard> boards) {
+        for (CellLayoutBoard board : boards) {
+            WidgetRect main = board.getMain();
+            if (main != null) {
+                return main;
+            }
+        }
+        return null;
+    }
+
     public static CellLayoutBoard boardFromString(String boardStr) {
         String[] lines = boardStr.split("\n");
         CellLayoutBoard board = new CellLayoutBoard();
@@ -213,18 +357,52 @@
             String line = lines[y];
             for (int x = 0; x < line.length(); x++) {
                 char c = line.charAt(x);
-                if (c == CellType.MAIN_WIDGET) {
-                    board.mMain = new Point(x, y);
-                }
                 if (c != CellType.EMPTY) {
                     board.mWidget[x][y] = line.charAt(x);
                 }
             }
         }
         board.mWidgetsRects = getRects(board.mWidget);
-        board.mWidgetsRects.forEach(
-                widgetRect -> board.mWidgetsMap.put(widgetRect.mType, widgetRect));
+        board.mWidgetsRects.forEach(widgetRect -> {
+            if (widgetRect.mType == CellType.MAIN_WIDGET) {
+                board.mMain = widgetRect;
+            }
+            board.mWidgetsMap.put(widgetRect.mType, widgetRect);
+        });
         board.mIconPoints = getIconPoints(board.mWidget);
         return board;
     }
+
+    public String toString(int maxX, int maxY) {
+        StringBuilder s = new StringBuilder();
+        maxX = Math.min(maxX, mWidget.length);
+        maxY = Math.min(maxY, mWidget[0].length);
+        for (int y = 0; y < maxY; y++) {
+            for (int x = 0; x < maxX; x++) {
+                s.append(mWidget[x][y]);
+            }
+            s.append('\n');
+        }
+        return s.toString();
+    }
+
+    public static List<CellLayoutBoard> boardListFromString(String boardsStr) {
+        String[] lines = boardsStr.split("\n");
+        ArrayList<String> individualBoards = new ArrayList<>();
+        ArrayList<CellLayoutBoard> boards = new ArrayList<>();
+        for (String line : lines) {
+            String[] boardSegment = line.split("\\|");
+            for (int i = 0; i < boardSegment.length; i++) {
+                if (i >= individualBoards.size()) {
+                    individualBoards.add(boardSegment[i]);
+                } else {
+                    individualBoards.set(i, individualBoards.get(i) + "\n" + boardSegment[i]);
+                }
+            }
+        }
+        for (String board : individualBoards) {
+            boards.add(CellLayoutBoard.boardFromString(board));
+        }
+        return boards;
+    }
 }
diff --git a/tests/src/com/android/launcher3/celllayout/MultipleCellLayoutsSimpleReorder.java b/tests/src/com/android/launcher3/celllayout/MultipleCellLayoutsSimpleReorder.java
new file mode 100644
index 0000000..9b52fe8
--- /dev/null
+++ b/tests/src/com/android/launcher3/celllayout/MultipleCellLayoutsSimpleReorder.java
@@ -0,0 +1,88 @@
+/*
+ * 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.celllayout.testcases;
+
+import android.graphics.Point;
+
+import java.util.Map;
+
+/**
+ * The grids represent the workspace to be build by TestWorkspaceBuilder, to see what each character
+ * in the board mean refer to {@code CellType}
+ */
+public class MultipleCellLayoutsSimpleReorder {
+
+    /** 5x5 Test
+     **/
+    private static final String START_BOARD_STR_5x5 = ""
+            + "xxxxx|-----\n"
+            + "--mm-|-----\n"
+            + "--mm-|-----\n"
+            + "-----|-----\n"
+            + "-----|-----";
+    private static final Point MOVE_TO_5x5 = new Point(8, 3);
+    private static final String END_BOARD_STR_5x5 = ""
+            + "xxxxx|-----\n"
+            + "-----|-----\n"
+            + "-----|-----\n"
+            + "-----|---mm\n"
+            + "-----|---mm";
+    private static final ReorderTestCase TEST_CASE_5x5 = new ReorderTestCase(START_BOARD_STR_5x5,
+            MOVE_TO_5x5,
+            END_BOARD_STR_5x5);
+
+    /** 4x4 Test
+     **/
+    private static final String START_BOARD_STR_4x4 = ""
+            + "xxxx|----\n"
+            + "--mm|----\n"
+            + "--mm|----\n"
+            + "----|----";
+    private static final Point MOVE_TO_4x4 = new Point(5, 3);
+    private static final String END_BOARD_STR_4x4 = ""
+            + "xxxx|----\n"
+            + "----|----\n"
+            + "----|-mm-\n"
+            + "----|-mm-";
+    private static final ReorderTestCase TEST_CASE_4x4 = new ReorderTestCase(START_BOARD_STR_4x4,
+            MOVE_TO_4x4,
+            END_BOARD_STR_4x4);
+
+
+    /** 6x5 Test
+     **/
+    private static final String START_BOARD_STR_6x5 = ""
+            + "xxxxxx|------\n"
+            + "--m---|------\n"
+            + "------|------\n"
+            + "------|------\n"
+            + "------|------";
+    private static final Point MOVE_TO_6x5 = new Point(10, 4);
+    private static final String END_BOARD_STR_6x5 = ""
+            + "xxxxxx|------\n"
+            + "------|------\n"
+            + "------|------\n"
+            + "------|------\n"
+            + "------|----m-";
+    private static final ReorderTestCase TEST_CASE_6x5 = new ReorderTestCase(START_BOARD_STR_6x5,
+            MOVE_TO_6x5,
+            END_BOARD_STR_6x5);
+
+    public static final Map<Point, ReorderTestCase> TEST_BY_GRID_SIZE =
+            Map.of(new Point(5, 5), TEST_CASE_5x5,
+                    new Point(4, 4), TEST_CASE_4x4,
+                    new Point(6, 5), TEST_CASE_6x5);
+}
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
index 9da7e0f..35f6cbc 100644
--- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
+++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
@@ -26,8 +26,10 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.launcher3.CellLayout;
+import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.celllayout.testcases.FullReorderCase;
 import com.android.launcher3.celllayout.testcases.MoveOutReorderCase;
+import com.android.launcher3.celllayout.testcases.MultipleCellLayoutsSimpleReorder;
 import com.android.launcher3.celllayout.testcases.PushReorderCase;
 import com.android.launcher3.celllayout.testcases.ReorderTestCase;
 import com.android.launcher3.celllayout.testcases.SimpleReorderCase;
@@ -37,7 +39,6 @@
 import com.android.launcher3.ui.TaplTestsLauncher3;
 import com.android.launcher3.util.rule.ShellCommandRule;
 import com.android.launcher3.views.DoubleShadowBubbleTextView;
-import com.android.launcher3.widget.LauncherAppWidgetHostView;
 
 import org.junit.Assume;
 import org.junit.Before;
@@ -46,6 +47,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
 
@@ -60,20 +63,6 @@
 
     TestWorkspaceBuilder mWorkspaceBuilder;
 
-    private View getViewAt(int cellX, int cellY) {
-        return getFromLauncher(l -> l.getWorkspace().getScreenWithId(
-                l.getWorkspace().getScreenIdForPageIndex(0)).getChildAt(cellX, cellY));
-    }
-
-    private Point getCellDimensions() {
-        return getFromLauncher(l -> {
-            CellLayout cellLayout = l.getWorkspace().getScreenWithId(
-                    l.getWorkspace().getScreenIdForPageIndex(0));
-            return new Point(cellLayout.getWidth() / cellLayout.getCountX(),
-                    cellLayout.getHeight() / cellLayout.getCountY());
-        });
-    }
-
     @Before
     public void setup() throws Throwable {
         mWorkspaceBuilder = new TestWorkspaceBuilder(this, mTargetContext);
@@ -84,49 +73,87 @@
     /**
      * Validate if the given board represent the current CellLayout
      **/
-    private boolean validateBoard(CellLayoutBoard board) {
-        boolean match = true;
-        Point cellDimensions = getCellDimensions();
-        for (CellLayoutBoard.WidgetRect widgetRect : board.getWidgets()) {
-            if (widgetRect.shouldIgnore()) {
-                continue;
+    private boolean validateBoard(List<CellLayoutBoard> testBoards) {
+        ArrayList<CellLayoutBoard> workspaceBoards = workspaceToBoards();
+        if (workspaceBoards.size() < testBoards.size()) {
+            return false;
+        }
+        for (int i = 0; i < testBoards.size(); i++) {
+            if (testBoards.get(i).compareTo(workspaceBoards.get(i)) != 0) {
+                return false;
             }
-            View widget = getViewAt(widgetRect.getCellX(), widgetRect.getCellY());
-            assertTrue("The view selected at " + board + " is not a widget",
-                    widget instanceof LauncherAppWidgetHostView);
-            match &= widgetRect.getSpanX()
-                    == Math.round(widget.getWidth() / (float) cellDimensions.x);
-            match &= widgetRect.getSpanY()
-                    == Math.round(widget.getHeight() / (float) cellDimensions.y);
-            if (!match) return match;
         }
-        for (CellLayoutBoard.IconPoint iconPoint : board.getIcons()) {
-            View icon = getViewAt(iconPoint.getCoord().x, iconPoint.getCoord().y);
-            assertTrue("The view selected at " + iconPoint.coord + " is not an Icon",
-                    icon instanceof DoubleShadowBubbleTextView);
+        return true;
+    }
+
+    private FavoriteItemsTransaction buildWorkspaceFromBoards(List<CellLayoutBoard> boards,
+            FavoriteItemsTransaction transaction) {
+        for (int i = 0; i < boards.size(); i++) {
+            CellLayoutBoard board = boards.get(i);
+            mWorkspaceBuilder.buildFromBoard(board, transaction, i);
         }
-        return match;
+        return transaction;
+    }
+
+    private void printCurrentWorkspace() {
+        InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mTargetContext);
+        ArrayList<CellLayoutBoard> boards = workspaceToBoards();
+        for (int i = 0; i < boards.size(); i++) {
+            Log.d(TAG, "Screen number " + i);
+            Log.d(TAG, ".\n" + boards.get(i).toString(idp.numColumns, idp.numRows));
+        }
+    }
+
+    private ArrayList<CellLayoutBoard> workspaceToBoards() {
+        return getFromLauncher(l -> {
+            ArrayList<CellLayoutBoard> boards = new ArrayList<>();
+            int widgetCount = 0;
+            for (CellLayout cellLayout : l.getWorkspace().mWorkspaceScreens) {
+                CellLayoutBoard board = new CellLayoutBoard();
+                int count = cellLayout.getShortcutsAndWidgets().getChildCount();
+                for (int i = 0; i < count; i++) {
+                    View callView = cellLayout.getShortcutsAndWidgets().getChildAt(i);
+                    CellLayoutLayoutParams params =
+                            (CellLayoutLayoutParams) callView.getLayoutParams();
+                    // is icon
+                    if (callView instanceof DoubleShadowBubbleTextView) {
+                        board.addIcon(params.getCellX(), params.getCellY());
+                    } else {
+                        // is widget
+                        board.addWidget(params.getCellX(), params.getCellY(), params.cellHSpan,
+                                params.cellVSpan, (char) ('A' + widgetCount));
+                        widgetCount++;
+                    }
+                }
+                boards.add(board);
+            }
+            return boards;
+        });
     }
 
     private void runTestCase(ReorderTestCase testCase)
             throws ExecutionException, InterruptedException {
-        Point mainWidgetCellPos = testCase.mStart.getMain();
+        CellLayoutBoard.WidgetRect mainWidgetCellPos = CellLayoutBoard.getMainFromList(
+                testCase.mStart);
 
         FavoriteItemsTransaction transaction =
                 new FavoriteItemsTransaction(mTargetContext, this);
-        mWorkspaceBuilder.buildFromBoard(testCase.mStart, transaction).commit();
+        transaction = buildWorkspaceFromBoards(testCase.mStart, transaction);
+        transaction.commit();
         waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading());
-        Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.x,
-                mainWidgetCellPos.y);
+        Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.getCellX(),
+                mainWidgetCellPos.getCellY());
         assertNotNull(widget);
         WidgetResizeFrame resizeFrame = widget.dragWidgetToWorkspace(testCase.moveMainTo.x,
-                testCase.moveMainTo.y);
+                testCase.moveMainTo.y, mainWidgetCellPos.getSpanX(), mainWidgetCellPos.getSpanY());
         resizeFrame.dismiss();
 
         boolean isValid = false;
-        for (CellLayoutBoard board : testCase.mEnd) {
-            isValid |= validateBoard(board);
+        for (List<CellLayoutBoard> boards : testCase.mEnd) {
+            isValid |= validateBoard(boards);
+            if (isValid) break;
         }
+        printCurrentWorkspace();
         assertTrue("Non of the valid boards match with the current state", isValid);
     }
 
@@ -168,4 +195,11 @@
         runTestCaseMap(MoveOutReorderCase.TEST_BY_GRID_SIZE,
                 MoveOutReorderCase.class.getSimpleName());
     }
+
+    @Test
+    public void multipleCellLayoutsSimpleReorder() throws ExecutionException, InterruptedException {
+        Assume.assumeTrue("Test doesn't support foldables", !mLauncher.isTwoPanels());
+        runTestCaseMap(MultipleCellLayoutsSimpleReorder.TEST_BY_GRID_SIZE,
+                MultipleCellLayoutsSimpleReorder.class.getSimpleName());
+    }
 }
diff --git a/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java
index 16448af..5945605 100644
--- a/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java
+++ b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java
@@ -15,7 +15,6 @@
  */
 package com.android.launcher3.celllayout;
 
-import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
 import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;
 
 import android.content.ComponentName;
@@ -62,7 +61,7 @@
      * Fills the given rect in WidgetRect with 1x1 widgets. This is useful to equalize cases.
      */
     private FavoriteItemsTransaction fillWithWidgets(CellLayoutBoard.WidgetRect widgetRect,
-            FavoriteItemsTransaction transaction) {
+            FavoriteItemsTransaction transaction, int screenId) {
         int initX = widgetRect.getCellX();
         int initY = widgetRect.getCellY();
         for (int x = initX; x < initX + widgetRect.getSpanX(); x++) {
@@ -71,8 +70,7 @@
                     // this widgets are filling, we don't care if we can't place them
                     ItemInfo item = createWidgetInCell(
                             new CellLayoutBoard.WidgetRect(CellLayoutBoard.CellType.IGNORE,
-                                    new Rect(x, y, x, y))
-                    );
+                                    new Rect(x, y, x, y)), screenId);
                     transaction.addItem(item);
                 } catch (Exception e) {
                     Log.d(TAG, "Unable to place filling widget at " + x + "," + y);
@@ -94,11 +92,11 @@
     }
 
     private void addCorrespondingWidgetRect(CellLayoutBoard.WidgetRect widgetRect,
-            FavoriteItemsTransaction transaction) {
+            FavoriteItemsTransaction transaction, int screenId) {
         if (widgetRect.mType == 'x') {
-            fillWithWidgets(widgetRect, transaction);
+            fillWithWidgets(widgetRect, transaction, screenId);
         } else {
-            transaction.addItem(createWidgetInCell(widgetRect));
+            transaction.addItem(createWidgetInCell(widgetRect, screenId));
         }
     }
 
@@ -106,11 +104,11 @@
      * Builds the given board into the transaction
      */
     public FavoriteItemsTransaction buildFromBoard(CellLayoutBoard board,
-            FavoriteItemsTransaction transaction) {
+            FavoriteItemsTransaction transaction, final int screenId) {
         board.getWidgets().forEach(
-                (widgetRect) -> addCorrespondingWidgetRect(widgetRect, transaction));
+                (widgetRect) -> addCorrespondingWidgetRect(widgetRect, transaction, screenId));
         board.getIcons().forEach((iconPoint) ->
-                transaction.addItem(createIconInCell(iconPoint))
+                transaction.addItem(createIconInCell(iconPoint, screenId))
         );
         return transaction;
     }
@@ -120,14 +118,14 @@
      * be clean otherwise this doesn't overrides the existing icons.
      */
     public FavoriteItemsTransaction fillHotseatIcons(FavoriteItemsTransaction transaction) {
-        int hotseatCount = InvariantDeviceProfile.INSTANCE.get(mContext).numShownHotseatIcons;
+        int hotseatCount = InvariantDeviceProfile.INSTANCE.get(mContext).numDatabaseHotseatIcons;
         for (int i = 0; i < hotseatCount; i++) {
             transaction.addItem(getHotseatValues(i));
         }
         return transaction;
     }
 
-    private ItemInfo createWidgetInCell(CellLayoutBoard.WidgetRect widgetRect) {
+    private ItemInfo createWidgetInCell(CellLayoutBoard.WidgetRect widgetRect, int screenId) {
         LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(mTest, false);
         LauncherAppWidgetInfo item = createWidgetInfo(info,
                 ApplicationProvider.getApplicationContext(), true);
@@ -136,14 +134,14 @@
         item.cellY = widgetRect.getCellY();
         item.spanX = widgetRect.getSpanX();
         item.spanY = widgetRect.getSpanY();
-        item.screenId = FIRST_SCREEN_ID;
+        item.screenId = screenId;
         return item;
     }
 
-    private ItemInfo createIconInCell(CellLayoutBoard.IconPoint iconPoint) {
+    private ItemInfo createIconInCell(CellLayoutBoard.IconPoint iconPoint, int screenId) {
         WorkspaceItemInfo item = new WorkspaceItemInfo(getApp());
         item.id = getID();
-        item.screenId = FIRST_SCREEN_ID;
+        item.screenId = screenId;
         item.cellX = iconPoint.getCoord().x;
         item.cellY = iconPoint.getCoord().y;
         item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1;
diff --git a/tests/src/com/android/launcher3/celllayout/testcases/ReorderTestCase.java b/tests/src/com/android/launcher3/celllayout/testcases/ReorderTestCase.java
index 0a28668..1689e47 100644
--- a/tests/src/com/android/launcher3/celllayout/testcases/ReorderTestCase.java
+++ b/tests/src/com/android/launcher3/celllayout/testcases/ReorderTestCase.java
@@ -24,23 +24,23 @@
 import java.util.stream.Collectors;
 
 public class ReorderTestCase {
-    public CellLayoutBoard mStart;
+    public List<CellLayoutBoard> mStart;
     public Point moveMainTo;
-    public List<CellLayoutBoard> mEnd;
+    public List<List<CellLayoutBoard>> mEnd;
 
-    ReorderTestCase(CellLayoutBoard start, Point moveMainTo, CellLayoutBoard ... end) {
+    ReorderTestCase(List<CellLayoutBoard> start, Point moveMainTo, List<CellLayoutBoard> ... end) {
         mStart = start;
         this.moveMainTo = moveMainTo;
         mEnd = Arrays.asList(end);
     }
 
     ReorderTestCase(String start, Point moveMainTo, String ... end) {
-        mStart = CellLayoutBoard.boardFromString(start);
+        mStart = CellLayoutBoard.boardListFromString(start);
         this.moveMainTo = moveMainTo;
         mEnd = Arrays
                 .asList(end)
                 .stream()
-                .map(CellLayoutBoard::boardFromString)
+                .map(CellLayoutBoard::boardListFromString)
                 .collect(Collectors.toList());
     }
 }
diff --git a/tests/src/com/android/launcher3/celllayout/testcases/SimpleReorderCase.java b/tests/src/com/android/launcher3/celllayout/testcases/SimpleReorderCase.java
index 546c48b..c9f6849 100644
--- a/tests/src/com/android/launcher3/celllayout/testcases/SimpleReorderCase.java
+++ b/tests/src/com/android/launcher3/celllayout/testcases/SimpleReorderCase.java
@@ -33,13 +33,13 @@
             + "--mm-\n"
             + "-----\n"
             + "-----";
-    private static final Point MOVE_TO_5x5 = new Point(4, 4);
+    private static final Point MOVE_TO_5x5 = new Point(0, 4);
     private static final String END_BOARD_STR_5x5 = ""
             + "xxxxx\n"
             + "-----\n"
             + "-----\n"
-            + "---mm\n"
-            + "---mm";
+            + "mm---\n"
+            + "mm---";
     private static final ReorderTestCase TEST_CASE_5x5 = new ReorderTestCase(START_BOARD_STR_5x5,
             MOVE_TO_5x5,
             END_BOARD_STR_5x5);
@@ -61,7 +61,27 @@
             MOVE_TO_4x4,
             END_BOARD_STR_4x4);
 
+    /** 6x5 Test
+     **/
+    private static final String START_BOARD_STR_6x5 = ""
+            + "xxxxxx\n"
+            + "-mm---\n"
+            + "-mm---\n"
+            + "------\n"
+            + "------";
+    private static final Point MOVE_TO_6x5 = new Point(4, 3);
+    private static final String END_BOARD_STR_6x5 = ""
+            + "xxxxxx\n"
+            + "------\n"
+            + "------\n"
+            + "----mm\n"
+            + "----mm";
+    private static final ReorderTestCase TEST_CASE_6x5 = new ReorderTestCase(START_BOARD_STR_6x5,
+            MOVE_TO_6x5,
+            END_BOARD_STR_6x5);
+
     public static final Map<Point, ReorderTestCase> TEST_BY_GRID_SIZE =
             Map.of(new Point(5, 5), TEST_CASE_5x5,
-                    new Point(4, 4), TEST_CASE_4x4);
+                    new Point(4, 4), TEST_CASE_4x4,
+                    new Point(6, 5), TEST_CASE_6x5);
 }
diff --git a/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt b/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
index d26381d..03352fe 100644
--- a/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
+++ b/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
@@ -30,9 +30,7 @@
 import com.android.launcher3.util.LauncherModelHelper
 import java.util.UUID
 
-/**
- * Base class for workspace related tests.
- */
+/** Base class for workspace related tests. */
 abstract class AbstractWorkspaceModelTest {
     companion object {
         val emptyScreenSpaces = listOf(Rect(0, 0, 5, 5))
@@ -64,10 +62,7 @@
         mModelHelper.destroy()
     }
 
-
-    /**
-     * Sets up workspaces with the given screen IDs with some items and a 2x2 space.
-     */
+    /** Sets up workspaces with the given screen IDs with some items and a 2x2 space. */
     fun setupWorkspaces(screenIdsWithItems: List<Int>) {
         var nextItemId = 1
         screenIdsWithItems.forEach { screenId ->
@@ -83,8 +78,7 @@
         screen1: List<Rect>? = null,
         screen2: List<Rect>? = null,
         screen3: List<Rect>? = null,
-    ) = listOf(screen0, screen1, screen2, screen3)
-        .let(this::setupWithSpaces)
+    ) = listOf(screen0, screen1, screen2, screen3).let(this::setupWithSpaces)
 
     private fun setupWithSpaces(workspaceSpaces: List<List<Rect>?>) {
         var nextItemId = 1
@@ -110,9 +104,7 @@
         var itemId = itemStartId
         val occupancy = GridOccupancy(mIdp.numColumns, mIdp.numRows)
         occupancy.markCells(0, 0, mIdp.numColumns, mIdp.numRows, true)
-        spaces.forEach { spaceRect ->
-            occupancy.markCells(spaceRect, false)
-        }
+        spaces.forEach { spaceRect -> occupancy.markCells(spaceRect, false) }
         mExistingScreens.add(screenId)
         mScreenOccupancy.append(screenId, occupancy)
         for (x in 0 until mIdp.numColumns) {
@@ -139,24 +131,21 @@
         return itemId
     }
 
-    fun getExistingItem() = WorkspaceItemInfo()
-        .apply { intent = Intent().setComponent(ComponentName("a", "b")) }
+    fun getExistingItem() =
+        WorkspaceItemInfo().apply { intent = Intent().setComponent(ComponentName("a", "b")) }
 
     fun getNewItem(): WorkspaceItemInfo {
         val itemPackage = UUID.randomUUID().toString()
-        return WorkspaceItemInfo()
-            .apply { intent = Intent().setComponent(ComponentName(itemPackage, itemPackage)) }
+        return WorkspaceItemInfo().apply {
+            intent = Intent().setComponent(ComponentName(itemPackage, itemPackage))
+        }
     }
 }
 
-data class NewItemSpace(
-    val screenId: Int,
-    val cellX: Int,
-    val cellY: Int
-) {
+data class NewItemSpace(val screenId: Int, val cellX: Int, val cellY: Int) {
     fun toIntArray() = intArrayOf(screenId, cellX, cellY)
 
     companion object {
         fun fromIntArray(array: kotlin.IntArray) = NewItemSpace(array[0], array[1], array[2])
     }
-}
\ No newline at end of file
+}
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
index 65d938b..749ffcf 100644
--- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
+++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
@@ -23,9 +23,9 @@
 import com.android.launcher3.model.data.WorkspaceItemInfo
 import com.android.launcher3.util.Executors
 import com.android.launcher3.util.IntArray
-import com.android.launcher3.util.same
-import com.android.launcher3.util.eq
 import com.android.launcher3.util.any
+import com.android.launcher3.util.eq
+import com.android.launcher3.util.same
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Before
@@ -34,31 +34,24 @@
 import org.mockito.ArgumentCaptor
 import org.mockito.Captor
 import org.mockito.Mock
-import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.Mockito.times
 import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
 
-/**
- * Tests for [AddWorkspaceItemsTask]
- */
+/** Tests for [AddWorkspaceItemsTask] */
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
 
-    @Captor
-    private lateinit var mAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
+    @Captor private lateinit var mAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
 
-    @Captor
-    private lateinit var mNotAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
+    @Captor private lateinit var mNotAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
 
-    @Mock
-    private lateinit var mDataModelCallbacks: BgDataModel.Callbacks
+    @Mock private lateinit var mDataModelCallbacks: BgDataModel.Callbacks
 
-    @Mock
-    private lateinit var mWorkspaceItemSpaceFinder: WorkspaceItemSpaceFinder
-
+    @Mock private lateinit var mWorkspaceItemSpaceFinder: WorkspaceItemSpaceFinder
 
     @Before
     override fun setup() {
@@ -89,10 +82,7 @@
 
     @Test
     fun givenNewAndExistingItems_whenExecuteTask_thenOnlyAddNewItem() {
-        val itemsToAdd = arrayOf(
-            getNewItem(),
-            getExistingItem()
-        )
+        val itemsToAdd = arrayOf(getNewItem(), getExistingItem())
         givenNewItemSpaces(NewItemSpace(1, 0, 0))
         val nonEmptyScreenIds = listOf(0)
 
@@ -132,13 +122,14 @@
 
     @Test
     fun givenMultipleItems_whenExecuteTask_thenAddThem() {
-        val itemsToAdd = arrayOf(
-            getNewItem(),
-            getExistingItem(),
-            getNewItem(),
-            getNewItem(),
-            getExistingItem(),
-        )
+        val itemsToAdd =
+            arrayOf(
+                getNewItem(),
+                getExistingItem(),
+                getNewItem(),
+                getNewItem(),
+                getExistingItem(),
+            )
         givenNewItemSpaces(
             NewItemSpace(1, 3, 3),
             NewItemSpace(2, 0, 0),
@@ -159,27 +150,16 @@
         // Items that are added to the second screen should be animated
         val itemsAddedToSecondScreen = addedItems.filter { it.itemInfo.screenId == 2 }
         assertThat(itemsAddedToSecondScreen.size).isEqualTo(2)
-        itemsAddedToSecondScreen.forEach {
-            assertThat(it.isAnimated).isTrue()
-        }
+        itemsAddedToSecondScreen.forEach { assertThat(it.isAnimated).isTrue() }
         verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 3)
     }
 
-    /**
-     * Sets up the item space data that will be returned from WorkspaceItemSpaceFinder.
-     */
+    /** Sets up the item space data that will be returned from WorkspaceItemSpaceFinder. */
     private fun givenNewItemSpaces(vararg newItemSpaces: NewItemSpace) {
         val spaceStack = newItemSpaces.toMutableList()
         whenever(
-            mWorkspaceItemSpaceFinder.findSpaceForItem(
-                any(),
-                any(),
-                any(),
-                any(),
-                any(),
-                any()
+                mWorkspaceItemSpaceFinder.findSpaceForItem(any(), any(), any(), any(), any(), any())
             )
-        )
             .then { spaceStack.removeFirst().toIntArray() }
     }
 
@@ -187,20 +167,21 @@
      * Verifies if WorkspaceItemSpaceFinder was called with proper arguments and how many times was
      * it called.
      */
-    private fun verifyItemSpaceFinderCall(
-        nonEmptyScreenIds: List<Int>,
-        numberOfExpectedCall: Int
-    ) {
+    private fun verifyItemSpaceFinderCall(nonEmptyScreenIds: List<Int>, numberOfExpectedCall: Int) {
         verify(mWorkspaceItemSpaceFinder, times(numberOfExpectedCall))
             .findSpaceForItem(
-                same(mAppState), same(mModelHelper.bgDataModel),
-                eq(IntArray.wrap(*nonEmptyScreenIds.toIntArray())), eq(IntArray()), eq(1), eq(1)
+                same(mAppState),
+                same(mModelHelper.bgDataModel),
+                eq(IntArray.wrap(*nonEmptyScreenIds.toIntArray())),
+                eq(IntArray()),
+                eq(1),
+                eq(1)
             )
     }
 
     /**
-     * Sets up the workspaces with items, executes the task, collects the added items from the
-     * model callback then returns it.
+     * Sets up the workspaces with items, executes the task, collects the added items from the model
+     * callback then returns it.
      */
     private fun testAddItems(
         nonEmptyScreenIds: List<Int>,
@@ -209,21 +190,21 @@
         setupWorkspaces(nonEmptyScreenIds)
         val task = newTask(*itemsToAdd)
         var updateCount = 0
-        mModelHelper.executeTaskForTest(task)
-            .forEach {
-                updateCount++
-                it.run()
-            }
+        mModelHelper.executeTaskForTest(task).forEach {
+            updateCount++
+            it.run()
+        }
 
         val addedItems = mutableListOf<AddedItem>()
         if (updateCount > 0) {
-            verify(mDataModelCallbacks).bindAppsAdded(
-                any(),
-                mNotAnimatedItemArgumentCaptor.capture(), mAnimatedItemArgumentCaptor.capture()
-            )
+            verify(mDataModelCallbacks)
+                .bindAppsAdded(
+                    any(),
+                    mNotAnimatedItemArgumentCaptor.capture(),
+                    mAnimatedItemArgumentCaptor.capture()
+                )
             addedItems.addAll(mAnimatedItemArgumentCaptor.value.map { AddedItem(it, true) })
             addedItems.addAll(mNotAnimatedItemArgumentCaptor.value.map { AddedItem(it, false) })
-
         }
 
         return addedItems
@@ -234,12 +215,10 @@
      * with a mock.
      */
     private fun newTask(vararg items: ItemInfo): AddWorkspaceItemsTask =
-        items.map { Pair.create(it, Any()) }
+        items
+            .map { Pair.create(it, Any()) }
             .toMutableList()
             .let { AddWorkspaceItemsTask(it, mWorkspaceItemSpaceFinder) }
 }
 
-private data class AddedItem(
-    val itemInfo: ItemInfo,
-    val isAnimated: Boolean
-)
+private data class AddedItem(val itemInfo: ItemInfo, val isAnimated: Boolean)
diff --git a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
index 7d36740..f55b244 100644
--- a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
+++ b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
@@ -1,7 +1,5 @@
 package com.android.launcher3.model;
 
-import static com.android.launcher3.testing.shared.TestProtocol.INCORRECT_INFO_UPDATED;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotSame;
@@ -16,7 +14,6 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -29,7 +26,6 @@
 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.testing.shared.TestProtocol;
 import com.android.launcher3.util.LauncherModelHelper;
 
 import org.junit.After;
@@ -47,15 +43,12 @@
 @RunWith(AndroidJUnit4.class)
 public class CacheDataUpdatedTaskTest {
 
-    private static final String TAG = "CacheDataUpdatedTaskTest";
-
     private static final String NEW_LABEL_PREFIX = "new-label-";
 
     private LauncherModelHelper mModelHelper;
 
     @Before
     public void setup() throws Exception {
-        TestProtocol.sDebugTracing = true;
         mModelHelper = new LauncherModelHelper();
         mModelHelper.initializeData("cache_data_updated_task_data");
 
@@ -98,7 +91,6 @@
     @After
     public void tearDown() {
         mModelHelper.destroy();
-        TestProtocol.sDebugTracing = false;
     }
 
     private CacheDataUpdatedTask newTask(int op, String... pkg) {
@@ -122,7 +114,6 @@
         // Verify that only app1 var updated in allAppsList
         assertFalse(mModelHelper.getAllAppsList().data.isEmpty());
         for (AppInfo info : mModelHelper.getAllAppsList().data) {
-            Log.i(INCORRECT_INFO_UPDATED, "testCacheUpdate_update_apps: checking info=" + info);
             if (info.componentName.getPackageName().equals("app1")) {
                 assertFalse(info.bitmap.isNullOrLowRes());
             } else {
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
index 76a186b..a85fa3a 100644
--- a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
+++ b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
@@ -17,14 +17,15 @@
 
 import android.content.Context
 import android.content.Intent
-import android.database.Cursor;
+import android.database.Cursor
 import android.database.sqlite.SQLiteDatabase
 import android.graphics.Point
 import android.os.Process
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.launcher3.InvariantDeviceProfile
-import com.android.launcher3.LauncherFiles
+import com.android.launcher3.LauncherPrefs
+import com.android.launcher3.LauncherPrefs.Companion.WORKSPACE_SIZE
 import com.android.launcher3.LauncherSettings.Favorites.*
 import com.android.launcher3.config.FeatureFlags
 import com.android.launcher3.model.GridSizeMigrationUtil.DbReader
@@ -38,7 +39,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 
-/** Unit tests for [GridSizeMigrationUtil]  */
+/** Unit tests for [GridSizeMigrationUtil] */
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class GridSizeMigrationUtilTest {
@@ -64,19 +65,20 @@
         context = modelHelper.sandboxContext
         db = modelHelper.provider.db
 
-        validPackages = setOf(
-            TEST_PACKAGE,
-            testPackage1,
-            testPackage2,
-            testPackage3,
-            testPackage4,
-            testPackage5,
-            testPackage6,
-            testPackage7,
-            testPackage8,
-            testPackage9,
-            testPackage10
-        )
+        validPackages =
+            setOf(
+                TEST_PACKAGE,
+                testPackage1,
+                testPackage2,
+                testPackage3,
+                testPackage4,
+                testPackage5,
+                testPackage6,
+                testPackage7,
+                testPackage8,
+                testPackage9,
+                testPackage10
+            )
 
         idp = InvariantDeviceProfile.INSTANCE[context]
         val userSerial = UserCache.INSTANCE[context].getSerialNumberForUser(Process.myUserHandle())
@@ -90,8 +92,8 @@
     }
 
     /**
-     * Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is
-     * not needed anymore
+     * Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is not
+     * needed anymore
      */
     @Test
     @Throws(Exception::class)
@@ -124,25 +126,27 @@
         val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
         val destReader = DbReader(db, TABLE_NAME, context, validPackages)
         GridSizeMigrationUtil.migrate(
-                context,
-                db,
-                srcReader,
-                destReader,
-                idp.numDatabaseHotseatIcons,
-                Point(idp.numColumns, idp.numRows),
-                DeviceGridState(context),
-                DeviceGridState(idp)
+            context,
+            db,
+            srcReader,
+            destReader,
+            idp.numDatabaseHotseatIcons,
+            Point(idp.numColumns, idp.numRows),
+            DeviceGridState(context),
+            DeviceGridState(idp)
         )
 
         // Check hotseat items
-        var c = context.contentResolver.query(
-            CONTENT_URI,
-            arrayOf(SCREEN, INTENT),
-            "container=$CONTAINER_HOTSEAT",
-            null,
-            SCREEN,
-            null
-        ) ?: throw IllegalStateException()
+        var c =
+            context.contentResolver.query(
+                CONTENT_URI,
+                arrayOf(SCREEN, INTENT),
+                "container=$CONTAINER_HOTSEAT",
+                null,
+                SCREEN,
+                null
+            )
+                ?: throw IllegalStateException()
 
         assertThat(c.count).isEqualTo(idp.numDatabaseHotseatIcons)
 
@@ -163,14 +167,16 @@
         c.close()
 
         // Check workspace items
-        c = context.contentResolver.query(
-            CONTENT_URI,
-            arrayOf(CELLX, CELLY, INTENT),
-            "container=$CONTAINER_DESKTOP",
-            null,
-            null,
-            null
-        ) ?: throw IllegalStateException()
+        c =
+            context.contentResolver.query(
+                CONTENT_URI,
+                arrayOf(CELLX, CELLY, INTENT),
+                "container=$CONTAINER_DESKTOP",
+                null,
+                null,
+                null
+            )
+                ?: throw IllegalStateException()
 
         intentIndex = c.getColumnIndex(INTENT)
         val cellXIndex = c.getColumnIndex(CELLX)
@@ -195,8 +201,8 @@
     }
 
     /**
-     * Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is
-     * not needed anymore
+     * Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is not
+     * needed anymore
      */
     @Test
     @Throws(Exception::class)
@@ -235,39 +241,46 @@
         val readerGridB = DbReader(db, TABLE_NAME, context, validPackages)
         // migrate from A -> B
         GridSizeMigrationUtil.migrate(
-                context,
-                db,
-                readerGridA,
-                readerGridB,
-                idp.numDatabaseHotseatIcons,
-                Point(idp.numColumns, idp.numRows),
-                DeviceGridState(context),
-                DeviceGridState(idp)
+            context,
+            db,
+            readerGridA,
+            readerGridB,
+            idp.numDatabaseHotseatIcons,
+            Point(idp.numColumns, idp.numRows),
+            DeviceGridState(context),
+            DeviceGridState(idp)
         )
 
         // Check hotseat items in grid B
-        var c = context.contentResolver.query(
+        var c =
+            context.contentResolver.query(
                 CONTENT_URI,
                 arrayOf(SCREEN, INTENT),
                 "container=$CONTAINER_HOTSEAT",
                 null,
                 SCREEN,
                 null
-        ) ?: throw IllegalStateException()
+            )
+                ?: throw IllegalStateException()
         // Expected hotseat items in grid B
         // 2 1 3 4
-        verifyHotseat(c, idp,
-                mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList())
+        verifyHotseat(
+            c,
+            idp,
+            mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList()
+        )
 
         // Check workspace items in grid B
-        c = context.contentResolver.query(
+        c =
+            context.contentResolver.query(
                 CONTENT_URI,
                 arrayOf(SCREEN, CELLX, CELLY, INTENT),
                 "container=$CONTAINER_DESKTOP",
                 null,
                 null,
                 null
-        ) ?: throw IllegalStateException()
+            )
+                ?: throw IllegalStateException()
         var locMap = parseLocMap(context, c)
         // Expected items in grid B
         // _ _ _ _
@@ -285,38 +298,45 @@
 
         // migrate from B -> A
         GridSizeMigrationUtil.migrate(
-                context,
-                db,
-                readerGridB,
-                readerGridA,
-                5,
-                Point(5, 5),
-                DeviceGridState(idp),
-                DeviceGridState(context)
+            context,
+            db,
+            readerGridB,
+            readerGridA,
+            5,
+            Point(5, 5),
+            DeviceGridState(idp),
+            DeviceGridState(context)
         )
         // Check hotseat items in grid A
-        c = context.contentResolver.query(
+        c =
+            context.contentResolver.query(
                 TMP_CONTENT_URI,
                 arrayOf(SCREEN, INTENT),
                 "container=$CONTAINER_HOTSEAT",
                 null,
                 SCREEN,
                 null
-        ) ?: throw IllegalStateException()
+            )
+                ?: throw IllegalStateException()
         // Expected hotseat items in grid A
         // 1 2 _ 3 4
-        verifyHotseat(c, idp, mutableListOf(
-                testPackage1, testPackage2, null, testPackage3, testPackage4).toList())
+        verifyHotseat(
+            c,
+            idp,
+            mutableListOf(testPackage1, testPackage2, null, testPackage3, testPackage4).toList()
+        )
 
         // Check workspace items in grid A
-        c = context.contentResolver.query(
+        c =
+            context.contentResolver.query(
                 TMP_CONTENT_URI,
                 arrayOf(SCREEN, CELLX, CELLY, INTENT),
                 "container=$CONTAINER_DESKTOP",
                 null,
                 null,
                 null
-        ) ?: throw IllegalStateException()
+            )
+                ?: throw IllegalStateException()
         locMap = parseLocMap(context, c)
         // Expected workspace items in grid A
         // _ _ _ _ _
@@ -338,39 +358,46 @@
 
         // migrate from A -> B
         GridSizeMigrationUtil.migrate(
-                context,
-                db,
-                readerGridA,
-                readerGridB,
-                idp.numDatabaseHotseatIcons,
-                Point(idp.numColumns, idp.numRows),
-                DeviceGridState(context),
-                DeviceGridState(idp)
+            context,
+            db,
+            readerGridA,
+            readerGridB,
+            idp.numDatabaseHotseatIcons,
+            Point(idp.numColumns, idp.numRows),
+            DeviceGridState(context),
+            DeviceGridState(idp)
         )
 
         // Check hotseat items in grid B
-        c = context.contentResolver.query(
+        c =
+            context.contentResolver.query(
                 CONTENT_URI,
                 arrayOf(SCREEN, INTENT),
                 "container=$CONTAINER_HOTSEAT",
                 null,
                 SCREEN,
                 null
-        ) ?: throw IllegalStateException()
+            )
+                ?: throw IllegalStateException()
         // Expected hotseat items in grid B
         // 2 1 3 4
-        verifyHotseat(c, idp,
-                mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList())
+        verifyHotseat(
+            c,
+            idp,
+            mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList()
+        )
 
         // Check workspace items in grid B
-        c = context.contentResolver.query(
+        c =
+            context.contentResolver.query(
                 CONTENT_URI,
                 arrayOf(SCREEN, CELLX, CELLY, INTENT),
                 "container=$CONTAINER_DESKTOP",
                 null,
                 null,
                 null
-        ) ?: throw IllegalStateException()
+            )
+                ?: throw IllegalStateException()
         locMap = parseLocMap(context, c)
         // Expected workspace items in grid B
         // _ _ _ _
@@ -406,7 +433,7 @@
         val locMap = mutableMapOf<String, Triple<Int, Int, Int>>()
         while (c.moveToNext()) {
             locMap[Intent.parseUri(c.getString(intentIndex), 0).getPackage()] =
-                    Triple(c.getInt(screenIndex), c.getInt(cellXIndex), c.getInt(cellYIndex))
+                Triple(c.getInt(screenIndex), c.getInt(cellXIndex), c.getInt(cellYIndex))
         }
         c.close()
         return locMap.toMap()
@@ -414,12 +441,13 @@
 
     @Test
     fun migrateToLargerHotseat() {
-        val srcHotseatItems = intArrayOf(
-            modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
-            modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
-            modelHelper.addItem(APP_ICON, 2, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI),
-            modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
-        )
+        val srcHotseatItems =
+            intArrayOf(
+                modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
+                modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
+                modelHelper.addItem(APP_ICON, 2, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI),
+                modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
+            )
         val numSrcDatabaseHotseatIcons = srcHotseatItems.size
         idp.numDatabaseHotseatIcons = 6
         idp.numColumns = 4
@@ -427,25 +455,27 @@
         val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
         val destReader = DbReader(db, TABLE_NAME, context, validPackages)
         GridSizeMigrationUtil.migrate(
-                context,
-                db,
-                srcReader,
-                destReader,
-                idp.numDatabaseHotseatIcons,
-                Point(idp.numColumns, idp.numRows),
-                DeviceGridState(context),
-                DeviceGridState(idp)
+            context,
+            db,
+            srcReader,
+            destReader,
+            idp.numDatabaseHotseatIcons,
+            Point(idp.numColumns, idp.numRows),
+            DeviceGridState(context),
+            DeviceGridState(idp)
         )
 
         // Check hotseat items
-        val c = context.contentResolver.query(
-            CONTENT_URI,
-            arrayOf(SCREEN, INTENT),
-            "container=$CONTAINER_HOTSEAT",
-            null,
-            SCREEN,
-            null
-        ) ?: throw IllegalStateException()
+        val c =
+            context.contentResolver.query(
+                CONTENT_URI,
+                arrayOf(SCREEN, INTENT),
+                "container=$CONTAINER_HOTSEAT",
+                null,
+                SCREEN,
+                null
+            )
+                ?: throw IllegalStateException()
 
         assertThat(c.count.toLong()).isEqualTo(numSrcDatabaseHotseatIcons.toLong())
         val screenIndex = c.getColumnIndex(SCREEN)
@@ -483,25 +513,27 @@
         val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
         val destReader = DbReader(db, TABLE_NAME, context, validPackages)
         GridSizeMigrationUtil.migrate(
-                context,
-                db,
-                srcReader,
-                destReader,
-                idp.numDatabaseHotseatIcons,
-                Point(idp.numColumns, idp.numRows),
-                DeviceGridState(context),
-                DeviceGridState(idp)
+            context,
+            db,
+            srcReader,
+            destReader,
+            idp.numDatabaseHotseatIcons,
+            Point(idp.numColumns, idp.numRows),
+            DeviceGridState(context),
+            DeviceGridState(idp)
         )
 
         // Check hotseat items
-        val c = context.contentResolver.query(
-            CONTENT_URI,
-            arrayOf(SCREEN, INTENT),
-            "container=$CONTAINER_HOTSEAT",
-            null,
-            SCREEN,
-            null
-        ) ?: throw IllegalStateException()
+        val c =
+            context.contentResolver.query(
+                CONTENT_URI,
+                arrayOf(SCREEN, INTENT),
+                "container=$CONTAINER_HOTSEAT",
+                null,
+                SCREEN,
+                null
+            )
+                ?: throw IllegalStateException()
 
         assertThat(c.count.toLong()).isEqualTo(idp.numDatabaseHotseatIcons.toLong())
         val screenIndex = c.getColumnIndex(SCREEN)
@@ -527,8 +559,8 @@
     }
 
     /**
-     * Migrating from a smaller grid to a large one should keep the pages
-     * if the column difference is less than 2
+     * Migrating from a smaller grid to a large one should keep the pages if the column difference
+     * is less than 2
      */
     @Test
     @Throws(Exception::class)
@@ -549,25 +581,27 @@
         val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
         val destReader = DbReader(db, TABLE_NAME, context, validPackages)
         GridSizeMigrationUtil.migrate(
-                context,
-                db,
-                srcReader,
-                destReader,
-                idp.numDatabaseHotseatIcons,
-                Point(idp.numColumns, idp.numRows),
-                DeviceGridState(context),
-                DeviceGridState(idp)
+            context,
+            db,
+            srcReader,
+            destReader,
+            idp.numDatabaseHotseatIcons,
+            Point(idp.numColumns, idp.numRows),
+            DeviceGridState(context),
+            DeviceGridState(idp)
         )
 
         // Get workspace items
-        val c = context.contentResolver.query(
-            CONTENT_URI,
-            arrayOf(INTENT, SCREEN),
-            "container=$CONTAINER_DESKTOP",
-            null,
-            null,
-            null
-        ) ?: throw IllegalStateException()
+        val c =
+            context.contentResolver.query(
+                CONTENT_URI,
+                arrayOf(INTENT, SCREEN),
+                "container=$CONTAINER_DESKTOP",
+                null,
+                null,
+                null
+            )
+                ?: throw IllegalStateException()
         val intentIndex = c.getColumnIndex(INTENT)
         val screenIndex = c.getColumnIndex(SCREEN)
 
@@ -589,8 +623,8 @@
     }
 
     /**
-     * Migrating from a smaller grid to a large one should reflow the pages
-     * if the column difference is more than 2
+     * Migrating from a smaller grid to a large one should reflow the pages if the column difference
+     * is more than 2
      */
     @Test
     @Throws(Exception::class)
@@ -610,25 +644,27 @@
         val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
         val destReader = DbReader(db, TABLE_NAME, context, validPackages)
         GridSizeMigrationUtil.migrate(
-                context,
-                db,
-                srcReader,
-                destReader,
-                idp.numDatabaseHotseatIcons,
-                Point(idp.numColumns, idp.numRows),
-                DeviceGridState(context),
-                DeviceGridState(idp)
+            context,
+            db,
+            srcReader,
+            destReader,
+            idp.numDatabaseHotseatIcons,
+            Point(idp.numColumns, idp.numRows),
+            DeviceGridState(context),
+            DeviceGridState(idp)
         )
 
         // Get workspace items
-        val c = context.contentResolver.query(
-            CONTENT_URI,
-            arrayOf(INTENT, SCREEN),
-            "container=$CONTAINER_DESKTOP",
-            null,
-            null,
-            null
-        ) ?: throw IllegalStateException()
+        val c =
+            context.contentResolver.query(
+                CONTENT_URI,
+                arrayOf(INTENT, SCREEN),
+                "container=$CONTAINER_DESKTOP",
+                null,
+                null,
+                null
+            )
+                ?: throw IllegalStateException()
 
         val intentIndex = c.getColumnIndex(INTENT)
         val screenIndex = c.getColumnIndex(SCREEN)
@@ -651,9 +687,7 @@
         disableNewMigrationLogic()
     }
 
-    /**
-     * Migrating from a larger grid to a smaller, we reflow from page 0
-     */
+    /** Migrating from a larger grid to a smaller, we reflow from page 0 */
     @Test
     @Throws(Exception::class)
     fun migrateFromLargerGrid() {
@@ -672,25 +706,27 @@
         val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
         val destReader = DbReader(db, TABLE_NAME, context, validPackages)
         GridSizeMigrationUtil.migrate(
-                context,
-                db,
-                srcReader,
-                destReader,
-                idp.numDatabaseHotseatIcons,
-                Point(idp.numColumns, idp.numRows),
-                DeviceGridState(context),
-                DeviceGridState(idp)
+            context,
+            db,
+            srcReader,
+            destReader,
+            idp.numDatabaseHotseatIcons,
+            Point(idp.numColumns, idp.numRows),
+            DeviceGridState(context),
+            DeviceGridState(idp)
         )
 
         // Get workspace items
-        val c = context.contentResolver.query(
-            CONTENT_URI,
-            arrayOf(INTENT, SCREEN),
-            "container=$CONTAINER_DESKTOP",
-            null,
-            null,
-            null
-        ) ?: throw IllegalStateException()
+        val c =
+            context.contentResolver.query(
+                CONTENT_URI,
+                arrayOf(INTENT, SCREEN),
+                "container=$CONTAINER_DESKTOP",
+                null,
+                null,
+                null
+            )
+                ?: throw IllegalStateException()
         val intentIndex = c.getColumnIndex(INTENT)
         val screenIndex = c.getColumnIndex(SCREEN)
 
@@ -714,21 +750,20 @@
     }
 
     private fun enableNewMigrationLogic(srcGridSize: String) {
-        context.getSharedPreferences(FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE)
+        context
+            .getSharedPreferences(FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE)
             .edit()
             .putBoolean(FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC.key, true)
             .commit()
-        context.getSharedPreferences(LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
-            .edit()
-            .putString(DeviceGridState.KEY_WORKSPACE_SIZE, srcGridSize)
-            .commit()
+        LauncherPrefs.get(context).putSync(WORKSPACE_SIZE.to(srcGridSize))
         FeatureFlags.initialize(context)
     }
 
     private fun disableNewMigrationLogic() {
-        context.getSharedPreferences(FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE)
+        context
+            .getSharedPreferences(FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE)
             .edit()
             .putBoolean(FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC.key, false)
             .commit()
     }
-}
\ No newline at end of file
+}
diff --git a/tests/src/com/android/launcher3/model/WorkspaceItemSpaceFinderTest.kt b/tests/src/com/android/launcher3/model/WorkspaceItemSpaceFinderTest.kt
index bfb1ac6..b3d02be 100644
--- a/tests/src/com/android/launcher3/model/WorkspaceItemSpaceFinderTest.kt
+++ b/tests/src/com/android/launcher3/model/WorkspaceItemSpaceFinderTest.kt
@@ -24,9 +24,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 
-/**
- * Tests for [WorkspaceItemSpaceFinder]
- */
+/** Tests for [WorkspaceItemSpaceFinder] */
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class WorkspaceItemSpaceFinderTest : AbstractWorkspaceModelTest() {
@@ -44,17 +42,27 @@
     }
 
     private fun findSpace(spanX: Int, spanY: Int): NewItemSpace =
-        mItemSpaceFinder.findSpaceForItem(
-            mAppState, mModelHelper.bgDataModel,
-            mExistingScreens, mNewScreens, spanX, spanY
-        )
+        mItemSpaceFinder
+            .findSpaceForItem(
+                mAppState,
+                mModelHelper.bgDataModel,
+                mExistingScreens,
+                mNewScreens,
+                spanX,
+                spanY
+            )
             .let { NewItemSpace.fromIntArray(it) }
 
     private fun assertRegionVacant(newItemSpace: NewItemSpace, spanX: Int, spanY: Int) {
         assertThat(
-            mScreenOccupancy[newItemSpace.screenId]
-                .isRegionVacant(newItemSpace.cellX, newItemSpace.cellY, spanX, spanY)
-        ).isTrue()
+                mScreenOccupancy[newItemSpace.screenId].isRegionVacant(
+                    newItemSpace.cellX,
+                    newItemSpace.cellY,
+                    spanX,
+                    spanY
+                )
+            )
+            .isTrue()
     }
 
     @Test
diff --git a/tests/src/com/android/launcher3/nonquickstep/HotseatWidthCalculationTest.kt b/tests/src/com/android/launcher3/nonquickstep/HotseatWidthCalculationTest.kt
index c99ad76..951f5f8 100644
--- a/tests/src/com/android/launcher3/nonquickstep/HotseatWidthCalculationTest.kt
+++ b/tests/src/com/android/launcher3/nonquickstep/HotseatWidthCalculationTest.kt
@@ -29,8 +29,8 @@
 class HotseatWidthCalculationTest : DeviceProfileBaseTest() {
 
     /**
-     * This is a case when after setting the hotseat, the space needs to be recalculated
-     * but it doesn't need to change QSB width or remove icons
+     * This is a case when after setting the hotseat, the space needs to be recalculated but it
+     * doesn't need to change QSB width or remove icons
      */
     @Test
     fun distribute_border_space_when_space_is_enough_portrait() {
@@ -51,8 +51,8 @@
     }
 
     /**
-     * This is a case when after setting the hotseat, and recalculating spaces
-     * it still needs to remove icons for everything to fit
+     * This is a case when after setting the hotseat, and recalculating spaces it still needs to
+     * remove icons for everything to fit
      */
     @Test
     fun decrease_num_of_icons_when_not_enough_space_portrait() {
@@ -73,8 +73,8 @@
     }
 
     /**
-     * This is a case when after setting the hotseat, the space needs to be recalculated
-     * but it doesn't need to change QSB width or remove icons
+     * This is a case when after setting the hotseat, the space needs to be recalculated but it
+     * doesn't need to change QSB width or remove icons
      */
     @Test
     fun distribute_border_space_when_space_is_enough_landscape() {
@@ -94,8 +94,8 @@
     }
 
     /**
-     * This is a case when the hotseat spans a certain amount of columns
-     * and the nav buttons push the hotseat to the side, but not enough to change the border space.
+     * This is a case when the hotseat spans a certain amount of columns and the nav buttons push
+     * the hotseat to the side, but not enough to change the border space.
      */
     @Test
     fun nav_buttons_dont_interfere_with_required_hotseat_width() {
@@ -118,9 +118,7 @@
         assertThat(dp.hotseatQsbWidth).isEqualTo(1224)
     }
 
-    /**
-     * This is a case when after setting the hotseat, the QSB width needs to be changed to fit
-     */
+    /** This is a case when after setting the hotseat, the QSB width needs to be changed to fit */
     @Test
     fun decrease_qsb_when_not_enough_space_landscape() {
         initializeVarsForTablet(isGestureMode = false, isLandscape = true)
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 70d122b..eae1868 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -63,7 +63,7 @@
 import com.android.launcher3.testcomponent.TestCommandReceiver;
 import com.android.launcher3.testing.shared.TestProtocol;
 import com.android.launcher3.util.LooperExecutor;
-import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.SimpleBroadcastReceiver;
 import com.android.launcher3.util.Wait;
 import com.android.launcher3.util.WidgetUtils;
 import com.android.launcher3.util.rule.FailureWatcher;
@@ -196,15 +196,10 @@
 
     protected void clearPackageData(String pkg) throws IOException, InterruptedException {
         final CountDownLatch count = new CountDownLatch(2);
-        final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                count.countDown();
-            }
-        };
-        mTargetContext.registerReceiver(broadcastReceiver,
-                PackageManagerHelper.getPackageFilter(pkg,
-                        Intent.ACTION_PACKAGE_RESTARTED, Intent.ACTION_PACKAGE_DATA_CLEARED));
+        final SimpleBroadcastReceiver broadcastReceiver =
+                new SimpleBroadcastReceiver(i -> count.countDown());
+        broadcastReceiver.registerPkgActions(mTargetContext, pkg,
+                        Intent.ACTION_PACKAGE_RESTARTED, Intent.ACTION_PACKAGE_DATA_CLEARED);
 
         mDevice.executeShellCommand("pm clear " + pkg);
         assertTrue(pkg + " didn't restart", count.await(10, TimeUnit.SECONDS));
@@ -299,7 +294,7 @@
     /**
      * Removes all icons from homescreen and hotseat.
      */
-    public void clearHomescreen() throws Throwable {
+    public void clearHomescreen() {
         LauncherSettings.Settings.call(mTargetContext.getContentResolver(),
                 LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
         LauncherSettings.Settings.call(mTargetContext.getContentResolver(),
diff --git a/tests/src/com/android/launcher3/ui/WorkProfileTest.java b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
index 302bd2f..c7628cc 100644
--- a/tests/src/com/android/launcher3/ui/WorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
@@ -38,6 +38,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 
 import java.util.Objects;
@@ -118,6 +119,7 @@
     }
 
     @Test
+    @Ignore("b/243855320")
     public void toggleWorks() {
         assumeTrue(mWorkProfileSetupSuccessful);
         waitForWorkTabSetup();
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index 3f4a1c1..2c9785c 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -37,7 +37,6 @@
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -65,7 +64,6 @@
         mAppWidgetManager = AppWidgetManager.getInstance(mTargetContext);
     }
 
-    @Ignore
     @Test
     @PortraitLandscape
     public void testWidgetConfig() throws Throwable {
diff --git a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
index 0db719e..9669010 100644
--- a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
@@ -147,7 +147,8 @@
 
         // Set callback
         PendingIntent callback = PendingIntent.getBroadcast(mTargetContext, 0,
-                new Intent(mCallbackAction), FLAG_ONE_SHOT | FLAG_MUTABLE);
+                new Intent(mCallbackAction).setPackage(mTargetContext.getPackageName()),
+                FLAG_ONE_SHOT | FLAG_MUTABLE);
         mTargetContext.sendBroadcast(RequestPinItemActivity.getCommandIntent(
                 RequestPinItemActivity.class, "setCallback").putExtra(
                 RequestPinItemActivity.EXTRA_PARAM + "0", callback));
diff --git a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
index 9d5763b..7ba0b53 100644
--- a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
@@ -36,9 +36,7 @@
 import com.android.launcher3.ui.AbstractLauncherUiTest;
 import com.android.launcher3.ui.TaplTestsLauncher3;
 import com.android.launcher3.util.Executors;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 
-import org.junit.Ignore;
 import org.junit.Test;
 
 import java.util.ArrayDeque;
@@ -52,7 +50,7 @@
 @LargeTest
 public class ThemeIconsTest extends AbstractLauncherUiTest {
 
-    private static final String APP_NAME = "ThemeIconTestActivity";
+    private static final String APP_NAME = "IconThemedActivity";
     private static final String SHORTCUT_APP_NAME = "LauncherTestApp";
     private static final String SHORTCUT_NAME = "Shortcut 1";
 
@@ -111,9 +109,7 @@
         }
     }
 
-    @Ignore
     @Test
-    @ScreenRecord // b/260722220
     public void testShortcutIconWithTheme() throws Exception {
         setThemeEnabled(true);
         TaplTestsLauncher3.initialize(this);
diff --git a/tests/src/com/android/launcher3/util/KotlinMockitoHelpers.kt b/tests/src/com/android/launcher3/util/KotlinMockitoHelpers.kt
index 57db13a..4303bfb 100644
--- a/tests/src/com/android/launcher3/util/KotlinMockitoHelpers.kt
+++ b/tests/src/com/android/launcher3/util/KotlinMockitoHelpers.kt
@@ -22,43 +22,41 @@
  * be null"). To fix this, we can use methods that modify the return type to be nullable. This
  * causes Kotlin to skip the null checks.
  */
-
 import org.mockito.ArgumentCaptor
 import org.mockito.Mockito
 
 /**
- * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when
- * null is returned.
+ * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when null is
+ * returned.
  *
  * Generic T is nullable because implicitly bounded by Any?.
  */
 fun <T> eq(obj: T): T = Mockito.eq<T>(obj)
 
 /**
- * Returns Mockito.same() as nullable type to avoid java.lang.IllegalStateException when
- * null is returned.
+ * Returns Mockito.same() as nullable type to avoid java.lang.IllegalStateException when null is
+ * returned.
  *
  * Generic T is nullable because implicitly bounded by Any?.
  */
 fun <T> same(obj: T): T = Mockito.same<T>(obj)
 
 /**
- * Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when
- * null is returned.
+ * Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when null is
+ * returned.
  *
  * Generic T is nullable because implicitly bounded by Any?.
  */
 fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
+
 inline fun <reified T> any(): T = any(T::class.java)
 
-/**
- * Kotlin type-inferred version of Mockito.nullable()
- */
+/** Kotlin type-inferred version of Mockito.nullable() */
 inline fun <reified T> nullable(): T? = Mockito.nullable(T::class.java)
 
 /**
- * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException
- * when null is returned.
+ * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException when
+ * null is returned.
  *
  * Generic T is nullable because implicitly bounded by Any?.
  */
@@ -82,8 +80,9 @@
 /**
  * A kotlin implemented wrapper of [ArgumentCaptor] which prevents the following exception when
  * kotlin tests are mocking kotlin objects and the methods take non-null parameters:
- *
+ * ```
  *     java.lang.NullPointerException: capture() must not be null
+ * ```
  */
 class KotlinArgumentCaptor<T> constructor(clazz: Class<T>) {
     private val wrapped: ArgumentCaptor<T> = ArgumentCaptor.forClass(clazz)
@@ -102,15 +101,15 @@
 
 /**
  * Helper function for creating and using a single-use ArgumentCaptor in kotlin.
- *
+ * ```
  *    val captor = argumentCaptor<Foo>()
  *    verify(...).someMethod(captor.capture())
  *    val captured = captor.value
- *
+ * ```
  * becomes:
- *
+ * ```
  *    val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) }
- *
+ * ```
  * NOTE: this uses the KotlinArgumentCaptor to avoid the NullPointerException.
  */
 inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> Unit): T =
diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
index 93bf312..caec301 100644
--- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -55,6 +55,7 @@
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherModel;
 import com.android.launcher3.LauncherModel.ModelUpdateTask;
+import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.LauncherProvider;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.model.AllAppsList;
@@ -506,7 +507,7 @@
 
         SanboxModelContext() {
             super(ApplicationProvider.getApplicationContext(),
-                    UserCache.INSTANCE, InstallSessionHelper.INSTANCE,
+                    UserCache.INSTANCE, InstallSessionHelper.INSTANCE, LauncherPrefs.INSTANCE,
                     LauncherAppState.INSTANCE, InvariantDeviceProfile.INSTANCE,
                     DisplayController.INSTANCE, CustomWidgetManager.INSTANCE,
                     SettingsCache.INSTANCE, PluginManagerWrapper.INSTANCE,
diff --git a/tests/src/com/android/launcher3/util/LockedUserStateTest.kt b/tests/src/com/android/launcher3/util/LockedUserStateTest.kt
new file mode 100644
index 0000000..84156e7
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/LockedUserStateTest.kt
@@ -0,0 +1,88 @@
+/*
+ * 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.util
+
+import android.content.Context
+import android.content.Intent
+import android.os.Process
+import android.os.UserManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+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.verify
+import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+/** Unit tests for {@link LockedUserUtil} */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class LockedUserStateTest {
+
+    @Mock lateinit var userManager: UserManager
+    @Mock lateinit var context: Context
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        `when`(context.getSystemService(UserManager::class.java)).thenReturn(userManager)
+    }
+
+    @Test
+    fun runOnUserUnlocked_runs_action_immediately_if_already_unlocked() {
+        `when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(true)
+        LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
+        val action: Runnable = mock()
+
+        LockedUserState.get(context).runOnUserUnlocked(action)
+        verify(action).run()
+    }
+
+    @Test
+    fun runOnUserUnlocked_waits_to_run_action_until_user_is_unlocked() {
+        `when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(false)
+        LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
+        val action: Runnable = mock()
+
+        LockedUserState.get(context).runOnUserUnlocked(action)
+        verifyZeroInteractions(action)
+
+        LockedUserState.get(context)
+            .mUserUnlockedReceiver
+            .onReceive(context, Intent(Intent.ACTION_USER_UNLOCKED))
+
+        verify(action).run()
+    }
+
+    @Test
+    fun isUserUnlocked_returns_true_when_user_is_unlocked() {
+        `when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(true)
+        LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
+        assertThat(LockedUserState.get(context).isUserUnlocked).isTrue()
+    }
+
+    @Test
+    fun isUserUnlocked_returns_false_when_user_is_locked() {
+        `when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(false)
+        LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
+        assertThat(LockedUserState.get(context).isUserUnlocked).isFalse()
+    }
+}
diff --git a/tests/src/com/android/launcher3/util/MultiPropertyFactoryTest.kt b/tests/src/com/android/launcher3/util/MultiPropertyFactoryTest.kt
index bf3a092..a63136e 100644
--- a/tests/src/com/android/launcher3/util/MultiPropertyFactoryTest.kt
+++ b/tests/src/com/android/launcher3/util/MultiPropertyFactoryTest.kt
@@ -30,18 +30,18 @@
 
     private val received = mutableListOf<Float>()
 
-    private val receiveProperty: FloatProperty<Any> = object : FloatProperty<Any>("receive") {
-        override fun setValue(obj: Any?, value: Float) {
-            received.add(value)
+    private val receiveProperty: FloatProperty<Any> =
+        object : FloatProperty<Any>("receive") {
+            override fun setValue(obj: Any?, value: Float) {
+                received.add(value)
+            }
+            override fun get(o: Any): Float {
+                return 0f
+            }
         }
-        override fun get(o: Any): Float {
-            return 0f
-        }
-    }
 
-    private val factory = MultiPropertyFactory(null, receiveProperty, 3) {
-        x: Float, y: Float -> x + y
-    }
+    private val factory =
+        MultiPropertyFactory(null, receiveProperty, 3) { x: Float, y: Float -> x + y }
 
     private val p1 = factory.get(0)
     private val p2 = factory.get(1)
diff --git a/tests/src/com/android/launcher3/util/TouchUtilTest.kt b/tests/src/com/android/launcher3/util/TouchUtilTest.kt
index d6c6e91..235d6ec 100644
--- a/tests/src/com/android/launcher3/util/TouchUtilTest.kt
+++ b/tests/src/com/android/launcher3/util/TouchUtilTest.kt
@@ -18,9 +18,9 @@
 
 import android.view.InputDevice
 import android.view.MotionEvent
+import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth.assertThat
-import androidx.test.ext.junit.runners.AndroidJUnit4
 import org.junit.Test
 import org.junit.runner.RunWith
 
diff --git a/tests/tapl/com/android/launcher3/tapl/Widget.java b/tests/tapl/com/android/launcher3/tapl/Widget.java
index 046308b..d440903 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widget.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widget.java
@@ -71,7 +71,7 @@
     public WidgetResizeFrame dragWidgetToWorkspace() {
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
             return dragWidgetToWorkspace(/* configurable= */ false, /* acceptsConfig= */ false, -1,
-                    -1);
+                    -1, 1, 1);
         }
     }
 
@@ -80,12 +80,12 @@
      * cellY and returns the resize frame that is shown after the widget is added.
      */
     @NonNull
-    public WidgetResizeFrame dragWidgetToWorkspace(int cellX, int cellY) {
+    public WidgetResizeFrame dragWidgetToWorkspace(int cellX, int cellY, int spanX, int spanY) {
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                      "Dragging widget to workspace cell " + cellX + "," + cellY)) {
             return dragWidgetToWorkspace(/* configurable= */ false, /* acceptsConfig= */ false,
-                    cellX, cellY);
+                    cellX, cellY, spanX, spanY);
         }
     }
 
@@ -98,7 +98,7 @@
     public WidgetResizeFrame dragConfigWidgetToWorkspace(boolean acceptsConfig) {
         // TODO(b/239438337, fransebas) add correct event checking for this case
         //try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
-        return dragWidgetToWorkspace(/* configurable= */ true, acceptsConfig, -1, -1);
+        return dragWidgetToWorkspace(/* configurable= */ true, acceptsConfig, -1, -1, 1, 1);
         //}
     }
 
@@ -110,18 +110,17 @@
      * @param cellX            X position in the CellLayout
      * @param cellY            Y position in the CellLayout
      */
-    private void dragToWorkspace(boolean startsActivity, boolean isWidgetShortcut, int cellX,
-            int cellY) {
+    private void dragToWorkspaceCellPosition(boolean startsActivity, boolean isWidgetShortcut,
+            int cellX, int cellY, int spanX, int spanY) {
         Launchable launchable = getLaunchable();
         LauncherInstrumentation launcher = launchable.mLauncher;
-        Workspace.dragIconToWorkspace(
+        Workspace.dragIconToWorkspaceCellPosition(
                 launcher,
                 launchable,
-                () -> Workspace.getCellCenter(launchable.mLauncher, cellX, cellY),
+                cellX, cellY, spanX, spanY,
                 startsActivity,
                 isWidgetShortcut,
                 launchable::addExpectedEventsForLongClick);
-
     }
 
     /**
@@ -144,13 +143,13 @@
      */
     @Nullable
     private WidgetResizeFrame dragWidgetToWorkspace(boolean configurable, boolean acceptsConfig,
-            int cellX, int cellY) {
+            int cellX, int cellY, int spanX, int spanY) {
         if (cellX == -1 || cellY == -1) {
             internalDragToWorkspace(/* startsActivity= */ configurable, /* isWidgetShortcut= */
                     false);
         } else {
-            dragToWorkspace(/* startsActivity= */ configurable, /* isWidgetShortcut= */ false,
-                    cellX, cellY);
+            dragToWorkspaceCellPosition(/* startsActivity= */ configurable, /* isWidgetShortcut= */
+                    false, cellX, cellY, spanX, spanY);
         }
 
         if (configurable) {
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 2c82c50..473cfb9 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -408,9 +408,15 @@
     }
 
     static Point getCellCenter(LauncherInstrumentation launcher, int cellX, int cellY) {
-        return launcher.getTestInfo(WorkspaceCellCenterRequest.builder().setCellX(
-                cellX).setCellY(cellY).build()).getParcelable(
-                TestProtocol.TEST_INFO_RESPONSE_FIELD);
+        return launcher.getTestInfo(WorkspaceCellCenterRequest.builder().setCellX(cellX).setCellY(
+                cellY).build()).getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD);
+    }
+
+    static Point getCellCenter(LauncherInstrumentation launcher, int cellX, int cellY, int spanX,
+            int spanY) {
+        return launcher.getTestInfo(WorkspaceCellCenterRequest.builder().setCellX(cellX)
+                .setCellY(cellY).setSpanX(spanX).setSpanY(spanY).build())
+                .getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD);
     }
 
     static Point getHotseatCellCenter(LauncherInstrumentation launcher, int cellInd) {
@@ -418,6 +424,12 @@
                 .setCellInd(cellInd).build()).getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD);
     }
 
+    /** Returns the number of rows and columns in the workspace */
+    public Point getRowsAndCols() {
+        return mLauncher.getTestInfo(TestProtocol.REQUEST_WORKSPACE_COLUMNS_ROWS).getParcelable(
+                TestProtocol.TEST_INFO_RESPONSE_FIELD);
+    }
+
     /**
      * Finds folder icons in the current workspace.
      *
@@ -456,6 +468,19 @@
                 launcher, launchable, dest, expectLongClickEvents, expectDropEvents);
     }
 
+    static void dragIconToWorkspaceCellPosition(LauncherInstrumentation launcher,
+            Launchable launchable, int cellX, int cellY, int spanX, int spanY,
+            boolean startsActivity, boolean isWidgetShortcut, Runnable expectLongClickEvents) {
+        Runnable expectDropEvents = null;
+        if (startsActivity || isWidgetShortcut) {
+            expectDropEvents = () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN,
+                    LauncherInstrumentation.EVENT_START);
+        }
+        dragIconToWorkspaceCellPosition(
+                launcher, launchable, cellX, cellY, spanX, spanY, true, expectLongClickEvents,
+                expectDropEvents);
+    }
+
     /**
      * Drag icon in workspace to else where and drop it immediately.
      * (There is no slow down time before drop event)
@@ -525,6 +550,51 @@
         }
     }
 
+    static void dragIconToWorkspaceCellPosition(
+            LauncherInstrumentation launcher,
+            Launchable launchable,
+            int cellX, int cellY, int spanX, int spanY,
+            boolean isDecelerating,
+            Runnable expectLongClickEvents,
+            @Nullable Runnable expectDropEvents) {
+        try (LauncherInstrumentation.Closable ignored = launcher.addContextLayer(
+                "want to drag icon to workspace")) {
+            Point rowsAndCols = launcher.getWorkspace().getRowsAndCols();
+            int destinationWorkspace = cellX / rowsAndCols.x;
+            cellX = cellX % rowsAndCols.x;
+
+            final long downTime = SystemClock.uptimeMillis();
+            Point dragStart = launchable.startDrag(
+                    downTime,
+                    expectLongClickEvents,
+                    /* runToSpringLoadedState= */ true);
+            Point targetDest = getCellCenter(launcher, cellX, cellY, spanX, spanY);
+            int displayX = launcher.getRealDisplaySize().x;
+
+            // Since the destination can be on another page, we need to drag to the edge first
+            // until we reach the target page
+            for (int i = 0; i < destinationWorkspace; i++) {
+                // Don't drag all the way to the edge to prevent touch events from getting out of
+                //screen bounds.
+                Point screenEdge = new Point(displayX - 1, targetDest.y);
+                Point finalDragStart = dragStart;
+                executeAndWaitForPageScroll(launcher,
+                        () -> launcher.movePointer(finalDragStart, screenEdge, DEFAULT_DRAG_STEPS,
+                                true, downTime, downTime, true,
+                                LauncherInstrumentation.GestureScope.INSIDE));
+                dragStart = screenEdge;
+            }
+
+            // targetDest.x is now between 0 and displayX so we found the target page,
+            // we just have to put move the icon to the destination and drop it
+            launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, isDecelerating,
+                    downTime, SystemClock.uptimeMillis(), false,
+                    LauncherInstrumentation.GestureScope.INSIDE);
+            launcher.runCallbackIfActive(CALLBACK_HOLD_BEFORE_DROP);
+            dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents);
+        }
+    }
+
     private static void executeAndWaitForPageScroll(LauncherInstrumentation launcher,
             Runnable command) {
         launcher.executeAndWaitForEvent(command,