Merge "Adding support for dynamic letter spacing for icon labels" into sc-v2-dev
diff --git a/quickstep/res/drawable/default_sandbox_mock_launcher.xml b/quickstep/res/drawable/default_sandbox_mock_launcher.xml
deleted file mode 100644
index 38fbcf0..0000000
--- a/quickstep/res/drawable/default_sandbox_mock_launcher.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="360dp"
-    android:height="146dp"
-    android:viewportWidth="360"
-    android:viewportHeight="146">
-  <path
-      android:pathData="M25,96L335,96A25,25 0,0 1,360 121L360,121A25,25 0,0 1,335 146L25,146A25,25 0,0 1,0 121L0,121A25,25 0,0 1,25 96z"
-      android:fillColor="#3C4043"/>
-  <path
-      android:pathData="M30,30m-30,0a30,30 0,1 1,60 0a30,30 0,1 1,-60 0"
-      android:fillColor="#8AB4F8"/>
-  <path
-      android:pathData="M130,30m-30,0a30,30 0,1 1,60 0a30,30 0,1 1,-60 0"
-      android:fillColor="#F28B82"/>
-  <path
-      android:pathData="M230,30m-30,0a30,30 0,1 1,60 0a30,30 0,1 1,-60 0"
-      android:fillColor="#FDD663"/>
-  <path
-      android:pathData="M330,30m-30,0a30,30 0,1 1,60 0a30,30 0,1 1,-60 0"
-      android:fillColor="#81C995"/>
-</vector>
diff --git a/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation.xml b/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation.xml
new file mode 100644
index 0000000..34bd4e2
--- /dev/null
+++ b/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation.xml
@@ -0,0 +1,239 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout
+    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="match_parent">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/top_bar"
+        android:layout_width="match_parent"
+        android:layout_height="101dp"
+        android:background="@color/mock_conversation_top_bar"
+
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent">
+
+        <androidx.cardview.widget.CardView
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_marginTop="43dp"
+            android:layout_marginBottom="22dp"
+            android:layout_marginStart="126dp"
+            android:layout_marginEnd="548dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="4dp"
+            app:cardBackgroundColor="@color/mock_conversation_top_bar_item"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <androidx.cardview.widget.CardView
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_marginTop="43dp"
+            android:layout_marginBottom="22dp"
+            android:layout_marginStart="300dp"
+            android:layout_marginEnd="16dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="4dp"
+            app:cardBackgroundColor="@color/mock_conversation_top_bar_item"
+            app:layout_constraintDimensionRatio="1:1"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/top_bar_button"/>
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/top_bar_button"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_marginTop="43dp"
+            android:layout_marginBottom="22dp"
+            android:layout_marginStart="300dp"
+            android:layout_marginEnd="126dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="4dp"
+            app:cardBackgroundColor="@color/mock_conversation_top_bar_item"
+            app:layout_constraintDimensionRatio="1:1"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:background="@color/mock_conversation_background"
+        android:paddingBottom="80dp"
+
+        app:layout_constraintTop_toBottomOf="@id/top_bar"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent">
+
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:paddingBottom="@dimen/gesture_tutorial_message_input_margin_top"
+
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toTopOf="@id/message_bar"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent">
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/message_1"
+                android:layout_width="0dp"
+                android:layout_height="112dp"
+                android:layout_marginBottom="@dimen/gesture_tutorial_message_large_margin_bottom"
+                android:layout_marginStart="445dp"
+                android:layout_marginEnd="@dimen/gesture_tutorial_foldable_message_padding_start_end"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="18dp"
+                app:cardBackgroundColor="@color/mock_conversation_sent_message"
+                app:layout_constraintBottom_toTopOf="@id/reply_icon_1"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/reply_icon_1"
+                android:layout_width="@dimen/gesture_tutorial_message_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_message_icon_size"
+                android:layout_marginBottom="@dimen/gesture_tutorial_message_large_margin_bottom"
+                android:layout_marginStart="@dimen/gesture_tutorial_foldable_message_padding_start_end"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_message_icon_corner_radius"
+                app:cardBackgroundColor="@color/mock_conversation_profile_icon"
+                app:layout_constraintDimensionRatio="1:1"
+                app:layout_constraintBottom_toTopOf="@id/message_2"
+                app:layout_constraintStart_toStartOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:layout_width="0dp"
+                android:layout_height="36dp"
+                android:layout_marginStart="17dp"
+                android:layout_marginEnd="441dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="18dp"
+                app:cardBackgroundColor="@color/mock_conversation_received_message"
+                app:layout_constraintTop_toTopOf="@id/reply_icon_1"
+                app:layout_constraintBottom_toBottomOf="@id/reply_icon_1"
+                app:layout_constraintStart_toEndOf="@id/reply_icon_1"
+                app:layout_constraintEnd_toEndOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/message_2"
+                android:layout_width="0dp"
+                android:layout_height="36dp"
+                android:layout_marginBottom="@dimen/gesture_tutorial_message_small_margin_bottom"
+                android:layout_marginStart="601dp"
+                android:layout_marginEnd="@dimen/gesture_tutorial_foldable_message_padding_start_end"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="18dp"
+                app:cardBackgroundColor="@color/mock_conversation_sent_message"
+                app:layout_constraintBottom_toTopOf="@id/message_3"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/message_3"
+                android:layout_width="0dp"
+                android:layout_height="74dp"
+                android:layout_marginBottom="@dimen/gesture_tutorial_message_large_margin_bottom"
+                android:layout_marginStart="445dp"
+                android:layout_marginEnd="@dimen/gesture_tutorial_foldable_message_padding_start_end"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="18dp"
+                app:cardBackgroundColor="@color/mock_conversation_sent_message"
+                app:layout_constraintBottom_toTopOf="@id/reply_icon_2"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/reply_icon_2"
+                android:layout_width="@dimen/gesture_tutorial_message_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_message_icon_size"
+                android:layout_marginBottom="32dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_foldable_message_padding_start_end"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_message_icon_corner_radius"
+                app:cardBackgroundColor="@color/mock_conversation_profile_icon"
+                app:layout_constraintDimensionRatio="1:1"
+                app:layout_constraintBottom_toTopOf="@id/message_4"
+                app:layout_constraintStart_toStartOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:layout_width="0dp"
+                android:layout_height="36dp"
+                android:layout_marginStart="17dp"
+                android:layout_marginEnd="473dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="18dp"
+                app:cardBackgroundColor="@color/mock_conversation_received_message"
+                app:layout_constraintTop_toTopOf="@id/reply_icon_2"
+                app:layout_constraintBottom_toBottomOf="@id/reply_icon_2"
+                app:layout_constraintStart_toEndOf="@id/reply_icon_2"
+                app:layout_constraintEnd_toEndOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/message_4"
+                android:layout_width="0dp"
+                android:layout_height="74dp"
+                android:layout_marginStart="445dp"
+                android:layout_marginEnd="@dimen/gesture_tutorial_foldable_message_padding_start_end"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="18dp"
+                app:cardBackgroundColor="@color/mock_conversation_sent_message"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"/>
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/message_bar"
+            android:layout_width="0dp"
+            android:layout_height="44dp"
+            android:layout_marginTop="36dp"
+            android:layout_marginBottom="24dp"
+            android:layout_marginStart="134dp"
+            android:layout_marginEnd="126dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="164dp"
+            app:cardBackgroundColor="@color/mock_conversation_message_input"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation_list.xml b/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation_list.xml
new file mode 100644
index 0000000..0309cc3
--- /dev/null
+++ b/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation_list.xml
@@ -0,0 +1,396 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout
+    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="match_parent">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/top_bar"
+        android:layout_width="match_parent"
+        android:layout_height="101dp"
+        android:background="@color/mock_list_top_bar"
+
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent">
+
+        <androidx.cardview.widget.CardView
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_marginTop="43dp"
+            android:layout_marginBottom="22dp"
+            android:layout_marginStart="126dp"
+            android:layout_marginEnd="126dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="4dp"
+            app:cardBackgroundColor="@color/mock_list_top_bar_item"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:background="@color/mock_list_background"
+        android:paddingBottom="80dp"
+
+        app:layout_constraintTop_toBottomOf="@id/top_bar"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent">
+
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:paddingTop="@dimen/gesture_tutorial_conversation_list_padding_top"
+            android:paddingStart="126dp"
+
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/mock_button">
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_icon_1"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+                app:cardBackgroundColor="@color/mock_list_profile_icon"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintStart_toStartOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_1"
+                android:layout_width="0dp"
+                android:layout_height="18dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="270dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintVertical_chainStyle="packed"
+                app:layout_constraintTop_toTopOf="@id/conversation_icon_1"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_1"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toTopOf="@id/conversation_line_2"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_2"
+                android:layout_width="0dp"
+                android:layout_height="16dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="110dp"
+                android:layout_marginTop="4dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintTop_toBottomOf="@id/conversation_line_1"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_1"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toBottomOf="@id/conversation_icon_1"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_icon_2"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_marginTop="32dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+                app:cardBackgroundColor="@color/mock_list_profile_icon"
+                app:layout_constraintTop_toBottomOf="@id/conversation_icon_1"
+                app:layout_constraintStart_toStartOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_3"
+                android:layout_width="0dp"
+                android:layout_height="18dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="243dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintVertical_chainStyle="packed"
+                app:layout_constraintTop_toTopOf="@id/conversation_icon_2"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_2"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toTopOf="@id/conversation_line_4"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_4"
+                android:layout_width="0dp"
+                android:layout_height="16dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="154dp"
+                android:layout_marginTop="4dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintTop_toBottomOf="@id/conversation_line_3"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_2"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toBottomOf="@id/conversation_icon_2"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_icon_3"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_marginTop="32dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+                app:cardBackgroundColor="@color/mock_list_profile_icon"
+                app:layout_constraintTop_toBottomOf="@id/conversation_icon_2"
+                app:layout_constraintStart_toStartOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_5"
+                android:layout_width="0dp"
+                android:layout_height="18dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="251dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintVertical_chainStyle="packed"
+                app:layout_constraintTop_toTopOf="@id/conversation_icon_3"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_3"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toTopOf="@id/conversation_line_6"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_6"
+                android:layout_width="0dp"
+                android:layout_height="16dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="15dp"
+                android:layout_marginTop="4dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintTop_toBottomOf="@id/conversation_line_5"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_3"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toBottomOf="@id/conversation_icon_3"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_icon_4"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_marginTop="32dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+                app:cardBackgroundColor="@color/mock_list_profile_icon"
+                app:layout_constraintTop_toBottomOf="@id/conversation_icon_3"
+                app:layout_constraintStart_toStartOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_7"
+                android:layout_width="0dp"
+                android:layout_height="18dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="227dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintVertical_chainStyle="packed"
+                app:layout_constraintTop_toTopOf="@id/conversation_icon_4"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_4"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toTopOf="@id/conversation_line_8"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_8"
+                android:layout_width="0dp"
+                android:layout_height="16dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="72dp"
+                android:layout_marginTop="4dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintTop_toBottomOf="@id/conversation_line_7"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_4"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toBottomOf="@id/conversation_icon_4"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_icon_5"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_marginTop="32dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+                app:cardBackgroundColor="@color/mock_list_profile_icon"
+                app:layout_constraintTop_toBottomOf="@id/conversation_icon_4"
+                app:layout_constraintStart_toStartOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_9"
+                android:layout_width="0dp"
+                android:layout_height="18dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="297dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintVertical_chainStyle="packed"
+                app:layout_constraintTop_toTopOf="@id/conversation_icon_5"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_5"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toTopOf="@id/conversation_line_10"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_10"
+                android:layout_width="0dp"
+                android:layout_height="16dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="111dp"
+                android:layout_marginTop="4dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintTop_toBottomOf="@id/conversation_line_9"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_5"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toBottomOf="@id/conversation_icon_5"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_icon_6"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_marginTop="32dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+                app:cardBackgroundColor="@color/mock_list_profile_icon"
+                app:layout_constraintTop_toBottomOf="@id/conversation_icon_5"
+                app:layout_constraintStart_toStartOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_11"
+                android:layout_width="0dp"
+                android:layout_height="18dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="230dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintVertical_chainStyle="packed"
+                app:layout_constraintTop_toTopOf="@id/conversation_icon_6"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_6"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toTopOf="@id/conversation_line_12"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_12"
+                android:layout_width="0dp"
+                android:layout_height="16dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="72dp"
+                android:layout_marginTop="4dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintTop_toBottomOf="@id/conversation_line_11"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_6"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toBottomOf="@id/conversation_icon_6"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_icon_7"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_marginTop="32dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+                app:cardBackgroundColor="@color/mock_list_profile_icon"
+                app:layout_constraintTop_toBottomOf="@id/conversation_icon_6"
+                app:layout_constraintStart_toStartOf="parent"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_13"
+                android:layout_width="0dp"
+                android:layout_height="18dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="242dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintVertical_chainStyle="packed"
+                app:layout_constraintTop_toTopOf="@id/conversation_icon_7"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_7"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toTopOf="@id/conversation_line_14"/>
+
+            <androidx.cardview.widget.CardView
+                android:id="@+id/conversation_line_14"
+                android:layout_width="0dp"
+                android:layout_height="16dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+                android:layout_marginEnd="219dp"
+                android:layout_marginTop="4dp"
+
+                app:cardElevation="0dp"
+                app:cardCornerRadius="4dp"
+                app:cardBackgroundColor="@color/mock_list_preview_message"
+                app:layout_constraintTop_toBottomOf="@id/conversation_line_13"
+                app:layout_constraintStart_toEndOf="@id/conversation_icon_7"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintBottom_toBottomOf="@id/conversation_icon_7"/>
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/mock_button"
+            android:layout_width="149dp"
+            android:layout_height="56dp"
+            android:layout_marginEnd="126dp"
+            android:layout_marginBottom="24dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="164dp"
+            app:cardBackgroundColor="@color/mock_list_button"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+</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
new file mode 100644
index 0000000..5612666
--- /dev/null
+++ b/quickstep/res/layout/gesture_tutorial_foldable_mock_hotseat.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingBottom="32dp"
+    android:paddingStart="170dp"
+    android:paddingEnd="170dp">
+
+    <androidx.cardview.widget.CardView
+        android:id="@+id/hotseat_search_bar"
+        android:layout_width="0dp"
+        android:layout_height="@dimen/gesture_tutorial_hotseat_search_height"
+
+        app:cardElevation="0dp"
+        app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_search_corner_radius"
+        app:cardBackgroundColor="@color/mock_search_bar"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+    <androidx.cardview.widget.CardView
+        android:id="@+id/hotseat_icon_1"
+        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_1"
+        app:layout_constraintDimensionRatio="1:1"
+        app:layout_constraintHorizontal_chainStyle="spread_inside"
+        app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/hotseat_icon_2"/>
+
+    <androidx.cardview.widget.CardView
+        android:id="@+id/hotseat_icon_2"
+        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_1"
+        app:layout_constraintEnd_toStartOf="@id/hotseat_icon_3"/>
+
+    <androidx.cardview.widget.CardView
+        android:id="@+id/hotseat_icon_3"
+        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_3"
+        app:layout_constraintDimensionRatio="1:1"
+        app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
+        app:layout_constraintStart_toEndOf="@id/hotseat_icon_2"
+        app:layout_constraintEnd_toStartOf="@id/hotseat_icon_4"/>
+
+    <androidx.cardview.widget.CardView
+        android:id="@+id/hotseat_icon_4"
+        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_1"
+        app:layout_constraintDimensionRatio="1:1"
+        app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
+        app:layout_constraintStart_toEndOf="@id/hotseat_icon_3"
+        app:layout_constraintEnd_toStartOf="@id/hotseat_icon_5"/>
+
+    <androidx.cardview.widget.CardView
+        android:id="@+id/hotseat_icon_5"
+        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_4"
+        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_foldable_mock_webpage.xml b/quickstep/res/layout/gesture_tutorial_foldable_mock_webpage.xml
new file mode 100644
index 0000000..67e9b02
--- /dev/null
+++ b/quickstep/res/layout/gesture_tutorial_foldable_mock_webpage.xml
@@ -0,0 +1,275 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout
+    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="match_parent"
+    android:background="@color/mock_webpage_background">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/url_bar"
+        android:layout_width="match_parent"
+        android:layout_height="101dp"
+        android:background="@color/mock_webpage_url_bar"
+
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent">
+
+        <androidx.cardview.widget.CardView
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_marginTop="48dp"
+            android:layout_marginBottom="16dp"
+            android:layout_marginStart="100dp"
+            android:layout_marginEnd="100dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="100dp"
+            app:cardBackgroundColor="@color/mock_webpage_url_bar_item"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/top_bar"
+        android:layout_width="match_parent"
+        android:layout_height="88dp"
+        android:layout_marginStart="100dp"
+        android:layout_marginEnd="100dp"
+        android:background="@color/mock_webpage_top_bar"
+
+        app:layout_constraintTop_toBottomOf="@id/url_bar"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent">
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/top_bar_button"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_marginTop="22dp"
+            android:layout_marginBottom="22dp"
+            android:layout_marginStart="24dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="8dp"
+            app:cardBackgroundColor="@color/mock_webpage_top_bar_item"
+            app:layout_constraintDimensionRatio="1:1"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"/>
+
+        <androidx.cardview.widget.CardView
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_marginTop="28dp"
+            android:layout_marginBottom="28dp"
+            android:layout_marginStart="97dp"
+            android:layout_marginEnd="325dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="2dp"
+            app:cardBackgroundColor="@color/mock_webpage_top_bar_item"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:background="@color/mock_webpage_background"
+        android:paddingTop="@dimen/gesture_tutorial_webpage_padding_top"
+        android:paddingStart="124dp"
+        android:paddingEnd="100dp"
+
+        app:layout_constraintTop_toBottomOf="@id/top_bar"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent">
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/mock_line_1"
+            android:layout_width="0dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_large_line_height"
+            android:layout_marginEnd="126dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_small_corner_radius"
+            app:cardBackgroundColor="@color/mock_webpage_page_text"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/mock_line_2"
+            android:layout_width="0dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_large_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
+            android:layout_marginEnd="64dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_small_corner_radius"
+            app:cardBackgroundColor="@color/mock_webpage_page_text"
+            app:layout_constraintTop_toBottomOf="@id/mock_line_1"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/mock_line_3"
+            android:layout_width="0dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_large_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
+            android:layout_marginEnd="151dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_small_corner_radius"
+            app:cardBackgroundColor="@color/mock_webpage_page_text"
+            app:layout_constraintTop_toBottomOf="@id/mock_line_2"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/mock_button"
+            android:layout_width="47dp"
+            android:layout_height="12dp"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_small_corner_radius"
+            app:cardBackgroundColor="@color/mock_webpage_page_text"
+            app:layout_constraintTop_toBottomOf="@id/mock_line_3"
+            app:layout_constraintStart_toStartOf="parent"/>
+
+        <androidx.cardview.widget.CardView
+            android:layout_width="47dp"
+            android:layout_height="12dp"
+            android:background="@color/mock_webpage_page_text"
+            android:layout_marginStart="11dp"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_small_corner_radius"
+            app:cardBackgroundColor="@color/mock_webpage_page_text"
+            app:layout_constraintTop_toBottomOf="@id/mock_line_3"
+            app:layout_constraintStart_toEndOf="@id/mock_button"/>
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/mock_block"
+            android:layout_width="0dp"
+            android:layout_height="240dp"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_large_margin_top"
+            android:layout_marginEnd="24dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_large_corner_radius"
+            app:cardBackgroundColor="@color/mock_webpage_page_text"
+            app:layout_constraintTop_toBottomOf="@id/mock_button"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/mock_line_4"
+            android:layout_width="0dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_large_margin_top"
+            android:layout_marginEnd="52dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
+            app:cardBackgroundColor="@color/mock_webpage_page_text"
+            app:layout_constraintTop_toBottomOf="@id/mock_block"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/mock_line_5"
+            android:layout_width="0dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
+            android:layout_marginEnd="41dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
+            app:cardBackgroundColor="@color/mock_webpage_page_text"
+            app:layout_constraintTop_toBottomOf="@id/mock_line_4"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/mock_line_6"
+            android:layout_width="0dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
+            android:layout_marginEnd="71dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
+            app:cardBackgroundColor="@color/mock_webpage_page_text"
+            app:layout_constraintTop_toBottomOf="@id/mock_line_5"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/mock_line_7"
+            android:layout_width="0dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
+            android:layout_marginEnd="198dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
+            app:cardBackgroundColor="@color/mock_webpage_page_text"
+            app:layout_constraintTop_toBottomOf="@id/mock_line_6"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/mock_line_8"
+            android:layout_width="0dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_large_margin_top"
+            android:layout_marginEnd="64dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
+            app:cardBackgroundColor="@color/mock_webpage_page_text"
+            app:layout_constraintTop_toBottomOf="@id/mock_line_7"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <androidx.cardview.widget.CardView
+            android:layout_width="0dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
+            android:layout_marginEnd="71dp"
+
+            app:cardElevation="0dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
+            app:cardBackgroundColor="@color/mock_webpage_page_text"
+            app:layout_constraintTop_toBottomOf="@id/mock_line_8"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+</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 0f01190..41d0a1d 100644
--- a/quickstep/res/layout/gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/gesture_tutorial_fragment.xml
@@ -25,13 +25,12 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-        <ImageView
+        <FrameLayout
             android:id="@+id/gesture_tutorial_fake_hotseat_view"
-            android:layout_width="wrap_content"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_centerHorizontal="true"
-            android:layout_alignParentBottom="true"
-            android:layout_marginBottom="70dp"/>
+            android:layout_alignParentBottom="true"/>
 
     </RelativeLayout>
 
@@ -128,8 +127,6 @@
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
         android:layout_centerHorizontal="true"
-        android:layout_marginStart="@dimen/gesture_tutorial_feedback_margin_start_end"
-        android:layout_marginEnd="@dimen/gesture_tutorial_feedback_margin_start_end"
         android:layout_marginTop="24dp"
         android:paddingTop="24dp"
         android:paddingBottom="16dp"
diff --git a/quickstep/res/layout/gesture_tutorial_mock_conversation.xml b/quickstep/res/layout/gesture_tutorial_mock_conversation.xml
index 9951663..e8d5d79 100644
--- a/quickstep/res/layout/gesture_tutorial_mock_conversation.xml
+++ b/quickstep/res/layout/gesture_tutorial_mock_conversation.xml
@@ -94,7 +94,7 @@
         <androidx.constraintlayout.widget.ConstraintLayout
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:paddingBottom="36dp"
+            android:paddingBottom="@dimen/gesture_tutorial_message_input_margin_top"
 
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toTopOf="@id/message_bar"
@@ -105,9 +105,9 @@
                 android:id="@+id/message_1"
                 android:layout_width="0dp"
                 android:layout_height="112dp"
-                android:layout_marginBottom="32dp"
+                android:layout_marginBottom="@dimen/gesture_tutorial_message_large_margin_bottom"
                 android:layout_marginStart="124dp"
-                android:layout_marginEnd="18dp"
+                android:layout_marginEnd="@dimen/gesture_tutorial_message_padding_end"
 
                 app:cardElevation="0dp"
                 app:cardCornerRadius="18dp"
@@ -118,13 +118,13 @@
 
             <androidx.cardview.widget.CardView
                 android:id="@+id/reply_icon_1"
-                android:layout_width="44dp"
-                android:layout_height="44dp"
-                android:layout_marginBottom="32dp"
-                android:layout_marginStart="26dp"
+                android:layout_width="@dimen/gesture_tutorial_message_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_message_icon_size"
+                android:layout_marginBottom="@dimen/gesture_tutorial_message_large_margin_bottom"
+                android:layout_marginStart="@dimen/gesture_tutorial_message_padding_start"
 
                 app:cardElevation="0dp"
-                app:cardCornerRadius="100dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_message_icon_corner_radius"
                 app:cardBackgroundColor="@color/mock_conversation_profile_icon"
                 app:layout_constraintDimensionRatio="1:1"
                 app:layout_constraintBottom_toTopOf="@id/message_2"
@@ -148,9 +148,9 @@
                 android:id="@+id/message_2"
                 android:layout_width="0dp"
                 android:layout_height="36dp"
-                android:layout_marginBottom="4dp"
+                android:layout_marginBottom="@dimen/gesture_tutorial_message_small_margin_bottom"
                 android:layout_marginStart="280dp"
-                android:layout_marginEnd="18dp"
+                android:layout_marginEnd="@dimen/gesture_tutorial_message_padding_end"
 
                 app:cardElevation="0dp"
                 app:cardCornerRadius="18dp"
@@ -163,9 +163,9 @@
                 android:id="@+id/message_3"
                 android:layout_width="0dp"
                 android:layout_height="74dp"
-                android:layout_marginBottom="32dp"
+                android:layout_marginBottom="@dimen/gesture_tutorial_message_large_margin_bottom"
                 android:layout_marginStart="124dp"
-                android:layout_marginEnd="18dp"
+                android:layout_marginEnd="@dimen/gesture_tutorial_message_padding_end"
 
                 app:cardElevation="0dp"
                 app:cardCornerRadius="18dp"
@@ -176,13 +176,13 @@
 
             <androidx.cardview.widget.CardView
                 android:id="@+id/reply_icon_2"
-                android:layout_width="44dp"
-                android:layout_height="44dp"
-                android:layout_marginBottom="32dp"
-                android:layout_marginStart="26dp"
+                android:layout_width="@dimen/gesture_tutorial_message_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_message_icon_size"
+                android:layout_marginBottom="@dimen/gesture_tutorial_message_large_margin_bottom"
+                android:layout_marginStart="@dimen/gesture_tutorial_message_padding_start"
 
                 app:cardElevation="0dp"
-                app:cardCornerRadius="100dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_message_icon_corner_radius"
                 app:cardBackgroundColor="@color/mock_conversation_profile_icon"
                 app:layout_constraintDimensionRatio="1:1"
                 app:layout_constraintBottom_toTopOf="@id/message_4"
@@ -207,7 +207,7 @@
                 android:layout_width="0dp"
                 android:layout_height="74dp"
                 android:layout_marginStart="124dp"
-                android:layout_marginEnd="18dp"
+                android:layout_marginEnd="@dimen/gesture_tutorial_message_padding_end"
 
                 app:cardElevation="0dp"
                 app:cardCornerRadius="18dp"
diff --git a/quickstep/res/layout/gesture_tutorial_mock_conversation_list.xml b/quickstep/res/layout/gesture_tutorial_mock_conversation_list.xml
index ad6b165..364ad6d 100644
--- a/quickstep/res/layout/gesture_tutorial_mock_conversation_list.xml
+++ b/quickstep/res/layout/gesture_tutorial_mock_conversation_list.xml
@@ -61,7 +61,7 @@
         <androidx.constraintlayout.widget.ConstraintLayout
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:paddingTop="28dp"
+            android:paddingTop="@dimen/gesture_tutorial_conversation_list_padding_top"
             android:paddingStart="26dp"
             android:paddingBottom="14dp"
 
@@ -70,11 +70,11 @@
 
             <androidx.cardview.widget.CardView
                 android:id="@+id/conversation_icon_1"
-                android:layout_width="56dp"
-                android:layout_height="56dp"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
 
                 app:cardElevation="0dp"
-                app:cardCornerRadius="100dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
                 app:cardBackgroundColor="@color/mock_list_profile_icon"
                 app:layout_constraintTop_toTopOf="parent"
                 app:layout_constraintStart_toStartOf="parent"/>
@@ -83,7 +83,7 @@
                 android:id="@+id/conversation_line_1"
                 android:layout_width="0dp"
                 android:layout_height="18dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="217dp"
 
                 app:cardElevation="0dp"
@@ -99,7 +99,7 @@
                 android:id="@+id/conversation_line_2"
                 android:layout_width="0dp"
                 android:layout_height="16dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="142dp"
                 android:layout_marginTop="4dp"
 
@@ -113,12 +113,12 @@
 
             <androidx.cardview.widget.CardView
                 android:id="@+id/conversation_icon_2"
-                android:layout_width="56dp"
-                android:layout_height="56dp"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
                 android:layout_marginTop="32dp"
 
                 app:cardElevation="0dp"
-                app:cardCornerRadius="100dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
                 app:cardBackgroundColor="@color/mock_list_profile_icon"
                 app:layout_constraintTop_toBottomOf="@id/conversation_icon_1"
                 app:layout_constraintStart_toStartOf="parent"/>
@@ -127,7 +127,7 @@
                 android:id="@+id/conversation_line_3"
                 android:layout_width="0dp"
                 android:layout_height="18dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="190dp"
 
                 app:cardElevation="0dp"
@@ -143,7 +143,7 @@
                 android:id="@+id/conversation_line_4"
                 android:layout_width="0dp"
                 android:layout_height="16dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="171dp"
                 android:layout_marginTop="4dp"
 
@@ -157,12 +157,12 @@
 
             <androidx.cardview.widget.CardView
                 android:id="@+id/conversation_icon_3"
-                android:layout_width="56dp"
-                android:layout_height="56dp"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
                 android:layout_marginTop="32dp"
 
                 app:cardElevation="0dp"
-                app:cardCornerRadius="100dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
                 app:cardBackgroundColor="@color/mock_list_profile_icon"
                 app:layout_constraintTop_toBottomOf="@id/conversation_icon_2"
                 app:layout_constraintStart_toStartOf="parent"/>
@@ -171,7 +171,7 @@
                 android:id="@+id/conversation_line_5"
                 android:layout_width="0dp"
                 android:layout_height="18dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="198dp"
 
                 app:cardElevation="0dp"
@@ -187,7 +187,7 @@
                 android:id="@+id/conversation_line_6"
                 android:layout_width="0dp"
                 android:layout_height="16dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="79dp"
                 android:layout_marginTop="4dp"
 
@@ -201,12 +201,12 @@
 
             <androidx.cardview.widget.CardView
                 android:id="@+id/conversation_icon_4"
-                android:layout_width="56dp"
-                android:layout_height="56dp"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
                 android:layout_marginTop="32dp"
 
                 app:cardElevation="0dp"
-                app:cardCornerRadius="100dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
                 app:cardBackgroundColor="@color/mock_list_profile_icon"
                 app:layout_constraintTop_toBottomOf="@id/conversation_icon_3"
                 app:layout_constraintStart_toStartOf="parent"/>
@@ -215,7 +215,7 @@
                 android:id="@+id/conversation_line_7"
                 android:layout_width="0dp"
                 android:layout_height="18dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="174dp"
 
                 app:cardElevation="0dp"
@@ -231,7 +231,7 @@
                 android:id="@+id/conversation_line_8"
                 android:layout_width="0dp"
                 android:layout_height="16dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="117dp"
                 android:layout_marginTop="4dp"
 
@@ -245,12 +245,12 @@
 
             <androidx.cardview.widget.CardView
                 android:id="@+id/conversation_icon_5"
-                android:layout_width="56dp"
-                android:layout_height="56dp"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
                 android:layout_marginTop="32dp"
 
                 app:cardElevation="0dp"
-                app:cardCornerRadius="100dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
                 app:cardBackgroundColor="@color/mock_list_profile_icon"
                 app:layout_constraintTop_toBottomOf="@id/conversation_icon_4"
                 app:layout_constraintStart_toStartOf="parent"/>
@@ -259,7 +259,7 @@
                 android:id="@+id/conversation_line_9"
                 android:layout_width="0dp"
                 android:layout_height="18dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="244dp"
 
                 app:cardElevation="0dp"
@@ -275,7 +275,7 @@
                 android:id="@+id/conversation_line_10"
                 android:layout_width="0dp"
                 android:layout_height="16dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="143dp"
                 android:layout_marginTop="4dp"
 
@@ -289,12 +289,12 @@
 
             <androidx.cardview.widget.CardView
                 android:id="@+id/conversation_icon_6"
-                android:layout_width="56dp"
-                android:layout_height="56dp"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
                 android:layout_marginTop="32dp"
 
                 app:cardElevation="0dp"
-                app:cardCornerRadius="100dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
                 app:cardBackgroundColor="@color/mock_list_profile_icon"
                 app:layout_constraintTop_toBottomOf="@id/conversation_icon_5"
                 app:layout_constraintStart_toStartOf="parent"/>
@@ -303,7 +303,7 @@
                 android:id="@+id/conversation_line_11"
                 android:layout_width="0dp"
                 android:layout_height="18dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="177dp"
 
                 app:cardElevation="0dp"
@@ -319,7 +319,7 @@
                 android:id="@+id/conversation_line_12"
                 android:layout_width="0dp"
                 android:layout_height="16dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="117dp"
                 android:layout_marginTop="4dp"
 
@@ -333,12 +333,12 @@
 
             <androidx.cardview.widget.CardView
                 android:id="@+id/conversation_icon_7"
-                android:layout_width="56dp"
-                android:layout_height="56dp"
+                android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+                android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
                 android:layout_marginTop="32dp"
 
                 app:cardElevation="0dp"
-                app:cardCornerRadius="100dp"
+                app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
                 app:cardBackgroundColor="@color/mock_list_profile_icon"
                 app:layout_constraintTop_toBottomOf="@id/conversation_icon_6"
                 app:layout_constraintStart_toStartOf="parent"/>
@@ -347,7 +347,7 @@
                 android:id="@+id/conversation_line_13"
                 android:layout_width="0dp"
                 android:layout_height="18dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="189dp"
 
                 app:cardElevation="0dp"
@@ -363,7 +363,7 @@
                 android:id="@+id/conversation_line_14"
                 android:layout_width="0dp"
                 android:layout_height="16dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
                 android:layout_marginEnd="166dp"
                 android:layout_marginTop="4dp"
 
diff --git a/quickstep/res/layout/gesture_tutorial_mock_hotseat.xml b/quickstep/res/layout/gesture_tutorial_mock_hotseat.xml
new file mode 100644
index 0000000..b3e86cf
--- /dev/null
+++ b/quickstep/res/layout/gesture_tutorial_mock_hotseat.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingBottom="70dp"
+    android:paddingStart="26dp"
+    android:paddingEnd="26dp">
+
+    <androidx.cardview.widget.CardView
+        android:id="@+id/hotseat_icon_1"
+        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_1"
+        app:layout_constraintDimensionRatio="1:1"
+        app:layout_constraintHorizontal_chainStyle="spread_inside"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/hotseat_icon_2"/>
+
+    <androidx.cardview.widget.CardView
+        android:id="@+id/hotseat_icon_2"
+        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_constraintStart_toEndOf="@id/hotseat_icon_1"
+        app:layout_constraintEnd_toStartOf="@id/hotseat_icon_3"/>
+
+    <androidx.cardview.widget.CardView
+        android:id="@+id/hotseat_icon_3"
+        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_3"
+        app:layout_constraintDimensionRatio="1:1"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toEndOf="@id/hotseat_icon_2"
+        app:layout_constraintEnd_toStartOf="@id/hotseat_icon_4"/>
+
+    <androidx.cardview.widget.CardView
+        android:id="@+id/hotseat_icon_4"
+        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_4"
+        app:layout_constraintDimensionRatio="1:1"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toEndOf="@id/hotseat_icon_3"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+    <androidx.cardview.widget.CardView
+        android:layout_width="0dp"
+        android:layout_height="@dimen/gesture_tutorial_hotseat_search_height"
+        android:layout_marginTop="@dimen/gesture_tutorial_hotseat_icon_search_margin"
+
+        app:cardElevation="0dp"
+        app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_search_corner_radius"
+        app:cardBackgroundColor="@color/mock_search_bar"
+        app:layout_constraintTop_toBottomOf="@id/hotseat_icon_1"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_mock_webpage.xml b/quickstep/res/layout/gesture_tutorial_mock_webpage.xml
index ab00a11..bb20968 100644
--- a/quickstep/res/layout/gesture_tutorial_mock_webpage.xml
+++ b/quickstep/res/layout/gesture_tutorial_mock_webpage.xml
@@ -64,7 +64,6 @@
             android:layout_marginTop="22dp"
             android:layout_marginBottom="22dp"
             android:layout_marginStart="24dp"
-            android:layout_marginEnd="344dp"
 
             app:cardElevation="0dp"
             app:cardCornerRadius="8dp"
@@ -72,8 +71,7 @@
             app:layout_constraintDimensionRatio="1:1"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"/>
+            app:layout_constraintStart_toStartOf="parent"/>
 
         <androidx.cardview.widget.CardView
             android:layout_width="0dp"
@@ -97,9 +95,8 @@
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:background="@color/mock_webpage_background"
-        android:paddingTop="32dp"
+        android:paddingTop="@dimen/gesture_tutorial_webpage_padding_top"
         android:paddingStart="24dp"
-        android:paddingBottom="50dp"
 
         app:layout_constraintTop_toBottomOf="@id/top_bar"
         app:layout_constraintBottom_toBottomOf="parent"
@@ -109,11 +106,11 @@
         <androidx.cardview.widget.CardView
             android:id="@+id/mock_line_1"
             android:layout_width="0dp"
-            android:layout_height="36dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_large_line_height"
             android:layout_marginEnd="126dp"
 
             app:cardElevation="0dp"
-            app:cardCornerRadius="4dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_small_corner_radius"
             app:cardBackgroundColor="@color/mock_webpage_page_text"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintStart_toStartOf="parent"
@@ -122,12 +119,12 @@
         <androidx.cardview.widget.CardView
             android:id="@+id/mock_line_2"
             android:layout_width="0dp"
-            android:layout_height="36dp"
-            android:layout_marginTop="8dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_large_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
             android:layout_marginEnd="64dp"
 
             app:cardElevation="0dp"
-            app:cardCornerRadius="4dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_small_corner_radius"
             app:cardBackgroundColor="@color/mock_webpage_page_text"
             app:layout_constraintTop_toBottomOf="@id/mock_line_1"
             app:layout_constraintStart_toStartOf="parent"
@@ -136,12 +133,12 @@
         <androidx.cardview.widget.CardView
             android:id="@+id/mock_line_3"
             android:layout_width="0dp"
-            android:layout_height="36dp"
-            android:layout_marginTop="8dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_large_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
             android:layout_marginEnd="151dp"
 
             app:cardElevation="0dp"
-            app:cardCornerRadius="4dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_small_corner_radius"
             app:cardBackgroundColor="@color/mock_webpage_page_text"
             app:layout_constraintTop_toBottomOf="@id/mock_line_2"
             app:layout_constraintStart_toStartOf="parent"
@@ -151,10 +148,10 @@
             android:id="@+id/mock_button"
             android:layout_width="47dp"
             android:layout_height="12dp"
-            android:layout_marginTop="8dp"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
 
             app:cardElevation="0dp"
-            app:cardCornerRadius="4dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_small_corner_radius"
             app:cardBackgroundColor="@color/mock_webpage_page_text"
             app:layout_constraintTop_toBottomOf="@id/mock_line_3"
             app:layout_constraintStart_toStartOf="parent"/>
@@ -164,10 +161,10 @@
             android:layout_height="12dp"
             android:background="@color/mock_webpage_page_text"
             android:layout_marginStart="11dp"
-            android:layout_marginTop="8dp"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
 
             app:cardElevation="0dp"
-            app:cardCornerRadius="4dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_small_corner_radius"
             app:cardBackgroundColor="@color/mock_webpage_page_text"
             app:layout_constraintTop_toBottomOf="@id/mock_line_3"
             app:layout_constraintStart_toEndOf="@id/mock_button"/>
@@ -176,11 +173,11 @@
             android:id="@+id/mock_block"
             android:layout_width="0dp"
             android:layout_height="240dp"
-            android:layout_marginTop="24dp"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_large_margin_top"
             android:layout_marginEnd="24dp"
 
             app:cardElevation="0dp"
-            app:cardCornerRadius="22dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_large_corner_radius"
             app:cardBackgroundColor="@color/mock_webpage_page_text"
             app:layout_constraintTop_toBottomOf="@id/mock_button"
             app:layout_constraintStart_toStartOf="parent"
@@ -189,12 +186,12 @@
         <androidx.cardview.widget.CardView
             android:id="@+id/mock_line_4"
             android:layout_width="0dp"
-            android:layout_height="22dp"
-            android:layout_marginTop="24dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_large_margin_top"
             android:layout_marginEnd="52dp"
 
             app:cardElevation="0dp"
-            app:cardCornerRadius="8dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
             app:cardBackgroundColor="@color/mock_webpage_page_text"
             app:layout_constraintTop_toBottomOf="@id/mock_block"
             app:layout_constraintStart_toStartOf="parent"
@@ -203,12 +200,12 @@
         <androidx.cardview.widget.CardView
             android:id="@+id/mock_line_5"
             android:layout_width="0dp"
-            android:layout_height="22dp"
-            android:layout_marginTop="8dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
             android:layout_marginEnd="41dp"
 
             app:cardElevation="0dp"
-            app:cardCornerRadius="8dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
             app:cardBackgroundColor="@color/mock_webpage_page_text"
             app:layout_constraintTop_toBottomOf="@id/mock_line_4"
             app:layout_constraintStart_toStartOf="parent"
@@ -217,12 +214,12 @@
         <androidx.cardview.widget.CardView
             android:id="@+id/mock_line_6"
             android:layout_width="0dp"
-            android:layout_height="22dp"
-            android:layout_marginTop="8dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
             android:layout_marginEnd="71dp"
 
             app:cardElevation="0dp"
-            app:cardCornerRadius="8dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
             app:cardBackgroundColor="@color/mock_webpage_page_text"
             app:layout_constraintTop_toBottomOf="@id/mock_line_5"
             app:layout_constraintStart_toStartOf="parent"
@@ -231,12 +228,12 @@
         <androidx.cardview.widget.CardView
             android:id="@+id/mock_line_7"
             android:layout_width="0dp"
-            android:layout_height="22dp"
-            android:layout_marginTop="8dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
             android:layout_marginEnd="198dp"
 
             app:cardElevation="0dp"
-            app:cardCornerRadius="8dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
             app:cardBackgroundColor="@color/mock_webpage_page_text"
             app:layout_constraintTop_toBottomOf="@id/mock_line_6"
             app:layout_constraintStart_toStartOf="parent"
@@ -245,12 +242,12 @@
         <androidx.cardview.widget.CardView
             android:id="@+id/mock_line_8"
             android:layout_width="0dp"
-            android:layout_height="22dp"
-            android:layout_marginTop="24dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_large_margin_top"
             android:layout_marginEnd="64dp"
 
             app:cardElevation="0dp"
-            app:cardCornerRadius="8dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
             app:cardBackgroundColor="@color/mock_webpage_page_text"
             app:layout_constraintTop_toBottomOf="@id/mock_line_7"
             app:layout_constraintStart_toStartOf="parent"
@@ -258,12 +255,12 @@
 
         <androidx.cardview.widget.CardView
             android:layout_width="0dp"
-            android:layout_height="22dp"
-            android:layout_marginTop="8dp"
+            android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
+            android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
             android:layout_marginEnd="71dp"
 
             app:cardElevation="0dp"
-            app:cardCornerRadius="8dp"
+            app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
             app:cardBackgroundColor="@color/mock_webpage_page_text"
             app:layout_constraintTop_toBottomOf="@id/mock_line_8"
             app:layout_constraintStart_toStartOf="parent"
diff --git a/quickstep/res/layout/taskbar.xml b/quickstep/res/layout/taskbar.xml
index 83ad9f3..3b1d217 100644
--- a/quickstep/res/layout/taskbar.xml
+++ b/quickstep/res/layout/taskbar.xml
@@ -30,6 +30,11 @@
         android:layout_gravity="bottom"
         android:clipChildren="false" />
 
+    <com.android.launcher3.taskbar.TaskbarScrimView
+        android:id="@+id/taskbar_scrim"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
     <FrameLayout
         android:id="@+id/navbuttons_view"
         android:layout_width="match_parent"
@@ -42,6 +47,7 @@
             android:layout_height="match_parent"
             android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"
             android:paddingRight="@dimen/taskbar_nav_buttons_spacing"
+            android:paddingTop="@dimen/taskbar_contextual_padding_top"
             android:gravity="center_vertical"
             android:layout_gravity="start"/>
 
@@ -62,6 +68,7 @@
             android:layout_height="match_parent"
             android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"
             android:paddingRight="@dimen/taskbar_nav_buttons_spacing"
+            android:paddingTop="@dimen/taskbar_contextual_padding_top"
             android:gravity="center_vertical"
             android:layout_gravity="end"/>
     </FrameLayout>
diff --git a/quickstep/res/layout/taskbar_contextual_button.xml b/quickstep/res/layout/taskbar_contextual_button.xml
index cbbbfab..4ffb8d8 100644
--- a/quickstep/res/layout/taskbar_contextual_button.xml
+++ b/quickstep/res/layout/taskbar_contextual_button.xml
@@ -15,9 +15,7 @@
 -->
 <ImageView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="@dimen/taskbar_contextual_buttons_size"
-    android:layout_height="@dimen/taskbar_contextual_buttons_size"
-    android:layout_marginTop="@dimen/taskbar_contextual_button_margin"
-    android:paddingStart="@dimen/taskbar_nav_buttons_spacing"
+    android:layout_width="@dimen/taskbar_nav_buttons_size"
+    android:layout_height="@dimen/taskbar_nav_buttons_size"
     android:background="@drawable/taskbar_icon_click_feedback_roundrect"
     android:scaleType="center"/>
\ No newline at end of file
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index 26b1965..2f0129b 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"አጋራ"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"ቅጽበታዊ ገጽ እይታ"</string>
     <string name="action_split" msgid="2098009717623550676">"ክፈል"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"የተከፈለ ማያን ለመጠቀም ሌላ መተግበሪያ መታ ያድርጉ"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"ይህ ድርጊት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"የአሰሳ አጋዥ ሥልጠናን ይዝለሉ?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ይህን በኋላ በ<xliff:g id="NAME">%1$s</xliff:g> መተግበሪያው ውስጥ ማግኘት ይችላሉ"</string>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index ed8d195..afba62e 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"مشاركة"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"لقطة شاشة"</string>
     <string name="action_split" msgid="2098009717623550676">"تقسيم"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"انقر على تطبيق آخر لاستخدام وضع تقسيم الشاشة."</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"لا يسمح التطبيق أو لا تسمح مؤسستك بهذا الإجراء."</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"هل تريد تخطي الدليل التوجيهي؟"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"يمكنك العثور على هذا الدليل التوجيهي لاحقًا في التطبيق \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index cc2fbfb..a77efa4 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"শ্বেয়াৰ কৰক"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"স্ক্ৰীনশ্বট"</string>
     <string name="action_split" msgid="2098009717623550676">"বিভাজন কৰক"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰিবলৈ অন্য এটা এপত টিপক"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"এপ্‌টোৱে অথবা আপোনাৰ প্ৰতিষ্ঠানে এই কাৰ্যটোৰ অনুমতি নিদিয়ে"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"নেভিগেশ্বনৰ টিউট’ৰিয়েল এৰিব বিচাৰে নেকি?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"আপুনি এয়া পাছত <xliff:g id="NAME">%1$s</xliff:g> এপ্‌টোত বিচাৰিব পাৰিব"</string>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 778cc76..f98ca49 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Абагуліць"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Здымак экрана"</string>
     <string name="action_split" msgid="2098009717623550676">"Падзелены экран"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Для падзеленага экрана націсніце на іншую праграму"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Гэта дзеянне не дазволена праграмай ці вашай арганізацыяй"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Прапусціць дапаможнік па навігацыі?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Знайсці дапаможнік можна ў праграме \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index 1194b3f..5a7400a 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"শেয়ার করুন"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"স্ক্রিনশট নিন"</string>
     <string name="action_split" msgid="2098009717623550676">"স্প্লিট"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"স্প্লিটস্ক্রিন ব্যবহার করতে অন্য অ্যাপে ট্যাপ করুন"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"এই অ্যাপ বা আপনার প্রতিষ্ঠান এই অ্যাকশনটি পারফর্ম করার অনুমতি দেয়নি"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"নেভিগেশন টিউটোরিয়াল এড়িয়ে যেতে চান?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"আপনি <xliff:g id="NAME">%1$s</xliff:g> অ্যাপে পরে এটি খুঁজে পাবেন"</string>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index 93b2859..affac8d 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Comparteix"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Captura de pantalla"</string>
     <string name="action_split" msgid="2098009717623550676">"Divideix"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Toca una altra aplicació per dividir la pantalla"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"L\'aplicació o la teva organització no permeten aquesta acció"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vols ometre el tutorial de navegació?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Pots trobar-lo més tard a l\'aplicació <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index 29fd8e0..dbdc828 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Sdílet"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Snímek obrazovky"</string>
     <string name="action_split" msgid="2098009717623550676">"Rozdělit"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Klepnutím na jinou aplikaci rozdělíte obrazovku"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Aplikace nebo organizace zakazuje tuto akci"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Přeskočit výukový program k navigaci?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Program později najdete v aplikaci <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 8ec0e6d..61a2751 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Teilen"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Teilen"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Für „Bildschirm teilen“ auf weitere App tippen"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Die App oder deine Organisation lässt diese Aktion nicht zu"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Navigationstutorial überspringen?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Du findest es später auch in der <xliff:g id="NAME">%1$s</xliff:g> App"</string>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 382b6d4..ce6f893 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Κοινοποίηση"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Στιγμιότυπο οθόνης"</string>
     <string name="action_split" msgid="2098009717623550676">"Διαχωρισμός"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Πατήστε άλλη εφαρμογή για χρήση διαχωρισμού οθόνης"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Αυτή η ενέργεια δεν επιτρέπεται από την εφαρμογή ή τον οργανισμό σας."</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Παράβλεψη οδηγού πλοήγησης;"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Βρείτε τον αργότερα στην εφαρμογή <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 2259ff3..43928b9 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Partager"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Capture d\'écran"</string>
     <string name="action_split" msgid="2098009717623550676">"Séparé"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Touchez une autre appli pour partager l\'écran"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"L\'application ou votre organisation n\'autorise pas cette action"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorer le tutoriel sur la navigation?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Vous trouverez le tutoriel dans l\'application <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 210dd50..ca88b00 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Compartir"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Facer captura"</string>
     <string name="action_split" msgid="2098009717623550676">"Dividir"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Para usar a pantalla dividida, toca outra app"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"A aplicación ou a túa organización non permite realizar esta acción"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Queres omitir o titorial de navegación?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Podes atopar isto máis tarde na aplicación <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 4fb3823..aec0960 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"શેર કરો"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"સ્ક્રીનશૉટ"</string>
     <string name="action_split" msgid="2098009717623550676">"વિભાજિત કરો"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"સ્પલિટસ્ક્રીનના વપરાશ માટે, કોઈ અન્ય ઍપ પર ટૅપ કરો"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"ઍપ કે તમારી સંસ્થા દ્વારા આ ક્રિયા કરવાની મંજૂરી નથી"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"નૅવિગેશન ટ્યૂટૉરિઅલ છોડી દઈએ?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"તમે આને પછીથી <xliff:g id="NAME">%1$s</xliff:g> ઍપમાં જોઈ શકો છો"</string>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index 3521e17..c019908 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -80,7 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"शेयर करें"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट लें"</string>
     <string name="action_split" msgid="2098009717623550676">"स्प्लिट स्क्रीन मोड"</string>
-    <string name="toast_split_select_app" msgid="5453865907322018352">"स्प्लिट स्क्रीन मोड इस्तेमाल करने के लिए, दूसरे ऐप पर टैप करें"</string>
+    <string name="toast_split_select_app" msgid="5453865907322018352">"स्प्लिट स्क्रीन मोड के लिए, दूसरे ऐप पर टैप करें"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"ऐप्लिकेशन या आपका संगठन इस कार्रवाई की अनुमति नहीं देता"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"नेविगेशन ट्यूटोरियल छोड़ना चाहते हैं?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"आप बाद में <xliff:g id="NAME">%1$s</xliff:g> ऐप्लिकेशन पर इसे देख सकते हैं"</string>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 9ce3e6c..682d071 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Կիսվել"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Սքրինշոթ անել"</string>
     <string name="action_split" msgid="2098009717623550676">"Տրոհել"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Հպեք այլ հավելվածի՝ էկրանը տրոհելու համար"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Այս գործողությունն արգելված է հավելվածի կամ ձեր կազմակերպության կողմից"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Բաց թողնե՞լ նավիգացիայի ուղեցույցը"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Հետագայում սա կարող եք գտնել «<xliff:g id="NAME">%1$s</xliff:g>» հավելվածում"</string>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 235642c..4774ae4 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Bagikan"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Pisahkan"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Ketuk aplikasi lain untuk menggunakan layar terpisah"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Tindakan ini tidak diizinkan oleh aplikasi atau organisasi Anda"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Lewati tutorial navigasi?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Anda dapat menemukan tutorial ini di lain waktu di aplikasi <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 0de2c9b..18980d8 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"שיתוף"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"צילום מסך"</string>
     <string name="action_split" msgid="2098009717623550676">"פיצול"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"צריך להקיש על אפליקציה אחרת כדי להשתמש במסך מפוצל"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"האפליקציה או הארגון שלך אינם מתירים את הפעולה הזאת"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"לדלג על המדריך לניווט?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ניתן למצוא את המדריך מאוחר יותר באפליקציה <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index 0f5a2bf..2d0c621 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"ចែករំលែក"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"រូបថតអេក្រង់"</string>
     <string name="action_split" msgid="2098009717623550676">"បំបែក"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"ចុចកម្មវិធី​ផ្សេងទៀត ដើម្បីប្រើមុខងារ​បំបែកអេក្រង់"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"សកម្មភាពនេះ​មិនត្រូវបានអនុញ្ញាតដោយកម្មវិធី​ ឬ​ស្ថាប័ន​របស់អ្នកទេ"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"រំលង​មេរៀន​អំពី​ការរុករក​ឬ?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"អ្នកអាចស្វែងរកមេរៀននេះនៅពេលក្រោយក្នុងកម្មវិធី <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 7a0c930..31340c8 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"ಹಂಚಿಕೊಳ್ಳಿ"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್"</string>
     <string name="action_split" msgid="2098009717623550676">"ವಿಭಜಿಸಿ"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಬಳಸಲು ಬೇರೊಂದು ಆ್ಯಪ್ ಮೇಲೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"ಆ್ಯಪ್ ಅಥವಾ ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಕ್ರಿಯೆಯನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ನ್ಯಾವಿಗೇಷನ್ ಟ್ಯುಟೋರಿಯಲ್ ಸ್ಕಿಪ್ ಮಾಡಿ?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> ಆ್ಯಪ್‌ನಲ್ಲಿ ಇದನ್ನು ನಂತರ ಕಾಣಬಹುದು"</string>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 00ffa82..4cf8593 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Бөлүшүү"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
     <string name="action_split" msgid="2098009717623550676">"Бөлүү"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Экранды бөлүү үчүн башка колдонмону таптап коюңуз"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Бул аракетти аткарууга колдонмо же ишканаңыз тыюу салган"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Жаңсоолор үйрөткүчүн өткөрүп жибересизби?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Аны кийин <xliff:g id="NAME">%1$s</xliff:g> колдонмосунан табасыз"</string>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index 3fc0f59..45d7c92 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"ແບ່ງປັນ"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"ຮູບໜ້າຈໍ"</string>
     <string name="action_split" msgid="2098009717623550676">"ແບ່ງ"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"ແຕະແອັບອື່ນເພື່ອໃຊ້ການແຍກໜ້າຈໍ"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"ແອັບ ຫຼື ອົງການຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ໃຊ້ຄຳສັ່ງນີ້"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ຂ້າມການສອນການນຳໃຊ້ການນຳທາງບໍ?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ທ່ານສາມາດຊອກສ່ວນນີ້ພາຍຫຼັງໄດ້ໃນແອັບ <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 9c44614..b7a4a36 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Bendrinti"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Ekrano kopija"</string>
     <string name="action_split" msgid="2098009717623550676">"Išskaidymo režimas"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Pal. kitą progr., kad gal. naud. išsk. ekr. rež."</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Jūsų organizacijoje arba naudojant šią programą neleidžiama atlikti šio veiksmo"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Praleisti naršymo mokymo programą?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Tai galėsite rasti vėliau programoje „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index 6fd8e39..1371b2a 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Kopīgot"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Veikt ekrānuzņēmumu"</string>
     <string name="action_split" msgid="2098009717623550676">"Sadalīt"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Piesk. citai lietotnei, lai izm. ekrāna sadalīšanu"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Lietotne vai jūsu organizācija neatļauj veikt šo darbību."</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vai izlaist navigācijas mācības?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Varēsiet to vēlāk atrast lietotnē <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index 2ea42dd..15040c3 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"പങ്കിടുക"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"സ്ക്രീൻഷോട്ട്"</string>
     <string name="action_split" msgid="2098009717623550676">"വിഭജിക്കുക"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"സ്പ്ലിറ്റ് സ്ക്രീനിനായി മറ്റൊരു ആപ്പ് ടാപ്പുചെയ്യൂ"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"ഈ നടപടി എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"നാവിഗേഷൻ ട്യൂട്ടോറിയൽ ഒഴിവാക്കണോ?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> ആപ്പിൽ നിങ്ങൾക്ക് ഇത് പിന്നീട് കാണാനാകും"</string>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index a368f19..e1bfe39 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"शेअर करा"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट"</string>
     <string name="action_split" msgid="2098009717623550676">"स्प्लिट"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"स्प्लिटस्क्रीन वापरण्यासाठी दुसऱ्या ॲपवर टॅप करा"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"अ‍ॅप किंवा तुमच्या संस्थेद्वारे ही क्रिया करण्याची अनुमती नाही"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"नेव्हिगेशन ट्यूटोरियल वगळायचे आहे का?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"तुम्हाला हे नंतर <xliff:g id="NAME">%1$s</xliff:g> ॲपमध्ये मिळेल"</string>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index ed0e278..fc9b7eb 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Del"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Skjermdump"</string>
     <string name="action_split" msgid="2098009717623550676">"Del opp"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Trykk på en annen app for å bruke delt skjerm"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller organisasjonen din tillater ikke denne handlingen"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vil du hoppe over navigeringsveiledning?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Du kan finne dette i <xliff:g id="NAME">%1$s</xliff:g>-appen senere"</string>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index e1053b4..536264d 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"सेयर गर्नुहोस्"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"स्क्रिनसट"</string>
     <string name="action_split" msgid="2098009717623550676">"स्प्लिट गर्नुहोस्"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"स्प्लिटक्रिन प्रयोग गर्न अर्को एपमा ट्याप गर्नुहोस्"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"यो एप वा तपाईंको सङ्गठनले यो कारबाही गर्ने अनुमति दिँदैन"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"नेभिगेसन ट्युटोरियल स्किप गर्ने हो?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"तपाईं पछि <xliff:g id="NAME">%1$s</xliff:g> नामक एपमा गई यो ट्युटोरियल भेट्टाउन सक्नुहुन्छ"</string>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 0390572..5b7147e 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"ସେୟାର୍ କରନ୍ତୁ"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"ସ୍କ୍ରିନସଟ୍"</string>
     <string name="action_split" msgid="2098009717623550676">"ସ୍ପ୍ଲିଟ୍"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"ସ୍ପ୍ଲିଟସ୍କ୍ରିନ ବ୍ୟବହାର କରିବାକୁ ଅନ୍ୟ ଏକ ଆପରେ ଟାପ କର"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"ଆପ୍ କିମ୍ବା ଆପଣଙ୍କ ସଂସ୍ଥା ଦ୍ୱାରା ଏହି କାର୍ଯ୍ୟକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ନାଭିଗେସନ୍ ଟ୍ୟୁଟୋରିଆଲକୁ ବାଦ୍ ଦେବେ?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ଆପଣ ପରେ ଏହାକୁ <xliff:g id="NAME">%1$s</xliff:g> ଆପରେ ପାଇପାରିବେ"</string>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 927ab8b..5206908 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Поделиться"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
     <string name="action_split" msgid="2098009717623550676">"Разделить"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Для разделения экрана нажмите на другое приложение."</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Это действие заблокировано приложением или организацией."</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропустить руководство по жестам?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Его можно найти в приложении \"<xliff:g id="NAME">%1$s</xliff:g>\"."</string>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 1d55ebd..1d42eb8 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Deli"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Posnetek zaslona"</string>
     <string name="action_split" msgid="2098009717623550676">"Razdeli"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Za uporabo razdeljenega zaslona se dotaknite še ene aplikacije."</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ali vaša organizacija ne dovoljuje tega dejanja"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite preskočiti vadnico za krmarjenje?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"To lahko pozneje najdete v aplikaciji <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index a1b46a1..4d010e3 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Ndaj"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Pamja e ekranit"</string>
     <string name="action_split" msgid="2098009717623550676">"Ndaj"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Trokit aplikacion tjetër e përdor ekranin e ndarë"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Ky veprim nuk lejohet nga aplikacioni ose organizata jote"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Të kapërcehet udhëzuesi i navigimit?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Këtë mund ta gjesh më vonë tek aplikacioni <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index c2c520f..9c32401 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Dela"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Skärmbild"</string>
     <string name="action_split" msgid="2098009717623550676">"Delat"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Tryck på en annan app för att använda delad skärm"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller organisationen tillåter inte den här åtgärden"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vill du hoppa över självstudierna?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Du hittar det här igen i <xliff:g id="NAME">%1$s</xliff:g>-appen"</string>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index 9379f40..d237fb9 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Shiriki"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Picha ya skrini"</string>
     <string name="action_split" msgid="2098009717623550676">"Iliyogawanywa"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Gusa programu nyingine ili utumie skrini iliyogawanywa"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Kitendo hiki hakiruhusiwi na programu au shirika lako"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ungependa kuruka mafunzo ya usogezaji?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Utapata mafunzo haya baadaye katika programu ya <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index e629e58..8a6aa1a2 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"షేర్ చేయండి"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"స్క్రీన్‌షాట్"</string>
     <string name="action_split" msgid="2098009717623550676">"స్ప్లిట్ చేయండి"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"స్క్రీన్ విభజనను ఉపయోగించడానికి మరొక యాప్ నొక్కండి"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"ఈ చర్యను యాప్ గానీ, మీ సంస్థ గానీ అనుమతించవు"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"నావిగేషన్ ట్యుటోరియల్‌ను స్కిప్ చేయాలా?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> యాప్‌లో మీరు తర్వాత కనుగొనవచ్చు"</string>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 5755d2e..5163a5c 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Поділитися"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Знімок екрана"</string>
     <string name="action_split" msgid="2098009717623550676">"Розділити"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Щоб розділити екран, виберіть ще один додаток"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Ця дія заборонена додатком або адміністратором організації"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропустити посібник із навігації?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Ви знайдете його пізніше в додатку <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 72cda26..5e210ff 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"اشتراک کریں"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"اسکرین شاٹ"</string>
     <string name="action_split" msgid="2098009717623550676">"اسپلٹ"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"اسپلٹ اسکرین کا استعمال کرنے کیلئے دوسری ایپ پر تھپتھپائیں"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"ایپ یا آپ کی تنظیم کی جانب سے اس کارروائی کی اجازت نہیں ہے"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"نیویگیشن کا ٹیوٹوریل نظر انداز کریں؟"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"آپ اسے بعد میں <xliff:g id="NAME">%1$s</xliff:g> ایپ میں تلاش کر سکتے ہیں"</string>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index b38b60a..a376f93 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"分享"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"屏幕截图"</string>
     <string name="action_split" msgid="2098009717623550676">"拆分"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"点按另一个应用即可使用分屏"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"该应用或您所在的单位不允许执行此操作"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"要跳过导航教程吗?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"您之后可以在“<xliff:g id="NAME">%1$s</xliff:g>”应用中找到此教程"</string>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index cc92184..b377106 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -80,8 +80,7 @@
     <string name="action_share" msgid="2648470652637092375">"Yabelana"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Isithombe-skrini"</string>
     <string name="action_split" msgid="2098009717623550676">"Hlukanisa"</string>
-    <!-- no translation found for toast_split_select_app (5453865907322018352) -->
-    <skip />
+    <string name="toast_split_select_app" msgid="5453865907322018352">"Thepha enye i-app ukuze usebenzise isikrini sokuhlukanisa"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"Lesi senzo asivunyelwanga uhlelo lokusebenza noma inhlangano yakho"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Yeqa isifundo sokuzulazula?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Lokhu ungakuthola kamuva ku-app ye-<xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml
index 4755292..5edcc9d 100644
--- a/quickstep/res/values/colors.xml
+++ b/quickstep/res/values/colors.xml
@@ -41,6 +41,13 @@
     <color name="gesture_tutorial_action_button_label_color">#FF000000</color>
     <color name="gesture_tutorial_primary_color">#B7F29F</color> <!-- Light Green -->
 
+    <!-- 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_search_bar">#3C4043</color>
+
     <!-- Mock conversation -->
     <color name="mock_conversation_background">#f1f3f4</color>
     <color name="mock_conversation_top_bar">#e8eaed</color>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index e903377..e08eda8 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -117,13 +117,44 @@
     <dimen name="gestures_overscroll_finish_threshold">136dp</dimen>
 
     <!-- Tips Gesture Tutorial -->
-    <dimen name="gesture_tutorial_title_margin_start_end">40dp</dimen>
-    <dimen name="gesture_tutorial_subtitle_margin_start_end">16dp</dimen>
     <dimen name="gesture_tutorial_feedback_margin_start_end">24dp</dimen>
-    <dimen name="gesture_tutorial_button_margin_start_end">18dp</dimen>
+    <dimen name="gesture_tutorial_foldable_feedback_margin_start_end">140dp</dimen>
     <dimen name="gesture_tutorial_multi_row_task_view_spacing">72dp</dimen>
     <dimen name="gesture_tutorial_small_task_view_corner_radius">18dp</dimen>
 
+    <!-- Gesture Tutorial mock conversations -->
+    <dimen name="gesture_tutorial_message_icon_size">44dp</dimen>
+    <dimen name="gesture_tutorial_message_icon_corner_radius">100dp</dimen>
+    <dimen name="gesture_tutorial_message_input_margin_top">36dp</dimen>
+    <dimen name="gesture_tutorial_message_large_margin_bottom">32dp</dimen>
+    <dimen name="gesture_tutorial_message_small_margin_bottom">4dp</dimen>
+    <dimen name="gesture_tutorial_message_padding_start">26dp</dimen>
+    <dimen name="gesture_tutorial_message_padding_end">18dp</dimen>
+    <dimen name="gesture_tutorial_foldable_message_padding_start_end">126dp</dimen>
+
+    <!-- Gesture Tutorial mock conversation lists -->
+    <dimen name="gesture_tutorial_conversation_icon_size">56dp</dimen>
+    <dimen name="gesture_tutorial_conversation_icon_corner_radius">100dp</dimen>
+    <dimen name="gesture_tutorial_conversation_list_padding_top">28dp</dimen>
+    <dimen name="gesture_tutorial_conversation_line_padding_start">20dp</dimen>
+
+    <!-- Gesture Tutorial mock hotseats -->
+    <dimen name="gesture_tutorial_hotseat_icon_size">60dp</dimen>
+    <dimen name="gesture_tutorial_hotseat_icon_corner_radius">100dp</dimen>
+    <dimen name="gesture_tutorial_hotseat_search_height">50dp</dimen>
+    <dimen name="gesture_tutorial_hotseat_search_corner_radius">100dp</dimen>
+    <dimen name="gesture_tutorial_hotseat_icon_search_margin">36dp</dimen>
+
+    <!-- Gesture Tutorial mock webpages -->
+    <dimen name="gesture_tutorial_webpage_padding_top">32dp</dimen>
+    <dimen name="gesture_tutorial_webpage_large_margin_top">24dp</dimen>
+    <dimen name="gesture_tutorial_webpage_small_margin_top">8dp</dimen>
+    <dimen name="gesture_tutorial_webpage_large_corner_radius">22dp</dimen>
+    <dimen name="gesture_tutorial_webpage_medium_corner_radius">8dp</dimen>
+    <dimen name="gesture_tutorial_webpage_small_corner_radius">4dp</dimen>
+    <dimen name="gesture_tutorial_webpage_large_line_height">36dp</dimen>
+    <dimen name="gesture_tutorial_webpage_small_line_height">22dp</dimen>
+
     <!-- All Set page -->
     <dimen name="allset_page_margin_horizontal">40dp</dimen>
     <dimen name="allset_title_margin_top">24dp</dimen>
@@ -165,8 +196,10 @@
     <dimen name="taskbar_icon_drag_icon_size">54dp</dimen>
     <dimen name="taskbar_folder_margin">16dp</dimen>
     <dimen name="taskbar_nav_buttons_spacing">16dp</dimen>
-    <dimen name="taskbar_nav_buttons_size">48dp</dimen>
-    <dimen name="taskbar_contextual_button_margin">16dp</dimen>
+    <dimen name="taskbar_contextual_padding_top">8dp</dimen>
+    <dimen name="taskbar_nav_buttons_size">44dp</dimen>
+    <dimen name="taskbar_contextual_button_margin">40dp</dimen>
+    <dimen name="taskbar_hotseat_nav_spacing">42dp</dimen>
     <dimen name="taskbar_contextual_buttons_size">35dp</dimen>
     <dimen name="taskbar_stashed_size">24dp</dimen>
     <dimen name="taskbar_stashed_handle_width">220dp</dimen>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 52bd48b..6af0d60 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -53,8 +53,6 @@
 
     <!-- Accessibility title for the row of all-apps containing app predictions. [CHAR LIMIT=50] -->
     <string name="title_app_suggestions">App suggestions</string>
-    <!-- Label for the header text of the All Apps section in All Apps view, used to separate Predicted Apps and Actions section from All Apps section. [CHAR_LIMIT=50] -->
-    <string name="all_apps_label">All apps</string>
     <!-- Text of the tip when user lands in all apps view for the first time, indicating where the tip toast points to is the predicted apps section. [CHAR_LIMIT=50] -->
     <string name="all_apps_prediction_tip">Your predicted apps</string>
 
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 088009a..216e79b 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -31,19 +31,14 @@
 import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
 import android.app.ActivityOptions;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
-import android.content.ServiceConnection;
 import android.graphics.Insets;
 import android.hardware.SensorManager;
 import android.hardware.devicestate.DeviceStateManager;
 import android.os.Bundle;
 import android.os.CancellationSignal;
-import android.os.Handler;
-import android.os.IBinder;
-import android.util.Log;
 import android.view.View;
 import android.view.WindowInsets;
 import android.window.SplashScreen;
@@ -76,13 +71,13 @@
 import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TaskUtils;
-import com.android.quickstep.TouchInteractionService;
 import com.android.quickstep.TouchInteractionService.TISBinder;
 import com.android.quickstep.util.LauncherUnfoldAnimationController;
 import com.android.quickstep.util.ProxyScreenStatusProvider;
 import com.android.quickstep.util.RemoteAnimationProvider;
 import com.android.quickstep.util.RemoteFadeOutAnimationListener;
 import com.android.quickstep.util.SplitSelectStateController;
+import com.android.quickstep.util.TISBindHelper;
 import com.android.quickstep.views.OverviewActionsView;
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -103,11 +98,6 @@
 public abstract class BaseQuickstepLauncher extends Launcher
         implements NavigationModeChangeListener {
 
-    private static final long BACKOFF_MILLIS = 1000;
-
-    // Max backoff caps at 5 mins
-    private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000;
-
     private DepthController mDepthController = new DepthController(this);
     private QuickstepTransitionManager mAppTransitionManager;
 
@@ -120,45 +110,12 @@
 
     private OverviewActionsView mActionsView;
 
+    private TISBindHelper mTISBindHelper;
     private @Nullable TaskbarManager mTaskbarManager;
     private @Nullable OverviewCommandHelper mOverviewCommandHelper;
     private @Nullable LauncherTaskbarUIController mTaskbarUIController;
-    private final ServiceConnection mTisBinderConnection = new ServiceConnection() {
-        @Override
-        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
-            if (!(iBinder instanceof TISBinder)) {
-                // Seems like there can be a race condition when user unlocks, which kills the TIS
-                // process and re-starts it. I guess in the meantime service can be connected to
-                // a killed TIS? Either way, unbind and try to re-connect in that case.
-                internalUnbindToTIS();
-                mHandler.postDelayed(mConnectionRunnable, BACKOFF_MILLIS);
-                return;
-            }
 
-            mTaskbarManager = ((TISBinder) iBinder).getTaskbarManager();
-            mTaskbarManager.setLauncher(BaseQuickstepLauncher.this);
-
-            Log.d(TAG, "TIS service connected");
-            resetServiceBindRetryState();
-
-            mOverviewCommandHelper = ((TISBinder) iBinder).getOverviewCommandHelper();
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName componentName) { }
-
-        @Override
-        public void onBindingDied(ComponentName name) {
-            Log.w(TAG, "TIS binding died");
-            internalBindToTIS();
-        }
-    };
-
-    private final Runnable mConnectionRunnable = this::internalBindToTIS;
-    private short mConnectionAttempts;
     private final TaskbarStateHandler mTaskbarStateHandler = new TaskbarStateHandler(this);
-    private final Handler mHandler = new Handler();
-    private boolean mTisServiceBound;
 
     // Will be updated when dragging from taskbar.
     private @Nullable DragOptions mNextWorkspaceDragOptions = null;
@@ -201,11 +158,10 @@
 
         SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this);
 
-        internalUnbindToTIS();
+        mTISBindHelper.onDestroy();
         if (mTaskbarManager != null) {
             mTaskbarManager.clearLauncher(this);
         }
-        resetServiceBindRetryState();
 
         if (mLauncherUnfoldAnimationController != null) {
             mLauncherUnfoldAnimationController.onDestroy();
@@ -357,42 +313,13 @@
         mAppTransitionManager.registerRemoteAnimations();
         mAppTransitionManager.registerRemoteTransitions();
 
-        internalBindToTIS();
+        mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
     }
 
-    /**
-     * Binds {@link #mTisBinderConnection} to {@link TouchInteractionService}. If the binding fails,
-     * attempts to retry via {@link #mConnectionRunnable}.
-     * Unbind via {@link #internalUnbindToTIS()}
-     */
-    private void internalBindToTIS() {
-        mTisServiceBound = bindService(new Intent(this, TouchInteractionService.class),
-                        mTisBinderConnection, 0);
-        if (mTisServiceBound) {
-            resetServiceBindRetryState();
-            return;
-        }
-
-        Log.w(TAG, "Retrying TIS Binder connection attempt: " + mConnectionAttempts);
-        final long timeoutMs = (long) Math.min(
-                Math.scalb(BACKOFF_MILLIS, mConnectionAttempts), MAX_BACKOFF_MILLIS);
-        mHandler.postDelayed(mConnectionRunnable, timeoutMs);
-        mConnectionAttempts++;
-    }
-
-    /** See {@link #internalBindToTIS()} */
-    private void internalUnbindToTIS() {
-        if (mTisServiceBound) {
-            unbindService(mTisBinderConnection);
-            mTisServiceBound = false;
-        }
-    }
-
-    private void resetServiceBindRetryState() {
-        if (mHandler.hasCallbacks(mConnectionRunnable)) {
-            mHandler.removeCallbacks(mConnectionRunnable);
-        }
-        mConnectionAttempts = 0;
+    private void onTISConnected(TISBinder binder) {
+        mTaskbarManager = binder.getTaskbarManager();
+        mTaskbarManager.setLauncher(BaseQuickstepLauncher.this);
+        mOverviewCommandHelper = binder.getOverviewCommandHelper();
     }
 
     private void initUnfoldTransitionProgressProvider() {
diff --git a/quickstep/src/com/android/launcher3/model/AppEventProducer.java b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
index eed493d..b665db6 100644
--- a/quickstep/src/com/android/launcher3/model/AppEventProducer.java
+++ b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
@@ -30,6 +30,7 @@
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_REMOVE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_FOLDER_CREATED;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ONRESUME;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_LEFT;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
@@ -161,6 +162,11 @@
             if (isTrackedForHotseatPrediction(atomInfo)) {
                 sendEvent(atomInfo, ACTION_PIN, CONTAINER_HOTSEAT_PREDICTION);
             }
+        } else if (event == LAUNCHER_ONRESUME) {
+            AppTarget target = new AppTarget.Builder(new AppTargetId("id:launcher"),
+                    mContext.getPackageName(), Process.myUserHandle())
+                    .build();
+            sendEvent(target, atomInfo, ACTION_LAUNCH, CONTAINER_PREDICTION);
         }
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 68dfac7..71a93d1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -16,10 +16,10 @@
 package com.android.launcher3.taskbar;
 
 import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW;
+import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
 import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
 import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
+import static com.android.launcher3.taskbar.TaskbarStashController.TASKBAR_STASH_DURATION;
 import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME;
 
 import android.animation.Animator;
@@ -39,6 +39,7 @@
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatorListeners;
+import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logging.InstanceId;
 import com.android.launcher3.logging.InstanceIdSequence;
@@ -52,11 +53,11 @@
 import com.android.quickstep.RecentsAnimationCallbacks;
 import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
 import com.android.quickstep.RecentsAnimationController;
-import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 
 import java.util.Arrays;
+import java.util.function.Supplier;
 import java.util.stream.Stream;
 
 /**
@@ -65,7 +66,6 @@
 public class LauncherTaskbarUIController extends TaskbarUIController {
 
     private final BaseQuickstepLauncher mLauncher;
-    private final TaskbarStateHandler mTaskbarStateHandler;
 
     private final TaskbarActivityContext mContext;
     private final TaskbarDragLayer mTaskbarDragLayer;
@@ -75,17 +75,64 @@
             new AnimatedFloat(this::onIconAlignmentRatioChanged);
     private final AnimatedFloat mIconAlignmentForGestureState =
             new AnimatedFloat(this::onIconAlignmentRatioChanged);
+    private final AnimatedFloat mIconAlignmentForLauncherState =
+            new AnimatedFloat(this::onIconAlignmentRatioChangedForStateTransition);
 
     private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener =
             this::onStashedInAppChanged;
 
     private final StateManager.StateListener<LauncherState> mStateListener =
             new StateManager.StateListener<LauncherState>() {
+                private Animator mAnimator;
+
+                @Override
+                public void onStateTransitionStart(LauncherState toState) {
+                    // Stash animation from going to launcher should be already handled in
+                    // createAnimToLauncher.
+                    TaskbarStashController controller = mControllers.taskbarStashController;
+                    long duration = TASKBAR_STASH_DURATION;
+                    controller.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
+                            toState.isTaskbarStashed());
+                    Animator stashAnimator = controller.applyStateWithoutStart(duration);
+                    if (stashAnimator != null) {
+                        if (mAnimator != null) {
+                            mAnimator.cancel();
+                        }
+                        PendingAnimation pendingAnimation = new PendingAnimation(duration);
+                        pendingAnimation.add(stashAnimator);
+                        pendingAnimation.setFloat(mIconAlignmentForLauncherState,
+                                AnimatedFloat.VALUE, toState.isTaskbarStashed() ? 0 : 1,
+                                FAST_OUT_SLOW_IN);
+                        pendingAnimation.addListener(new AnimatorListenerAdapter() {
+                            @Override
+                            public void onAnimationStart(Animator animator) {
+                                mTargetStateOverrideForStateTransition = toState;
+                                // Copy hotseat alpha over to taskbar icons
+                                mIconAlphaForHome.setValue(mLauncher.getHotseat().getIconsAlpha());
+                                mLauncher.getHotseat().setIconsAlpha(0);
+                            }
+
+                            @Override
+                            public void onAnimationEnd(Animator animator) {
+                                if (toState.isTaskbarStashed()) {
+                                    // Reset hotseat alpha to default
+                                    mLauncher.getHotseat().setIconsAlpha(1);
+                                }
+                                mTargetStateOverrideForStateTransition = null;
+                                mAnimator = null;
+                            }
+                        });
+                        mAnimator = pendingAnimation.buildAnim();
+                        mAnimator.start();
+                    }
+                }
+
                 @Override
                 public void onStateTransitionComplete(LauncherState finalState) {
                     TaskbarStashController controller = mControllers.taskbarStashController;
                     controller.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
                             finalState.isTaskbarStashed());
+                    controller.applyState();
                 }
             };
 
@@ -99,6 +146,16 @@
     private TaskbarKeyguardController mKeyguardController;
 
     private LauncherState mTargetStateOverride = null;
+    private LauncherState mTargetStateOverrideForStateTransition = null;
+
+    private final DeviceProfile.OnDeviceProfileChangeListener mProfileChangeListener =
+            new DeviceProfile.OnDeviceProfileChangeListener() {
+                @Override
+                public void onDeviceProfileChanged(DeviceProfile dp) {
+                    mControllers.taskbarViewController.onRotationChanged(
+                            mLauncher.getDeviceProfile());
+                }
+            };
 
     public LauncherTaskbarUIController(
             BaseQuickstepLauncher launcher, TaskbarActivityContext context) {
@@ -107,7 +164,6 @@
         mTaskbarView = mTaskbarDragLayer.findViewById(R.id.taskbar_view);
 
         mLauncher = launcher;
-        mTaskbarStateHandler = mLauncher.getTaskbarStateHandler();
     }
 
     @Override
@@ -125,13 +181,14 @@
         mLauncher.setTaskbarUIController(this);
         mKeyguardController = taskbarControllers.taskbarKeyguardController;
 
-        onLauncherResumedOrPaused(mLauncher.hasBeenResumed());
+        onLauncherResumedOrPaused(mLauncher.hasBeenResumed(), true /* fromInit */);
         mIconAlignmentForResumedState.finishAnimation();
         onIconAlignmentRatioChanged();
 
         onStashedInAppChanged(mLauncher.getDeviceProfile());
         mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
         mLauncher.getStateManager().addStateListener(mStateListener);
+        mLauncher.addOnDeviceProfileChangeListener(mProfileChangeListener);
     }
 
     @Override
@@ -139,11 +196,13 @@
         onLauncherResumedOrPaused(false);
         mIconAlignmentForResumedState.finishAnimation();
         mIconAlignmentForGestureState.finishAnimation();
+        mIconAlignmentForLauncherState.finishAnimation();
 
         mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
         mLauncher.getStateManager().removeStateListener(mStateListener);
         mLauncher.getHotseat().setIconsAlpha(1f);
         mLauncher.setTaskbarUIController(null);
+        mLauncher.removeOnDeviceProfileChangeListener(mProfileChangeListener);
     }
 
     @Override
@@ -165,6 +224,10 @@
      * Should be called from onResume() and onPause(), and animates the Taskbar accordingly.
      */
     public void onLauncherResumedOrPaused(boolean isResumed) {
+        onLauncherResumedOrPaused(isResumed, false /* fromInit */);
+    }
+
+    private void onLauncherResumedOrPaused(boolean isResumed, boolean fromInit) {
         if (mKeyguardController.isScreenOff()) {
             if (!isResumed) {
                 return;
@@ -175,6 +238,11 @@
         }
 
         long duration = QuickstepTransitionManager.CONTENT_ALPHA_DURATION;
+        if (fromInit) {
+            // Since we are creating the starting state, we don't have a state to animate from, so
+            // set our state immediately.
+            duration = 0;
+        }
         ObjectAnimator anim = mIconAlignmentForResumedState.animateToValue(
                 getCurrentIconAlignmentRatio(), isResumed ? 1 : 0)
                 .setDuration(duration);
@@ -187,8 +255,6 @@
         TaskbarStashController stashController = mControllers.taskbarStashController;
         stashController.updateStateForFlag(FLAG_IN_APP, !isResumed);
         stashController.applyState(duration);
-        SystemUiProxy.INSTANCE.get(mContext).notifyTaskbarStatus(!isResumed,
-                mControllers.taskbarStashController.isStashedInApp());
     }
 
     /**
@@ -241,25 +307,35 @@
         return Math.max(mIconAlignmentForResumedState.value, mIconAlignmentForGestureState.value);
     }
 
+    private float getCurrentIconAlignmentRatioForLauncherState() {
+        return mIconAlignmentForLauncherState.value;
+    }
+
+    private void onIconAlignmentRatioChangedForStateTransition() {
+        onIconAlignmentRatioChanged(
+                mTargetStateOverrideForStateTransition != null
+                        ? mTargetStateOverrideForStateTransition
+                        : mLauncher.getStateManager().getState(),
+                this::getCurrentIconAlignmentRatioForLauncherState);
+    }
+
     private void onIconAlignmentRatioChanged() {
+        onIconAlignmentRatioChanged(mTargetStateOverride != null ? mTargetStateOverride
+                : mLauncher.getStateManager().getState(), this::getCurrentIconAlignmentRatio);
+    }
+
+    private void onIconAlignmentRatioChanged(LauncherState state,
+            Supplier<Float> alignmentSupplier) {
         if (mControllers == null) {
             return;
         }
-        float alignment = getCurrentIconAlignmentRatio();
+        float alignment = alignmentSupplier.get();
         mControllers.taskbarViewController.setLauncherIconAlignment(
                 alignment, mLauncher.getDeviceProfile());
 
         mTaskbarBackgroundAlpha.updateValue(1 - alignment);
 
-        LauncherState state = mTargetStateOverride != null ? mTargetStateOverride
-                : mLauncher.getStateManager().getState();
-        if ((state.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
-            // If the hotseat icons are visible, then switch taskbar in last frame
-            setTaskbarViewVisible(alignment < 1);
-        } else {
-            mLauncher.getHotseat().setIconsAlpha(1);
-            mIconAlphaForHome.setValue(1 - alignment);
-        }
+        setIconAlpha(state, alignment);
     }
 
     /**
@@ -278,6 +354,15 @@
         return mTaskbarDragLayer;
     }
 
+    private void setIconAlpha(LauncherState state, float progress) {
+        if ((state.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
+            // If the hotseat icons are visible, then switch taskbar in last frame
+            setTaskbarViewVisible(progress < 1);
+        } else {
+            mIconAlphaForHome.setValue(1 - progress);
+        }
+    }
+
     private void setTaskbarViewVisible(boolean isVisible) {
         mIconAlphaForHome.setValue(isVisible ? 1 : 0);
         mLauncher.getHotseat().setIconsAlpha(isVisible ? 0f : 1f);
@@ -286,11 +371,6 @@
     @Override
     protected void onStashedInAppChanged() {
         onStashedInAppChanged(mLauncher.getDeviceProfile());
-        if (mControllers.taskbarStashController.isStashedInApp()) {
-            mContext.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_LONGPRESS_HIDE);
-        } else {
-            mContext.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_LONGPRESS_SHOW);
-        }
     }
 
     private void onStashedInAppChanged(DeviceProfile deviceProfile) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 3f621fd..b768d60 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.taskbar;
 
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y_LONG_CLICK;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK;
@@ -35,12 +36,13 @@
 import android.annotation.DrawableRes;
 import android.annotation.IdRes;
 import android.annotation.LayoutRes;
+import android.content.res.ColorStateList;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.Region.Op;
 import android.graphics.drawable.AnimatedVectorDrawable;
-import android.provider.Settings;
 import android.util.Property;
+import android.view.Gravity;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.View.OnHoverListener;
@@ -56,7 +58,7 @@
 import com.android.launcher3.taskbar.contextual.RotationButton;
 import com.android.launcher3.taskbar.contextual.RotationButtonController;
 import com.android.launcher3.util.MultiValueAlpha;
-import com.android.launcher3.util.SettingsCache;
+import com.android.launcher3.util.Themes;
 import com.android.quickstep.AnimatedFloat;
 
 import java.util.ArrayList;
@@ -94,6 +96,9 @@
     private final ViewGroup mEndContextualContainer;
     private final ViewGroup mStartContextualContainer;
 
+    private final AnimatedFloat mTaskbarNavButtonTranslationY = new AnimatedFloat(
+            this::updateNavButtonTranslationY);
+
     // Initialized in init.
     private TaskbarControllers mControllers;
     private View mA11yButton;
@@ -111,9 +116,10 @@
     /**
      * Initializes the controller
      */
-    public void init(TaskbarControllers controllers) {
+    public void init(TaskbarControllers controllers, TaskbarSharedState sharedState) {
         mControllers = controllers;
         mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize;
+        parseSystemUiFlags(sharedState.sysuiStateFlags);
 
         mA11yLongClickListener = view -> {
             mControllers.navButtonController.onButtonClick(BUTTON_A11Y_LONG_CLICK);
@@ -132,8 +138,7 @@
                 mControllers.navButtonController, R.id.ime_switcher);
         mPropertyHolders.add(new StatePropertyHolder(imeSwitcherButton,
                 flags -> ((flags & MASK_IME_SWITCHER_VISIBLE) == MASK_IME_SWITCHER_VISIBLE)
-                        && ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)
-                        && ((flags & FLAG_A11Y_VISIBLE) == 0)));
+                        && ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)));
 
         mPropertyHolders.add(new StatePropertyHolder(
                 mControllers.taskbarViewController.getTaskbarIconAlpha()
@@ -145,12 +150,32 @@
                 flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0, AnimatedFloat.VALUE, 1, 0));
 
         // Force nav buttons (specifically back button) to be visible during setup wizard.
-        boolean areButtonsForcedVisible = !SettingsCache.INSTANCE.get(mContext).getValue(
-                Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0);
-        if (isThreeButtonNav || areButtonsForcedVisible) {
+        boolean isInSetup = !mContext.isUserSetupComplete();
+        if (isThreeButtonNav || isInSetup) {
             initButtons(mNavButtonContainer, mEndContextualContainer,
                     mControllers.navButtonController);
 
+            if (isInSetup) {
+                // Since setup wizard only has back button enabled, it looks strange to be
+                // end-aligned, so start-align instead.
+                FrameLayout.LayoutParams navButtonsLayoutParams = (FrameLayout.LayoutParams)
+                        mNavButtonContainer.getLayoutParams();
+                navButtonsLayoutParams.setMarginStart(navButtonsLayoutParams.getMarginEnd());
+                navButtonsLayoutParams.setMarginEnd(0);
+                navButtonsLayoutParams.gravity = Gravity.START;
+                mNavButtonContainer.requestLayout();
+
+                if (!isThreeButtonNav) {
+                    // Tint all the nav buttons since there's no taskbar background in SUW.
+                    for (int i = 0; i < mNavButtonContainer.getChildCount(); i++) {
+                        if (!(mNavButtonContainer.getChildAt(i) instanceof ImageView)) continue;
+                        ImageView button = (ImageView) mNavButtonContainer.getChildAt(i);
+                        button.setImageTintList(ColorStateList.valueOf(Themes.getAttrColor(
+                                button.getContext(), android.R.attr.textColorPrimary)));
+                    }
+                }
+            }
+
             // Animate taskbar background when IME shows
             mPropertyHolders.add(new StatePropertyHolder(
                     mControllers.taskbarDragLayerController.getNavbarBackgroundAlpha(),
@@ -194,6 +219,14 @@
                 flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 ||
                         (flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0 ||
                         (flags & FLAG_KEYGUARD_OCCLUDED) != 0));
+        // Translate back button to be at end/start of other buttons for keyguard
+        int navButtonSize = mContext.getResources().getDimensionPixelSize(
+                R.dimen.taskbar_nav_buttons_size);
+        mPropertyHolders.add(new StatePropertyHolder(
+                mBackButton, flags -> (flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0
+                        || (flags & FLAG_KEYGUARD_VISIBLE) != 0,
+                VIEW_TRANSLATE_X, navButtonSize * (isRtl ? -2 : 2), 0));
+
 
         // home and recents buttons
         View homeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, navContainer,
@@ -217,24 +250,16 @@
         mA11yButton.setOnLongClickListener(mA11yLongClickListener);
     }
 
-    public void updateStateForSysuiFlags(int systemUiStateFlags, boolean forceUpdate) {
-        boolean isImeVisible = (systemUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0;
-        boolean isImeSwitcherShowing = (systemUiStateFlags & SYSUI_STATE_IME_SWITCHER_SHOWING) != 0;
-        boolean a11yVisible = (systemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
-        boolean a11yLongClickable =
-                (systemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0;
-        boolean isHomeDisabled =
-                (systemUiStateFlags & SYSUI_STATE_HOME_DISABLED) != 0;
-        boolean isRecentsDisabled =
-                (systemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0;
-        boolean isBackDisabled =
-                (systemUiStateFlags & SYSUI_STATE_BACK_DISABLED) != 0;
+    private void parseSystemUiFlags(int sysUiStateFlags) {
+        mSysuiStateFlags = sysUiStateFlags;
+        boolean isImeVisible = (sysUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0;
+        boolean isImeSwitcherShowing = (sysUiStateFlags & SYSUI_STATE_IME_SWITCHER_SHOWING) != 0;
+        boolean a11yVisible = (sysUiStateFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
+        boolean isHomeDisabled = (sysUiStateFlags & SYSUI_STATE_HOME_DISABLED) != 0;
+        boolean isRecentsDisabled = (sysUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0;
+        boolean isBackDisabled = (sysUiStateFlags & SYSUI_STATE_BACK_DISABLED) != 0;
 
-        if (!forceUpdate && systemUiStateFlags == mSysuiStateFlags) {
-            return;
-        }
-        mSysuiStateFlags = systemUiStateFlags;
-
+        // TODO(b/202218289) we're getting IME as not visible on lockscreen from system
         updateStateForFlag(FLAG_IME_VISIBLE, isImeVisible);
         updateStateForFlag(FLAG_SWITCHER_SUPPORTED, isImeSwitcherShowing);
         updateStateForFlag(FLAG_A11Y_VISIBLE, a11yVisible);
@@ -244,8 +269,17 @@
 
         if (mA11yButton != null) {
             // Only used in 3 button
+            boolean a11yLongClickable =
+                    (sysUiStateFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0;
             mA11yButton.setLongClickable(a11yLongClickable);
         }
+    }
+
+    public void updateStateForSysuiFlags(int systemUiStateFlags) {
+        if (systemUiStateFlags == mSysuiStateFlags) {
+            return;
+        }
+        parseSystemUiFlags(systemUiStateFlags);
         applyState();
     }
 
@@ -275,6 +309,13 @@
     }
 
     /**
+     * Returns true if the home button is disabled
+     */
+    public boolean isHomeDisabled() {
+        return (mState & FLAG_DISABLE_HOME) != 0;
+    }
+
+    /**
      * Returns true if the recents (overview) button is disabled
      */
     public boolean isRecentsDisabled() {
@@ -295,6 +336,11 @@
         }
     }
 
+    /** Use to set the translationY for the all nav+contextual buttons */
+    public AnimatedFloat getTaskbarNavButtonTranslationY() {
+        return mTaskbarNavButtonTranslationY;
+    }
+
     /**
      * Does not call {@link #applyState()}. Don't forget to!
      */
@@ -313,6 +359,10 @@
         }
     }
 
+    private void updateNavButtonTranslationY() {
+        mNavButtonsView.setTranslationY(mTaskbarNavButtonTranslationY.value);
+    }
+
     private ImageView addButton(@DrawableRes int drawableId, @TaskbarButton int buttonType,
             ViewGroup parent, TaskbarNavButtonController navButtonController, @IdRes int id) {
         return addButton(drawableId, buttonType, parent, navButtonController, id,
@@ -337,6 +387,10 @@
         return buttonView;
     }
 
+    public void onDestroy() {
+        mPropertyHolders.clear();
+    }
+
     private class RotationButtonImpl implements RotationButton {
 
         private final ImageView mButton;
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index 10da826..2c80f06 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -30,6 +30,7 @@
 import com.android.launcher3.anim.RevealOutlineAnimation;
 import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
 import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.MultiValueAlpha;
 import com.android.quickstep.AnimatedFloat;
 import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
 
@@ -38,6 +39,10 @@
  */
 public class StashedHandleViewController {
 
+    public static final int ALPHA_INDEX_STASHED = 0;
+    public static final int ALPHA_INDEX_HOME_DISABLED = 1;
+    private static final int NUM_ALPHA_CHANNELS = 2;
+
     /**
      * The SharedPreferences key for whether the stashed handle region is dark.
      */
@@ -50,8 +55,7 @@
     private final int mStashedHandleWidth;
     private final int mStashedHandleHeight;
     private final RegionSamplingHelper mRegionSamplingHelper;
-    private final AnimatedFloat mTaskbarStashedHandleAlpha = new AnimatedFloat(
-            this::updateStashedHandleAlpha);
+    private final MultiValueAlpha mTaskbarStashedHandleAlpha;
     private final AnimatedFloat mTaskbarStashedHandleHintScale = new AnimatedFloat(
             this::updateStashedHandleHintScale);
 
@@ -69,6 +73,8 @@
         mActivity = activity;
         mPrefs = Utilities.getPrefs(mActivity);
         mStashedHandleView = stashedHandleView;
+        mTaskbarStashedHandleAlpha = new MultiValueAlpha(mStashedHandleView, NUM_ALPHA_CHANNELS);
+        mTaskbarStashedHandleAlpha.setUpdateVisibility(true);
         mStashedHandleView.updateHandleColor(
                 mPrefs.getBoolean(SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY, false),
                 false /* animate */);
@@ -96,7 +102,7 @@
         mControllers = controllers;
         mStashedHandleView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
 
-        updateStashedHandleAlpha();
+        mTaskbarStashedHandleAlpha.getProperty(ALPHA_INDEX_STASHED).setValue(0);
         mTaskbarStashedHandleHintScale.updateValue(1f);
 
         final int stashedTaskbarHeight = mControllers.taskbarStashController.getStashedHeight();
@@ -129,7 +135,7 @@
         mRegionSamplingHelper.stopAndDestroy();
     }
 
-    public AnimatedFloat getStashedHandleAlpha() {
+    public MultiValueAlpha getStashedHandleAlpha() {
         return mTaskbarStashedHandleAlpha;
     }
 
@@ -163,12 +169,20 @@
         }
     }
 
-    protected void updateStashedHandleAlpha() {
-        mStashedHandleView.setAlpha(mTaskbarStashedHandleAlpha.value);
-    }
-
     protected void updateStashedHandleHintScale() {
         mStashedHandleView.setScaleX(mTaskbarStashedHandleHintScale.value);
         mStashedHandleView.setScaleY(mTaskbarStashedHandleHintScale.value);
     }
+
+    /**
+     * Should be called when the home button is disabled, so we can hide this handle as well.
+     */
+    public void setIsHomeButtonDisabled(boolean homeDisabled) {
+        mTaskbarStashedHandleAlpha.getProperty(ALPHA_INDEX_HOME_DISABLED).setValue(
+                homeDisabled ? 0 : 1);
+    }
+
+    public boolean isStashedHandleVisible() {
+        return mStashedHandleView.getVisibility() == View.VISIBLE;
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 0316333..f1d7d41 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -35,6 +35,7 @@
 import android.graphics.Rect;
 import android.os.Process;
 import android.os.SystemProperties;
+import android.provider.Settings;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.Display;
@@ -61,12 +62,14 @@
 import com.android.launcher3.taskbar.contextual.RotationButtonController;
 import com.android.launcher3.touch.ItemClickHandler;
 import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.SettingsCache;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.TraceHelper;
 import com.android.launcher3.util.ViewCache;
 import com.android.launcher3.views.ActivityContext;
 import com.android.quickstep.SysUINavigationMode;
 import com.android.quickstep.SysUINavigationMode.Mode;
+import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.ScopedUnfoldTransitionProgressProvider;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -101,6 +104,7 @@
     private final ViewCache mViewCache = new ViewCache();
 
     private final boolean mIsSafeModeEnabled;
+    private final boolean mIsUserSetupComplete;
     private boolean mIsDestroyed = false;
 
     public TaskbarActivityContext(Context windowContext, DeviceProfile dp,
@@ -112,6 +116,8 @@
         mNavMode = SysUINavigationMode.getMode(windowContext);
         mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode",
                 () -> getPackageManager().isSafeMode());
+        mIsUserSetupComplete = SettingsCache.INSTANCE.get(this).getValue(
+                Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0);
 
         float taskbarIconSize = getResources().getDimension(R.dimen.taskbar_icon_size);
         mDeviceProfile.updateIconSize(1, getResources());
@@ -124,6 +130,7 @@
         mDragLayer = (TaskbarDragLayer) mLayoutInflater.inflate(
                 R.layout.taskbar, null, false);
         TaskbarView taskbarView = mDragLayer.findViewById(R.id.taskbar_view);
+        TaskbarScrimView taskbarScrimView = mDragLayer.findViewById(R.id.taskbar_scrim);
         FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view);
         StashedHandleView stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle);
 
@@ -144,6 +151,7 @@
                         R.color.popup_color_primary_light),
                 new TaskbarDragLayerController(this, mDragLayer),
                 new TaskbarViewController(this, taskbarView),
+                new TaskbarScrimViewController(this, taskbarScrimView),
                 new TaskbarUnfoldAnimationController(unfoldTransitionProgressProvider,
                         mWindowManager),
                 new TaskbarKeyguardController(this),
@@ -152,7 +160,7 @@
                 new TaskbarEduController(this));
     }
 
-    public void init() {
+    public void init(TaskbarSharedState sharedState) {
         mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight();
         mWindowLayoutParams = new WindowManager.LayoutParams(
                 MATCH_PARENT,
@@ -181,7 +189,7 @@
                 getDefaultTaskbarWindowHeight() - mDeviceProfile.taskbarSize, 0, 0);
 
         // Initialize controllers after all are constructed.
-        mControllers.init();
+        mControllers.init(sharedState);
 
         mWindowManager.addView(mDragLayer, mWindowLayoutParams);
     }
@@ -300,6 +308,13 @@
     }
 
     /**
+     * Sets the flag indicating setup UI is visible
+     */
+    public void setSetupUIVisible(boolean isVisible) {
+        mControllers.taskbarStashController.setSetupUIVisible(isVisible);
+    }
+
+    /**
      * Called when this instance of taskbar is no longer needed
      */
     public void onDestroy() {
@@ -309,9 +324,8 @@
         mWindowManager.removeViewImmediate(mDragLayer);
     }
 
-    public void updateSysuiStateFlags(int systemUiStateFlags, boolean forceUpdate) {
-        mControllers.navbarButtonsViewController.updateStateForSysuiFlags(
-                systemUiStateFlags, forceUpdate);
+    public void updateSysuiStateFlags(int systemUiStateFlags) {
+        mControllers.navbarButtonsViewController.updateStateForSysuiFlags(systemUiStateFlags);
         mControllers.taskbarViewController.setImeIsVisible(
                 mControllers.navbarButtonsViewController.isImeVisible());
         boolean panelExpanded = (systemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
@@ -320,7 +334,11 @@
                 panelExpanded || inSettings);
         mControllers.taskbarViewController.setRecentsButtonDisabled(
                 mControllers.navbarButtonsViewController.isRecentsDisabled());
+        mControllers.stashedHandleViewController.setIsHomeButtonDisabled(
+                mControllers.navbarButtonsViewController.isHomeDisabled());
         mControllers.taskbarKeyguardController.updateStateForSysuiFlags(systemUiStateFlags);
+        mControllers.taskbarStashController.updateStateForSysuiFlags(systemUiStateFlags);
+        mControllers.taskbarScrimViewController.updateStateForSysuiFlags(systemUiStateFlags);
     }
 
     public void onRotationProposal(int rotation, boolean isValid) {
@@ -342,6 +360,7 @@
      * Updates the TaskbarContainer to MATCH_PARENT vs original Taskbar size.
      */
     public void setTaskbarWindowFullscreen(boolean fullscreen) {
+        SystemUiProxy.INSTANCE.getNoCreate().notifyTaskbarAutohideSuspend(fullscreen);
         mIsFullscreen = fullscreen;
         setTaskbarWindowHeight(fullscreen ? MATCH_PARENT : mLastRequestedNonFullscreenHeight);
     }
@@ -459,4 +478,8 @@
     public void startTaskbarUnstashHint(boolean animateForward) {
         mControllers.taskbarStashController.startUnstashHint(animateForward);
     }
+
+    protected boolean isUserSetupComplete() {
+        return mIsUserSetupComplete;
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 6144881..8684c29 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -30,6 +30,7 @@
     public final NavbarButtonsViewController navbarButtonsViewController;
     public final RotationButtonController rotationButtonController;
     public final TaskbarDragLayerController taskbarDragLayerController;
+    public final TaskbarScrimViewController taskbarScrimViewController;
     public final TaskbarViewController taskbarViewController;
     public final TaskbarUnfoldAnimationController taskbarUnfoldAnimationController;
     public final TaskbarKeyguardController taskbarKeyguardController;
@@ -47,6 +48,7 @@
             RotationButtonController rotationButtonController,
             TaskbarDragLayerController taskbarDragLayerController,
             TaskbarViewController taskbarViewController,
+            TaskbarScrimViewController taskbarScrimViewController,
             TaskbarUnfoldAnimationController taskbarUnfoldAnimationController,
             TaskbarKeyguardController taskbarKeyguardController,
             StashedHandleViewController stashedHandleViewController,
@@ -59,6 +61,7 @@
         this.rotationButtonController = rotationButtonController;
         this.taskbarDragLayerController = taskbarDragLayerController;
         this.taskbarViewController = taskbarViewController;
+        this.taskbarScrimViewController = taskbarScrimViewController;
         this.taskbarUnfoldAnimationController = taskbarUnfoldAnimationController;
         this.taskbarKeyguardController = taskbarKeyguardController;
         this.stashedHandleViewController = stashedHandleViewController;
@@ -71,17 +74,18 @@
      * TaskbarControllers instance, but should be careful to only access things that were created
      * in constructors for now, as some controllers may still be waiting for init().
      */
-    public void init() {
-        navbarButtonsViewController.init(this);
+    public void init(TaskbarSharedState sharedState) {
+        navbarButtonsViewController.init(this, sharedState);
         if (taskbarActivityContext.isThreeButtonNav()) {
             rotationButtonController.init();
         }
         taskbarDragLayerController.init(this);
         taskbarViewController.init(this);
+        taskbarScrimViewController.init(this);
         taskbarUnfoldAnimationController.init(this);
         taskbarKeyguardController.init(navbarButtonsViewController);
         stashedHandleViewController.init(this);
-        taskbarStashController.init(this);
+        taskbarStashController.init(this, sharedState);
         taskbarEduController.init(this);
     }
 
@@ -89,6 +93,7 @@
      * Cleans up all controllers.
      */
     public void onDestroy() {
+        navbarButtonsViewController.onDestroy();
         uiController.onDestroy();
         rotationButtonController.onDestroy();
         taskbarDragLayerController.onDestroy();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 2e9d8bc..63d07f3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -76,7 +76,7 @@
      * Cache a copy here so we can initialize state whenever taskbar is recreated, since
      * this class does not get re-initialized w/ new taskbars.
      */
-    private int mSysuiStateFlags;
+    private final TaskbarSharedState mSharedState = new TaskbarSharedState();
 
     private static final int CHANGE_FLAGS =
             CHANGE_ACTIVE_SCREEN | CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS;
@@ -96,7 +96,10 @@
 
             @Override
             public void onConfigurationChanged(Configuration newConfig) {
-                if ((mOldConfig.diff(newConfig) & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
+                int configDiff = mOldConfig.diff(newConfig);
+                int configsRequiringRecreate = ActivityInfo.CONFIG_ASSETS_PATHS
+                        | ActivityInfo.CONFIG_LAYOUT_DIRECTION;
+                if ((configDiff & configsRequiringRecreate) != 0) {
                     // Color has changed, recreate taskbar to reload background color & icons.
                     recreateTaskbar();
                 }
@@ -189,22 +192,27 @@
 
         mTaskbarActivityContext = new TaskbarActivityContext(mContext, dp.copy(mContext),
                 mNavButtonController, mUnfoldProgressProvider);
-        mTaskbarActivityContext.init();
+        mTaskbarActivityContext.init(mSharedState);
         if (mLauncher != null) {
             mTaskbarActivityContext.setUIController(
                     new LauncherTaskbarUIController(mLauncher, mTaskbarActivityContext));
         }
-        onSysuiFlagsChangedInternal(mSysuiStateFlags, true /* forceUpdate */);
     }
 
     public void onSystemUiFlagsChanged(int systemUiStateFlags) {
-        onSysuiFlagsChangedInternal(systemUiStateFlags, false /* forceUpdate */);
+        mSharedState.sysuiStateFlags = systemUiStateFlags;
+        if (mTaskbarActivityContext != null) {
+            mTaskbarActivityContext.updateSysuiStateFlags(systemUiStateFlags);
+        }
     }
 
-    private void onSysuiFlagsChangedInternal(int systemUiStateFlags, boolean forceUpdate) {
-        mSysuiStateFlags = systemUiStateFlags;
+    /**
+     * Sets the flag indicating setup UI is visible
+     */
+    public void setSetupUIVisible(boolean isVisible) {
+        mSharedState.setupUIVisible = isVisible;
         if (mTaskbarActivityContext != null) {
-            mTaskbarActivityContext.updateSysuiStateFlags(systemUiStateFlags, forceUpdate);
+            mTaskbarActivityContext.setSetupUIVisible(isVisible);
         }
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
index fc5abd0..5e76b96 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
@@ -45,6 +45,9 @@
     private final TaskbarActivityContext mContext;
     private final TaskbarView mContainer;
 
+    // Initialized in init.
+    private TaskbarControllers mControllers;
+
     private boolean mBindInProgress = false;
 
     public TaskbarModelCallbacks(
@@ -53,6 +56,10 @@
         mContainer = container;
     }
 
+    public void init(TaskbarControllers controllers) {
+        mControllers = controllers;
+    }
+
     @Override
     public void startBinding() {
         mBindInProgress = true;
@@ -161,6 +168,7 @@
         int predictionSize = mPredictedItems.size();
         int predictionNextIndex = 0;
 
+        boolean isHotseatEmpty = true;
         for (int i = 0; i < hotseatItemInfos.length; i++) {
             hotseatItemInfos[i] = mHotseatItems.get(i);
             if (hotseatItemInfos[i] == null && predictionNextIndex < predictionSize) {
@@ -168,7 +176,14 @@
                 hotseatItemInfos[i].screenId = i;
                 predictionNextIndex++;
             }
+            if (hotseatItemInfos[i] != null) {
+                isHotseatEmpty = false;
+            }
         }
         mContainer.updateHotseatItems(hotseatItemInfos);
+
+        mControllers.taskbarStashController.updateStateForFlag(
+                TaskbarStashController.FLAG_STASHED_IN_APP_EMPTY, isHotseatEmpty);
+        mControllers.taskbarStashController.applyState();
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
new file mode 100644
index 0000000..94a3307
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * View that handles scrimming the taskbar and the inverted corners it draws. The scrim is used
+ * when bubbles is expanded.
+ */
+public class TaskbarScrimView extends View {
+    private final Paint mTaskbarScrimPaint;
+    private final Path mInvertedLeftCornerPath, mInvertedRightCornerPath;
+
+    private boolean mShowScrim;
+    private float mLeftCornerRadius, mRightCornerRadius;
+    private float mBackgroundHeight;
+
+    public TaskbarScrimView(Context context) {
+        this(context, null);
+    }
+
+    public TaskbarScrimView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public TaskbarScrimView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public TaskbarScrimView(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        mTaskbarScrimPaint = new Paint();
+        mTaskbarScrimPaint.setColor(getResources().getColor(android.R.color.system_neutral1_1000));
+        mTaskbarScrimPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
+        mTaskbarScrimPaint.setStyle(Paint.Style.FILL);
+
+        mInvertedLeftCornerPath = new Path();
+        mInvertedRightCornerPath = new Path();
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+
+        if (mShowScrim) {
+            canvas.save();
+            canvas.translate(0, canvas.getHeight() - mBackgroundHeight);
+
+            // Scrim the taskbar itself.
+            canvas.drawRect(0, 0, canvas.getWidth(), mBackgroundHeight, mTaskbarScrimPaint);
+
+            // Scrim the inverted rounded corners above the taskbar.
+            canvas.translate(0, -mLeftCornerRadius);
+            canvas.drawPath(mInvertedLeftCornerPath, mTaskbarScrimPaint);
+            canvas.translate(0, mLeftCornerRadius);
+            canvas.translate(canvas.getWidth() - mRightCornerRadius, -mRightCornerRadius);
+            canvas.drawPath(mInvertedRightCornerPath, mTaskbarScrimPaint);
+
+            canvas.restore();
+        }
+    }
+
+    /**
+     * Sets the height of the taskbar background.
+     * @param height the height of the background.
+     */
+    protected void setBackgroundHeight(float height) {
+        mBackgroundHeight = height;
+        if (mShowScrim) {
+            invalidate();
+        }
+    }
+
+    /**
+     * Sets the alpha of the taskbar scrim.
+     * @param alpha the alpha of the scrim.
+     */
+    protected void setScrimAlpha(float alpha) {
+        mShowScrim = alpha > 0f;
+        mTaskbarScrimPaint.setAlpha((int) (alpha * 255));
+        invalidate();
+    }
+
+    /**
+     * Sets the radius of the left and right corners above the taskbar.
+     * @param leftCornerRadius the radius of the left corner.
+     * @param rightCornerRadius the radius of the right corner.
+     */
+    protected void setCornerSizes(float leftCornerRadius, float rightCornerRadius) {
+        mLeftCornerRadius = leftCornerRadius;
+        mRightCornerRadius = rightCornerRadius;
+
+        Path square = new Path();
+        square.addRect(0, 0, mLeftCornerRadius, mLeftCornerRadius, Path.Direction.CW);
+        Path circle = new Path();
+        circle.addCircle(mLeftCornerRadius, 0, mLeftCornerRadius, Path.Direction.CW);
+        mInvertedLeftCornerPath.op(square, circle, Path.Op.DIFFERENCE);
+        square.reset();
+        square.addRect(0, 0, mRightCornerRadius, mRightCornerRadius, Path.Direction.CW);
+        circle.reset();
+        circle.addCircle(0, 0, mRightCornerRadius, Path.Direction.CW);
+        mInvertedRightCornerPath.op(square, circle, Path.Op.DIFFERENCE);
+
+        if (mShowScrim) {
+            invalidate();
+        }
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
new file mode 100644
index 0000000..e7e55ef
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar;
+
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED;
+
+import android.animation.ObjectAnimator;
+import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
+
+import com.android.quickstep.AnimatedFloat;
+import com.android.quickstep.SystemUiProxy;
+
+/**
+ * Handles properties/data collection, and passes the results to {@link TaskbarScrimView} to render.
+ */
+public class TaskbarScrimViewController {
+
+    private static final float SCRIM_ALPHA = 0.6f;
+
+    private static final Interpolator SCRIM_ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
+    private static final Interpolator SCRIM_ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
+
+    private final TaskbarActivityContext mActivity;
+    private final TaskbarScrimView mScrimView;
+
+    // Alpha property for the scrim.
+    private final AnimatedFloat mScrimAlpha = new AnimatedFloat(this::updateScrimAlpha);
+
+    // Initialized in init.
+    private TaskbarControllers mControllers;
+
+    public TaskbarScrimViewController(TaskbarActivityContext activity, TaskbarScrimView scrimView) {
+        mActivity = activity;
+        mScrimView = scrimView;
+        mScrimView.setCornerSizes(mActivity.getLeftCornerRadius(),
+                mActivity.getRightCornerRadius());
+        mScrimView.setBackgroundHeight(mActivity.getDeviceProfile().taskbarSize);
+    }
+
+    /**
+     * Initializes the controller
+     */
+    public void init(TaskbarControllers controllers) {
+        mControllers = controllers;
+    }
+
+    /**
+     * Updates the scrim state based on the flags.
+     */
+    public void updateStateForSysuiFlags(int stateFlags) {
+        final boolean bubblesExpanded = (stateFlags & SYSUI_STATE_BUBBLES_EXPANDED) != 0;
+        final boolean manageMenuExpanded =
+                (stateFlags & SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED) != 0;
+        final boolean showScrim = !mControllers.navbarButtonsViewController.isImeVisible()
+                && bubblesExpanded && mControllers.taskbarStashController.isInAppAndNotStashed();
+        final float scrimAlpha = manageMenuExpanded
+                // When manage menu shows there's the first scrim and second scrim so figure out
+                // what the total transparency would be.
+                ? (SCRIM_ALPHA + (SCRIM_ALPHA * (1 - SCRIM_ALPHA)))
+                : showScrim ? SCRIM_ALPHA : 0;
+        showScrim(showScrim, scrimAlpha);
+    }
+
+    private void showScrim(boolean showScrim, float alpha) {
+        mScrimView.setOnClickListener(showScrim ? (view) -> onClick() : null);
+        mScrimView.setClickable(showScrim);
+        ObjectAnimator anim = mScrimAlpha.animateToValue(showScrim ? alpha : 0);
+        anim.setInterpolator(showScrim ? SCRIM_ALPHA_IN : SCRIM_ALPHA_OUT);
+        anim.start();
+    }
+
+    private void updateScrimAlpha() {
+        mScrimView.setScrimAlpha(mScrimAlpha.value);
+    }
+
+    private void onClick() {
+        SystemUiProxy.INSTANCE.get(mActivity).onBackPressed();
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
new file mode 100644
index 0000000..23beef0
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar;
+
+/**
+ * State shared across different taskbar instance
+ */
+public class TaskbarSharedState {
+
+    public int sysuiStateFlags;
+
+    public boolean setupUIVisible = false;
+
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 02170ab..0dd4ef1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -17,6 +17,10 @@
 
 import static android.view.HapticFeedbackConstants.LONG_PRESS;
 
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -40,13 +44,20 @@
 public class TaskbarStashController {
 
     public static final int FLAG_IN_APP = 1 << 0;
-    public static final int FLAG_STASHED_IN_APP = 1 << 1;
-    public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 2;
+    public static final int FLAG_STASHED_IN_APP_MANUAL = 1 << 1; // long press, persisted
+    public static final int FLAG_STASHED_IN_APP_PINNED = 1 << 2; // app pinning
+    public static final int FLAG_STASHED_IN_APP_EMPTY = 1 << 3; // no hotseat icons
+    public static final int FLAG_STASHED_IN_APP_SETUP = 1 << 4; // setup wizard and AllSetActivity
+    public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 5;
+
+    // If we're in an app and any of these flags are enabled, taskbar should be stashed.
+    public static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL
+            | FLAG_STASHED_IN_APP_PINNED | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP;
 
     /**
      * How long to stash/unstash when manually invoked via long press.
      */
-    private static final long TASKBAR_STASH_DURATION = 300;
+    public static final long TASKBAR_STASH_DURATION = 300;
 
     /**
      * The scale TaskbarView animates to when being stashed.
@@ -93,11 +104,9 @@
     private AnimatedFloat mIconScaleForStash;
     private AnimatedFloat mIconTranslationYForStash;
     // Stashed handle properties.
-    private AnimatedFloat mTaskbarStashedHandleAlpha;
+    private AlphaProperty mTaskbarStashedHandleAlpha;
     private AnimatedFloat mTaskbarStashedHandleHintScale;
 
-    /** Whether the user has manually invoked taskbar stashing, which we persist. */
-    private boolean mIsStashedInApp;
     /** Whether we are currently visually stashed (might change based on launcher state). */
     private boolean mIsStashed = false;
     private int mState;
@@ -107,12 +116,9 @@
     // Evaluate whether the handle should be stashed
     private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder(
             flags -> {
-                if (!supportsVisualStashing()) {
-                    return false;
-                }
-                boolean inApp = (flags & FLAG_IN_APP) != 0;
-                boolean stashedInApp = (flags & FLAG_STASHED_IN_APP) != 0;
-                boolean stashedLauncherState = (flags & FLAG_IN_STASHED_LAUNCHER_STATE) != 0;
+                boolean inApp = hasAnyFlag(flags, FLAG_IN_APP);
+                boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP);
+                boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE);
                 return (inApp && stashedInApp) || (!inApp && stashedLauncherState);
             });
 
@@ -124,7 +130,7 @@
         mUnstashedHeight = mActivity.getDeviceProfile().taskbarSize;
     }
 
-    public void init(TaskbarControllers controllers) {
+    public void init(TaskbarControllers controllers, TaskbarSharedState sharedState) {
         mControllers = controllers;
 
         TaskbarDragLayerController dragLayerController = controllers.taskbarDragLayerController;
@@ -138,15 +144,19 @@
 
         StashedHandleViewController stashedHandleController =
                 controllers.stashedHandleViewController;
-        mTaskbarStashedHandleAlpha = stashedHandleController.getStashedHandleAlpha();
+        mTaskbarStashedHandleAlpha = stashedHandleController.getStashedHandleAlpha().getProperty(
+                StashedHandleViewController.ALPHA_INDEX_STASHED);
         mTaskbarStashedHandleHintScale = stashedHandleController.getStashedHandleHintScale();
 
-        mIsStashedInApp = supportsManualStashing()
+        boolean isManuallyStashedInApp = supportsManualStashing()
                 && mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF);
-        updateStateForFlag(FLAG_STASHED_IN_APP, mIsStashedInApp);
+        updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp);
+        updateStateForFlag(FLAG_STASHED_IN_APP_SETUP,
+                !mActivity.isUserSetupComplete() || sharedState.setupUIVisible);
+        applyState();
 
         SystemUiProxy.INSTANCE.get(mActivity)
-                .notifyTaskbarStatus(/* visible */ true, /* stashed */ mIsStashedInApp);
+                .notifyTaskbarStatus(/* visible */ false, /* stashed */ isStashedInApp());
     }
 
     /**
@@ -171,6 +181,15 @@
     }
 
     /**
+     * Sets the flag indicating setup UI is visible
+     */
+    protected void setSetupUIVisible(boolean isVisible) {
+        updateStateForFlag(FLAG_STASHED_IN_APP_SETUP,
+                isVisible || !mActivity.isUserSetupComplete());
+        applyState();
+    }
+
+    /**
      * Returns whether the taskbar is currently visually stashed.
      */
     public boolean isStashed() {
@@ -178,14 +197,35 @@
     }
 
     /**
-     * Returns whether the user has manually stashed the taskbar in apps.
+     * Returns whether the taskbar should be stashed in apps (e.g. user long pressed to stash).
      */
     public boolean isStashedInApp() {
-        return mIsStashedInApp;
+        return hasAnyFlag(FLAGS_STASHED_IN_APP);
+    }
+
+    private boolean hasAnyFlag(int flagMask) {
+        return hasAnyFlag(mState, flagMask);
+    }
+
+    private boolean hasAnyFlag(int flags, int flagMask) {
+        return (flags & flagMask) != 0;
+    }
+
+
+    /**
+     * Returns whether the taskbar is currently visible and in an app.
+     */
+    public boolean isInAppAndNotStashed() {
+        return !mIsStashed && (mState & FLAG_IN_APP) != 0;
     }
 
     public int getContentHeight() {
-        return isStashed() ? mStashedHeight : mUnstashedHeight;
+        if (isStashed()) {
+            boolean isAnimating = mAnimator != null && mAnimator.isStarted();
+            return mControllers.stashedHandleViewController.isStashedHandleVisible() || isAnimating
+                    ? mStashedHeight : 0;
+        }
+        return mUnstashedHeight;
     }
 
     public int getStashedHeight() {
@@ -202,7 +242,7 @@
             // taskbar, we use an OnLongClickListener on TaskbarView instead.
             return false;
         }
-        if (updateAndAnimateIsStashedInApp(false)) {
+        if (updateAndAnimateIsManuallyStashedInApp(false)) {
             mControllers.taskbarActivityContext.getDragLayer().performHapticFeedback(LONG_PRESS);
             return true;
         }
@@ -213,25 +253,37 @@
      * Updates whether we should stash the taskbar when in apps, and animates to the changed state.
      * @return Whether we started an animation to either be newly stashed or unstashed.
      */
-    public boolean updateAndAnimateIsStashedInApp(boolean isStashedInApp) {
+    public boolean updateAndAnimateIsManuallyStashedInApp(boolean isManuallyStashedInApp) {
         if (!supportsManualStashing()) {
             return false;
         }
-        if (mIsStashedInApp != isStashedInApp) {
-            mIsStashedInApp = isStashedInApp;
-            mPrefs.edit().putBoolean(SHARED_PREFS_STASHED_KEY, mIsStashedInApp).apply();
-            updateStateForFlag(FLAG_STASHED_IN_APP, mIsStashedInApp);
+        if (hasAnyFlag(FLAG_STASHED_IN_APP_MANUAL) != isManuallyStashedInApp) {
+            mPrefs.edit().putBoolean(SHARED_PREFS_STASHED_KEY, isManuallyStashedInApp).apply();
+            updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp);
             applyState();
-
-            SystemUiProxy.INSTANCE.get(mActivity)
-                    .notifyTaskbarStatus(/* visible */ true, /* stashed */ mIsStashedInApp);
-            mControllers.uiController.onStashedInAppChanged();
             return true;
         }
         return false;
     }
 
-    private Animator createAnimToIsStashed(boolean isStashed, long duration) {
+    /**
+     * 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
+     */
+    private void createAnimToIsStashed(boolean isStashed, long duration) {
+        if (mAnimator != null) {
+            mAnimator.cancel();
+        }
+        mAnimator = new AnimatorSet();
+
+        if (!supportsVisualStashing()) {
+            // Just hide/show the icons instead of stashing into a handle.
+            mAnimator.play(mIconAlphaForStash.animateToValue(isStashed ? 0 : 1)
+                    .setDuration(duration));
+            return;
+        }
+
         AnimatorSet fullLengthAnimatorSet = new AnimatorSet();
         // Not exactly half and may overlap. See [first|second]HalfDurationScale below.
         AnimatorSet firstHalfAnimatorSet = new AnimatorSet();
@@ -287,10 +339,6 @@
         secondHalfAnimatorSet.setDuration((long) (duration * secondHalfDurationScale));
         secondHalfAnimatorSet.setStartDelay((long) (duration * (1 - secondHalfDurationScale)));
 
-        if (mAnimator != null) {
-            mAnimator.cancel();
-        }
-        mAnimator = new AnimatorSet();
         mAnimator.playTogether(fullLengthAnimatorSet, firstHalfAnimatorSet,
                 secondHalfAnimatorSet);
         mAnimator.addListener(new AnimatorListenerAdapter() {
@@ -305,7 +353,6 @@
                 mAnimator = null;
             }
         });
-        return mAnimator;
     }
 
     /**
@@ -360,6 +407,13 @@
         return mStatePropertyHolder.setState(mState, duration, false);
     }
 
+    /** Called when some system ui state has changed. (See SYSUI_STATE_... in QuickstepContract) */
+    public void updateStateForSysuiFlags(int systemUiStateFlags) {
+        updateStateForFlag(FLAG_STASHED_IN_APP_PINNED,
+                hasAnyFlag(systemUiStateFlags, SYSUI_STATE_SCREEN_PINNING));
+        applyState();
+    }
+
     /**
      * Updates the proper flag to indicate whether the task bar should be stashed.
      *
@@ -377,25 +431,54 @@
         }
     }
 
+    /**
+     * Called after updateStateForFlag() and applyState() have been called.
+     * @param changedFlags The flags that have changed.
+     */
+    private void onStateChangeApplied(int changedFlags) {
+        if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP)) {
+            mControllers.uiController.onStashedInAppChanged();
+        }
+        if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP | FLAG_IN_APP)) {
+            SystemUiProxy.INSTANCE.get(mActivity)
+                    .notifyTaskbarStatus(/* visible */ hasAnyFlag(FLAG_IN_APP),
+                            /* stashed */ isStashedInApp());
+        }
+        if (hasAnyFlag(changedFlags, FLAG_STASHED_IN_APP_MANUAL)) {
+            if (hasAnyFlag(FLAG_STASHED_IN_APP_MANUAL)) {
+                mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_LONGPRESS_HIDE);
+            } else {
+                mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_LONGPRESS_SHOW);
+            }
+        }
+    }
+
     private class StatePropertyHolder {
         private final IntPredicate mStashCondition;
 
         private boolean mIsStashed;
+        private int mPrevFlags;
 
         StatePropertyHolder(IntPredicate stashCondition) {
             mStashCondition = stashCondition;
         }
 
         public Animator setState(int flags, long duration, boolean start) {
+            if (mPrevFlags != flags) {
+                int changedFlags = mPrevFlags ^ flags;
+                onStateChangeApplied(changedFlags);
+                mPrevFlags = flags;
+            }
             boolean isStashed = mStashCondition.test(flags);
             if (mIsStashed != isStashed) {
                 mIsStashed = isStashed;
-                Animator animator = createAnimToIsStashed(mIsStashed, duration);
+                createAnimToIsStashed(mIsStashed, duration);
                 if (start) {
-                    animator.start();
+                    mAnimator.start();
                 }
+                return mAnimator;
             }
-            return mAnimator;
+            return null;
         }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 4cd6814..d14622b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -60,6 +60,7 @@
             this::updateTranslationY);
     private final AnimatedFloat mTaskbarIconTranslationYForStash = new AnimatedFloat(
             this::updateTranslationY);
+    private AnimatedFloat mTaskbarNavButtonTranslationY;
 
     private final TaskbarModelCallbacks mModelCallbacks;
 
@@ -85,7 +86,14 @@
         mTaskbarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
 
         mTaskbarIconScaleForStash.updateValue(1f);
-        LauncherAppState.getInstance(mActivity).getModel().addCallbacksAndLoad(mModelCallbacks);
+
+        mModelCallbacks.init(controllers);
+        if (mActivity.isUserSetupComplete()) {
+            // Only load the callbacks if user setup is completed
+            LauncherAppState.getInstance(mActivity).getModel().addCallbacksAndLoad(mModelCallbacks);
+        }
+        mTaskbarNavButtonTranslationY =
+                controllers.navbarButtonsViewController.getTaskbarNavButtonTranslationY();
     }
 
     public void onDestroy() {
@@ -212,6 +220,7 @@
 
         int offsetY = launcherDp.getTaskbarOffsetY();
         setter.setFloat(mTaskbarIconTranslationYForHome, VALUE, -offsetY, LINEAR);
+        setter.setFloat(mTaskbarNavButtonTranslationY, VALUE, -offsetY, LINEAR);
 
         int collapsedHeight = mActivity.getDefaultTaskbarWindowHeight();
         int expandedHeight = Math.max(collapsedHeight,
@@ -236,6 +245,14 @@
         return controller;
     }
 
+    public void onRotationChanged(DeviceProfile deviceProfile) {
+        if (areIconsVisible()) {
+            // We only translate on rotation when on home
+            return;
+        }
+        mTaskbarNavButtonTranslationY.updateValue(-deviceProfile.getTaskbarOffsetY());
+    }
+
     /**
      * Callbacks for {@link TaskbarView} to interact with its controller.
      */
@@ -254,7 +271,8 @@
         }
 
         public View.OnLongClickListener getBackgroundOnLongClickListener() {
-            return view -> mControllers.taskbarStashController.updateAndAnimateIsStashedInApp(true);
+            return view -> mControllers.taskbarStashController
+                    .updateAndAnimateIsManuallyStashedInApp(true);
         }
 
         /**
diff --git a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
index c9909cc..aa26645 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -57,13 +57,13 @@
         if (SysUINavigationMode.INSTANCE.get(context).getMode() == Mode.THREE_BUTTONS) {
             Resources res = context.getResources();
             /*
-            * 2 (left + right) x Padding +
             * 3 nav buttons +
-            * Little space at the end for contextual buttons
+            * Little space at the end for contextual buttons +
+            * Little space between icons and nav buttons
             */
-            return 2 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_spacing)
-                    + 3 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
-                    + res.getDimensionPixelSize(R.dimen.taskbar_contextual_button_margin);
+            return 3 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
+                    + res.getDimensionPixelSize(R.dimen.taskbar_contextual_button_margin)
+                    + res.getDimensionPixelSize(R.dimen.taskbar_hotseat_nav_spacing);
         } else {
             return 0;
         }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index d74b6c5..2fa8b07 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3.uioverrides;
 
+import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
 import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
 import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
 import static com.android.launcher3.anim.Interpolators.INSTANT;
@@ -72,6 +73,8 @@
         getTaskModalnessProperty().set(mRecentsView, state.getOverviewModalness());
         RECENTS_GRID_PROGRESS.set(mRecentsView,
                 state.displayOverviewTasksAsGrid(mLauncher.getDeviceProfile()) ? 1f : 0f);
+
+        applySplitScrollOffset(state);
     }
 
     @Override
@@ -117,6 +120,16 @@
         boolean showAsGrid = toState.displayOverviewTasksAsGrid(mLauncher.getDeviceProfile());
         setter.setFloat(mRecentsView, RECENTS_GRID_PROGRESS, showAsGrid ? 1f : 0f,
                 showAsGrid ? INSTANT : FINAL_FRAME);
+
+        applySplitScrollOffset(toState);
+    }
+
+    private void applySplitScrollOffset(@NonNull final LauncherState state) {
+        if (state == OVERVIEW_SPLIT_SELECT) {
+            mRecentsView.applySplitPrimaryScrollOffset();
+        } else {
+            mRecentsView.resetSplitPrimaryScrollOffset();
+        }
     }
 
     abstract FloatProperty getTaskModalnessProperty();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index f8c9fd1..c554fd0 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -69,6 +69,11 @@
     }
 
     @Override
+    public boolean isTaskbarStashed() {
+        return true;
+    }
+
+    @Override
     protected float getDepthUnchecked(Context context) {
         // The scrim fades in at approximately 50% of the swipe gesture.
         // This means that the depth should be greater than 1, in order to fully zoom out.
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index 37a1674..308bca6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -179,7 +179,7 @@
                         mAllowGoingDown = i == mRecentsView.getCurrentPage()
                                 && SysUINavigationMode.getMode(mActivity).hasGestures
                                 && (!mRecentsView.showAsGrid() || mTaskBeingDragged.isFocusedTask())
-                                && mRecentsView.isTaskSnapped(i);
+                                && mRecentsView.isTaskInExpectedScrollPosition(i);
 
                         directionsToDetectScroll = mAllowGoingDown ? DIRECTION_BOTH : upDirection;
                         break;
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 3aeab7b..3ab73bb 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -271,7 +271,9 @@
         mActivityInterface = gestureState.getActivityInterface();
         mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit);
         mInputConsumerProxy =
-                new InputConsumerProxy(inputConsumer, () -> {
+                new InputConsumerProxy(context,
+                        () -> mRecentsView.getPagedViewOrientedState().getRecentsActivityRotation(),
+                        inputConsumer, () -> {
                     endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */);
                     endLauncherTransitionController();
                 }, new InputProxyHandlerFactory(mActivityInterface, mGestureState));
@@ -1049,6 +1051,7 @@
                 isFling, isCancel);
         // Set the state, but don't notify until the animation completes
         mGestureState.setEndTarget(endTarget, false /* isAtomic */);
+        mAnimationFactory.setEndTarget(endTarget);
 
         float endShift = endTarget.isLauncher ? 1 : 0;
         final float startShift;
@@ -1466,7 +1469,9 @@
             mActivity.clearRunOnceOnStartCallback();
             resetLauncherListeners();
         }
-        if (mGestureState.getEndTarget() != null && !mGestureState.isRunningAnimationToLauncher()) {
+        if (mGestureState.isRecentsAnimationRunning() && mGestureState.getEndTarget() != null
+                && !mGestureState.getEndTarget().isLauncher) {
+            // Continued quick switch.
             cancelCurrentAnimation();
         } else {
             mStateCallback.setStateOnUiThread(STATE_FINISH_WITH_NO_END);
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 8a1b391..ec9a325 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -77,12 +77,14 @@
 
     public final boolean rotationSupportedByActivity;
 
-    private final STATE_TYPE mOverviewState, mBackgroundState;
+    private final STATE_TYPE mBackgroundState;
+
+    private STATE_TYPE mTargetState;
 
     protected BaseActivityInterface(boolean rotationSupportedByActivity,
             STATE_TYPE overviewState, STATE_TYPE backgroundState) {
         this.rotationSupportedByActivity = rotationSupportedByActivity;
-        mOverviewState = overviewState;
+        mTargetState = overviewState;
         mBackgroundState = backgroundState;
     }
 
@@ -412,6 +414,9 @@
         default boolean hasRecentsEverAttachedToAppWindow() {
             return false;
         }
+
+        /** Called when the gesture ends and we know what state it is going towards */
+        default void setEndTarget(GestureState.GestureEndTarget endTarget) { }
     }
 
     class DefaultAnimationFactory implements AnimationFactory {
@@ -449,7 +454,7 @@
 
             // Since we are changing the start position of the UI, reapply the state, at the end
             controller.setEndAction(() -> mActivity.getStateManager().goToState(
-                    controller.getInterpolatedProgress() > 0.5 ? mOverviewState : mBackgroundState,
+                    controller.getInterpolatedProgress() > 0.5 ? mTargetState : mBackgroundState,
                     false));
 
             RecentsView recentsView = mActivity.getOverviewPanel();
@@ -512,6 +517,11 @@
             return mHasEverAttachedToWindow;
         }
 
+        @Override
+        public void setEndTarget(GestureState.GestureEndTarget endTarget) {
+            mTargetState = stateFromGestureEndTarget(endTarget);
+        }
+
         protected void createBackgroundToOverviewAnim(ACTIVITY_TYPE activity, PendingAnimation pa) {
             //  Scale down recents from being full screen to being in overview.
             RecentsView recentsView = activity.getOverviewPanel();
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index e3ae361..99f1dc7 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -122,10 +122,6 @@
     public static final int STATE_RECENTS_ANIMATION_ENDED =
             getFlagForIndex("STATE_RECENTS_ANIMATION_ENDED");
 
-    // Called when we create an overscroll window when swiping right to left on the most recent app
-    public static final int STATE_OVERSCROLL_WINDOW_CREATED =
-            getFlagForIndex("STATE_OVERSCROLL_WINDOW_CREATED");
-
     // Called when RecentsView stops scrolling and settles on a TaskView.
     public static final int STATE_RECENTS_SCROLLING_FINISHED =
             getFlagForIndex("STATE_RECENTS_SCROLLING_FINISHED");
@@ -346,8 +342,8 @@
      * @return whether the recents animation is started but not yet ended
      */
     public boolean isRecentsAnimationRunning() {
-        return mStateCallback.hasStates(STATE_RECENTS_ANIMATION_INITIALIZED) &&
-                !mStateCallback.hasStates(STATE_RECENTS_ANIMATION_ENDED);
+        return mStateCallback.hasStates(STATE_RECENTS_ANIMATION_STARTED)
+                && !mStateCallback.hasStates(STATE_RECENTS_ANIMATION_ENDED);
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/OrientationRectF.java b/quickstep/src/com/android/quickstep/OrientationRectF.java
new file mode 100644
index 0000000..59a202c
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/OrientationRectF.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.launcher3.states.RotationHelper.deltaRotation;
+import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation;
+
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.util.Log;
+import android.view.MotionEvent;
+
+public class OrientationRectF extends RectF {
+
+    private static final String TAG = "OrientationRectF";
+    private static final boolean DEBUG = false;
+
+    private final int mRotation;
+    private final float mHeight;
+    private final float mWidth;
+
+    private final Matrix mTmpMatrix = new Matrix();
+    private final float[] mTmpPoint = new float[2];
+
+    public OrientationRectF(float left, float top, float right, float bottom, int rotation) {
+        super(left, top, right, bottom);
+        mRotation = rotation;
+        mHeight = bottom;
+        mWidth = right;
+    }
+
+    @Override
+    public String toString() {
+        String s = super.toString();
+        s += " rotation: " + mRotation;
+        return s;
+    }
+
+    @Override
+    public boolean contains(float x, float y) {
+        // Mark bottom right as included in the Rect (copied from Rect src, added "=" in "<=")
+        return left < right && top < bottom  // check for empty first
+                && x >= left && x <= right && y >= top && y <= bottom;
+    }
+
+    public boolean applyTransformFromRotation(MotionEvent event, int currentRotation,
+            boolean forceTransform) {
+        return applyTransform(event, deltaRotation(currentRotation, mRotation), forceTransform);
+    }
+
+    public boolean applyTransformToRotation(MotionEvent event, int currentRotation,
+            boolean forceTransform) {
+        return applyTransform(event, deltaRotation(mRotation, currentRotation), forceTransform);
+    }
+
+    private boolean applyTransform(MotionEvent event, int deltaRotation, boolean forceTransform) {
+        mTmpMatrix.reset();
+        postDisplayRotation(deltaRotation, mHeight, mWidth, mTmpMatrix);
+        if (forceTransform) {
+            if (DEBUG) {
+                Log.d(TAG, "Transforming rotation due to forceTransform, "
+                        + "deltaRotation: " + deltaRotation
+                        + "mRotation: " + mRotation
+                        + " this: " + this);
+            }
+            event.applyTransform(mTmpMatrix);
+            return true;
+        }
+        mTmpPoint[0] = event.getX();
+        mTmpPoint[1] = event.getY();
+        mTmpMatrix.mapPoints(mTmpPoint);
+
+        if (DEBUG) {
+            Log.d(TAG, "original: " + event.getX() + ", " + event.getY()
+                    + " new: " + mTmpPoint[0] + ", " + mTmpPoint[1]
+                    + " rect: " + this + " forceTransform: " + forceTransform
+                    + " contains: " + contains(mTmpPoint[0], mTmpPoint[1])
+                    + " this: " + this);
+        }
+
+        if (contains(mTmpPoint[0], mTmpPoint[1])) {
+            event.applyTransform(mTmpMatrix);
+            return true;
+        }
+        return false;
+    }
+
+    int getRotation() {
+        return mRotation;
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
index 81e6917..ecff4f1 100644
--- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
@@ -22,11 +22,7 @@
 import static android.view.MotionEvent.ACTION_POINTER_DOWN;
 import static android.view.MotionEvent.ACTION_UP;
 
-import static com.android.launcher3.states.RotationHelper.deltaRotation;
-import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation;
-
 import android.content.res.Resources;
-import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.RectF;
 import android.util.Log;
@@ -44,8 +40,8 @@
 
 /**
  * Maintains state for supporting nav bars and tracking their gestures in multiple orientations.
- * See {@link OrientationRectF#applyTransform(MotionEvent, boolean)} for transformation of
- * MotionEvents from one orientation's coordinate space to another's.
+ * See {@link OrientationRectF#applyTransformToRotation(MotionEvent, int, boolean)} for
+ * transformation of MotionEvents from one orientation's coordinate space to another's.
  *
  * This class only supports single touch/pointer gesture tracking for touches started in a supported
  * nav bar region.
@@ -95,9 +91,6 @@
 
     private static final int QUICKSTEP_ROTATION_UNINITIALIZED = -1;
 
-    private final Matrix mTmpMatrix = new Matrix();
-    private final float[] mTmpPoint = new float[2];
-
     private final Map<CurrentDisplay, OrientationRectF> mSwipeTouchRegions =
             new HashMap<CurrentDisplay, OrientationRectF>();
     private final RectF mAssistantLeftRegion = new RectF();
@@ -365,7 +358,7 @@
                 if (mLastRectTouched == null) {
                     return;
                 }
-                mLastRectTouched.applyTransform(event, true);
+                mLastRectTouched.applyTransformFromRotation(event, mCurrentDisplay.rotation, true);
                 break;
             }
             case ACTION_CANCEL:
@@ -373,7 +366,7 @@
                 if (mLastRectTouched == null) {
                     return;
                 }
-                mLastRectTouched.applyTransform(event, true);
+                mLastRectTouched.applyTransformFromRotation(event, mCurrentDisplay.rotation, true);
                 mLastRectTouched = null;
                 break;
             }
@@ -387,14 +380,14 @@
                     if (rect == null) {
                         continue;
                     }
-                    if (rect.applyTransform(event, false)) {
+                    if (rect.applyTransformFromRotation(event, mCurrentDisplay.rotation, false)) {
                         mLastRectTouched = rect;
-                        mActiveTouchRotation = rect.mRotation;
+                        mActiveTouchRotation = rect.getRotation();
                         if (mEnableMultipleRegions
                                 && mCurrentDisplay.rotation == mActiveTouchRotation) {
                             // TODO(b/154580671) might make this block unnecessary
                             // Start a touch session for the default nav region for the display
-                            mQuickStepStartingRotation = mLastRectTouched.mRotation;
+                            mQuickStepStartingRotation = mLastRectTouched.getRotation();
                             resetSwipeRegions();
                         }
                         if (DEBUG) {
@@ -423,65 +416,4 @@
         pw.println("  mNavBarLargerGesturalHeight=" + mNavBarLargerGesturalHeight);
         pw.println("  mOneHandedModeRegion=" + mOneHandedModeRegion);
     }
-
-    private class OrientationRectF extends RectF {
-
-        private int mRotation;
-        private float mHeight;
-        private float mWidth;
-
-        OrientationRectF(float left, float top, float right, float bottom, int rotation) {
-            super(left, top, right, bottom);
-            this.mRotation = rotation;
-            mHeight = bottom;
-            mWidth = right;
-        }
-
-        @Override
-        public String toString() {
-            String s = super.toString();
-            s += " rotation: " + mRotation;
-            return s;
-        }
-
-        @Override
-        public boolean contains(float x, float y) {
-            // Mark bottom right as included in the Rect (copied from Rect src, added "=" in "<=")
-            return left < right && top < bottom  // check for empty first
-                    && x >= left && x <= right && y >= top && y <= bottom;
-        }
-
-        boolean applyTransform(MotionEvent event, boolean forceTransform) {
-            mTmpMatrix.reset();
-            postDisplayRotation(deltaRotation(mCurrentDisplay.rotation, mRotation),
-                    mHeight, mWidth, mTmpMatrix);
-            if (forceTransform) {
-                if (DEBUG) {
-                    Log.d(TAG, "Transforming rotation due to forceTransform, "
-                            + "mCurrentRotation: " + mCurrentDisplay.rotation
-                            + "mRotation: " + mRotation
-                            + " this: " + this);
-                }
-                event.applyTransform(mTmpMatrix);
-                return true;
-            }
-            mTmpPoint[0] = event.getX();
-            mTmpPoint[1] = event.getY();
-            mTmpMatrix.mapPoints(mTmpPoint);
-
-            if (DEBUG) {
-                Log.d(TAG, "original: " + event.getX() + ", " + event.getY()
-                        + " new: " + mTmpPoint[0] + ", " + mTmpPoint[1]
-                        + " rect: " + this + " forceTransform: " + forceTransform
-                        + " contains: " + contains(mTmpPoint[0], mTmpPoint[1])
-                        + " this: " + this);
-            }
-
-            if (contains(mTmpPoint[0], mTmpPoint[1])) {
-                event.applyTransform(mTmpMatrix);
-                return true;
-            }
-            return false;
-        }
-    }
 }
diff --git a/quickstep/src/com/android/quickstep/OverscrollPluginFactory.java b/quickstep/src/com/android/quickstep/OverscrollPluginFactory.java
deleted file mode 100644
index 4c261ab..0000000
--- a/quickstep/src/com/android/quickstep/OverscrollPluginFactory.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep;
-
-import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
-
-import com.android.launcher3.R;
-import com.android.launcher3.util.MainThreadInitializedObject;
-import com.android.launcher3.util.ResourceBasedOverride;
-import com.android.systemui.plugins.OverscrollPlugin;
-
-/**
- * Resource overrideable factory for forcing a local overscroll plugin.
- * Override {@link R.string#overscroll_plugin_factory_class} to set a different class.
- */
-public class OverscrollPluginFactory implements ResourceBasedOverride {
-    public static final MainThreadInitializedObject<OverscrollPluginFactory> INSTANCE = forOverride(
-            OverscrollPluginFactory.class,
-            R.string.overscroll_plugin_factory_class);
-
-    /**
-     * Get the plugin that is defined locally in launcher, as opposed to a dynamic side loaded one.
-     */
-    public OverscrollPlugin getLocalOverscrollPlugin() {
-        return null;
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index 12fba0d..6ccb152 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -53,14 +53,14 @@
                         Bundle::putInt, PortraitStatesTouchController::getHotseatTop);
             }
 
-            case TestProtocol.REQUEST_GET_FOCUSED_TASK_WIDTH_FOR_TABLET: {
+            case TestProtocol.REQUEST_GET_FOCUSED_TASK_HEIGHT_FOR_TABLET: {
                 if (!mDeviceProfile.isTablet) {
                     return null;
                 }
                 Rect focusedTaskRect = new Rect();
                 LauncherActivityInterface.INSTANCE.calculateTaskSize(mContext, mDeviceProfile,
                         focusedTaskRect);
-                response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, focusedTaskRect.width());
+                response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, focusedTaskRect.height());
                 return response;
             }
         }
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 8a9bf7c..e2441ed 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -84,7 +84,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.stream.Collectors;
 
 /**
  * Manages the state of the system during a swipe up gesture.
@@ -398,14 +397,6 @@
     }
 
     /**
-     * @return the packages of gesture-blocked activities.
-     */
-    public List<String> getGestureBlockedActivityPackages() {
-        return mGestureBlockedActivities.stream().map(ComponentName::getPackageName)
-                .collect(Collectors.toList());
-    }
-
-    /**
      * Updates the system ui state flags from SystemUI.
      */
     public void setSystemUiFlags(int stateFlags) {
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index dc04016..825abed 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -16,9 +16,8 @@
 
 package com.android.quickstep;
 
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-
 import android.content.Context;
+import android.util.Log;
 
 import androidx.annotation.Nullable;
 
@@ -34,7 +33,9 @@
  * {@link TaskViewSimulator}
  */
 public class RemoteTargetGluer {
-    private final RemoteTargetHandle[] mRemoteTargetHandles;
+    private static final String TAG = "RemoteTargetGluer";
+
+    private RemoteTargetHandle[] mRemoteTargetHandles;
     private SplitConfigurationOptions.StagedSplitBounds mStagedSplitBounds;
 
     /**
@@ -93,6 +94,16 @@
     public RemoteTargetHandle[] assignTargetsForSplitScreen(RemoteAnimationTargets targets) {
         int[] splitIds = LauncherSplitScreenListener.INSTANCE.getNoCreate()
                 .getRunningSplitTaskIds();
+        Log.d(TAG, "splitIds length: " + splitIds.length
+                + " targetAppsLength: " + targets.apps.length
+                + " remoteHandlesLength: " + mRemoteTargetHandles.length);
+        if (splitIds.length == 0 && mRemoteTargetHandles.length > 1) {
+            // There's a chance that between the creation of this class and assigning targets,
+            // LauncherSplitScreenListener may have received callback that removes split
+            mRemoteTargetHandles = new RemoteTargetHandle[]{mRemoteTargetHandles[0]};
+            Log.w(TAG, "splitTaskIds changed between creation and assignment");
+        }
+
         RemoteAnimationTargetCompat primaryTaskTarget;
         RemoteAnimationTargetCompat secondaryTaskTarget;
         if (mRemoteTargetHandles.length == 1) {
diff --git a/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java
new file mode 100644
index 0000000..f474796
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
+import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
+import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
+
+import android.content.Context;
+import android.view.MotionEvent;
+
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.MainThreadInitializedObject;
+
+public class SimpleOrientationTouchTransformer implements
+        DisplayController.DisplayInfoChangeListener {
+
+    public static final MainThreadInitializedObject<SimpleOrientationTouchTransformer> INSTANCE =
+            new MainThreadInitializedObject<>(SimpleOrientationTouchTransformer::new);
+
+    private OrientationRectF mOrientationRectF;
+
+    public SimpleOrientationTouchTransformer(Context context) {
+        DisplayController.INSTANCE.get(context).addChangeListener(this);
+        onDisplayInfoChanged(context, DisplayController.INSTANCE.get(context).getInfo(),
+                CHANGE_ALL);
+    }
+
+    @Override
+    public void onDisplayInfoChanged(Context context, DisplayController.Info info, int flags) {
+        if ((flags & (CHANGE_ROTATION | CHANGE_ACTIVE_SCREEN)) == 0) {
+            return;
+        }
+        mOrientationRectF = new OrientationRectF(0, 0, info.currentSize.y, info.currentSize.x,
+                info.rotation);
+    }
+
+    public void transform(MotionEvent ev, int rotation) {
+        mOrientationRectF.applyTransformToRotation(ev, rotation, true /* forceTransform */);
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 61540d1..d9319a9 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -418,6 +418,22 @@
         }
     }
 
+    /**
+     * NOTE: If called to suspend, caller MUST call this method to also un-suspend
+     * @param suspend should be true to stop auto-hide, false to resume normal behavior
+     */
+    @Override
+    public void notifyTaskbarAutohideSuspend(boolean suspend) {
+        if (mSystemUiProxy != null) {
+            try {
+                mSystemUiProxy.notifyTaskbarAutohideSuspend(suspend);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call notifyTaskbarAutohideSuspend with arg: " +
+                        suspend, e);
+            }
+        }
+    }
+
     @Override
     public void handleImageBundleAsScreenshot(Bundle screenImageBundle, Rect locationInScreen,
             Insets visibleInsets, Task.TaskKey task) {
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index fe07cbd..4b89981 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -107,6 +107,13 @@
         // But force-finish it anyways
         finishRunningRecentsAnimation(false /* toHome */);
 
+        if (mCallbacks != null) {
+            // If mCallbacks still != null, that means we are getting this startRecentsAnimation()
+            // before the previous one got onRecentsAnimationStart(). In that case, cleanup the
+            // previous animation so it doesn't mess up/listen to state changes in this animation.
+            cleanUpRecentsAnimation();
+        }
+
         final BaseActivityInterface activityInterface = gestureState.getActivityInterface();
         mLastGestureState = gestureState;
         mCallbacks = new RecentsAnimationCallbacks(SystemUiProxy.INSTANCE.get(mCtx),
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 9ac00e8..c45159e 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -111,19 +111,30 @@
     }
 
 
+    /**
+     * Does NOT add split options in the following scenarios:
+     * * The taskView to add split options is already showing split screen tasks
+     * * There aren't at least 2 tasks in overview to show split options for
+     * * The taskView to show split options for is the focused task AND we haven't started
+     *   scrolling in overview (if we haven't scrolled, there's a split overview action so
+     *   we don't need this menu option)
+     */
     private static void addSplitOptions(List<SystemShortcut> outShortcuts,
             BaseDraggingActivity activity, TaskView taskView, DeviceProfile deviceProfile) {
+        RecentsView recentsView = taskView.getRecentsView();
+        PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
         int[] taskViewTaskIds = taskView.getTaskIds();
         boolean taskViewHasMultipleTasks = taskViewTaskIds[0] != -1 &&
                 taskViewTaskIds[1] != -1;
-        boolean notEnoughTasksToSplit = taskView.getRecentsView().getTaskViewCount() < 2;
+        boolean notEnoughTasksToSplit = recentsView.getTaskViewCount() < 2;
+        boolean isFocusedTask = deviceProfile.overviewShowAsGrid && taskView.isFocusedTask();
+        boolean isTaskInExpectedScrollPosition =
+                recentsView.isTaskInExpectedScrollPosition(recentsView.indexOfChild(taskView));
         if (taskViewHasMultipleTasks || notEnoughTasksToSplit ||
-                (deviceProfile.overviewShowAsGrid && taskView.isFocusedTask())) {
+                (isFocusedTask && isTaskInExpectedScrollPosition)) {
             return;
         }
 
-        PagedOrientationHandler orientationHandler =
-                taskView.getRecentsView().getPagedOrientationHandler();
         List<SplitPositionOption> positions =
                 orientationHandler.getSplitPositionOptions(deviceProfile);
         for (SplitPositionOption option : positions) {
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 284bc03..12b071d 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -170,7 +170,7 @@
 
         RemoteTargetHandle[] remoteTargetHandles;
         RemoteTargetHandle[] recentsViewHandles = recentsView.getRemoteTargetHandles();
-        if (v.isRunningTask()) {
+        if (v.isRunningTask() && recentsViewHandles != null) {
             // Re-use existing handles
             remoteTargetHandles = recentsViewHandles;
         } else {
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index bb8473b..4844f6b 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -40,7 +40,6 @@
 import android.app.RemoteAction;
 import android.app.Service;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
@@ -67,7 +66,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
-import androidx.annotation.WorkerThread;
 
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.R;
@@ -90,7 +88,6 @@
 import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer;
 import com.android.quickstep.inputconsumers.OneHandedModeInputConsumer;
 import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
-import com.android.quickstep.inputconsumers.OverscrollInputConsumer;
 import com.android.quickstep.inputconsumers.OverviewInputConsumer;
 import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer;
 import com.android.quickstep.inputconsumers.ResetGestureInputConsumer;
@@ -103,8 +100,6 @@
 import com.android.quickstep.util.ProtoTracer;
 import com.android.quickstep.util.ProxyScreenStatusProvider;
 import com.android.quickstep.util.SplitScreenBounds;
-import com.android.systemui.plugins.OverscrollPlugin;
-import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -129,8 +124,8 @@
  * Service connected by system-UI for handling touch interaction.
  */
 @TargetApi(Build.VERSION_CODES.R)
-public class TouchInteractionService extends Service implements PluginListener<OverscrollPlugin>,
-        ProtoTraceable<LauncherTraceProto.Builder> {
+public class TouchInteractionService extends Service
+        implements ProtoTraceable<LauncherTraceProto.Builder> {
 
     private static final String TAG = "TouchInteractionService";
 
@@ -149,8 +144,6 @@
             SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false);
 
     private int mBackGestureNotificationCounter = -1;
-    @Nullable
-    private OverscrollPlugin mOverscrollPlugin;
 
     /**
      * Local IOverviewProxy implementation with some methods for local components
@@ -423,9 +416,6 @@
                 .getInt(KEY_BACK_NOTIFICATION_COUNT, MAX_BACK_NOTIFICATION_COUNT));
         resetHomeBounceSeenOnQuickstepEnabledFirstTime();
 
-        PluginManagerWrapper.INSTANCE.get(getBaseContext()).addPluginListener(this,
-                OverscrollPlugin.class, false /* allowMultiple */);
-
         mOverviewComponentObserver.setOverviewChangeListener(this::onOverviewTargetChange);
         onOverviewTargetChange(mOverviewComponentObserver.isHomeAndOverviewSame());
     }
@@ -507,7 +497,6 @@
         if (mDeviceState.isUserUnlocked()) {
             mInputConsumer.unregisterInputConsumer();
             mOverviewComponentObserver.onDestroy();
-            PluginManagerWrapper.INSTANCE.get(getBaseContext()).removePluginListener(this);
         }
         disposeEventHandlers();
         mDeviceState.destroy();
@@ -691,26 +680,6 @@
                         mTaskbarManager.getCurrentActivityContext());
             }
 
-            if (FeatureFlags.ENABLE_QUICK_CAPTURE_GESTURE.get()) {
-                OverscrollPlugin plugin = null;
-                if (FeatureFlags.FORCE_LOCAL_OVERSCROLL_PLUGIN.get()) {
-                    plugin = OverscrollPluginFactory.INSTANCE.get(
-                            getApplicationContext()).getLocalOverscrollPlugin();
-                }
-
-                // If not local plugin was forced, use the actual overscroll plugin if available.
-                if (plugin == null && mOverscrollPlugin != null && mOverscrollPlugin.isActive()) {
-                    plugin = mOverscrollPlugin;
-                }
-
-                if (plugin != null) {
-                    // Put the overscroll gesture as higher priority than the Assistant or base
-                    // gestures
-                    base = new OverscrollInputConsumer(this, newGestureState, base,
-                        mInputMonitorCompat, plugin);
-                }
-            }
-
             // If Bubbles is expanded, use the overlay input consumer, which will close Bubbles
             // instead of going all the way home when a swipe up is detected.
             if (mDeviceState.isBubblesExpanded() || mDeviceState.isGlobalActionsShowing()) {
@@ -1002,32 +971,6 @@
                 mInputConsumer);
     }
 
-    protected boolean shouldNotifyBackGesture() {
-        return mBackGestureNotificationCounter > 0 &&
-                !mDeviceState.getGestureBlockedActivityPackages().isEmpty();
-    }
-
-    @WorkerThread
-    protected void tryNotifyBackGesture() {
-        if (shouldNotifyBackGesture()) {
-            mBackGestureNotificationCounter--;
-            Utilities.getDevicePrefs(this).edit()
-                    .putInt(KEY_BACK_NOTIFICATION_COUNT, mBackGestureNotificationCounter).apply();
-            mDeviceState.getGestureBlockedActivityPackages().forEach(blockedPackage ->
-                    sendBroadcast(new Intent(NOTIFY_ACTION_BACK).setPackage(blockedPackage)));
-        }
-    }
-
-    @Override
-    public void onPluginConnected(OverscrollPlugin overscrollPlugin, Context context) {
-        mOverscrollPlugin = overscrollPlugin;
-    }
-
-    @Override
-    public void onPluginDisconnected(OverscrollPlugin overscrollPlugin) {
-        mOverscrollPlugin = null;
-    }
-
     @Override
     public void writeToProto(LauncherTraceProto.Builder proto) {
         TouchInteractionServiceProto.Builder serviceProto =
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 725c7c4..0bd8832 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -29,7 +29,6 @@
 import static com.android.launcher3.Utilities.squaredHypot;
 import static com.android.launcher3.util.TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS;
 import static com.android.launcher3.util.VelocityUtils.PX_PER_MS;
-import static com.android.quickstep.GestureState.STATE_OVERSCROLL_WINDOW_CREATED;
 import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
 
 import android.annotation.TargetApi;
@@ -490,7 +489,7 @@
 
     @Override
     public boolean allowInterceptByParent() {
-        return !mPassedPilferInputSlop || mGestureState.hasState(STATE_OVERSCROLL_WINDOW_CREATED);
+        return !mPassedPilferInputSlop;
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java
deleted file mode 100644
index e984b4f..0000000
--- a/quickstep/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.inputconsumers;
-
-import static android.view.MotionEvent.ACTION_CANCEL;
-import static android.view.MotionEvent.ACTION_DOWN;
-import static android.view.MotionEvent.ACTION_MOVE;
-import static android.view.MotionEvent.ACTION_POINTER_DOWN;
-import static android.view.MotionEvent.ACTION_POINTER_UP;
-import static android.view.MotionEvent.ACTION_UP;
-
-import static com.android.launcher3.Utilities.squaredHypot;
-
-import static java.lang.Math.abs;
-
-import android.content.Context;
-import android.graphics.PointF;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.ViewConfiguration;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.R;
-import com.android.quickstep.GestureState;
-import com.android.quickstep.InputConsumer;
-import com.android.quickstep.views.RecentsView;
-import com.android.systemui.plugins.OverscrollPlugin;
-import com.android.systemui.shared.system.InputMonitorCompat;
-
-/**
- * Input consumer for handling events to pass to an {@code OverscrollPlugin}.
- */
-public class OverscrollInputConsumer extends DelegateInputConsumer {
-    private static final String TAG = "OverscrollInputConsumer";
-    private static final boolean DEBUG_LOGS_ENABLED = false;
-    private static void debugPrint(String log) {
-        if (DEBUG_LOGS_ENABLED) {
-            Log.v(TAG, log);
-        }
-    }
-
-    private final PointF mDownPos = new PointF();
-    private final PointF mLastPos = new PointF();
-    private final PointF mStartDragPos = new PointF();
-    private final int mAngleThreshold;
-
-    private final int mFlingDistanceThresholdPx;
-    private final int mFlingVelocityThresholdPx;
-    private int mActivePointerId = -1;
-    private boolean mPassedSlop = false;
-    // True if we set ourselves as active, meaning we no longer pass events to the delegate.
-    private boolean mPassedActiveThreshold = false;
-    // When a gesture crosses this length, this recognizer will attempt to interpret touch events.
-    private final float mSquaredSlop;
-    // When a gesture crosses this length, this recognizer will become the sole active recognizer.
-    private final float mSquaredActiveThreshold;
-    // When a gesture crosses this length, the overscroll view should be shown.
-    private final float mSquaredFinishThreshold;
-    private boolean mThisDownIsIgnored = false;
-
-    private final GestureState mGestureState;
-    @Nullable
-    private final OverscrollPlugin mPlugin;
-
-    @Nullable
-    private RecentsView mRecentsView;
-
-    public OverscrollInputConsumer(Context context, GestureState gestureState,
-            InputConsumer delegate, InputMonitorCompat inputMonitor, OverscrollPlugin plugin) {
-        super(delegate, inputMonitor);
-
-        mAngleThreshold = context.getResources()
-                .getInteger(R.integer.assistant_gesture_corner_deg_threshold);
-        mFlingDistanceThresholdPx = (int) context.getResources()
-                .getDimension(R.dimen.gestures_overscroll_fling_threshold);
-        mFlingVelocityThresholdPx = ViewConfiguration.get(context).getScaledMinimumFlingVelocity();
-        mGestureState = gestureState;
-        mPlugin = plugin;
-
-        float slop = ViewConfiguration.get(context).getScaledTouchSlop();
-
-        mSquaredSlop = slop * slop;
-
-
-        float finishGestureThreshold = (int) context.getResources()
-                .getDimension(R.dimen.gestures_overscroll_finish_threshold);
-        mSquaredFinishThreshold = finishGestureThreshold * finishGestureThreshold;
-
-        float activeThreshold = (int) context.getResources()
-                .getDimension(R.dimen.gestures_overscroll_active_threshold);
-        mSquaredActiveThreshold = activeThreshold * activeThreshold;
-    }
-
-    @Override
-    public int getType() {
-        return TYPE_OVERSCROLL | mDelegate.getType();
-    }
-
-    @Override
-    public void onMotionEvent(MotionEvent ev) {
-        if (mPlugin == null) {
-            return;
-        }
-
-        debugPrint("got event, underlying activity is " + getUnderlyingActivity());
-        switch (ev.getActionMasked()) {
-            case ACTION_DOWN: {
-                debugPrint("ACTION_DOWN");
-                mActivePointerId = ev.getPointerId(0);
-                mDownPos.set(ev.getX(), ev.getY());
-                mLastPos.set(mDownPos);
-                if (mPlugin.blockOtherGestures()) {
-                    debugPrint("mPlugin.blockOtherGestures(), becoming active on ACTION_DOWN");
-                    // Otherwise, if an appear gesture is performed when the Activity is visible,
-                    // the Activity will dismiss its keyboard.
-                    mPassedActiveThreshold = true;
-                    mPassedSlop = true;
-                    mStartDragPos.set(mLastPos.x, mLastPos.y);
-                    setActive(ev);
-                }
-                break;
-            }
-            case ACTION_POINTER_DOWN: {
-                if (mState != STATE_ACTIVE) {
-                    mState = STATE_DELEGATE_ACTIVE;
-                }
-                break;
-            }
-            case ACTION_POINTER_UP: {
-                int ptrIdx = ev.getActionIndex();
-                int ptrId = ev.getPointerId(ptrIdx);
-                if (ptrId == mActivePointerId) {
-                    final int newPointerIdx = ptrIdx == 0 ? 1 : 0;
-                    mDownPos.set(
-                            ev.getX(newPointerIdx) - (mLastPos.x - mDownPos.x),
-                            ev.getY(newPointerIdx) - (mLastPos.y - mDownPos.y));
-                    mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx));
-                    mActivePointerId = ev.getPointerId(newPointerIdx);
-                }
-                break;
-            }
-            case ACTION_MOVE: {
-                if (mState == STATE_DELEGATE_ACTIVE) {
-                    break;
-                }
-
-                if (!mDelegate.allowInterceptByParent()) {
-                    mState = STATE_DELEGATE_ACTIVE;
-                    break;
-                }
-
-                // Update last touch position.
-                int pointerIndex = ev.findPointerIndex(mActivePointerId);
-                if (pointerIndex == -1) {
-                    break;
-                }
-                mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
-
-                float squaredDist = squaredHypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y);
-                if ((!mPassedSlop) && (squaredDist > mSquaredSlop)) {
-                    mPassedSlop = true;
-                    mStartDragPos.set(mLastPos.x, mLastPos.y);
-                    mGestureState.setState(GestureState.STATE_OVERSCROLL_WINDOW_CREATED);
-                }
-
-                boolean becomeActive = mPassedSlop && !mPassedActiveThreshold && isOverscrolled()
-                        && (squaredDist > mSquaredActiveThreshold);
-                if (becomeActive) {
-                    debugPrint("Past slop and past threshold, set active");
-                    mPassedActiveThreshold = true;
-                    setActive(ev);
-                }
-
-                if (mPassedActiveThreshold) {
-                    debugPrint("ACTION_MOVE Relaying touch event");
-                    mPlugin.onTouchEvent(ev, getHorizontalDistancePx(), getVerticalDistancePx(),
-                            (int) Math.sqrt(mSquaredFinishThreshold), mFlingDistanceThresholdPx,
-                            mFlingVelocityThresholdPx, getDeviceState(), getUnderlyingActivity());
-                }
-
-                break;
-            }
-            case ACTION_CANCEL:
-            case ACTION_UP:
-                debugPrint("ACTION_UP");
-                if (mPassedActiveThreshold) {
-                    debugPrint("ACTION_UP Relaying touch event");
-
-                    mPlugin.onTouchEvent(ev, getHorizontalDistancePx(), getVerticalDistancePx(),
-                            (int) Math.sqrt(mSquaredFinishThreshold), mFlingDistanceThresholdPx,
-                            mFlingVelocityThresholdPx, getDeviceState(), getUnderlyingActivity());
-                }
-
-
-                mPassedSlop = false;
-                mPassedActiveThreshold = false;
-                mState = STATE_INACTIVE;
-                break;
-        }
-
-        if (mState != STATE_ACTIVE) {
-            mDelegate.onMotionEvent(ev);
-        }
-    }
-
-    private boolean isOverscrolled() {
-        if (mRecentsView == null) {
-            BaseDraggingActivity activity = mGestureState.getActivityInterface()
-                    .getCreatedActivity();
-            if (activity != null) {
-                mRecentsView = activity.getOverviewPanel();
-            }
-        }
-
-        // Make sure there isn't an app to quick switch to on our right
-        int maxIndex = 0;
-
-        boolean atRightMostApp = mRecentsView == null
-                || (mRecentsView.getRunningTaskIndex() <= maxIndex);
-
-        // Check if the gesture is within our angle threshold of horizontal
-        float deltaY = abs(mLastPos.y - mDownPos.y);
-        float deltaX = mLastPos.x - mDownPos.x;
-
-        boolean angleInBounds = (Math.toDegrees(Math.atan2(deltaY, abs(deltaX))) < mAngleThreshold);
-
-        boolean overscrollVisible = mPlugin.blockOtherGestures();
-        boolean overscrollInvisibleAndLeftSwipe = !overscrollVisible && deltaX < 0;
-        boolean gestureDirectionMatchesVisibility = overscrollVisible
-                || overscrollInvisibleAndLeftSwipe;
-        return atRightMostApp && angleInBounds && gestureDirectionMatchesVisibility;
-    }
-
-    private String getDeviceState() {
-        String deviceState = OverscrollPlugin.DEVICE_STATE_UNKNOWN;
-        int consumerType = mDelegate.getType();
-        if (((consumerType & InputConsumer.TYPE_OVERVIEW) > 0)
-                || ((consumerType & InputConsumer.TYPE_OVERVIEW_WITHOUT_FOCUS)) > 0) {
-            deviceState = OverscrollPlugin.DEVICE_STATE_LAUNCHER;
-        } else if ((consumerType & InputConsumer.TYPE_OTHER_ACTIVITY) > 0) {
-            deviceState = OverscrollPlugin.DEVICE_STATE_APP;
-        } else if (((consumerType & InputConsumer.TYPE_RESET_GESTURE) > 0)
-                || ((consumerType & InputConsumer.TYPE_DEVICE_LOCKED) > 0)) {
-            deviceState = OverscrollPlugin.DEVICE_STATE_LOCKED;
-        }
-
-        return deviceState;
-    }
-
-    private int getHorizontalDistancePx() {
-        return (int) (mLastPos.x - mDownPos.x);
-    }
-
-    private int getVerticalDistancePx() {
-        return (int) (mLastPos.y - mDownPos.y);
-    }
-
-    private @NonNull String getUnderlyingActivity() {
-        // Overly defensive, got guidance on code review that something in the chain of
-        // `mGestureState.getRunningTask().topActivity` can be null and thus cause a null pointer
-        // exception to be thrown, but we aren't sure which part can be null.
-        if ((mGestureState == null) || (mGestureState.getRunningTask() == null)
-                || (mGestureState.getRunningTask().topActivity == null)) {
-            return "";
-        }
-        return mGestureState.getRunningTask().topActivity.flattenToString();
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index 4472bdc..f731cb3 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -32,6 +32,8 @@
 
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
+import com.android.quickstep.TouchInteractionService.TISBinder;
+import com.android.quickstep.util.TISBindHelper;
 
 import java.net.URISyntaxException;
 
@@ -47,6 +49,9 @@
     private static final String EXTRA_ACCENT_COLOR_DARK_MODE = "suwColorAccentDark";
     private static final String EXTRA_ACCENT_COLOR_LIGHT_MODE = "suwColorAccentLight";
 
+    private TISBindHelper mTISBindHelper;
+    private TISBinder mBinder;
+
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -73,6 +78,34 @@
         });
 
         findViewById(R.id.hint).setAccessibilityDelegate(new SkipButtonAccessibilityDelegate());
+        mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (mBinder != null) {
+            mBinder.getTaskbarManager().setSetupUIVisible(true);
+        }
+    }
+
+    private void onTISConnected(TISBinder binder) {
+        mBinder = binder;
+        mBinder.getTaskbarManager().setSetupUIVisible(isResumed());
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        if (mBinder != null) {
+            mBinder.getTaskbarManager().setSetupUIVisible(false);
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        mTISBindHelper.onDestroy();
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
index 30f9008..fb6cd8a 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -49,12 +49,16 @@
 
     @LayoutRes
     int getMockAppTaskCurrentPageLayoutResId() {
-        return R.layout.gesture_tutorial_mock_conversation;
+        return mTutorialFragment.isLargeScreen()
+                ? R.layout.gesture_tutorial_foldable_mock_conversation
+                : R.layout.gesture_tutorial_mock_conversation;
     }
 
     @LayoutRes
     int getMockAppTaskPreviousPageLayoutResId() {
-        return R.layout.gesture_tutorial_mock_conversation_list;
+        return mTutorialFragment.isLargeScreen()
+                ? R.layout.gesture_tutorial_foldable_mock_conversation_list
+                : R.layout.gesture_tutorial_mock_conversation_list;
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
index 3ad84f0..a45f273 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
@@ -43,7 +43,9 @@
 
     @Override
     protected int getMockAppTaskLayoutResId() {
-        return R.layout.gesture_tutorial_mock_webpage;
+        return mTutorialFragment.isLargeScreen()
+                ? R.layout.gesture_tutorial_foldable_mock_webpage
+                : R.layout.gesture_tutorial_mock_webpage;
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
index 9d60e1b..24ef1fa 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -53,7 +53,9 @@
 
     @Override
     protected int getMockAppTaskLayoutResId() {
-        return R.layout.gesture_tutorial_mock_conversation_list;
+        return mTutorialFragment.isLargeScreen()
+                ? R.layout.gesture_tutorial_foldable_mock_conversation_list
+                : R.layout.gesture_tutorial_mock_conversation_list;
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
index 968412b..57a76ca 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
@@ -57,17 +57,6 @@
             }
         });
 
-        Animator swipeAnimator =
-                controller.createFingerDotOverviewSwipeAnimator(fingerDotStartTranslationY);
-        swipeAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                super.onAnimationEnd(animation);
-                mFakePreviousTaskView.setVisibility(View.VISIBLE);
-                controller.onMotionPaused(true /*arbitrary value*/);
-            }
-        });
-
         AnimatorSet fingerDotDisappearanceAnimator =
                 controller.createFingerDotDisappearanceAnimatorSet();
         fingerDotDisappearanceAnimator.addListener(new AnimatorListenerAdapter() {
@@ -89,7 +78,7 @@
         ArrayList<Animator> animators = new ArrayList<>();
 
         animators.add(fingerDotAppearanceAnimator);
-        animators.add(swipeAnimator);
+        animators.add(controller.createFingerDotOverviewSwipeAnimator(fingerDotStartTranslationY));
         animators.add(controller.createAnimationPause());
         animators.add(fingerDotDisappearanceAnimator);
         animators.add(animationPause);
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index 0c7b35b..a923519 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -320,8 +320,8 @@
                 @Override
                 public RectF getWindowTargetRect() {
                     int fakeHomeIconSizePx = Utilities.dpToPx(60);
-                    int fakeHomeIconLeft = mFakeHotseatView.getLeft();
-                    int fakeHomeIconTop = mFakeHotseatView.getTop();
+                    int fakeHomeIconLeft = getHotseatIconLeft();
+                    int fakeHomeIconTop = getHotseatIconTop();
                     return new RectF(fakeHomeIconLeft, fakeHomeIconTop,
                             fakeHomeIconLeft + fakeHomeIconSizePx,
                             fakeHomeIconTop + fakeHomeIconSizePx);
@@ -374,8 +374,19 @@
     }
 
     protected Animator createFingerDotOverviewSwipeAnimator(float fingerDotStartTranslationY) {
-        return createFingerDotSwipeUpAnimator(fingerDotStartTranslationY)
+        Animator overviewSwipeAnimator = createFingerDotSwipeUpAnimator(fingerDotStartTranslationY)
                 .setDuration(OVERVIEW_SWIPE_ANIMATION_DURATION_MILLIS);
+
+        overviewSwipeAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                mFakePreviousTaskView.setVisibility(View.VISIBLE);
+                onMotionPaused(true /*arbitrary value*/);
+            }
+        });
+
+        return overviewSwipeAnimator;
     }
 
 
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 94fb556..9c1ff4d 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -85,7 +85,8 @@
     final TextView mFeedbackTitleView;
     final ImageView mEdgeGestureVideoView;
     final RelativeLayout mFakeLauncherView;
-    final ImageView mFakeHotseatView;
+    final FrameLayout mFakeHotseatView;
+    @Nullable View mHotseatIconView;
     final ClipIconView mFakeIconView;
     final FrameLayout mFakeTaskView;
     final AnimatedTaskView mFakePreviousTaskView;
@@ -164,13 +165,25 @@
         }
     }
 
+    public int getHotseatIconTop() {
+        return mHotseatIconView == null
+                ? 0 : mFakeHotseatView.getTop() + mHotseatIconView.getTop();
+    }
+
+    public int getHotseatIconLeft() {
+        return mHotseatIconView == null
+                ? 0 : mFakeHotseatView.getLeft() + mHotseatIconView.getLeft();
+    }
+
     void setTutorialType(TutorialType tutorialType) {
         mTutorialType = tutorialType;
     }
 
-    @DrawableRes
+    @LayoutRes
     protected int getMockHotseatResId() {
-        return R.drawable.default_sandbox_mock_launcher;
+        return mTutorialFragment.isLargeScreen()
+                ? R.layout.gesture_tutorial_foldable_mock_hotseat
+                : R.layout.gesture_tutorial_mock_hotseat;
     }
 
     @LayoutRes
@@ -384,6 +397,7 @@
         hideActionButton();
         updateSubtext();
         updateDrawables();
+        updateLayout();
 
         mGestureCompleted = false;
         if (mFakeHotseatView != null) {
@@ -416,10 +430,14 @@
     }
 
     void updateFakeAppTaskViewLayout(@LayoutRes int mockAppTaskLayoutResId) {
-        mFakeTaskView.removeAllViews();
-        if (mockAppTaskLayoutResId != NO_ID) {
-            mFakeTaskView.addView(
-                    inflate(mContext, mockAppTaskLayoutResId, null),
+        updateFakeViewLayout(mFakeTaskView, mockAppTaskLayoutResId);
+    }
+
+    void updateFakeViewLayout(ViewGroup view, @LayoutRes int mockLayoutResId) {
+        view.removeAllViews();
+        if (mockLayoutResId != NO_ID) {
+            view.addView(
+                    inflate(mContext, mockLayoutResId, null),
                     new FrameLayout.LayoutParams(
                             ViewGroup.LayoutParams.MATCH_PARENT,
                             ViewGroup.LayoutParams.MATCH_PARENT));
@@ -438,9 +456,9 @@
             mTutorialFragment.updateFeedbackAnimation();
             mFakeLauncherView.setBackgroundColor(
                     mContext.getColor(R.color.gesture_tutorial_fake_wallpaper_color));
-            mFakeHotseatView.setImageDrawable(AppCompatResources.getDrawable(
-                    mContext, getMockHotseatResId()));
-            updateFakeAppTaskViewLayout(getMockAppTaskLayoutResId());
+            updateFakeViewLayout(mFakeHotseatView, getMockHotseatResId());
+            mHotseatIconView = mFakeHotseatView.findViewById(R.id.hotseat_icon_1);
+            updateFakeViewLayout(mFakeTaskView, getMockAppTaskLayoutResId());
             mFakeTaskView.animate().alpha(1).setListener(
                     AnimatorListeners.forSuccessCallback(() -> mFakeTaskView.animate().cancel()));
             mFakePreviousTaskView.setFakeTaskViewFillColor(mContext.getResources().getColor(
@@ -450,6 +468,21 @@
         }
     }
 
+    private void updateLayout() {
+        if (mContext != null) {
+            RelativeLayout.LayoutParams feedbackLayoutParams =
+                    (RelativeLayout.LayoutParams) mFeedbackView.getLayoutParams();
+            feedbackLayoutParams.setMarginStart(mContext.getResources().getDimensionPixelSize(
+                    mTutorialFragment.isLargeScreen()
+                            ? R.dimen.gesture_tutorial_foldable_feedback_margin_start_end
+                            : R.dimen.gesture_tutorial_feedback_margin_start_end));
+            feedbackLayoutParams.setMarginEnd(mContext.getResources().getDimensionPixelSize(
+                    mTutorialFragment.isLargeScreen()
+                            ? R.dimen.gesture_tutorial_foldable_feedback_margin_start_end
+                            : R.dimen.gesture_tutorial_feedback_margin_start_end));
+        }
+    }
+
     private AlertDialog createSkipTutorialDialog() {
         if (mContext instanceof GestureSandboxActivity) {
             GestureSandboxActivity sandboxActivity = (GestureSandboxActivity) mContext;
diff --git a/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java b/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java
index 2e5b33a..c2101a8 100644
--- a/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java
+++ b/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java
@@ -19,12 +19,14 @@
 import static android.view.MotionEvent.ACTION_DOWN;
 import static android.view.MotionEvent.ACTION_UP;
 
+import android.content.Context;
 import android.util.Log;
 import android.view.InputEvent;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 
 import com.android.quickstep.InputConsumer;
+import com.android.quickstep.SimpleOrientationTouchTransformer;
 import com.android.systemui.shared.system.InputConsumerController;
 
 import java.util.function.Supplier;
@@ -37,6 +39,8 @@
 
     private static final String TAG = "InputConsumerProxy";
 
+    private final Context mContext;
+    private final Supplier<Integer> mRotationSupplier;
     private final InputConsumerController mInputConsumerController;
     private Runnable mCallback;
     private Supplier<InputConsumer> mConsumerSupplier;
@@ -48,8 +52,11 @@
     private boolean mTouchInProgress = false;
     private boolean mDestroyPending = false;
 
-    public InputConsumerProxy(InputConsumerController inputConsumerController,
+    public InputConsumerProxy(Context context, Supplier<Integer> rotationSupplier,
+            InputConsumerController inputConsumerController,
             Runnable callback, Supplier<InputConsumer> consumerSupplier) {
+        mContext = context;
+        mRotationSupplier = rotationSupplier;
         mInputConsumerController = inputConsumerController;
         mCallback = callback;
         mConsumerSupplier = consumerSupplier;
@@ -98,6 +105,8 @@
             }
         }
         if (mInputConsumer != null) {
+            SimpleOrientationTouchTransformer.INSTANCE.get(mContext).transform(ev,
+                    mRotationSupplier.get());
             mInputConsumer.onMotionEvent(ev);
         }
 
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index e9a695d..1dae2c8 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -163,10 +163,8 @@
                                 if (mSuccessCallback != null) {
                                     mSuccessCallback.accept(true);
                                 }
+                                resetState();
                             }));
-
-            // After successful launch, call resetState
-            resetState();
         }
 
         @Override
@@ -175,9 +173,8 @@
                 if (mSuccessCallback != null) {
                     mSuccessCallback.accept(false);
                 }
+                resetState();
             });
-
-            resetState();
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/util/TISBindHelper.java b/quickstep/src/com/android/quickstep/util/TISBindHelper.java
new file mode 100644
index 0000000..92c60c8
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/TISBindHelper.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.util.Log;
+
+import com.android.quickstep.TouchInteractionService;
+import com.android.quickstep.TouchInteractionService.TISBinder;
+
+import java.util.function.Consumer;
+
+/**
+ * Utility class to simplify binding to {@link TouchInteractionService}
+ */
+public class TISBindHelper implements ServiceConnection {
+
+    private static final String TAG = "TISBindHelper";
+
+    private static final long BACKOFF_MILLIS = 1000;
+
+    // Max backoff caps at 5 mins
+    private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000;
+
+    private final Handler mHandler = new Handler();
+    private final Runnable mConnectionRunnable = this::internalBindToTIS;
+    private final Context mContext;
+    private final Consumer<TISBinder> mConnectionCallback;
+
+    private short mConnectionAttempts;
+    private boolean mTisServiceBound;
+
+    public TISBindHelper(Context context, Consumer<TISBinder> connectionCallback) {
+        mContext = context;
+        mConnectionCallback = connectionCallback;
+        internalBindToTIS();
+    }
+
+    @Override
+    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
+        if (!(iBinder instanceof TISBinder)) {
+            // Seems like there can be a race condition when user unlocks, which kills the TIS
+            // process and re-starts it. I guess in the meantime service can be connected to
+            // a killed TIS? Either way, unbind and try to re-connect in that case.
+            internalUnbindToTIS();
+            mHandler.postDelayed(mConnectionRunnable, BACKOFF_MILLIS);
+            return;
+        }
+
+        Log.d(TAG, "TIS service connected");
+        mConnectionCallback.accept((TISBinder) iBinder);
+        resetServiceBindRetryState();
+    }
+
+    @Override
+    public void onServiceDisconnected(ComponentName componentName) { }
+
+    @Override
+    public void onBindingDied(ComponentName name) {
+        Log.w(TAG, "TIS binding died");
+        internalBindToTIS();
+    }
+
+
+    /**
+     * Binds to {@link TouchInteractionService}. If the binding fails, attempts to retry via
+     * {@link #mConnectionRunnable}. Unbind via {@link #internalUnbindToTIS()}
+     */
+    private void internalBindToTIS() {
+        mTisServiceBound = mContext.bindService(new Intent(mContext, TouchInteractionService.class),
+                this, 0);
+        if (mTisServiceBound) {
+            resetServiceBindRetryState();
+            return;
+        }
+
+        Log.w(TAG, "Retrying TIS Binder connection attempt: " + mConnectionAttempts);
+        final long timeoutMs = (long) Math.min(
+                Math.scalb(BACKOFF_MILLIS, mConnectionAttempts), MAX_BACKOFF_MILLIS);
+        mHandler.postDelayed(mConnectionRunnable, timeoutMs);
+        mConnectionAttempts++;
+    }
+
+    /** See {@link #internalBindToTIS()} */
+    private void internalUnbindToTIS() {
+        if (mTisServiceBound) {
+            mContext.unbindService(this);
+            mTisServiceBound = false;
+        }
+    }
+
+    private void resetServiceBindRetryState() {
+        if (mHandler.hasCallbacks(mConnectionRunnable)) {
+            mHandler.removeCallbacks(mConnectionRunnable);
+        }
+        mConnectionAttempts = 0;
+    }
+
+    /**
+     * Called when the activity is destroyed to clear the binding
+     */
+    public void onDestroy() {
+        internalUnbindToTIS();
+        resetServiceBindRetryState();
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
index 22c87b0..86be210 100644
--- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java
+++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
@@ -66,6 +66,7 @@
     private float mGridTranslationPrimary;
     private float mGridScrollOffset;
     private float mScrollOffsetPrimary;
+    private float mSplitSelectScrollOffsetPrimary;
 
     private int mSidePadding;
 
@@ -167,6 +168,10 @@
         mScrollOffsetPrimary = scrollOffsetPrimary;
     }
 
+    public void setSplitSelectScrollOffsetPrimary(float splitSelectScrollOffsetPrimary) {
+        mSplitSelectScrollOffsetPrimary = splitSelectScrollOffsetPrimary;
+    }
+
     public float getScrollAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
         float scrollAdjustment = 0;
         if (fullscreenEnabled) {
@@ -176,6 +181,7 @@
             scrollAdjustment += mGridTranslationPrimary + mGridScrollOffset;
         }
         scrollAdjustment += mScrollOffsetPrimary;
+        scrollAdjustment += mSplitSelectScrollOffsetPrimary;
         return scrollAdjustment;
     }
 
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index e1a3895..4d488db 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -189,6 +189,9 @@
         TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback,
         TaskVisualsChangeListener, SplitScreenBounds.OnChangeListener {
 
+    private static final String TAG = "RecentsView";
+    private static final boolean DEBUG = false;
+
     // TODO(b/184899234): We use this timeout to wait a fixed period after switching to the
     // screenshot when dismissing the current live task to ensure the app can try and get stopped.
     private static final int REMOVE_TASK_WAIT_FOR_APP_STOP_MS = 100;
@@ -409,7 +412,7 @@
     private final float mFastFlingVelocity;
     private final int mScrollHapticMinGapMillis;
     private final RecentsModel mModel;
-    private final int mGridSideMargin;
+    private final int mSplitPlaceholderSize;
     private final ClearAllButton mClearAllButton;
     private final Rect mClearAllButtonDeadZoneRect = new Rect();
     private final Rect mTaskViewDeadZoneRect = new Rect();
@@ -660,7 +663,8 @@
 
         mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
         setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
-        mGridSideMargin = getResources().getDimensionPixelSize(R.dimen.overview_grid_side_margin);
+        mSplitPlaceholderSize = getResources().getDimensionPixelSize(
+                R.dimen.split_placeholder_size);
         mSquaredTouchSlop = squaredTouchSlop(context);
 
         mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents);
@@ -1055,11 +1059,11 @@
     }
 
     /**
-     * Returns true if the task is snapped.
+     * Returns true if the task is in expected scroll position.
      *
      * @param taskIndex the index of the task
      */
-    public boolean isTaskSnapped(int taskIndex) {
+    public boolean isTaskInExpectedScrollPosition(int taskIndex) {
         return getScrollForPage(taskIndex) == getPagedOrientationHandler().getPrimaryScroll(this);
     }
 
@@ -1726,8 +1730,7 @@
         if (showAsGrid()) {
             TaskView focusedTaskView = getFocusedTaskView();
             hiddenFocusedScroll = focusedTaskView == null
-                    || getScrollForPage(indexOfChild(focusedTaskView))
-                    != mOrientationHandler.getPrimaryScroll(this);
+                    || !isTaskInExpectedScrollPosition(indexOfChild(focusedTaskView));
         } else {
             hiddenFocusedScroll = false;
         }
@@ -2643,8 +2646,7 @@
      * and then animates it into the split position that was desired
      */
     private void createInitialSplitSelectAnimation(PendingAnimation anim) {
-        float placeholderHeight = getResources().getDimension(R.dimen.split_placeholder_size);
-        mOrientationHandler.getInitialSplitPlaceholderBounds((int) placeholderHeight,
+        mOrientationHandler.getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
                 mActivity.getDeviceProfile(),
                 mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
 
@@ -3238,14 +3240,13 @@
         }
 
         Rect splitBounds = new Rect();
-        float placeholderSize = getResources().getDimension(R.dimen.split_placeholder_size);
         // This acts as a best approximation on where the splitplaceholder view would be,
         // doesn't need to be exact necessarily. This also doesn't need to take translations
         // into account since placeholder view is not translated
         if (stagePosition == SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT) {
-            splitBounds.set((int) (getWidth() - placeholderSize), 0, getWidth(), getHeight());
+            splitBounds.set(getWidth() - mSplitPlaceholderSize, 0, getWidth(), getHeight());
         } else {
-            splitBounds.set(0, 0, (int) (placeholderSize), getHeight());
+            splitBounds.set(0, 0, mSplitPlaceholderSize, getHeight());
         }
         Rect taskBounds = new Rect();
         int taskCount = getTaskViewCount();
@@ -3746,6 +3747,50 @@
     }
 
     /**
+     * Apply scroll offset to children of RecentsView when entering split select.
+     */
+    public void applySplitPrimaryScrollOffset() {
+        if (!mActivity.getDeviceProfile().isLandscape || !showAsGrid()) {
+            return;
+        }
+
+        @StagePosition int position = mSplitSelectStateController.getActiveSplitStagePosition();
+        boolean shouldShiftThumbnailsForSplitSelect = shouldShiftThumbnailsForSplitSelect(
+                position);
+        boolean expandLeft = false;
+        boolean expandRight = false;
+        if (mIsRtl) {
+            if (position == SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT
+                    && shouldShiftThumbnailsForSplitSelect) {
+                expandLeft = true;
+            } else if (position == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
+                if (shouldShiftThumbnailsForSplitSelect) {
+                    expandRight = true;
+                } else {
+                    expandLeft = true;
+                }
+            }
+        } // TODO(b/200537659): Handle system RTL.
+        if (expandRight) {
+            for (int i = 0; i < getTaskViewCount(); i++) {
+                getTaskViewAt(i).setSplitScrollOffsetPrimary(mSplitPlaceholderSize);
+            }
+        } else if (expandLeft) {
+            mClearAllButton.setSplitSelectScrollOffsetPrimary(-mSplitPlaceholderSize);
+        }
+    }
+
+    /**
+     * Reset scroll offset on children of RecentsView when exiting split select.
+     */
+    public void resetSplitPrimaryScrollOffset() {
+        for (int i = 0; i < getTaskViewCount(); i++) {
+            getTaskViewAt(i).setSplitScrollOffsetPrimary(0);
+        }
+        mClearAllButton.setSplitSelectScrollOffsetPrimary(0);
+    }
+
+    /**
      * Resets the visuals when exit modal state.
      */
     public void resetModalVisuals() {
@@ -3918,7 +3963,6 @@
 
     /** TODO(b/181707736) More gracefully handle exiting split selection state */
     private void resetFromSplitSelectionState() {
-        mSplitHiddenTaskView.setTranslationY(0);
         if (!showAsGrid()) {
             int pageToSnapTo = mCurrentPage;
             if (mSplitHiddenTaskViewIndex <= pageToSnapTo) {
@@ -3930,9 +3974,12 @@
         }
         onLayout(false /*  changed */, getLeft(), getTop(), getRight(), getBottom());
         resetTaskVisuals();
-        mSplitHiddenTaskView.setVisibility(VISIBLE);
-        mSplitHiddenTaskView = null;
         mSplitHiddenTaskViewIndex = -1;
+        if (mSplitHiddenTaskView != null) {
+            mSplitHiddenTaskView.setTranslationY(0);
+            mSplitHiddenTaskView.setVisibility(VISIBLE);
+            mSplitHiddenTaskView = null;
+        }
         if (mFirstFloatingTaskView != null) {
             mActivity.getRootView().removeView(mFirstFloatingTaskView);
             mFirstFloatingTaskView = null;
@@ -4236,13 +4283,19 @@
             return;
         }
 
-        if (mSyncTransactionApplier != null) {
-            recentsAnimationTargets.addReleaseCheck(mSyncTransactionApplier);
-        }
-
         RemoteTargetGluer gluer = new RemoteTargetGluer(getContext(), getSizeStrategy());
         mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(recentsAnimationTargets);
         mSplitBoundsConfig = gluer.getStagedSplitBounds();
+        if (mSyncTransactionApplier != null) {
+            // 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
+            // to create new RemoteAnimationTargets in assignTargetsForSplitScreen(), and the
+            // mSyncTransactionApplier doesn't get transferred over
+            runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle
+                    .getTransformParams().getTargetSet()
+                    .addReleaseCheck(mSyncTransactionApplier));
+        }
+
         TaskView runningTaskView = getRunningTaskView();
         if (runningTaskView instanceof GroupedTaskView) {
             // We initially create a GroupedTaskView in showCurrentTask() before launcher even
@@ -4347,6 +4400,15 @@
     }
 
     @Override
+    protected void updateMinAndMaxScrollX() {
+        super.updateMinAndMaxScrollX();
+        if (DEBUG) {
+            Log.d(TAG, "updateMinAndMaxScrollX - mMinScroll: " + mMinScroll);
+            Log.d(TAG, "updateMinAndMaxScrollX - mMaxScroll: " + mMaxScroll);
+        }
+    }
+
+    @Override
     protected int computeMinScroll() {
         if (getTaskViewCount() > 0) {
             if (mIsRtl) {
@@ -4430,6 +4492,12 @@
                 pageScrollChanged = true;
                 outPageScrolls[i] = pageScroll;
             }
+            if (DEBUG) {
+                Log.d(TAG, "getPageScrolls - outPageScrolls[" + i + "]: " + outPageScrolls[i]);
+            }
+        }
+        if (DEBUG) {
+            Log.d(TAG, "getPageScrolls - clearAllScroll: " + clearAllScroll);
         }
         return pageScrollChanged;
     }
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index ea8282f..31a73e9 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -389,6 +389,7 @@
     // Used when in SplitScreenSelectState
     private float mSplitSelectTranslationY;
     private float mSplitSelectTranslationX;
+    private float mSplitSelectScrollOffsetPrimary;
 
     private ObjectAnimator mIconAndDimAnimator;
     private float mIconScaleAnimStartProgress = 0;
@@ -1031,6 +1032,11 @@
         mSplitSelectTranslationY = y;
         applyTranslationY();
     }
+
+    public void setSplitScrollOffsetPrimary(float splitSelectScrollOffsetPrimary) {
+        mSplitSelectScrollOffsetPrimary = splitSelectScrollOffsetPrimary;
+    }
+
     private void setDismissTranslationX(float x) {
         mDismissTranslationX = x;
         applyTranslationX();
@@ -1101,6 +1107,7 @@
         } else {
             scrollAdjustment += getPrimaryNonGridTranslationProperty().get(this);
         }
+        scrollAdjustment += mSplitSelectScrollOffsetPrimary;
         return scrollAdjustment;
     }
 
diff --git a/res/color-night-v31/folder_background_dark.xml b/res/color-night-v31/folder_background_dark.xml
index a5bd636..d607395 100644
--- a/res/color-night-v31/folder_background_dark.xml
+++ b/res/color-night-v31/folder_background_dark.xml
@@ -16,5 +16,5 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android" >
     <item
         android:color="@android:color/system_neutral2_50"
-        android:lStar="30" />
+        android:lStar="35" />
 </selector>
diff --git a/res/color-night-v31/folder_preview_dark.xml b/res/color-night-v31/folder_preview_dark.xml
new file mode 100644
index 0000000..a5bd636
--- /dev/null
+++ b/res/color-night-v31/folder_preview_dark.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item
+        android:color="@android:color/system_neutral2_50"
+        android:lStar="30" />
+</selector>
diff --git a/res/color-v31/folder_preview_light.xml b/res/color-v31/folder_preview_light.xml
new file mode 100644
index 0000000..fe30c87
--- /dev/null
+++ b/res/color-v31/folder_preview_light.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item
+        android:color="@android:color/system_accent2_50"
+        android:lStar="80" />
+</selector>
diff --git a/res/drawable-v28/round_rect_folder.xml b/res/drawable-v28/round_rect_folder.xml
index 0403be0..77a4aa4 100644
--- a/res/drawable-v28/round_rect_folder.xml
+++ b/res/drawable-v28/round_rect_folder.xml
@@ -16,6 +16,6 @@
 -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
-    <solid android:color="?attr/folderFillColor" />
+    <solid android:color="?attr/folderBackgroundColor" />
     <corners android:radius="?android:attr/dialogCornerRadius" />
 </shape>
diff --git a/res/drawable/round_rect_folder.xml b/res/drawable/round_rect_folder.xml
index 8b3d06c..6c5864e 100644
--- a/res/drawable/round_rect_folder.xml
+++ b/res/drawable/round_rect_folder.xml
@@ -16,6 +16,6 @@
 -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
-    <solid android:color="?attr/folderFillColor" />
+    <solid android:color="?attr/folderBackgroundColor" />
     <corners android:radius="@dimen/bg_round_rect_radius" />
 </shape>
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index 9ac6ed0..a34baef 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -42,10 +42,19 @@
         <include layout="@layout/floating_header_content" />
 
         <include layout="@layout/all_apps_personal_work_tabs" />
+
+        <Button
+            android:id="@+id/all_apps_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:text="@string/all_apps_label"
+            android:background="@drawable/padded_rounded_action_button"
+            android:visibility="gone"/>
+
     </com.android.launcher3.allapps.FloatingHeaderView>
 
-    <include
-        layout="@layout/search_container_all_apps"/>
+    <include layout="@layout/search_container_all_apps" />
 
     <include layout="@layout/all_apps_fast_scroller" />
 </com.android.launcher3.allapps.LauncherAllAppsContainerView>
\ No newline at end of file
diff --git a/res/layout/keyboard_drag_and_drop.xml b/res/layout/keyboard_drag_and_drop.xml
index e9463c4..bc3a9c1 100644
--- a/res/layout/keyboard_drag_and_drop.xml
+++ b/res/layout/keyboard_drag_and_drop.xml
@@ -26,7 +26,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_horizontal"
-        android:background="?attr/folderFillColor"
+        android:background="?attr/folderBackgroundColor"
         android:padding="8dp"
         android:textColor="?attr/folderTextColor"
         />
diff --git a/res/layout/system_shortcut_content.xml b/res/layout/system_shortcut_content.xml
index 3ef0b94..e693dbd 100644
--- a/res/layout/system_shortcut_content.xml
+++ b/res/layout/system_shortcut_content.xml
@@ -32,6 +32,7 @@
         android:minLines="1"
         android:maxLines="2"
         android:ellipsize="end"
+        android:hyphenationFrequency="full"
         android:textColor="?android:attr/textColorPrimary"
         launcher:iconDisplay="shortcut_popup"
         launcher:layoutHorizontal="true"
@@ -44,4 +45,4 @@
         android:layout_marginStart="@dimen/system_shortcut_margin_start"
         android:layout_gravity="start|center_vertical"
         android:backgroundTint="?android:attr/textColorPrimary"/>
-</merge>
\ No newline at end of file
+</merge>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 2601056..8d6206a 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"መተግብሪያው ቅንብሮችን እና አቋራጮችን በመነሻ ውስጥ እንዲቀይራቸው ያስችለዋል።"</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> ተሰናክሏል"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index beeedaf..095c3bd 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"للسماح للتطبيق بتغيير الإعدادات والاختصارات في الشاشة الرئيسية."</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"تم إيقاف <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index bf88ad6..95ead40 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"এপটোক গৃহ পৃষ্ঠাত ছেটিং আৰু শ্বৰ্টকাটসমূহ সলনি কৰাৰ অনুমতি দিয়ে।"</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> অক্ষম কৰা হ’ল"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index eca341b..d5b8391 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Дазваляе праграме змяняць налады і ярлыкі на Галоўнай старонцы."</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> адключана"</string>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index f1eff99..d6cef8b 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"হোমে অ্যাপ্লিকেশানটিকে সেটিংস এবং শর্টকাটগুলি পরিবর্তন করতে দেয়৷"</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> অক্ষম করা হয়েছে"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index f9a0d2b..422ee65 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Permet que l\'aplicació canviï la configuració i les dreceres de la pantalla d\'inici."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> no té permís per fer trucades telefòniques"</string>
     <string name="gadget_error_text" msgid="740356548025791839">"No es pot carregar el widget"</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Configuració del widget"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Toca per finalitzar la configuració"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Aquesta aplicació és una aplicació del sistema i no es pot desinstal·lar."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Edita el nom"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"S\'ha desactivat <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index b45e3bb..729fc11 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Umožňuje aplikaci změnit nastavení a odkazy na ploše."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> nemá oprávnění telefonovat"</string>
     <string name="gadget_error_text" msgid="740356548025791839">"Widget se nepodařilo načíst"</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Nastavení widgetů"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Klepnutím dokončíte konfiguraci"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Toto je systémová aplikace a nelze ji odinstalovat."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Upravit název"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> je zakázána"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 14bf8d6..583aa50 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Ermöglicht der App, die Einstellungen und Verknüpfungen auf dem Startbildschirm zu ändern"</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> darf keine Telefonanrufe tätigen."</string>
     <string name="gadget_error_text" msgid="740356548025791839">"Widget kann nicht geladen werden"</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Widget-Einstellungen"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Tippen, um Einrichtung abzuschließen"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Dies ist eine Systemanwendung, die nicht deinstalliert werden kann."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Name bearbeiten"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> deaktiviert"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 970003c..bc0d4ec 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Επιτρέπει στην εφαρμογή την αλλαγή των ρυθμίσεων και των συντομεύσεων στην Αρχική οθόνη."</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> είναι απενεργοποιημένη"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index b0a1f4d..d8e2849 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Permet à l\'application de modifier les paramètres et les raccourcis de l\'écran d\'accueil."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"L\'application <xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas autorisée à faire des appels téléphoniques"</string>
     <string name="gadget_error_text" msgid="740356548025791839">"Impossible de charger le widget"</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Paramètres du widget"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Touchez pour terminer la configuration"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Impossible de désinstaller cette application, car il s\'agit d\'une application système."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Modifier le nom"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"L\'application <xliff:g id="APP_NAME">%1$s</xliff:g> est désactivée"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 6326fc2..2a42771 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite a unha aplicación cambiar a configuración e os atallos da pantalla de inicio."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> non ten permiso para facer chamadas telefónicas"</string>
     <string name="gadget_error_text" msgid="740356548025791839">"Non se puido cargar o widget"</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Configuración do widget"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Toca para rematar a configuración"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Esta aplicación é do sistema e non se pode desinstalar."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Edita o nome"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"Desactivouse <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index d9ba8fd..990db91 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"ઍપને હોમમાં સેટિંગ અને શૉર્ટકટ બદલવાની મંજૂરી આપે છે."</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> અક્ષમ કરી"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index b82fb49..1226fd3 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Ծրագրին թույլ է տալիս փոփոխել հիմնաէջի կարգավորումներն ու դյուրանցումները:"</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածն անջատված է"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 4111ed5..d0d3f60 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Mengizinkan aplikasi mengubah setelan dan pintasan di layar Utama."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak diizinkan untuk melakukan panggilan telepon"</string>
     <string name="gadget_error_text" msgid="740356548025791839">"Tidak dapat memuat widget"</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Setelan widget"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Ketuk untuk menyelesaikan penyiapan"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Ini adalah aplikasi sistem dan tidak dapat dicopot pemasangannya."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Sunting Nama"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> dinonaktifkan"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 278b80e..fbd591c 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"מאפשר לאפליקציה לשנות את ההגדרות וקיצורי הדרך בדף הבית."</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> מושבתת"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index e9cef5f..abc68aa 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"អនុញ្ញាត​ឲ្យ​កម្មវិធី​ប្ដូរ​ការ​កំណត់ និង​ផ្លូវ​កាត់​ក្នុង​អេក្រង់​ដើម។"</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"បានបិទដំណើរការ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index d088c65..cfe2edb 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"ಮುಖಪುಟದಲ್ಲಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿ ನೀಡುತ್ತದೆ."</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 54b52ab..ab5ca5d 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Колдонмого Үйдүн тууралоолорун жана тез чакырмаларын өзгөртүүгө уруксат берет."</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> өчүрүлгөн"</string>
@@ -109,7 +107,7 @@
     <string name="notification_dots_desc_off" msgid="1760796511504341095">"Өчүк"</string>
     <string name="title_missing_notification_access" msgid="7503287056163941064">"Эскертмелерге уруксат берилиши керек"</string>
     <string name="msg_missing_notification_access" msgid="281113995110910548">"Эскертме белгилерин көрсөтүү максатында, <xliff:g id="NAME">%1$s</xliff:g> үчүн колдонмонун билдирмелерин күйгүзүү керек"</string>
-    <string name="title_change_settings" msgid="1376365968844349552">"Жөндөөлөрдү өзгөртүү"</string>
+    <string name="title_change_settings" msgid="1376365968844349552">"Параметрлерди өзгөртүү"</string>
     <string name="notification_dots_service_title" msgid="4284221181793592871">"Билдирмелер белгилерин көрсөтүү"</string>
     <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Колдонмонун сүрөтчөсүн Башкы экранга кошуу"</string>
     <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Жаңы колдонмолор үчүн"</string>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 39c8db5..4616eec 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"ອະນຸຍາດໃຫ້ແອັບຯດັ່ງກ່າວ ປ່ຽນການຕັ້ງຄ່າ ແລະທາງລັດໃນໜ້າຫຼັກ."</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"ປິດການນຳໃຊ້ <xliff:g id="APP_NAME">%1$s</xliff:g> ແລ້ວ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index a99d8b0..5813b15 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Programai leidžiama keisti pagrindinio puslapio nustatymus ir sparčiuosius klavišus."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ neleidžiama skambinti"</string>
     <string name="gadget_error_text" msgid="740356548025791839">"Nepavyko įkelti valdiklio"</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Valdiklio nustatymai"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Palieskite, kad užbaigtumėte sąranką"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Tai sistemos programa ir jos negalima pašalinti."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Pavadinimo redagavimas"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ išjungta"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 78881c5..759c84e 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Ļauj lietotnei mainīt iestatījumus un saīsnes sākuma ekrānā."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"Lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g> nav atļauts veikt tālruņa zvanus."</string>
     <string name="gadget_error_text" msgid="740356548025791839">"Nevar ielādēt logrīku."</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Logrīka iestatījumi"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Pieskarieties, lai pabeigtu iestatīšanu"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Šī ir sistēmas lietotne, un to nevar atinstalēt."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Nosaukuma rediģēšana"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> ir atspējota"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 7b8b580..12df7b2 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"ഹോമിലെ ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും മാറ്റാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> പ്രവർത്തനരഹിതമാക്കി"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index c94d7ca..5b88da9 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट बदलण्यास अ‍ॅप ला अनुमती देते."</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> अक्षम केला आहे"</string>
@@ -115,7 +113,7 @@
     <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नवीन अ‍ॅप्ससाठी"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"काढा"</string>
-    <string name="abandoned_search" msgid="891119232568284442">"Search"</string>
+    <string name="abandoned_search" msgid="891119232568284442">"शोधा"</string>
     <string name="abandoned_promises_title" msgid="7096178467971716750">"हा अ‍ॅप इंस्टॉल केलेला नाही"</string>
     <string name="abandoned_promise_explanation" msgid="3990027586878167529">"या चिन्हासाठी अ‍ॅप इंस्टॉल केलेला नाही. तुम्ही ते काढू शकता किंवा अ‍ॅपचा शोध घेऊ शकता आणि त्यास व्यक्तिचलितपणे इंस्टॉल करू शकता."</string>
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> इंस्टॉल करत आहे, <xliff:g id="PROGRESS">%2$s</xliff:g> पूर्ण झाले"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index b568552..e95dc8b 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Lar appen endre innstillingene og snarveiene på startsiden."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> har ikke tillatelse til å ringe"</string>
     <string name="gadget_error_text" msgid="740356548025791839">"Kan ikke laste inn modulen"</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Modulinnstillinger"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Trykk for å fullføre konfigureringen"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Dette er en systemapp som ikke kan avinstalleres."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Rediger navn"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"Slo av <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index d91d891..3c33bf1 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"गृहमा एउटा एपलाई सेटिङ र सर्टकट बदल्न अनुमति दिनुहोस्।"</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"असक्षम पारिएको <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index b716048..8ec6a80 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"ହୋମରେ ସେଟିଙ୍ଗ ଏବଂ ଶର୍ଟକଟ୍‌ ପରିବର୍ତ୍ତନ କରିବାକୁ ଆପକୁ ଅନୁମତି ଦିଏ।"</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଅକ୍ଷମ କରାଗଲା"</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index b6acb97..d56d898 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -41,7 +41,7 @@
     <string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
     <string name="widget_button_text" msgid="2880537293434387943">"ਵਿਜੇਟ"</string>
     <string name="widgets_full_sheet_search_bar_hint" msgid="8484659090860596457">"ਖੋਜੋ"</string>
-    <string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"ਖੋਜ ਬਾਕਸ ਤੋਂ ਸਪੱਸ਼ਟ ਲਿਖਤ"</string>
+    <string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"ਖੋਜ ਬਾਕਸ ਤੋਂ ਲਿਖਤ ਕਲੀਅਰ ਕਰੋ"</string>
     <string name="no_widgets_available" msgid="4337693382501046170">"ਵਿਜੇਟ ਜਾਂ ਸ਼ਾਰਟਕੱਟ ਉਪਲਬਧ ਨਹੀਂ ਹਨ"</string>
     <string name="no_search_results" msgid="3787956167293097509">"ਕੋਈ ਵੀ ਵਿਜੇਟ ਜਾਂ ਸ਼ਾਰਟਕੱਟ ਨਹੀਂ ਮਿਲਿਆ"</string>
     <string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ਨਿੱਜੀ"</string>
@@ -115,7 +115,7 @@
     <string name="abandoned_clean_this" msgid="7610119707847920412">"ਹਟਾਓ"</string>
     <string name="abandoned_search" msgid="891119232568284442">"ਖੋਜੋ"</string>
     <string name="abandoned_promises_title" msgid="7096178467971716750">"ਇਹ ਐਪ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
-    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ਇਸ ਪ੍ਰਤੀਕ ਲਈ ਐਪ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤਾ ਹੋਇਆ ਹੈ। ਤੁਸੀਂ ਇਸਨੂੰ ਹਟਾ ਸਕਦੇ ਹੋ ਜਾਂ ਐਪ ਖੋਜ ਸਕਦੇ ਹੋ ਅਤੇ ਇਸਨੂੰ ਮੈਨੂਅਲੀ ਸਥਾਪਤ ਕਰ ਸਕਦੇ ਹੋ।"</string>
+    <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ਇਸ ਪ੍ਰਤੀਕ ਲਈ ਐਪ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤੀ ਹੋਈ ਹੈ। ਤੁਸੀਂ ਇਸਨੂੰ ਹਟਾ ਸਕਦੇ ਹੋ ਜਾਂ ਐਪ ਨੂੰ ਹੱਥੀਂ ਖੋਜ ਕੇ ਉਸਨੂੰ ਸਥਾਪਤ ਕਰ ਸਕਦੇ ਹੋ।"</string>
     <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ਨੂੰ ਸਥਾਪਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ, <xliff:g id="PROGRESS">%2$s</xliff:g> ਪੂਰਾ ਹੋਇਆ"</string>
     <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ਡਾਉਨਲੋਡ ਹੋਰ ਰਿਹਾ ਹੈ, <xliff:g id="PROGRESS">%2$s</xliff:g> ਸੰਪੂਰਣ"</string>
     <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ਸਥਾਪਤ ਕਰਨ ਦੀ ਉਡੀਕ ਕਰ ਰਿਹਾ ਹੈ"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 06559a7..78925b0 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Приложение сможет изменять настройки и ярлыки на главном экране."</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"Приложение <xliff:g id="APP_NAME">%1$s</xliff:g> отключено"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 46bab24..29e8a02 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Aplikaciji dovoli spreminjanje nastavitev in bližnjic na začetnem zaslonu."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"Aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> ni dovoljeno opravljanje klicev"</string>
     <string name="gadget_error_text" msgid="740356548025791839">"Pripomočka ni mogoče naložiti."</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Nastavitve pripomočka"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Dotaknite se, da dokončate postopek nastavitve."</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"To je sistemska aplikacija in je ni mogoče odstraniti."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Urejanje imena"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogočena"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 1bb446a..04ec414 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Lejon aplikacionin të ndryshojë cilësimet dhe shkurtoret në ekranin bazë."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk lejohet të kryejë telefonata"</string>
     <string name="gadget_error_text" msgid="740356548025791839">"S\'mund të ngarkohet miniaplikacioni"</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Cilësimet e miniaplikacionit"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Trokit për të përfunduar konfigurimin"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Ky është aplikacion sistemi dhe nuk mund të çinstalohet."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Redakto emrin"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> u çaktivizua"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 503325a..feae09b 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Tillåter att appen ändrar inställningar och genvägar på startsidan."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> har inte behörighet att ringa samtal"</string>
     <string name="gadget_error_text" msgid="740356548025791839">"Det gick inte att läsa in widgeten"</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Widgetinställningar"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Tryck för att slutföra konfigureringen"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Det här är en systemapp som inte kan avinstalleras."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Redigera namn"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> har inaktiverats"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 5b4c3a5..ca35210 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Huruhusu programu kubadilisha mipangilio na njia za mkato katika skrini ya Mwanzo."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> hairuhusiwi kupiga simu"</string>
     <string name="gadget_error_text" msgid="740356548025791839">"Imeshindwa kupakia wijeti"</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Mipangilio ya wijeti"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Gusa ili umalize kuweka mipangilio"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Hii ni programu ya mfumo na haiwezi kuondolewa."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Badilisha Jina"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> imezimwa"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 1eb8bb7..7430d63 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"హోమ్‌లో సెట్టింగ్‌లు మరియు షార్ట్‌కట్‌లను మార్చడానికి యాప్‌ను అనుమతిస్తుంది."</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> నిలిపివేయబడింది"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 0928665..2a7dce6 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Дозволяє програмі змінювати налаштування та ярлики на головному екрані."</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> вимкнено"</string>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 3985b1f..f536e12 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"ایپ کو ہوم میں ترتیبات اور شارٹ کٹس کو تبدیل کرنے کی اجازت دیتا ہے۔"</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> غیر فعال ہے"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 123cfe1..086a603 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"允许应用更改主屏幕中的设置和快捷方式。"</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>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <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>
     <string name="disabled_app_label" msgid="6673129024321402780">"已停用<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 206cd47..f236ec8 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -80,10 +80,8 @@
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Ivumela uhlelo lokusebenza ukuthi lushintshe izilungiselelo nezinqamuleli Ekhaya."</string>
     <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ayivunyelwe ukwenza amakholi wefoni"</string>
     <string name="gadget_error_text" msgid="740356548025791839">"Ayikwazi ukulayisha iwijethi"</string>
-    <!-- no translation found for gadget_setup_text (8348374825537681407) -->
-    <skip />
-    <!-- no translation found for gadget_complete_setup_text (309040266978007925) -->
-    <skip />
+    <string name="gadget_setup_text" msgid="8348374825537681407">"Amasethingi ewijethi"</string>
+    <string name="gadget_complete_setup_text" msgid="309040266978007925">"Thepha ukuze uqede ukusetha"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Lolu uhlelo lokusebenza lwesistimu futhi alikwazi ukukhishwa."</string>
     <string name="folder_hint_text" msgid="5174843001373488816">"Hlela igama"</string>
     <string name="disabled_app_label" msgid="6673129024321402780">"Kukhutshaziwe <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 319c87d..08f0089 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -43,7 +43,8 @@
 
     <attr name="folderDotColor" format="color" />
     <attr name="folderPaginationColor" format="color" />
-    <attr name="folderFillColor" format="color" />
+    <attr name="folderPreviewColor" format="color" />
+    <attr name="folderBackgroundColor" format="color" />
     <attr name="folderIconRadius" format="float" />
     <attr name="folderIconBorderColor" format="color" />
     <attr name="folderTextColor" format="color" />
@@ -72,7 +73,7 @@
 
     <!-- BubbleTextView specific attributes. -->
     <declare-styleable name="FolderIconPreview">
-        <attr name="folderFillColor" />
+        <attr name="folderPreviewColor" />
         <attr name="folderIconBorderColor" />
         <attr name="folderDotColor" />
     </declare-styleable>
@@ -153,12 +154,7 @@
         <attr name="demoModeLayoutId" format="reference" />
         <attr name="isScalable" format="boolean" />
         <attr name="devicePaddingId" format="reference" />
-        <attr name="gridEnabled" format="integer" >
-            <!-- Enable on all devices; default value -->
-            <enum name="all_displays" value="0" />
-            <!-- Enable on single display devices only -->
-            <enum name="single_display" value="1" />
-        </attr>
+        <attr name="gridEnabled" format="boolean" />
 
     </declare-styleable>
 
@@ -184,11 +180,9 @@
         <attr name="twoPanelPortraitMinCellHeightDps" format="float" />
         <!-- twoPanelPortraitMinCellHeightDps defaults to minCellWidthDps, if not specified -->
         <attr name="twoPanelPortraitMinCellWidthDps" format="float" />
-        <!-- twoPanelLandscapeMinCellHeightDps defaults to twoPanelPortraitMinCellHeightDps,
-        if not specified -->
+        <!-- twoPanelLandscapeMinCellHeightDps defaults to minCellHeightDps, if not specified -->
         <attr name="twoPanelLandscapeMinCellHeightDps" format="float" />
-        <!-- twoPanelLandscapeMinCellWidthDps defaults to twoPanelPortraitMinCellWidthDps,
-        if not specified -->
+        <!-- twoPanelLandscapeMinCellWidthDps defaults to minCellWidthDps, if not specified -->
         <attr name="twoPanelLandscapeMinCellWidthDps" format="float" />
 
         <!-- These border spaces are only used if GridDisplayOption#isScalable is true -->
@@ -217,15 +211,20 @@
         if not specified -->
         <attr name="twoPanelLandscapeBorderSpaceVerticalDps" format="float" />
 
-
+        <!-- allAppsCellSpacingDps defaults to borderSpaceDps, if not specified -->
         <attr name="allAppsCellSpacingDps" format="float" />
+        <!-- The following values are only enabled if grid is supported. -->
+        <!-- allAppsIconSize defaults to iconSize, if not specified -->
+        <attr name="allAppsIconSize" format="float" />
+        <!-- allAppsIconTextSize defaults to iconTextSize, if not specified -->
+        <attr name="allAppsIconTextSize" format="float" />
 
         <attr name="iconImageSize" format="float" />
         <!-- landscapeIconSize defaults to iconImageSize, if not specified -->
         <attr name="landscapeIconSize" format="float" />
         <!-- twoPanelPortraitIconSize defaults to iconImageSize, if not specified -->
         <attr name="twoPanelPortraitIconSize" format="float" />
-        <!-- twoPanelLandscapeIconSize defaults to landscapeIconSize, if not specified -->
+        <!-- twoPanelLandscapeIconSize defaults to iconImageSize, if not specified -->
         <attr name="twoPanelLandscapeIconSize" format="float" />
 
         <attr name="iconTextSize" format="float" />
@@ -233,20 +232,11 @@
         <attr name="landscapeIconTextSize" format="float" />
         <!-- twoPanelPortraitIconTextSize defaults to iconTextSize, if not specified -->
         <attr name="twoPanelPortraitIconTextSize" format="float" />
-        <!-- twoPanelLandscapeIconTextSize defaults to landscapeIconTextSize, if not specified -->
+        <!-- twoPanelLandscapeIconTextSize defaults to iconTextSize, if not specified -->
         <attr name="twoPanelLandscapeIconTextSize" format="float" />
 
         <!-- If set, this display option is used to determine the default grid -->
-        <attr name="canBeDefault" format="boolean|integer" >
-            <!-- The profile can be default on split display devices -->
-            <flag name="split_display" value="0x2" />
-        </attr>
-
-        <!-- The following values are only enabled if grid is supported. -->
-        <!-- allAppsIconSize defaults to iconSize, if not specified -->
-        <attr name="allAppsIconSize" format="float" />
-        <!-- allAppsIconTextSize defaults to iconTextSize, if not specified -->
-        <attr name="allAppsIconTextSize" format="float" />
+        <attr name="canBeDefault" format="boolean" />
 
         <!-- Margin on left and right of the workspace when GridDisplayOption#isScalable is true -->
         <attr name="horizontalMargin" format="float"/>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 5020127..0b1b451 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -63,6 +63,9 @@
     <color name="folder_background_light">#F9F9F9</color>
     <color name="folder_background_dark">#464746</color>
 
+    <color name="folder_preview_light">#F9F9F9</color>
+    <color name="folder_preview_dark">#464746</color>
+
     <color name="folder_dot_color">?attr/colorPrimary</color>
     <color name="folder_pagination_color_light">#ff006c5f</color>
     <color name="folder_pagination_color_dark">#ffbfebe3</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b1294b4..4d137c8 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -103,6 +103,7 @@
     <dimen name="all_apps_tabs_vertical_padding">6dp</dimen>
     <dimen name="all_apps_divider_height">2dp</dimen>
     <dimen name="all_apps_divider_width">128dp</dimen>
+    <dimen name="all_apps_content_fade_in_offset">150dp</dimen>
 
     <dimen name="all_apps_tip_bottom_margin">8dp</dimen>
     <!-- The size of corner radius of the arrow in the arrow toast. -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f315725..d7a1506 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
 /*
 * Copyright (C) 2008 The Android Open Source Project
 *
@@ -132,6 +131,8 @@
     <string name="all_apps_search_market_message">Search for more apps</string>
     <!-- Label for an icon representing any generic app. [CHAR_LIMIT=50] -->
     <string name="label_application">App</string>
+    <!-- Label for the header text of the All Apps section in All Apps view, used to separate Predicted Apps and Actions section from All Apps section. [CHAR_LIMIT=50] -->
+    <string name="all_apps_label">All apps</string>
 
     <!-- Popup items -->
     <!-- Text to display as the header above notifications. [CHAR_LIMIT=30] -->
@@ -193,7 +194,7 @@
     <string name="msg_no_phone_permission"><xliff:g id="app_name" example="Launcher3">%1$s</xliff:g> is not allowed to make phone calls</string>
 
     <!-- Widgets: -->
-    <skip />    
+    <skip />
 
     <!-- Error text that lets a user know that the widget can't load. -->
     <string name="gadget_error_text">Can\'t load widget</string>
@@ -308,7 +309,7 @@
     <!-- Text announced by accessibility when the popup containing the list of widgets is closed. [CHAR_LIMIT=100] -->
     <string name="widgets_list_closed">Widgets list closed</string>
 
-<!-- Strings for accessibility actions -->
+    <!-- Strings for accessibility actions -->
     <!-- Accessibility action to add an app to workspace. [CHAR_LIMIT=30] -->
     <string name="action_add_to_workspace">Add to Home screen</string>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 8ad4fcd..818a032 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -51,7 +51,8 @@
         <item name="widgetsTheme">@style/WidgetContainerTheme</item>
         <item name="folderDotColor">@color/folder_dot_color</item>
         <item name="folderPaginationColor">@color/folder_pagination_color_light</item>
-        <item name="folderFillColor">@color/folder_background_light</item>
+        <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="isFolderDarkText">true</item>
@@ -110,7 +111,8 @@
         <item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item>
         <item name="folderDotColor">@color/folder_dot_color</item>
         <item name="folderPaginationColor">@color/folder_pagination_color_dark</item>
-        <item name="folderFillColor">@color/folder_background_dark</item>
+        <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>
diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml
index 256999c..e030f81 100644
--- a/res/xml/device_profiles.xml
+++ b/res/xml/device_profiles.xml
@@ -121,7 +121,7 @@
             launcher:minHeightDps="694"
             launcher:iconImageSize="56"
             launcher:iconTextSize="14.4"
-            launcher:canBeDefault="split_display" />
+            launcher:canBeDefault="true" />
 
         <display-option
             launcher:name="Shorter Stubby"
diff --git a/res/xml/device_profiles_split.xml b/res/xml/device_profiles_split.xml
new file mode 100644
index 0000000..2fad0c9
--- /dev/null
+++ b/res/xml/device_profiles_split.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<profiles xmlns:launcher="http://schemas.android.com/apk/res-auto" >
+
+    <grid-option
+        launcher:name="3_by_3"
+        launcher:numRows="3"
+        launcher:numColumns="3"
+        launcher:numFolderRows="2"
+        launcher:numFolderColumns="3"
+        launcher:numHotseatIcons="3"
+        launcher:dbFile="launcher_3_by_3.db"
+        launcher:defaultLayoutId="@xml/default_workspace_3x3" >
+
+        <display-option
+            launcher:name="Super Short Stubby"
+            launcher:minWidthDps="255"
+            launcher:minHeightDps="300"
+            launcher:iconImageSize="48"
+            launcher:iconTextSize="13.0"
+            launcher:canBeDefault="true" />
+
+        <display-option
+            launcher:name="Shorter Stubby"
+            launcher:minWidthDps="255"
+            launcher:minHeightDps="400"
+            launcher:iconImageSize="48"
+            launcher:iconTextSize="13.0"
+            launcher:canBeDefault="true" />
+
+    </grid-option>
+
+    <grid-option
+        launcher:name="4_by_4"
+        launcher:numRows="4"
+        launcher:numColumns="4"
+        launcher:numFolderRows="3"
+        launcher:numFolderColumns="4"
+        launcher:numHotseatIcons="4"
+        launcher:dbFile="launcher_4_by_4.db"
+        launcher:defaultLayoutId="@xml/default_workspace_4x4" >
+
+        <display-option
+            launcher:name="Short Stubby"
+            launcher:minWidthDps="275"
+            launcher:minHeightDps="420"
+            launcher:iconImageSize="48"
+            launcher:iconTextSize="13.0"
+            launcher:canBeDefault="true" />
+
+        <display-option
+            launcher:name="Stubby"
+            launcher:minWidthDps="255"
+            launcher:minHeightDps="450"
+            launcher:iconImageSize="48"
+            launcher:iconTextSize="13.0"
+            launcher:canBeDefault="true" />
+
+        <display-option
+            launcher:name="Nexus S"
+            launcher:minWidthDps="296"
+            launcher:minHeightDps="491.33"
+            launcher:iconImageSize="48"
+            launcher:iconTextSize="13.0"
+            launcher:canBeDefault="true" />
+
+        <display-option
+            launcher:name="Nexus 4"
+            launcher:minWidthDps="359"
+            launcher:minHeightDps="567"
+            launcher:iconImageSize="54"
+            launcher:iconTextSize="13.0"
+            launcher:canBeDefault="true" />
+
+        <display-option
+            launcher:name="Nexus 5"
+            launcher:minWidthDps="335"
+            launcher:minHeightDps="567"
+            launcher:iconImageSize="54"
+            launcher:iconTextSize="13.0"
+            launcher:canBeDefault="true" />
+
+    </grid-option>
+
+    <grid-option
+        launcher:name="5_by_5"
+        launcher:numRows="5"
+        launcher:numColumns="5"
+        launcher:numFolderRows="4"
+        launcher:numFolderColumns="4"
+        launcher:numHotseatIcons="5"
+        launcher:numExtendedHotseatIcons="8"
+        launcher:dbFile="launcher.db"
+        launcher:defaultLayoutId="@xml/default_workspace_5x5" >
+
+        <display-option
+            launcher:name="Large Phone"
+            launcher:minWidthDps="406"
+            launcher:minHeightDps="694"
+            launcher:iconImageSize="56"
+            launcher:iconTextSize="14.4"
+            launcher:canBeDefault="true" />
+
+        <display-option
+            launcher:name="Large Phone Split Display"
+            launcher:minWidthDps="406"
+            launcher:minHeightDps="694"
+            launcher:iconImageSize="56"
+            launcher:iconTextSize="14.4"
+            launcher:canBeDefault="true" />
+
+        <display-option
+            launcher:name="Shorter Stubby"
+            launcher:minWidthDps="255"
+            launcher:minHeightDps="400"
+            launcher:iconImageSize="48"
+            launcher:iconTextSize="13.0"
+            launcher:canBeDefault="true" />
+
+    </grid-option>
+
+</profiles>
\ No newline at end of file
diff --git a/res/xml/size_limits_80x104.xml b/res/xml/size_limits_80x104.xml
deleted file mode 100644
index 4178664..0000000
--- a/res/xml/size_limits_80x104.xml
+++ /dev/null
@@ -1,114 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2021 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<device-paddings xmlns:launcher="http://schemas.android.com/apk/res-auto" >
-
-    <device-padding
-        launcher:maxEmptySpace="88dp">
-        <workspaceTopPadding
-            launcher:a="0"
-            launcher:b="0"/>
-        <workspaceBottomPadding
-            launcher:a="0.52"
-            launcher:b="0"/>
-        <hotseatBottomPadding
-            launcher:a="0.48"
-            launcher:b="0"/>
-    </device-padding>
-
-    <device-padding
-        launcher:maxEmptySpace="100dp">
-        <workspaceTopPadding
-            launcher:a="0"
-            launcher:b="9dp"/>
-        <workspaceBottomPadding
-            launcher:a="0.40"
-            launcher:b="0"
-            launcher:c="9dp"/>
-        <hotseatBottomPadding
-            launcher:a="0.60"
-            launcher:b="0"
-            launcher:c="9dp"/>
-    </device-padding>
-
-    <device-padding
-        launcher:maxEmptySpace="103dp">
-        <workspaceTopPadding
-            launcher:a="0"
-            launcher:b="26dp"/>
-        <workspaceBottomPadding
-            launcher:a="0"
-            launcher:b="20dp"/>
-        <hotseatBottomPadding
-            launcher:a="1"
-            launcher:b="0"
-            launcher:c="46dp"/>
-    </device-padding>
-
-    <device-padding
-        launcher:maxEmptySpace="107dp">
-        <workspaceTopPadding
-            launcher:a="0"
-            launcher:b="9dp"/>
-        <workspaceBottomPadding
-            launcher:a="0"
-            launcher:b="34dp"/>
-        <hotseatBottomPadding
-            launcher:a="1"
-            launcher:b="0"
-            launcher:c="43dp"/>
-    </device-padding>
-
-    <device-padding
-        launcher:maxEmptySpace="120dp">
-        <workspaceTopPadding
-            launcher:a="0"
-            launcher:b="16dp"/>
-        <workspaceBottomPadding
-            launcher:a="1"
-            launcher:c="72dp"/>
-        <hotseatBottomPadding
-            launcher:a="0"
-            launcher:b="56dp"/>
-    </device-padding>
-
-    <device-padding
-        launcher:maxEmptySpace="135dp">
-        <workspaceTopPadding
-            launcher:a="0"
-            launcher:b="39dp"/>
-        <workspaceBottomPadding
-            launcher:a="1"
-            launcher:c="95dp"/>
-        <hotseatBottomPadding
-            launcher:a="0"
-            launcher:b="56dp"/>
-    </device-padding>
-
-    <device-padding
-        launcher:maxEmptySpace="9999dp">
-        <workspaceTopPadding
-            launcher:a="0.40"
-            launcher:c="36dp"/>
-        <workspaceBottomPadding
-            launcher:a="0.60"
-            launcher:c="36dp"/>
-        <hotseatBottomPadding
-            launcher:a="0"
-            launcher:b="36dp"/>
-    </device-padding>
-</device-paddings>
\ No newline at end of file
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index eec6e0a..1acfae4 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -68,7 +68,6 @@
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.util.SafeCloseable;
 import com.android.launcher3.views.ActivityContext;
-import com.android.launcher3.views.BubbleTextHolder;
 import com.android.launcher3.views.IconLabelDotView;
 
 import java.text.NumberFormat;
@@ -168,6 +167,7 @@
     private HandlerRunnable mIconLoadRequest;
 
     private boolean mEnableIconUpdateAnimation = false;
+    private ItemInfoUpdateReceiver mItemInfoUpdateReceiver;
 
     public BubbleTextView(Context context) {
         this(context, null, 0);
@@ -245,6 +245,7 @@
         mDotParams.scale = 0f;
         mForceHideDot = false;
         setBackground(null);
+        mItemInfoUpdateReceiver = null;
     }
 
     private void cancelDotScaleAnim() {
@@ -342,13 +343,18 @@
         setDownloadStateContentDescription(info, info.getProgressLevel());
     }
 
-    private void setItemInfo(ItemInfo itemInfo) {
+    private void setItemInfo(ItemInfoWithIcon itemInfo) {
         setTag(itemInfo);
-        if (getParent() instanceof BubbleTextHolder) {
-            ((BubbleTextHolder) getParent()).onItemInfoChanged(itemInfo);
+        if (mItemInfoUpdateReceiver != null) {
+            mItemInfoUpdateReceiver.reapplyItemInfo(itemInfo);
         }
     }
 
+    public void setItemInfoUpdateReceiver(
+            ItemInfoUpdateReceiver itemInfoUpdateReceiver) {
+        mItemInfoUpdateReceiver = itemInfoUpdateReceiver;
+    }
+
     @UiThread
     protected void applyIconAndLabel(ItemInfoWithIcon info) {
         boolean useTheme = mDisplay == DISPLAY_WORKSPACE || mDisplay == DISPLAY_FOLDER
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 4e06ff9..0b60b32 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -80,6 +80,7 @@
     public final float aspectRatio;
 
     public final boolean isScalableGrid;
+    private final int mTypeIndex;
 
     /**
      * The maximum amount of left/right workspace padding as a percentage of the screen width.
@@ -169,7 +170,7 @@
     public int qsbBottomMarginPx;
 
     // All apps
-    public int allAppsCellSpacingPx;
+    public Point allAppsCellSpacePx;
     public int allAppsOpenVerticalTranslate;
     public int allAppsCellHeightPx;
     public int allAppsCellWidthPx;
@@ -262,6 +263,20 @@
         mMetrics = context.getResources().getDisplayMetrics();
         final Resources res = context.getResources();
 
+        if (isTwoPanels) {
+            if (isLandscape) {
+                mTypeIndex = InvariantDeviceProfile.INDEX_TWO_PANEL_LANDSCAPE;
+            } else {
+                mTypeIndex = InvariantDeviceProfile.INDEX_TWO_PANEL_PORTRAIT;
+            }
+        } else {
+            if (isLandscape) {
+                mTypeIndex = InvariantDeviceProfile.INDEX_LANDSCAPE;
+            } else {
+                mTypeIndex = InvariantDeviceProfile.INDEX_DEFAULT;
+            }
+        }
+
         hotseatQsbHeight = res.getDimensionPixelSize(R.dimen.qsb_widget_height);
         isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS
                 && FeatureFlags.ENABLE_TASKBAR.get();
@@ -283,7 +298,9 @@
         folderContentPaddingTop = res.getDimensionPixelSize(R.dimen.folder_content_padding_top);
 
         cellLayoutBorderSpacePx = getCellLayoutBorderSpace(inv);
-        allAppsCellSpacingPx = pxFromDp(inv.allAppsCellSpacing, mMetrics, 1f);
+        allAppsCellSpacePx = new Point(
+                pxFromDp(inv.borderSpaces[InvariantDeviceProfile.INDEX_ALL_APPS].x, mMetrics, 1f),
+                pxFromDp(inv.borderSpaces[InvariantDeviceProfile.INDEX_ALL_APPS].y, mMetrics, 1f));
         cellLayoutBorderSpaceOriginalPx = new Point(cellLayoutBorderSpacePx);
         folderCellLayoutBorderSpaceOriginalPx = pxFromDp(inv.folderBorderSpace, mMetrics, 1f);
         folderCellLayoutBorderSpacePx = new Point(folderCellLayoutBorderSpaceOriginalPx,
@@ -339,7 +356,8 @@
         hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
         hotseatExtraVerticalSize =
                 res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size);
-        updateHotseatIconSize(pxFromDp(inv.iconSize, mMetrics, 1f));
+        updateHotseatIconSize(
+                pxFromDp(inv.iconSize[InvariantDeviceProfile.INDEX_DEFAULT], mMetrics, 1f));
 
         qsbBottomMarginOriginalPx = isScalableGrid
                 ? res.getDimensionPixelSize(R.dimen.scalable_grid_qsb_bottom_margin)
@@ -451,22 +469,9 @@
             return 0;
         }
 
-        int horizontalMarginPx;
-
-        if (isScalableGrid) {
-            if (isTwoPanels) {
-                if (isLandscape) {
-                    horizontalMarginPx = pxFromDp(idp.twoPanelLandscapeHorizontalMargin, mMetrics);
-                } else {
-                    horizontalMarginPx = pxFromDp(idp.twoPanelPortraitHorizontalMargin, mMetrics);
-                }
-            } else {
-                horizontalMarginPx = pxFromDp(idp.horizontalMargin, mMetrics);
-            }
-        } else {
-            horizontalMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_left_right_margin);
-        }
-        return horizontalMarginPx;
+        return isScalableGrid
+                ? pxFromDp(idp.horizontalMargin[mTypeIndex], mMetrics)
+                : res.getDimensionPixelSize(R.dimen.dynamic_grid_left_right_margin);
     }
 
     private void updateHotseatIconSize(int hotseatIconSizePx) {
@@ -487,21 +492,8 @@
             return new Point(0, 0);
         }
 
-        int horizontalSpacePx;
-        int verticalSpacePx;
-
-        if (isTwoPanels) {
-            if (isLandscape) {
-                horizontalSpacePx = pxFromDp(idp.twoPanelLandscapeBorderSpace.x, mMetrics);
-                verticalSpacePx = pxFromDp(idp.twoPanelLandscapeBorderSpace.y, mMetrics);
-            } else {
-                horizontalSpacePx = pxFromDp(idp.twoPanelPortraitBorderSpace.x, mMetrics);
-                verticalSpacePx = pxFromDp(idp.twoPanelPortraitBorderSpace.y, mMetrics);
-            }
-        } else {
-            horizontalSpacePx = pxFromDp(idp.borderSpace.x, mMetrics);
-            verticalSpacePx = pxFromDp(idp.borderSpace.y, mMetrics);
-        }
+        int horizontalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].x, mMetrics);
+        int verticalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].y, mMetrics);
 
         return new Point(horizontalSpacePx, verticalSpacePx);
     }
@@ -598,7 +590,7 @@
     private void updateAllAppsWidth() {
         if (isTwoPanels) {
             int usedWidth = (allAppsCellWidthPx * numShownAllAppsColumns)
-                    + (allAppsCellSpacingPx * (numShownAllAppsColumns + 1));
+                    + (allAppsCellSpacePx.x * (numShownAllAppsColumns + 1));
             allAppsLeftRightPadding = Math.max(1, (availableWidthPx - usedWidth) / 2);
         } else {
             allAppsLeftRightPadding =
@@ -661,26 +653,8 @@
 
         // Workspace
         final boolean isVerticalLayout = isVerticalBarLayout();
-        float invIconSizeDp;
-        float invIconTextSizeSp;
-
-        if (isTwoPanels) {
-            if (isLandscape) {
-                invIconSizeDp = inv.twoPanelLandscapeIconSize;
-                invIconTextSizeSp = inv.twoPanelLandscapeIconTextSize;
-            } else {
-                invIconSizeDp = inv.twoPanelPortraitIconSize;
-                invIconTextSizeSp = inv.twoPanelPortraitIconTextSize;
-            }
-        } else {
-            if (isLandscape) {
-                invIconSizeDp = inv.landscapeIconSize;
-                invIconTextSizeSp = inv.landscapeIconTextSize;
-            } else {
-                invIconSizeDp = inv.iconSize;
-                invIconTextSizeSp = inv.iconTextSize;
-            }
-        }
+        float invIconSizeDp = inv.iconSize[mTypeIndex];
+        float invIconTextSizeSp = inv.iconTextSize[mTypeIndex];
 
         iconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics, iconScale));
         iconTextSizePx = (int) (pxFromSp(invIconTextSizeSp, mMetrics) * iconScale);
@@ -689,9 +663,8 @@
         cellLayoutBorderSpacePx = getCellLayoutBorderSpaceScaled(inv, scale);
 
         if (isScalableGrid) {
-            PointF minCellHeightAndWidth = getMinCellHeightAndWidth();
-            cellWidthPx = pxFromDp(minCellHeightAndWidth.x, mMetrics, scale);
-            cellHeightPx = pxFromDp(minCellHeightAndWidth.y, mMetrics, scale);
+            cellWidthPx = pxFromDp(inv.minCellSize[mTypeIndex].x, mMetrics, scale);
+            cellHeightPx = pxFromDp(inv.minCellSize[mTypeIndex].y, mMetrics, scale);
             int cellContentHeight = iconSizePx + iconDrawablePaddingPx
                     + Utilities.calculateTextHeight(iconTextSizePx);
             cellYPaddingPx = Math.max(0, cellHeightPx - cellContentHeight) / 2;
@@ -715,8 +688,10 @@
 
         // All apps
         if (numShownAllAppsColumns != inv.numColumns) {
-            allAppsIconSizePx = pxFromDp(inv.allAppsIconSize, mMetrics);
-            allAppsIconTextSizePx = pxFromSp(inv.allAppsIconTextSize, mMetrics);
+            allAppsIconSizePx =
+                    pxFromDp(inv.iconSize[InvariantDeviceProfile.INDEX_ALL_APPS], mMetrics);
+            allAppsIconTextSizePx =
+                    pxFromSp(inv.iconTextSize[InvariantDeviceProfile.INDEX_ALL_APPS], mMetrics);
             allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx;
             autoResizeAllAppsCells();
         } else {
@@ -752,28 +727,6 @@
         folderIconOffsetYPx = (iconSizePx - folderIconSizePx) / 2;
     }
 
-    /**
-     * Returns the minimum cell height and width as a pair.
-     */
-    private PointF getMinCellHeightAndWidth() {
-        PointF result = new PointF();
-
-        if (isTwoPanels) {
-            if (isLandscape) {
-                result.x = inv.twoPanelLandscapeMinCellWidthDps;
-                result.y = inv.twoPanelLandscapeMinCellHeightDps;
-            } else {
-                result.x = inv.twoPanelPortraitMinCellWidthDps;
-                result.y = inv.twoPanelPortraitMinCellHeightDps;
-            }
-        } else {
-            result.x = inv.minCellWidth;
-            result.y = inv.minCellHeight;
-        }
-
-        return result;
-    }
-
     private void updateAvailableFolderCellDimensions(Resources res) {
         updateFolderCellSize(1f, res);
 
@@ -804,9 +757,12 @@
     }
 
     private void updateFolderCellSize(float scale, Resources res) {
-        float invIconSizeDp = isVerticalBarLayout() ? inv.landscapeIconSize : inv.iconSize;
+        float invIconSizeDp = isVerticalBarLayout()
+                ? inv.iconSize[InvariantDeviceProfile.INDEX_LANDSCAPE]
+                : inv.iconSize[InvariantDeviceProfile.INDEX_DEFAULT];
         folderChildIconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics, scale));
-        folderChildTextSizePx = pxFromSp(inv.iconTextSize, mMetrics, scale);
+        folderChildTextSizePx =
+                pxFromSp(inv.iconTextSize[InvariantDeviceProfile.INDEX_DEFAULT], mMetrics, scale);
         folderLabelTextSizePx = (int) (folderChildTextSizePx * folderLabelTextScale);
 
         int textHeight = Utilities.calculateTextHeight(folderChildTextSizePx);
@@ -901,7 +857,7 @@
                     + workspaceBottomPadding - mWorkspacePageIndicatorOverlapWorkspace;
 
             padding.set(desiredWorkspaceHorizontalMarginPx,
-                    (isScalableGrid ? workspaceTopPadding : edgeMarginPx),
+                    workspaceTopPadding + (isScalableGrid ? 0 : edgeMarginPx),
                     desiredWorkspaceHorizontalMarginPx,
                     paddingBottom);
         }
@@ -1094,19 +1050,10 @@
 
         writer.println(prefix + "\tisScalableGrid:" + isScalableGrid);
 
-        writer.println(prefix + "\tinv.minCellWidth:" + inv.minCellWidth + "dp");
-        writer.println(prefix + "\tinv.minCellHeight:" + inv.minCellHeight + "dp");
-        writer.println(prefix + "\tinv.twoPanelPortraitMinCellHeightDps:"
-                + inv.twoPanelPortraitMinCellHeightDps + "dp");
-        writer.println(prefix + "\tinv.twoPanelPortraitMinCellWidthDps:"
-                + inv.twoPanelPortraitMinCellWidthDps + "dp");
-        writer.println(prefix + "\tinv.twoPanelLandscapeMinCellHeightDps:"
-                + inv.twoPanelLandscapeMinCellHeightDps + "dp");
-        writer.println(prefix + "\tinv.twoPanelLandscapeMinCellWidthDps:"
-                + inv.twoPanelLandscapeMinCellWidthDps + "dp");
+        writer.println(prefix + "\tinv.numColumns: " + inv.numColumns);
+        writer.println(prefix + "\tinv.numRows: " + inv.numRows);
 
-        writer.println(prefix + "\tinv.numColumns:" + inv.numColumns);
-        writer.println(prefix + "\tinv.numRows:" + inv.numRows);
+        writer.println(prefix + "\tminCellSize: " + inv.minCellSize[mTypeIndex] + "dp");
 
         writer.println(prefix + pxToDpStr("cellWidthPx", cellWidthPx));
         writer.println(prefix + pxToDpStr("cellHeightPx", cellHeightPx));
@@ -1114,7 +1061,11 @@
         writer.println(prefix + pxToDpStr("getCellSize().x", getCellSize().x));
         writer.println(prefix + pxToDpStr("getCellSize().y", getCellSize().y));
 
-        writer.println(prefix + "\tinv.iconSize:" + inv.iconSize + "dp");
+        writer.println(prefix + pxToDpStr("cellLayoutBorderSpacePx Horizontal",
+                cellLayoutBorderSpacePx.x));
+        writer.println(prefix + pxToDpStr("cellLayoutBorderSpacePx Vertical",
+                cellLayoutBorderSpacePx.y));
+
         writer.println(prefix + pxToDpStr("iconSizePx", iconSizePx));
         writer.println(prefix + pxToDpStr("iconTextSizePx", iconTextSizePx));
         writer.println(prefix + pxToDpStr("iconDrawablePaddingPx", iconDrawablePaddingPx));
@@ -1132,14 +1083,6 @@
         writer.println(prefix + pxToDpStr("folderCellLayoutBorderSpacePx Vertical",
                 folderCellLayoutBorderSpacePx.y));
 
-        writer.println(prefix + pxToDpStr("cellLayoutBorderSpacePx Horizontal",
-                cellLayoutBorderSpacePx.x));
-        writer.println(prefix + pxToDpStr("cellLayoutBorderSpacePx Vertical",
-                cellLayoutBorderSpacePx.y));
-
-        writer.println(prefix + pxToDpStr("desiredWorkspaceHorizontalMarginPx",
-                desiredWorkspaceHorizontalMarginPx));
-
         writer.println(prefix + pxToDpStr("allAppsIconSizePx", allAppsIconSizePx));
         writer.println(prefix + pxToDpStr("allAppsIconTextSizePx", allAppsIconTextSizePx));
         writer.println(prefix + pxToDpStr("allAppsIconDrawablePaddingPx",
@@ -1161,6 +1104,8 @@
         writer.println(prefix + "\tisTaskbarPresentInApps:" + isTaskbarPresentInApps);
         writer.println(prefix + pxToDpStr("taskbarSize", taskbarSize));
 
+        writer.println(prefix + pxToDpStr("desiredWorkspaceHorizontalMarginPx",
+                desiredWorkspaceHorizontalMarginPx));
         writer.println(prefix + pxToDpStr("workspacePadding.left", workspacePadding.left));
         writer.println(prefix + pxToDpStr("workspacePadding.top", workspacePadding.top));
         writer.println(prefix + pxToDpStr("workspacePadding.right", workspacePadding.right));
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index 08cc730..eb42a65 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -275,20 +275,8 @@
     @Override
     protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
         super.onVisibilityChanged(changedView, visibility);
-        if (TestProtocol.sDebugTracing) {
-            if (visibility == VISIBLE) {
-                Log.d(TestProtocol.NO_DROP_TARGET, "9");
-            } else {
-                Log.d(TestProtocol.NO_DROP_TARGET, "Hiding drop target", new Exception());
-            }
-        }
-    }
-
-    @Override
-    public void onVisibilityAggregated(boolean isVisible) {
-        super.onVisibilityAggregated(isVisible);
-        if (TestProtocol.sDebugTracing) {
-            Log.d(TestProtocol.NO_DROP_TARGET, "onVisibilityAggregated: " + isVisible);
+        if (TestProtocol.sDebugTracing && visibility == VISIBLE) {
+            Log.d(TestProtocol.NO_DROP_TARGET, "9");
         }
     }
 }
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index e86c02c..ffe3816 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -198,6 +198,10 @@
         getShortcutsAndWidgets().setAlpha(alpha);
     }
 
+    public float getIconsAlpha() {
+        return getShortcutsAndWidgets().getAlpha();
+    }
+
     /**
      * Returns the QSB inside hotseat
      */
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index cfc14b6..d844b87 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -46,6 +46,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.launcher3.model.DeviceGridState;
+import com.android.launcher3.provider.RestoreDbTask;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.DisplayController.Info;
 import com.android.launcher3.util.IntArray;
@@ -69,11 +70,6 @@
     public static final MainThreadInitializedObject<InvariantDeviceProfile> INSTANCE =
             new MainThreadInitializedObject<>(InvariantDeviceProfile::new);
 
-    private static final int DEFAULT_TRUE = -1;
-    private static final int DEFAULT_SPLIT_DISPLAY = 2;
-    private static final int GRID_ENABLED_ALL_DISPLAYS = 0;
-    private static final int GRID_ENABLED_SINGLE_DISPLAY = 1;
-
     private static final String KEY_IDP_GRID_NAME = "idp_grid_name";
 
     private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48;
@@ -86,6 +82,15 @@
     // used to offset float not being able to express extremely small weights in extreme cases.
     private static final float WEIGHT_EFFICIENT = 100000f;
 
+    // Used for arrays to specify different sizes (e.g. border spaces, width/height) in different
+    // constraints
+    static final int COUNT_SIZES = 5;
+    static final int INDEX_DEFAULT = 0;
+    static final int INDEX_LANDSCAPE = 1;
+    static final int INDEX_TWO_PANEL_PORTRAIT = 2;
+    static final int INDEX_TWO_PANEL_LANDSCAPE = 3;
+    static final int INDEX_ALL_APPS = 4;
+
     /**
      * Number of icons per row and column in the workspace.
      */
@@ -97,36 +102,18 @@
      */
     public int numFolderRows;
     public int numFolderColumns;
-    public float iconSize;
-    public float landscapeIconSize;
-    public float twoPanelPortraitIconSize;
-    public float twoPanelLandscapeIconSize;
-    public float landscapeIconTextSize;
-    public float twoPanelPortraitIconTextSize;
-    public float twoPanelLandscapeIconTextSize;
+    public float[] iconSize;
+    public float[] iconTextSize;
     public int iconBitmapSize;
     public int fillResIconDpi;
-    public float iconTextSize;
-    public float allAppsIconSize;
-    public float allAppsIconTextSize;
-    public float allAppsCellSpacing;
     public boolean isSplitDisplay;
 
-    public float minCellHeight;
-    public float minCellWidth;
-    public float twoPanelPortraitMinCellHeightDps;
-    public float twoPanelPortraitMinCellWidthDps;
-    public float twoPanelLandscapeMinCellHeightDps;
-    public float twoPanelLandscapeMinCellWidthDps;
+    public PointF[] minCellSize;
 
-    public PointF borderSpace;
-    public PointF twoPanelPortraitBorderSpace;
-    public PointF twoPanelLandscapeBorderSpace;
+    public PointF[] borderSpaces;
     public float folderBorderSpace;
 
-    public float horizontalMargin;
-    public float twoPanelLandscapeHorizontalMargin;
-    public float twoPanelPortraitHorizontalMargin;
+    public float[] horizontalMargin;
 
     private SparseArray<TypedValue> mExtraAttrs;
 
@@ -213,29 +200,52 @@
         // Get the display info based on default display and interpolate it to existing display
         DisplayOption defaultDisplayOption = invDistWeightedInterpolate(
                 DisplayController.INSTANCE.get(context).getInfo(),
-                getPredefinedDeviceProfiles(context, gridName, false), false);
+                getPredefinedDeviceProfiles(context, gridName, false, false), false);
 
         Info myInfo = new Info(context, display);
         DisplayOption myDisplayOption = invDistWeightedInterpolate(
-                myInfo, getPredefinedDeviceProfiles(context, gridName, false), false);
+                myInfo, getPredefinedDeviceProfiles(context, gridName, false, false), false);
 
         DisplayOption result = new DisplayOption(defaultDisplayOption.grid)
                 .add(myDisplayOption);
-        result.iconSizes[DisplayOption.INDEX_DEFAULT] =
-                defaultDisplayOption.iconSizes[DisplayOption.INDEX_DEFAULT];
-        for (int i = 1; i < DisplayOption.COUNT_SIZES; i++) {
+        result.iconSizes[INDEX_DEFAULT] =
+                defaultDisplayOption.iconSizes[INDEX_DEFAULT];
+        for (int i = 1; i < COUNT_SIZES; i++) {
             result.iconSizes[i] = Math.min(
                     defaultDisplayOption.iconSizes[i], myDisplayOption.iconSizes[i]);
         }
 
-        result.minCellHeight = defaultDisplayOption.minCellHeight;
-        result.minCellWidth = defaultDisplayOption.minCellWidth;
-        result.borderSpaces[DisplayOption.INDEX_ALL_APPS] =
-                defaultDisplayOption.borderSpaces[DisplayOption.INDEX_ALL_APPS];
+        System.arraycopy(defaultDisplayOption.minCellSize, 0, result.minCellSize, 0,
+                COUNT_SIZES);
+        System.arraycopy(defaultDisplayOption.borderSpaces, 0, result.borderSpaces, 0,
+                COUNT_SIZES);
 
         initGrid(context, myInfo, result, false);
     }
 
+    /**
+     * Reinitialize the current grid after a restore, where some grids might now be disabled.
+     */
+    public void reinitializeAfterRestore(Context context) {
+        String currentDbFile = dbFile;
+        String gridName = getCurrentGridName(context);
+        String newGridName = initGrid(context, gridName);
+        if (!newGridName.equals(gridName)) {
+            Log.d(TAG, "Restored grid is disabled : " + gridName
+                    + ", migrating to: " + newGridName
+                    + ", removing all other grid db files");
+            for (String gridDbFile : LauncherFiles.GRID_DB_FILES) {
+                if (gridDbFile.equals(currentDbFile)) {
+                    continue;
+                }
+                if (context.getDatabasePath(gridDbFile).delete()) {
+                    Log.d(TAG, "Removed old grid db file: " + gridDbFile);
+                }
+            }
+            setCurrentGrid(context, gridName);
+        }
+    }
+
     public static String getCurrentGridName(Context context) {
         return Utilities.isGridOptionsEnabled(context)
                 ? Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null) : null;
@@ -249,7 +259,8 @@
                 displayInfo.supportedBounds.size() >= 4 && ENABLE_TWO_PANEL_HOME.get();
 
         ArrayList<DisplayOption> allOptions =
-                getPredefinedDeviceProfiles(context, gridName, isSplitDisplay);
+                getPredefinedDeviceProfiles(context, gridName, isSplitDisplay,
+                        RestoreDbTask.isPending(context));
         DisplayOption displayOption =
                 invDistWeightedInterpolate(displayInfo, allOptions, isSplitDisplay);
         initGrid(context, displayInfo, displayOption, isSplitDisplay);
@@ -274,39 +285,18 @@
 
         mExtraAttrs = closestProfile.extraAttrs;
 
-        iconSize = displayOption.iconSizes[DisplayOption.INDEX_DEFAULT];
-        landscapeIconSize = displayOption.iconSizes[DisplayOption.INDEX_LANDSCAPE];
-        twoPanelPortraitIconSize = displayOption.iconSizes[DisplayOption.INDEX_TWO_PANEL_PORTRAIT];
-        twoPanelLandscapeIconSize =
-                displayOption.iconSizes[DisplayOption.INDEX_TWO_PANEL_LANDSCAPE];
-        iconBitmapSize = ResourceUtils.pxFromDp(iconSize, metrics);
+        iconSize = displayOption.iconSizes;
+        iconBitmapSize = ResourceUtils.pxFromDp(iconSize[INDEX_DEFAULT], metrics);
         fillResIconDpi = getLauncherIconDensity(iconBitmapSize);
 
-        iconTextSize = displayOption.textSizes[DisplayOption.INDEX_DEFAULT];
-        landscapeIconTextSize = displayOption.textSizes[DisplayOption.INDEX_LANDSCAPE];
-        twoPanelPortraitIconTextSize =
-                displayOption.textSizes[DisplayOption.INDEX_TWO_PANEL_PORTRAIT];
-        twoPanelLandscapeIconTextSize =
-                displayOption.textSizes[DisplayOption.INDEX_TWO_PANEL_LANDSCAPE];
+        iconTextSize = displayOption.textSizes;
 
-        minCellHeight = displayOption.minCellHeight;
-        minCellWidth = displayOption.minCellWidth;
-        twoPanelPortraitMinCellHeightDps = displayOption.twoPanelPortraitMinCellHeightDps;
-        twoPanelPortraitMinCellWidthDps = displayOption.twoPanelPortraitMinCellWidthDps;
-        twoPanelLandscapeMinCellHeightDps = displayOption.twoPanelLandscapeMinCellHeightDps;
-        twoPanelLandscapeMinCellWidthDps = displayOption.twoPanelLandscapeMinCellWidthDps;
+        minCellSize = displayOption.minCellSize;
 
-        borderSpace = displayOption.borderSpaces[DisplayOption.INDEX_DEFAULT];
-        twoPanelPortraitBorderSpace =
-                displayOption.borderSpaces[DisplayOption.INDEX_TWO_PANEL_PORTRAIT];
-        twoPanelLandscapeBorderSpace =
-                displayOption.borderSpaces[DisplayOption.INDEX_TWO_PANEL_LANDSCAPE];
-        allAppsCellSpacing = displayOption.borderSpaces[DisplayOption.INDEX_ALL_APPS].x;
+        borderSpaces = displayOption.borderSpaces;
         folderBorderSpace = displayOption.folderBorderSpace;
 
         horizontalMargin = displayOption.horizontalMargin;
-        twoPanelLandscapeHorizontalMargin = displayOption.twoPanelLandscapeHorizontalMargin;
-        twoPanelPortraitHorizontalMargin = displayOption.twoPanelPortraitHorizontalMargin;
 
         numShownHotseatIcons = closestProfile.numHotseatIcons;
         numDatabaseHotseatIcons = isSplitDisplay
@@ -316,12 +306,9 @@
         numDatabaseAllAppsColumns = isSplitDisplay
                 ? closestProfile.numDatabaseAllAppsColumns : closestProfile.numAllAppsColumns;
 
-        if (Utilities.isGridOptionsEnabled(context)) {
-            allAppsIconSize = displayOption.iconSizes[DisplayOption.INDEX_ALL_APPS];
-            allAppsIconTextSize = displayOption.textSizes[DisplayOption.INDEX_ALL_APPS];
-        } else {
-            allAppsIconSize = iconSize;
-            allAppsIconTextSize = iconTextSize;
+        if (!Utilities.isGridOptionsEnabled(context)) {
+            iconSize[INDEX_ALL_APPS] = iconSize[INDEX_DEFAULT];
+            iconTextSize[INDEX_ALL_APPS] = iconTextSize[INDEX_DEFAULT];
         }
 
         if (devicePaddingId != 0) {
@@ -399,9 +386,11 @@
     }
 
     private static ArrayList<DisplayOption> getPredefinedDeviceProfiles(
-            Context context, String gridName, boolean isSplitDisplay) {
+            Context context, String gridName, boolean isSplitDisplay, boolean allowDisabledGrid) {
         ArrayList<DisplayOption> profiles = new ArrayList<>();
-        try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
+        int xmlResource = isSplitDisplay ? R.xml.device_profiles_split : R.xml.device_profiles;
+
+        try (XmlResourceParser parser = context.getResources().getXml(xmlResource)) {
             final int depth = parser.getDepth();
             int type;
             while (((type = parser.next()) != XmlPullParser.END_TAG ||
@@ -411,7 +400,7 @@
 
                     GridOption gridOption =
                             new GridOption(context, Xml.asAttributeSet(parser), isSplitDisplay);
-                    if (gridOption.isEnabled) {
+                    if (gridOption.isEnabled || allowDisabledGrid) {
                         final int displayDepth = parser.getDepth();
                         while (((type = parser.next()) != XmlPullParser.END_TAG
                                 || parser.getDepth() > displayDepth)
@@ -419,8 +408,7 @@
                             if ((type == XmlPullParser.START_TAG) && "display-option".equals(
                                     parser.getName())) {
                                 profiles.add(new DisplayOption(gridOption, context,
-                                        Xml.asAttributeSet(parser),
-                                        isSplitDisplay ? DEFAULT_SPLIT_DISPLAY : DEFAULT_TRUE));
+                                        Xml.asAttributeSet(parser)));
                             }
                         }
                     }
@@ -433,7 +421,8 @@
         ArrayList<DisplayOption> filteredProfiles = new ArrayList<>();
         if (!TextUtils.isEmpty(gridName)) {
             for (DisplayOption option : profiles) {
-                if (gridName.equals(option.grid.name) && option.grid.isEnabled) {
+                if (gridName.equals(option.grid.name)
+                        && (option.grid.isEnabled || allowDisabledGrid)) {
                     filteredProfiles.add(option);
                 }
             }
@@ -457,7 +446,9 @@
      */
     public List<GridOption> parseAllGridOptions(Context context) {
         List<GridOption> result = new ArrayList<>();
-        try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
+        int xmlResource = isSplitDisplay ? R.xml.device_profiles_split : R.xml.device_profiles;
+
+        try (XmlResourceParser parser = context.getResources().getXml(xmlResource)) {
             final int depth = parser.getDepth();
             int type;
             while (((type = parser.next()) != XmlPullParser.END_TAG
@@ -566,11 +557,11 @@
 
         // Since the bitmaps are persisted, ensure that the default bitmap size is same as
         // predefined size to avoid cache invalidation
-        out.iconSizes[DisplayOption.INDEX_DEFAULT] =
-                closestPoint.iconSizes[DisplayOption.INDEX_DEFAULT];
-        for (int i = DisplayOption.INDEX_DEFAULT + 1; i < DisplayOption.COUNT_SIZES; i++) {
+        out.iconSizes[INDEX_DEFAULT] =
+                closestPoint.iconSizes[INDEX_DEFAULT];
+        for (int i = INDEX_DEFAULT + 1; i < COUNT_SIZES; i++) {
             out.iconSizes[i] = Math.min(out.iconSizes[i],
-                    out.iconSizes[DisplayOption.INDEX_DEFAULT]);
+                    out.iconSizes[INDEX_DEFAULT]);
         }
 
         return out;
@@ -709,11 +700,7 @@
             devicePaddingId = a.getResourceId(
                     R.styleable.GridDisplayOption_devicePaddingId, 0);
 
-            final int enabledInt =
-                    a.getInteger(R.styleable.GridDisplayOption_gridEnabled,
-                            GRID_ENABLED_ALL_DISPLAYS);
-            isEnabled = enabledInt == GRID_ENABLED_ALL_DISPLAYS
-                    || enabledInt == GRID_ENABLED_SINGLE_DISPLAY && !isSplitDisplay;
+            isEnabled = a.getBoolean(R.styleable.GridDisplayOption_gridEnabled, true);
 
             a.recycle();
             extraAttrs = Themes.createValueMap(context, attrs,
@@ -724,69 +711,57 @@
     @VisibleForTesting
     static final class DisplayOption {
 
-        static final int COUNT_SIZES = 5;
-        static final int INDEX_DEFAULT = 0;
-        static final int INDEX_LANDSCAPE = 1;
-        static final int INDEX_TWO_PANEL_PORTRAIT = 2;
-        static final int INDEX_TWO_PANEL_LANDSCAPE = 3;
-        static final int INDEX_ALL_APPS = 4;
-
         public final GridOption grid;
 
         private final float minWidthDps;
         private final float minHeightDps;
         private final boolean canBeDefault;
 
-        private float minCellHeight;
-        private float minCellWidth;
-        private float twoPanelPortraitMinCellHeightDps;
-        private float twoPanelPortraitMinCellWidthDps;
-        private float twoPanelLandscapeMinCellHeightDps;
-        private float twoPanelLandscapeMinCellWidthDps;
+        private final PointF[] minCellSize = new PointF[COUNT_SIZES];
 
         private float folderBorderSpace;
         private final PointF[] borderSpaces = new PointF[COUNT_SIZES];
-
-        private float horizontalMargin;
-        private float twoPanelLandscapeHorizontalMargin;
-        private float twoPanelPortraitHorizontalMargin;
+        private final float[] horizontalMargin = new float[COUNT_SIZES];
 
         private final float[] iconSizes = new float[COUNT_SIZES];
         private final float[] textSizes = new float[COUNT_SIZES];
 
-        DisplayOption(GridOption grid, Context context, AttributeSet attrs, int defaultFlagValue) {
+        DisplayOption(GridOption grid, Context context, AttributeSet attrs) {
             this.grid = grid;
 
-            TypedArray a = context.obtainStyledAttributes(
-                    attrs, R.styleable.ProfileDisplayOption);
+            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProfileDisplayOption);
 
             minWidthDps = a.getFloat(R.styleable.ProfileDisplayOption_minWidthDps, 0);
             minHeightDps = a.getFloat(R.styleable.ProfileDisplayOption_minHeightDps, 0);
 
-            canBeDefault = a.getInt(R.styleable.ProfileDisplayOption_canBeDefault, 0)
-                    == defaultFlagValue;
+            canBeDefault = a.getBoolean(R.styleable.ProfileDisplayOption_canBeDefault, false);
 
-            minCellHeight = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightDps, 0);
-            minCellWidth = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthDps, 0);
-            twoPanelPortraitMinCellHeightDps = a.getFloat(
-                    R.styleable.ProfileDisplayOption_twoPanelPortraitMinCellHeightDps,
-                    minCellHeight);
-            twoPanelPortraitMinCellWidthDps = a.getFloat(
-                    R.styleable.ProfileDisplayOption_twoPanelPortraitMinCellWidthDps, minCellWidth);
-            twoPanelLandscapeMinCellHeightDps = a.getFloat(
-                    R.styleable.ProfileDisplayOption_twoPanelLandscapeMinCellHeightDps,
-                    twoPanelPortraitMinCellHeightDps);
-            twoPanelLandscapeMinCellWidthDps = a.getFloat(
-                    R.styleable.ProfileDisplayOption_twoPanelLandscapeMinCellWidthDps,
-                    twoPanelPortraitMinCellWidthDps);
+            float x;
+            float y;
+
+            x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthDps, 0);
+            y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightDps, 0);
+            minCellSize[INDEX_DEFAULT] = new PointF(x, y);
+            minCellSize[INDEX_LANDSCAPE] = new PointF(x, y);
+            minCellSize[INDEX_ALL_APPS] = new PointF(x, y);
+
+            x = a.getFloat(R.styleable.ProfileDisplayOption_twoPanelPortraitMinCellWidthDps,
+                    minCellSize[INDEX_DEFAULT].x);
+            y = a.getFloat(R.styleable.ProfileDisplayOption_twoPanelPortraitMinCellHeightDps,
+                    minCellSize[INDEX_DEFAULT].y);
+            minCellSize[INDEX_TWO_PANEL_PORTRAIT] = new PointF(x, y);
+
+            x = a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeMinCellWidthDps,
+                    minCellSize[INDEX_DEFAULT].x);
+            y = a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeMinCellHeightDps,
+                    minCellSize[INDEX_DEFAULT].y);
+            minCellSize[INDEX_TWO_PANEL_LANDSCAPE] = new PointF(x, y);
 
             float borderSpace = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceDps, 0);
             float twoPanelPortraitBorderSpaceDps = a.getFloat(
                     R.styleable.ProfileDisplayOption_twoPanelPortraitBorderSpaceDps, borderSpace);
             float twoPanelLandscapeBorderSpaceDps = a.getFloat(
                     R.styleable.ProfileDisplayOption_twoPanelLandscapeBorderSpaceDps, borderSpace);
-            float x;
-            float y;
 
             x = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceHorizontalDps, borderSpace);
             y = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceVerticalDps, borderSpace);
@@ -827,7 +802,7 @@
                             iconSizes[INDEX_DEFAULT]);
             iconSizes[INDEX_TWO_PANEL_LANDSCAPE] =
                     a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeIconSize,
-                            iconSizes[INDEX_LANDSCAPE]);
+                            iconSizes[INDEX_DEFAULT]);
 
             textSizes[INDEX_DEFAULT] =
                     a.getFloat(R.styleable.ProfileDisplayOption_iconTextSize, 0);
@@ -842,15 +817,18 @@
                             textSizes[INDEX_DEFAULT]);
             textSizes[INDEX_TWO_PANEL_LANDSCAPE] =
                     a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeIconTextSize,
-                            textSizes[INDEX_LANDSCAPE]);
+                            textSizes[INDEX_DEFAULT]);
 
-            horizontalMargin = a.getFloat(R.styleable.ProfileDisplayOption_horizontalMargin, 0);
-            twoPanelLandscapeHorizontalMargin = a.getFloat(
+            horizontalMargin[INDEX_DEFAULT] = a.getFloat(
+                    R.styleable.ProfileDisplayOption_horizontalMargin, 0);
+            horizontalMargin[INDEX_LANDSCAPE] = horizontalMargin[INDEX_DEFAULT];
+            horizontalMargin[INDEX_ALL_APPS] = horizontalMargin[INDEX_DEFAULT];
+            horizontalMargin[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
                     R.styleable.ProfileDisplayOption_twoPanelLandscapeHorizontalMargin,
-                    horizontalMargin);
-            twoPanelPortraitHorizontalMargin = a.getFloat(
+                    horizontalMargin[INDEX_DEFAULT]);
+            horizontalMargin[INDEX_TWO_PANEL_PORTRAIT] = a.getFloat(
                     R.styleable.ProfileDisplayOption_twoPanelPortraitHorizontalMargin,
-                    horizontalMargin);
+                    horizontalMargin[INDEX_DEFAULT]);
 
             a.recycle();
         }
@@ -864,12 +842,11 @@
             minWidthDps = 0;
             minHeightDps = 0;
             canBeDefault = false;
-            minCellHeight = 0;
-            minCellWidth = 0;
             for (int i = 0; i < COUNT_SIZES; i++) {
                 iconSizes[i] = 0;
                 textSizes[i] = 0;
                 borderSpaces[i] = new PointF();
+                minCellSize[i] = new PointF();
             }
         }
 
@@ -877,21 +854,15 @@
             for (int i = 0; i < COUNT_SIZES; i++) {
                 iconSizes[i] *= w;
                 textSizes[i] *= w;
-                borderSpaces[i].x *=  w;
-                borderSpaces[i].y *=  w;
+                borderSpaces[i].x *= w;
+                borderSpaces[i].y *= w;
+                minCellSize[i].x *= w;
+                minCellSize[i].y *= w;
+                horizontalMargin[i] *= w;
             }
-            minCellHeight *= w;
-            minCellWidth *= w;
-            twoPanelPortraitMinCellHeightDps *= w;
-            twoPanelPortraitMinCellWidthDps *= w;
-            twoPanelLandscapeMinCellHeightDps *= w;
-            twoPanelLandscapeMinCellWidthDps *= w;
 
             folderBorderSpace *= w;
 
-            horizontalMargin *= w;
-            twoPanelLandscapeHorizontalMargin *= w;
-            twoPanelPortraitHorizontalMargin *= w;
             return this;
         }
 
@@ -899,21 +870,15 @@
             for (int i = 0; i < COUNT_SIZES; i++) {
                 iconSizes[i] += p.iconSizes[i];
                 textSizes[i] += p.textSizes[i];
-                borderSpaces[i].x +=  p.borderSpaces[i].x;
-                borderSpaces[i].y +=  p.borderSpaces[i].y;
+                borderSpaces[i].x += p.borderSpaces[i].x;
+                borderSpaces[i].y += p.borderSpaces[i].y;
+                minCellSize[i].x += p.minCellSize[i].x;
+                minCellSize[i].y += p.minCellSize[i].y;
+                horizontalMargin[i] += p.horizontalMargin[i];
             }
-            minCellHeight += p.minCellHeight;
-            minCellWidth += p.minCellWidth;
-            twoPanelPortraitMinCellHeightDps += p.twoPanelPortraitMinCellHeightDps;
-            twoPanelPortraitMinCellWidthDps += p.twoPanelPortraitMinCellWidthDps;
-            twoPanelLandscapeMinCellHeightDps += p.twoPanelLandscapeMinCellHeightDps;
-            twoPanelLandscapeMinCellWidthDps += p.twoPanelLandscapeMinCellWidthDps;
 
             folderBorderSpace += p.folderBorderSpace;
 
-            horizontalMargin += p.horizontalMargin;
-            twoPanelLandscapeHorizontalMargin += p.twoPanelLandscapeHorizontalMargin;
-            twoPanelPortraitHorizontalMargin += p.twoPanelPortraitHorizontalMargin;
             return this;
         }
     }
diff --git a/src/com/android/launcher3/LauncherFiles.java b/src/com/android/launcher3/LauncherFiles.java
index 6c0daa4..64f1d95 100644
--- a/src/com/android/launcher3/LauncherFiles.java
+++ b/src/com/android/launcher3/LauncherFiles.java
@@ -1,5 +1,6 @@
 package com.android.launcher3;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -29,16 +30,24 @@
     public static final String WIDGET_PREVIEWS_DB = "widgetpreviews.db";
     public static final String APP_ICONS_DB = "app_icons.db";
 
-    public static final List<String> ALL_FILES = Collections.unmodifiableList(Arrays.asList(
+    public static final List<String> GRID_DB_FILES = Collections.unmodifiableList(Arrays.asList(
             LAUNCHER_DB,
             LAUNCHER_4_BY_5_DB,
             LAUNCHER_4_BY_4_DB,
             LAUNCHER_3_BY_3_DB,
-            LAUNCHER_2_BY_2_DB,
+            LAUNCHER_2_BY_2_DB));
+
+    public static final List<String> OTHER_FILES = Collections.unmodifiableList(Arrays.asList(
             BACKUP_DB,
             SHARED_PREFERENCES_KEY + XML,
             WIDGET_PREVIEWS_DB,
             MANAGED_USER_PREFERENCES_KEY + XML,
             DEVICE_PREFERENCES_KEY + XML,
             APP_ICONS_DB));
+
+    public static final List<String> ALL_FILES = Collections.unmodifiableList(
+            new ArrayList<String>() {{
+                addAll(GRID_DB_FILES);
+                addAll(OTHER_FILES);
+            }});
 }
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index f38f662..ee6f51e 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -60,6 +60,7 @@
 import com.android.launcher3.pm.PackageInstallInfo;
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.shortcuts.ShortcutRequest;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.IntSet;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.PackageUserKey;
@@ -346,6 +347,12 @@
     public void addCallbacks(Callbacks callbacks) {
         Preconditions.assertUIThread();
         synchronized (mCallbacksList) {
+            if (TestProtocol.sDebugTracing) {
+                Log.d(TestProtocol.NULL_INT_SET, "addCallbacks pointer: "
+                        + callbacks
+                        + ", name: "
+                        + callbacks.getClass().getName(), new Exception());
+            }
             mCallbacksList.add(callbacks);
         }
     }
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index 7de2ee4..5ef3690 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -1,5 +1,6 @@
 package com.android.launcher3;
 
+import static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE;
 import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY;
 
 import android.annotation.TargetApi;
@@ -99,7 +100,11 @@
                 oldNavInsets.bottom);
 
         if (dp.isLandscape) {
-            if (dp.isTablet) {
+            boolean isGesturalMode = ResourceUtils.getIntegerByName(
+                    "config_navBarInteractionMode",
+                    resources,
+                    INVALID_RESOURCE_HANDLE) == 2;
+            if (dp.isTablet || isGesturalMode) {
                 newNavInsets.bottom = ResourceUtils.getNavbarSize(
                         "navigation_bar_height_landscape", resources);
             } else {
diff --git a/src/com/android/launcher3/Partner.java b/src/com/android/launcher3/Partner.java
index 0bdb37c..2e27f32 100644
--- a/src/com/android/launcher3/Partner.java
+++ b/src/com/android/launcher3/Partner.java
@@ -142,7 +142,7 @@
         }
 
         if (iconSize > 0) {
-            inv.iconSize = iconSize;
+            inv.iconSize[InvariantDeviceProfile.INDEX_DEFAULT] = iconSize;
         }
     }
 }
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index b92cf09..36faeee 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -45,6 +45,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.graphics.drawable.AdaptiveIconDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.InsetDrawable;
@@ -80,6 +81,7 @@
 import com.android.launcher3.icons.ShortcutCachingLogic;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
+import com.android.launcher3.model.data.SearchActionItemInfo;
 import com.android.launcher3.pm.ShortcutConfigActivityInfo;
 import com.android.launcher3.shortcuts.ShortcutKey;
 import com.android.launcher3.shortcuts.ShortcutRequest;
@@ -705,6 +707,10 @@
             }
             outObj[0] = icon;
             return icon;
+        } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION
+                && info instanceof SearchActionItemInfo) {
+            return new AdaptiveIconDrawable(
+                    new FastBitmapDrawable(((SearchActionItemInfo) info).bitmap), null);
         } else {
             return null;
         }
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 3f1f915..3ba6ea4 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -63,7 +63,6 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.keyboard.FocusedItemDecorator;
 import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.RecyclerViewFastScroller;
@@ -482,15 +481,13 @@
         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 (TestProtocol.sDebugTracing) {
-            Log.d(TestProtocol.WORK_PROFILE_REMOVED, "should show tabs:" + showTabs,
-                    new Exception());
-        }
         if (showTabs) {
             mViewPager = (AllAppsPagedView) newView;
             mViewPager.initParentViews(this);
             mViewPager.getPageIndicator().setOnActivePageChangedListener(this);
-            mWorkManager.attachWorkModeSwitch();
+            if (mWorkManager.attachWorkModeSwitch()) {
+                mWorkManager.getWorkModeSwitch().post(() -> mAH[AdapterHolder.WORK].applyPadding());
+            }
         } else {
             mWorkManager.detachWorkModeSwitch();
             mViewPager = null;
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index bddbbd0..bccd9b4 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -21,6 +21,7 @@
 
 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.util.LogConfig.SEARCH_LOGGING;
 import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync;
 
 import android.content.Context;
@@ -40,6 +41,7 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.views.ActivityContext;
@@ -54,6 +56,7 @@
 public class AllAppsRecyclerView extends BaseRecyclerView {
     private static final String TAG = "AllAppsContainerView";
     private static final boolean DEBUG = false;
+    private static final boolean DEBUG_LATENCY = Utilities.isPropertyEnabled(SEARCH_LOGGING);
 
     private AlphabeticalAppsList mApps;
     private final int mNumAppsPerRow;
@@ -133,6 +136,10 @@
         if (DEBUG) {
             Log.d(TAG, "onDraw at = " + System.currentTimeMillis());
         }
+        if (DEBUG_LATENCY) {
+            Log.d(SEARCH_LOGGING,
+                    "-- Recycle view onDraw, time stamp = " + System.currentTimeMillis());
+        }
         super.onDraw(c);
     }
 
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index debb5b2..3ca0303 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -47,6 +47,7 @@
         ValueAnimator.AnimatorUpdateListener, PluginListener<AllAppsRow>, Insettable,
         OnHeightUpdatedListener {
 
+    private static final long ALL_APPS_CONTENT_ANIM_DURATION = 150;
     private final Rect mRVClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
     private final Rect mHeaderClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
     private final ValueAnimator mAnimator = ValueAnimator.ofInt(0, 0);
@@ -108,6 +109,14 @@
     // enabled or disabled, and represent the current set of all rows.
     private FloatingHeaderRow[] mAllRows = FloatingHeaderRow.NO_ROWS;
 
+
+    // members for handling suggestion state
+    private final ValueAnimator mAllAppsContentAnimator = ValueAnimator.ofFloat(0, 0);
+    private View mAllAppsButton;
+    private int mAllAppsContentFadeInOffset;
+    private boolean mInSuggestionMode = false;
+
+
     public FloatingHeaderView(@NonNull Context context) {
         this(context, null);
     }
@@ -118,12 +127,20 @@
                 .getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
         mHeaderProtectionSupported = context.getResources().getBoolean(
                 R.bool.config_header_protection_supported);
+        mAllAppsContentFadeInOffset = context.getResources()
+                .getDimensionPixelSize(R.dimen.all_apps_content_fade_in_offset);
+        mAllAppsContentAnimator.setDuration(ALL_APPS_CONTENT_ANIM_DURATION);
+        mAllAppsContentAnimator.addUpdateListener(this::onAllAppsContentAnimationUpdate);
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
         mTabLayout = findViewById(R.id.tabs);
+        mAllAppsButton = findViewById(R.id.all_apps_button);
+        if (mAllAppsButton != null) {
+            mAllAppsButton.setOnClickListener(this::onAllAppsButtonClicked);
+        }
 
         // Find all floating header rows.
         ArrayList<FloatingHeaderRow> rows = new ArrayList<>();
@@ -312,6 +329,7 @@
         }
 
         mTabLayout.setTranslationY(mTranslationY);
+        setSuggestionMode(false);
 
         int clipHeight = mHeaderTopPadding - getPaddingBottom();
         mRVClip.top = mTabsHidden ? clipHeight : 0;
@@ -347,6 +365,7 @@
             mTranslationY = 0;
             applyVerticalMove();
         }
+        setSuggestionMode(false);
         mHeaderCollapsed = false;
         mSnappedScrolledY = -mMaxTranslation;
         mCurrentRV.scrollToTop();
@@ -442,6 +461,38 @@
         }
         return Math.max(getHeight() - getPaddingTop() + mTranslationY, 0);
     }
+
+    /**
+     * When suggestion mode is enabled, hides AllApps content view and shows AllApps button.
+     */
+    public void setSuggestionMode(boolean isSuggestMode) {
+        if (mInSuggestionMode == isSuggestMode || mAllAppsButton == null) return;
+        if (!FeatureFlags.ENABLE_ONE_SEARCH.get()) return;
+        AllAppsContainerView allApps = (AllAppsContainerView) getParent();
+        mInSuggestionMode = isSuggestMode;
+        if (isSuggestMode) {
+            mTabLayout.setVisibility(GONE);
+            mAllAppsButton.setVisibility(VISIBLE);
+            allApps.getContentView().setVisibility(GONE);
+        } else {
+            mTabLayout.setVisibility(mTabsHidden ? GONE : VISIBLE);
+            mAllAppsButton.setVisibility(GONE);
+            allApps.getContentView().setVisibility(VISIBLE);
+        }
+    }
+
+    private void onAllAppsButtonClicked(View view) {
+        setSuggestionMode(false);
+        mAllAppsContentAnimator.start();
+    }
+
+    private void onAllAppsContentAnimationUpdate(ValueAnimator valueAnimator) {
+        float prog = valueAnimator.getAnimatedFraction();
+        View allAppsList = ((AllAppsContainerView) getParent()).getContentView();
+        allAppsList.setAlpha(255 * prog);
+        allAppsList.setTranslationY((1 - prog) * mAllAppsContentFadeInOffset);
+    }
+
 }
 
 
diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java
index 5d64041..be01581 100644
--- a/src/com/android/launcher3/allapps/WorkModeSwitch.java
+++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java
@@ -113,10 +113,12 @@
     /**
      * Sets the enabled or disabled state of the button
      */
-    public void updateCurrentState(boolean active) {
+    public void updateCurrentState(boolean isEnabled) {
         removeFlag(FLAG_PROFILE_TOGGLE_ONGOING);
-        mWorkEnabled = active;
-        updateVisibility();
+        if (mWorkEnabled != isEnabled) {
+            mWorkEnabled = isEnabled;
+            updateVisibility();
+        }
     }
 
 
@@ -125,7 +127,6 @@
         if (mWorkEnabled && mOnWorkTab) {
             setFlag(FLAG_FADE_ONGOING);
             setVisibility(VISIBLE);
-            setAlpha(0);
             animate().alpha(1).withEndAction(() -> removeFlag(FLAG_FADE_ONGOING)).start();
         } else if (getVisibility() != GONE) {
             setFlag(FLAG_FADE_ONGOING);
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index c53360a..e223248 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -28,6 +28,7 @@
 import android.util.Log;
 
 import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 
 import com.android.launcher3.R;
@@ -127,11 +128,11 @@
     /**
      * Creates and attaches for profile toggle button to {@link AllAppsContainerView}
      */
-    public void attachWorkModeSwitch() {
+    public boolean attachWorkModeSwitch() {
         if (!mAllApps.getAppsStore().hasModelFlag(
                 FLAG_HAS_SHORTCUT_PERMISSION | FLAG_QUIET_MODE_CHANGE_PERMISSION)) {
-            Log.e(TAG, "Unable to attach widget; Missing required permissions");
-            return;
+            Log.e(TAG, "unable to attach work mode switch; Missing required permissions");
+            return false;
         }
         if (mWorkModeSwitch == null) {
             mWorkModeSwitch = (WorkModeSwitch) mAllApps.getLayoutInflater().inflate(
@@ -144,6 +145,7 @@
             getAH().applyPadding();
         }
         mWorkModeSwitch.updateCurrentState(mCurrentState == STATE_ENABLED);
+        return true;
     }
 
     /**
@@ -165,6 +167,7 @@
         return mMatcher;
     }
 
+    @Nullable
     public WorkModeSwitch getWorkModeSwitch() {
         return mWorkModeSwitch;
     }
@@ -172,4 +175,8 @@
     private AllAppsContainerView.AdapterHolder getAH() {
         return mAllApps.mAH[AllAppsContainerView.AdapterHolder.WORK];
     }
+
+    public int getCurrentState() {
+        return mCurrentState;
+    }
 }
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index f41c19b..796c912 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -72,12 +72,6 @@
             "PROMISE_APPS_NEW_INSTALLS", true,
             "Adds a promise icon to the home screen for new install sessions.");
 
-    public static final BooleanFlag QUICKSTEP_SPRINGS = getDebugFlag(
-            "QUICKSTEP_SPRINGS", true, "Enable springs for quickstep animations");
-
-    public static final BooleanFlag UNSTABLE_SPRINGS = getDebugFlag(
-            "UNSTABLE_SPRINGS", false, "Enable unstable springs for quickstep animations");
-
     public static final BooleanFlag ENABLE_LOCAL_COLOR_POPUPS = getDebugFlag(
             "ENABLE_LOCAL_COLOR_POPUPS", false, "Enable local color extraction for popups.");
 
@@ -97,6 +91,9 @@
     public static final BooleanFlag ENABLE_DEVICE_SEARCH = new DeviceFlag(
             "ENABLE_DEVICE_SEARCH", true, "Allows on device search in all apps");
 
+    public static final BooleanFlag ENABLE_ONE_SEARCH = new DeviceFlag("ENABLE_ONE_SEARCH", false,
+            "Use homescreen search box to complete allApps searches");
+
     public static final BooleanFlag ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING = new DeviceFlag(
             "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", true,
             "Allows on device search in all apps logging");
@@ -119,16 +116,6 @@
     public static final BooleanFlag ENABLE_PREDICTION_DISMISS = getDebugFlag(
             "ENABLE_PREDICTION_DISMISS", true, "Allow option to dimiss apps from predicted list");
 
-    public static final BooleanFlag ENABLE_QUICK_CAPTURE_GESTURE = getDebugFlag(
-            "ENABLE_QUICK_CAPTURE_GESTURE", true, "Swipe from right to left to quick capture");
-
-    public static final BooleanFlag ENABLE_QUICK_CAPTURE_WINDOW = getDebugFlag(
-            "ENABLE_QUICK_CAPTURE_WINDOW", false, "Use window to host quick capture");
-
-    public static final BooleanFlag FORCE_LOCAL_OVERSCROLL_PLUGIN = getDebugFlag(
-            "FORCE_LOCAL_OVERSCROLL_PLUGIN", false,
-            "Use a launcher-provided OverscrollPlugin if available");
-
     public static final BooleanFlag ASSISTANT_GIVES_LAUNCHER_FOCUS = getDebugFlag(
             "ASSISTANT_GIVES_LAUNCHER_FOCUS", false,
             "Allow Launcher to handle nav bar gestures while Assistant is running over it");
@@ -157,7 +144,7 @@
             "ENABLE_OVERVIEW_SELECTIONS", true, "Show Select Mode button in Overview Actions");
 
     public static final BooleanFlag ENABLE_WIDGETS_PICKER_AIAI_SEARCH = new DeviceFlag(
-            "ENABLE_WIDGETS_PICKER_AIAI_SEARCH", false, "Enable AiAi search in the widgets picker");
+            "ENABLE_WIDGETS_PICKER_AIAI_SEARCH", true, "Enable AiAi search in the widgets picker");
 
     public static final BooleanFlag ENABLE_OVERVIEW_SHARING_TO_PEOPLE = getDebugFlag(
             "ENABLE_OVERVIEW_SHARING_TO_PEOPLE", true,
@@ -176,10 +163,6 @@
             "Replace Smartspace with the enhanced version. "
                     + "Ignored if ENABLE_SMARTSPACE_UNIVERSAL is enabled.");
 
-    public static final BooleanFlag ENABLE_SMARTSPACE_FEEDBACK = getDebugFlag(
-            "ENABLE_SMARTSPACE_FEEDBACK", false,
-            "Adds a menu option to send feedback for Enhanced Smartspace.");
-
     public static final BooleanFlag ENABLE_SMARTSPACE_DISMISS = getDebugFlag(
             "ENABLE_SMARTSPACE_DISMISS", true,
             "Adds a menu option to dismiss the current Enhanced Smartspace card.");
@@ -262,7 +245,7 @@
             "Enables widgets in Launcher preview for the Wallpaper app.");
 
     public static final BooleanFlag QUICK_WALLPAPER_PICKER = getDebugFlag(
-            "QUICK_WALLPAPER_PICKER", false,
+            "QUICK_WALLPAPER_PICKER", true,
             "Shows quick wallpaper picker in long-press menu");
 
     public static final BooleanFlag ENABLE_BACK_SWIPE_HOME_ANIMATION = getDebugFlag(
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 57d6cc3..fa65945 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -205,6 +205,7 @@
     @TargetApi(Build.VERSION_CODES.O)
     public void setItemInfo(final ItemInfo info) {
         if (info.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+                && info.itemType != LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION
                 && info.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
                 && info.itemType != LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
             return;
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index 399d142..61ffd9d 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -22,7 +22,6 @@
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
 import static com.android.launcher3.graphics.IconShape.getShape;
-import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -175,15 +174,9 @@
         final float yDistance = initialY - lp.y;
 
         // Set up the Folder background.
-        final int finalColor;
-        int folderFillColor = Themes.getAttrColor(mContext, R.attr.folderFillColor);
-        if (mIsOpening) {
-            finalColor = folderFillColor;
-        } else {
-            finalColor = mFolderBackground.getColor().getDefaultColor();
-        }
-        final int initialColor = setColorAlphaBound(
-                folderFillColor, mPreviewBackground.getBackgroundAlpha());
+        final int initialColor = Themes.getAttrColor(mContext, R.attr.folderPreviewColor);
+        final int finalColor = Themes.getAttrColor(mContext, R.attr.folderBackgroundColor);
+
         mFolderBackground.mutate();
         mFolderBackground.setColor(mIsOpening ? initialColor : finalColor);
 
diff --git a/src/com/android/launcher3/folder/PreviewBackground.java b/src/com/android/launcher3/folder/PreviewBackground.java
index 18d0b10..8f9fa8a 100644
--- a/src/com/android/launcher3/folder/PreviewBackground.java
+++ b/src/com/android/launcher3/folder/PreviewBackground.java
@@ -66,7 +66,6 @@
     private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 
     float mScale = 1f;
-    private float mColorMultiplier = 1f;
     private int mBgColor;
     private int mStrokeColor;
     private int mDotColor;
@@ -87,7 +86,6 @@
 
     // Drawing / animation configurations
     private static final float ACCEPT_SCALE_FACTOR = 1.20f;
-    private static final float ACCEPT_COLOR_MULTIPLIER = 1.5f;
 
     // Expressed on a scale from 0 to 255.
     private static final int BG_OPACITY = 255;
@@ -154,7 +152,7 @@
         TypedArray ta = context.getTheme().obtainStyledAttributes(R.styleable.FolderIconPreview);
         mDotColor = ta.getColor(R.styleable.FolderIconPreview_folderDotColor, 0);
         mStrokeColor = ta.getColor(R.styleable.FolderIconPreview_folderIconBorderColor, 0);
-        mBgColor = ta.getColor(R.styleable.FolderIconPreview_folderFillColor, 0);
+        mBgColor = ta.getColor(R.styleable.FolderIconPreview_folderPreviewColor, 0);
         ta.recycle();
 
         DeviceProfile grid = activity.getDeviceProfile();
@@ -227,8 +225,7 @@
     }
 
     public int getBgColor() {
-        int alpha = (int) Math.min(MAX_BG_OPACITY, BG_OPACITY * mColorMultiplier);
-        return setColorAlphaBound(mBgColor, alpha);
+        return mBgColor;
     }
 
     public int getDotColor() {
@@ -384,14 +381,10 @@
         return mDrawingDelegate != null;
     }
 
-    private void animateScale(float finalScale, float finalMultiplier,
-                              final Runnable onStart, final Runnable onEnd) {
+    private void animateScale(float finalScale, final Runnable onStart, final Runnable onEnd) {
         final float scale0 = mScale;
         final float scale1 = finalScale;
 
-        final float bgMultiplier0 = mColorMultiplier;
-        final float bgMultiplier1 = finalMultiplier;
-
         if (mScaleAnimator != null) {
             mScaleAnimator.cancel();
         }
@@ -403,7 +396,6 @@
             public void onAnimationUpdate(ValueAnimator animation) {
                 float prog = animation.getAnimatedFraction();
                 mScale = prog * scale1 + (1 - prog) * scale0;
-                mColorMultiplier = prog * bgMultiplier1 + (1 - prog) * bgMultiplier0;
                 invalidate();
             }
         });
@@ -429,8 +421,7 @@
     }
 
     public void animateToAccept(CellLayout cl, int cellX, int cellY) {
-        animateScale(ACCEPT_SCALE_FACTOR, ACCEPT_COLOR_MULTIPLIER,
-                () -> delegateDrawing(cl, cellX, cellY), null);
+        animateScale(ACCEPT_SCALE_FACTOR, () -> delegateDrawing(cl, cellX, cellY), null);
     }
 
     public void animateToRest() {
@@ -440,11 +431,7 @@
         CellLayout cl = mDrawingDelegate;
         int cellX = mDelegateCellX;
         int cellY = mDelegateCellY;
-        animateScale(1f, 1f, () -> delegateDrawing(cl, cellX, cellY), this::clearDrawingDelegate);
-    }
-
-    public int getBackgroundAlpha() {
-        return (int) Math.min(MAX_BG_OPACITY, BG_OPACITY * mColorMultiplier);
+        animateScale(1f, () -> delegateDrawing(cl, cellX, cellY), this::clearDrawingDelegate);
     }
 
     public float getStrokeWidth() {
diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java
index e9feb1c..d270cc5 100644
--- a/src/com/android/launcher3/model/BaseLoaderResults.java
+++ b/src/com/android/launcher3/model/BaseLoaderResults.java
@@ -177,8 +177,10 @@
             if (TestProtocol.sDebugTracing) {
                 Log.d(TestProtocol.NULL_INT_SET, "bind (1) currentScreenIds: "
                         + currentScreenIds
-                        + ", mCallBacks: "
-                        + mCallbacks.getClass().getSimpleName());
+                        + ", pointer: "
+                        + mCallbacks
+                        + ", name: "
+                        + mCallbacks.getClass().getName());
             }
             filterCurrentWorkspaceItems(currentScreenIds, mWorkspaceItems, currentWorkspaceItems,
                     otherWorkspaceItems);
diff --git a/src/com/android/launcher3/model/UserManagerState.java b/src/com/android/launcher3/model/UserManagerState.java
index 3a4206c..97a5905 100644
--- a/src/com/android/launcher3/model/UserManagerState.java
+++ b/src/com/android/launcher3/model/UserManagerState.java
@@ -36,7 +36,7 @@
      * Initialises the state values for all users
      */
     public void init(UserCache userCache, UserManager userManager) {
-        for (UserHandle user : userCache.getUserProfiles()) {
+        for (UserHandle user : userManager.getUserProfiles()) {
             long serialNo = userCache.getSerialNumberForUser(user);
             boolean isUserQuiet = userManager.isQuietModeEnabled(user);
             allUsers.put(serialNo, user);
diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java
index 5ade22b..5aab41a 100644
--- a/src/com/android/launcher3/pm/UserCache.java
+++ b/src/com/android/launcher3/pm/UserCache.java
@@ -21,10 +21,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.ArrayMap;
-import android.util.Log;
 import android.util.LongSparseArray;
 
-import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.SafeCloseable;
 import com.android.launcher3.util.SimpleBroadcastReceiver;
@@ -60,9 +58,6 @@
     private void onUsersChanged(Intent intent) {
         enableAndResetCache();
         mUserChangeListeners.forEach(Runnable::run);
-        if (TestProtocol.sDebugTracing) {
-            Log.d(TestProtocol.WORK_PROFILE_REMOVED, "profile changed", new Exception());
-        }
     }
 
     /**
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 65dd8ea..d6e927b 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -46,7 +46,6 @@
 import com.android.launcher3.DropTarget;
 import com.android.launcher3.DropTarget.DragObject;
 import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherState;
 import com.android.launcher3.R;
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
 import com.android.launcher3.accessibility.ShortcutMenuAccessibilityDelegate;
@@ -64,7 +63,6 @@
 import com.android.launcher3.popup.PopupDataProvider.PopupDataChangeListener;
 import com.android.launcher3.shortcuts.DeepShortcutView;
 import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
-import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.touch.ItemLongClickListener;
 import com.android.launcher3.util.PackageUserKey;
 import com.android.launcher3.util.ShortcutUtil;
@@ -83,7 +81,7 @@
  *
  * @param <T> The activity on with the popup shows
  */
-public class PopupContainerWithArrow<T extends StatefulActivity<LauncherState>>
+public class PopupContainerWithArrow<T extends BaseDraggingActivity>
         extends ArrowPopup<T> implements DragSource, DragController.DragListener {
 
     private final List<DeepShortcutView> mShortcuts = new ArrayList<>();
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index d59429d..257d732 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -81,6 +81,8 @@
         // Set is pending to false irrespective of the result, so that it doesn't get
         // executed again.
         Utilities.getPrefs(context).edit().remove(RESTORED_DEVICE_TYPE).commit();
+
+        InvariantDeviceProfile.INSTANCE.get(context).reinitializeAfterRestore(context);
     }
 
     private static boolean performRestore(Context context, DatabaseHelper helper) {
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index ce01d4e..893a215 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -102,8 +102,8 @@
     public static final String REQUEST_GET_ACTIVITIES_CREATED_COUNT =
             "get-activities-created-count";
     public static final String REQUEST_GET_ACTIVITIES = "get-activities";
-    public static final String REQUEST_GET_FOCUSED_TASK_WIDTH_FOR_TABLET =
-            "get-focused-task-width-for-tablet";
+    public static final String REQUEST_GET_FOCUSED_TASK_HEIGHT_FOR_TABLET =
+            "get-focused-task-height-for-tablet";
 
     public static Long sForcePauseTimeout;
     public static final String REQUEST_SET_FORCE_PAUSE_TIMEOUT = "set-force-pause-timeout";
@@ -117,7 +117,6 @@
     public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
 
     public static final String PERMANENT_DIAG_TAG = "TaplTarget";
-    public static final String WORK_PROFILE_REMOVED = "b/159671700";
     public static final String TASK_VIEW_ID_CRASH = "b/195430732";
     public static final String NO_DROP_TARGET = "b/195031154";
     public static final String NULL_INT_SET = "b/200572078";
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 5f8a4d4..61d488c 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -21,7 +21,6 @@
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
-import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
@@ -217,7 +216,7 @@
                     mFlingBlockCheck.blockFling();
                 }
             }
-            if (mToState == LauncherState.ALL_APPS && !UNSTABLE_SPRINGS.get()) {
+            if (mToState == LauncherState.ALL_APPS) {
                 mAllAppsOvershootStarted = true;
                 // 1f, value when all apps container hit the top
                 mLauncher.getAppsView().onPull(progress - 1f, progress - 1f);
@@ -333,7 +332,7 @@
         anim.setFloatValues(startProgress, endProgress);
         updateSwipeCompleteAnimation(anim, duration, targetState, velocity, fling);
         mCurrentAnimation.dispatchOnStart();
-        if (targetState == LauncherState.ALL_APPS && !UNSTABLE_SPRINGS.get()) {
+        if (targetState == LauncherState.ALL_APPS) {
             if (mAllAppsOvershootStarted) {
                 mLauncher.getAppsView().onRelease();
                 mAllAppsOvershootStarted = false;
diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
index 4894b3b..989a9e4 100644
--- a/src/com/android/launcher3/touch/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -94,12 +94,28 @@
             LauncherState toState) {
         StateAnimationConfig config = super.getConfigForStates(fromState, toState);
         if (fromState == NORMAL && toState == ALL_APPS) {
-            config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
-            config.setInterpolator(ANIM_ALL_APPS_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
+            applyNormalToAllAppsAnimConfig(config);
         } else if (fromState == ALL_APPS && toState == NORMAL) {
-            config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
-            config.setInterpolator(ANIM_ALL_APPS_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
+            applyAllAppsToNormalConfig(config);
         }
         return config;
     }
+
+    /**
+     * Applies Animation config values for transition from all apps to home
+     */
+    public static void applyAllAppsToNormalConfig(StateAnimationConfig config) {
+        config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
+        config.setInterpolator(ANIM_ALL_APPS_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
+    }
+
+    /**
+     * Applies Animation config values for transition from home to all apps
+     */
+    public static void applyNormalToAllAppsAnimConfig(StateAnimationConfig config) {
+        config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
+        config.setInterpolator(ANIM_ALL_APPS_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
+    }
+
+
 }
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 931ecb8..2068c29 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -243,7 +243,7 @@
         }
 
         int change = 0;
-        if (!newInfo.mScreenSizeDp.equals(oldInfo.mScreenSizeDp)) {
+        if (!newInfo.displayId.equals(oldInfo.displayId)) {
             change |= CHANGE_ACTIVE_SCREEN;
         }
         if (newInfo.rotation != oldInfo.rotation) {
@@ -296,6 +296,7 @@
 
         public final Point currentSize;
 
+        public String displayId;
         public final Set<WindowBounds> supportedBounds = new ArraySet<>();
         private final Map<String, Set<WindowBounds>> mPerDisplayBounds = new ArrayMap<>();
         private final ArrayMap<String, PortraitSize> mInternalDisplays;
@@ -319,17 +320,17 @@
             currentSize = new Point();
             display.getRealSize(currentSize);
 
-            String myDisplayId = ApiWrapper.getUniqueId(display);
+            displayId = ApiWrapper.getUniqueId(display);
             Set<WindowBounds> currentSupportedBounds =
                     getSupportedBoundsForDisplay(display, currentSize);
-            mPerDisplayBounds.put(myDisplayId, currentSupportedBounds);
+            mPerDisplayBounds.put(displayId, currentSupportedBounds);
             supportedBounds.addAll(currentSupportedBounds);
 
             if (ApiWrapper.isInternalDisplay(display) && internalDisplays.size() > 1) {
                 int displayCount = internalDisplays.size();
                 for (int i = 0; i < displayCount; i++) {
                     String displayKey = internalDisplays.keyAt(i);
-                    if (TextUtils.equals(myDisplayId, displayKey)) {
+                    if (TextUtils.equals(displayId, displayKey)) {
                         continue;
                     }
 
diff --git a/src/com/android/launcher3/util/LogConfig.java b/src/com/android/launcher3/util/LogConfig.java
index 528a6e9..6bc26e7 100644
--- a/src/com/android/launcher3/util/LogConfig.java
+++ b/src/com/android/launcher3/util/LogConfig.java
@@ -35,4 +35,9 @@
      * When turned on, we enable doodle related logging.
      */
     public static final String DOODLE_LOGGING = "DoodleLogging";
+
+    /**
+     * When turned on, we enable suggest related logging.
+     */
+    public static final String SEARCH_LOGGING = "SearchLogging";
 }
diff --git a/src/com/android/launcher3/util/WindowManagerCompat.java b/src/com/android/launcher3/util/WindowManagerCompat.java
index bfdf1e4..e1b9478 100644
--- a/src/com/android/launcher3/util/WindowManagerCompat.java
+++ b/src/com/android/launcher3/util/WindowManagerCompat.java
@@ -60,10 +60,10 @@
         }
         WindowInsets defaultInsets = windowContext.getSystemService(WindowManager.class)
                 .getMaximumWindowMetrics().getWindowInsets();
-        boolean hasNavbar = ResourceUtils.getIntegerByName(
+        boolean isGesturalMode = ResourceUtils.getIntegerByName(
                 "config_navBarInteractionMode",
                 windowContext.getResources(),
-                INVALID_RESOURCE_HANDLE) != 0;
+                INVALID_RESOURCE_HANDLE) == 2;
 
         WindowInsets.Builder insetsBuilder = new WindowInsets.Builder(defaultInsets);
         Set<WindowBounds> result = new ArraySet<>();
@@ -74,7 +74,7 @@
         if (isTablet && !consumeTaskBar) {
             portraitNav = landscapeNav = Insets.of(0, 0, 0, windowContext.getResources()
                     .getDimensionPixelSize(R.dimen.taskbar_size));
-        } else if (hasNavbar) {
+        } else if (!isGesturalMode) {
             portraitNav = Insets.of(0, 0, 0,
                     getSystemResource(windowContext, "navigation_bar_height", swDP));
             landscapeNav = isTablet
diff --git a/src/com/android/launcher3/views/BubbleTextHolder.java b/src/com/android/launcher3/views/BubbleTextHolder.java
index 78aac06..42701c6 100644
--- a/src/com/android/launcher3/views/BubbleTextHolder.java
+++ b/src/com/android/launcher3/views/BubbleTextHolder.java
@@ -16,12 +16,14 @@
 package com.android.launcher3.views;
 
 import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.ItemInfoWithIcon;
 
 /**
  * Views that contain {@link BubbleTextView} should implement this interface.
  */
-public interface BubbleTextHolder {
+public interface BubbleTextHolder extends IconCache.ItemInfoUpdateReceiver {
     BubbleTextView getBubbleText();
 
     /**
@@ -29,6 +31,6 @@
      *
      * @param itemInfo the new itemInfo
      */
-    default void onItemInfoChanged(ItemInfo itemInfo) {
-    }
+    @Override
+    default void reapplyItemInfo(ItemInfoWithIcon itemInfo){};
 }
diff --git a/src_plugins/com/android/systemui/plugins/OverscrollPlugin.java b/src_plugins/com/android/systemui/plugins/OverscrollPlugin.java
deleted file mode 100644
index a434d07..0000000
--- a/src_plugins/com/android/systemui/plugins/OverscrollPlugin.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.plugins;
-
-import android.view.MotionEvent;
-
-import com.android.systemui.plugins.annotations.ProvidesInterface;
-
-/**
- * Implement this interface to receive a callback when the user swipes right
- * to left on the gesture area. It won't fire if the user has quick switched to a previous app
- * (swiped right) and the current app isn't yet the active one (i.e., if swiping left would take
- * the user to a more recent app).
- */
-@ProvidesInterface(action = com.android.systemui.plugins.OverscrollPlugin.ACTION,
-        version = com.android.systemui.plugins.OverscrollPlugin.VERSION)
-public interface OverscrollPlugin extends Plugin {
-
-    String ACTION = "com.android.systemui.action.PLUGIN_LAUNCHER_OVERSCROLL";
-    int VERSION = 4;
-
-    String DEVICE_STATE_LOCKED = "Locked";
-    String DEVICE_STATE_LAUNCHER = "Launcher";
-    String DEVICE_STATE_APP = "App";
-    String DEVICE_STATE_UNKNOWN = "Unknown";
-
-    /**
-     * @return true if the plugin is active and will accept overscroll gestures
-     */
-    boolean isActive();
-
-    /**
-     * Called when a touch has been recognized as an overscroll gesture.
-     * @param horizontalDistancePx Horizontal distance from the last finger location to the finger
-     *                               location when it first touched the screen.
-     * @param verticalDistancePx Horizontal distance from the last finger location to the finger
-     *                             location when it first touched the screen.
-     * @param thresholdPx Minimum distance for gesture.
-     * @param flingDistanceThresholdPx Minimum distance for gesture by fling.
-     * @param flingVelocityThresholdPx Minimum velocity for gesture by fling.
-     * @param deviceState String representing the current device state
-     * @param underlyingActivity String representing the currently active Activity
-     */
-    void onTouchEvent(MotionEvent event,
-                      int horizontalDistancePx,
-                      int verticalDistancePx,
-                      int thresholdPx,
-                      int flingDistanceThresholdPx,
-                      int flingVelocityThresholdPx,
-                      String deviceState,
-                      String underlyingActivity);
-
-    /**
-     * @return `true` if overscroll gesture handling should override all other gestures.
-     */
-    boolean blockOtherGestures();
-
-    /**
-     * @return `true` if the overscroll gesture can pan the underlying app.
-     */
-    boolean allowsUnderlyingActivityOverscroll();
-}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index b6b6cdd..0ffbeeb 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -262,8 +262,6 @@
         if (userManager != null) {
             for (UserHandle userHandle : userManager.getUserProfiles()) {
                 if (!userHandle.isSystem()) {
-                    Log.d(TestProtocol.WORK_PROFILE_REMOVED,
-                            "removing user " + userHandle.getIdentifier());
                     mDevice.executeShellCommand("pm remove-user " + userHandle.getIdentifier());
                 }
             }
diff --git a/tests/src/com/android/launcher3/ui/WorkProfileTest.java b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
new file mode 100644
index 0000000..fcb0b7f
--- /dev/null
+++ b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.ui;
+
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.view.View;
+
+import com.android.launcher3.R;
+import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.AllAppsPagedView;
+import com.android.launcher3.allapps.WorkAdapterProvider;
+import com.android.launcher3.allapps.WorkEduCard;
+import com.android.launcher3.allapps.WorkProfileManager;
+import com.android.launcher3.tapl.LauncherInstrumentation;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Objects;
+
+public class WorkProfileTest extends AbstractLauncherUiTest {
+
+    private static final int WORK_PAGE = AllAppsContainerView.AdapterHolder.WORK;
+
+    private int mProfileUserId;
+
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        String output =
+                mDevice.executeShellCommand(
+                        "pm create-user --profileOf 0 --managed TestProfile");
+        assertTrue("Failed to create work profile", output.startsWith("Success"));
+
+        String[] tokens = output.split("\\s+");
+        mProfileUserId = Integer.parseInt(tokens[tokens.length - 1]);
+        mDevice.executeShellCommand("am start-user " + mProfileUserId);
+    }
+
+    @After
+    public void removeWorkProfile() throws Exception {
+        mDevice.executeShellCommand("pm remove-user " + mProfileUserId);
+    }
+
+    @After
+    public void resumeAppStoreUpdate() {
+        executeOnLauncher(launcher -> {
+            if (launcher == null || launcher.getAppsView() == null) {
+                return;
+            }
+            launcher.getAppsView().getAppsStore().disableDeferUpdates(DEFER_UPDATES_TEST);
+        });
+    }
+
+    private void waitForWorkTabSetup() {
+        waitForLauncherCondition("Work tab not setup", launcher -> {
+            if (launcher.getAppsView().getContentView() instanceof AllAppsPagedView) {
+                launcher.getAppsView().getAppsStore().enableDeferUpdates(DEFER_UPDATES_TEST);
+                return true;
+            }
+            return false;
+        }, LauncherInstrumentation.WAIT_TIME_MS);
+    }
+
+    @Test
+    public void workTabExists() {
+        mDevice.pressHome();
+        waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
+        waitForState("Launcher internal state didn't switch to Normal", () -> NORMAL);
+        executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
+        waitForState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS);
+        waitForLauncherCondition("Personal tab is missing",
+                launcher -> launcher.getAppsView().isPersonalTabVisible(),
+                LauncherInstrumentation.WAIT_TIME_MS);
+        waitForLauncherCondition("Work tab is missing",
+                launcher -> launcher.getAppsView().isWorkTabVisible(),
+                LauncherInstrumentation.WAIT_TIME_MS);
+    }
+
+    @Test
+    public void toggleWorks() {
+        mDevice.pressHome();
+        waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
+        waitForState("Launcher internal state didn't switch to Normal", () -> NORMAL);
+        executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
+        waitForState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS);
+
+        waitForWorkTabSetup();
+
+        executeOnLauncher(launcher -> {
+            AllAppsPagedView pagedView = (AllAppsPagedView) launcher.getAppsView().getContentView();
+            pagedView.setCurrentPage(WORK_PAGE);
+        });
+
+        WorkProfileManager manager = getFromLauncher(l -> l.getAppsView().getWorkManager());
+
+
+        waitForLauncherCondition("work profile initial state check failed", launcher ->
+                        manager.getWorkModeSwitch() != null
+                                && manager.getCurrentState() == WorkProfileManager.STATE_ENABLED
+                                && manager.getWorkModeSwitch().isEnabled(),
+                LauncherInstrumentation.WAIT_TIME_MS);
+
+        //start work profile toggle OFF test
+        executeOnLauncher(l -> l.getAppsView().getWorkManager().getWorkModeSwitch().performClick());
+
+        waitForLauncherCondition("Work profile toggle OFF failed", launcher -> {
+            manager.reset(); // pulls current state from system
+            return manager.getCurrentState() == WorkProfileManager.STATE_DISABLED;
+        }, LauncherInstrumentation.WAIT_TIME_MS);
+
+        // start work profile toggle ON test
+        executeOnLauncher(l -> {
+            AllAppsContainerView allApps = l.getAppsView();
+            assertEquals("Work tab is not focused", allApps.getCurrentPage(), WORK_PAGE);
+            View workPausedCard = allApps.getActiveRecyclerView().findViewHolderForAdapterPosition(
+                    0).itemView;
+            workPausedCard.findViewById(R.id.enable_work_apps).performClick();
+        });
+        waitForLauncherCondition("Work profile toggle ON failed", launcher -> {
+            manager.reset(); // pulls current state from system
+            return manager.getCurrentState() == WorkProfileManager.STATE_ENABLED;
+        }, LauncherInstrumentation.WAIT_TIME_MS);
+
+    }
+
+    @Test
+    public void testEdu() {
+        mDevice.pressHome();
+        waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
+        waitForState("Launcher internal state didn't switch to Normal", () -> NORMAL);
+        executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
+        waitForState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS);
+        waitForWorkTabSetup();
+        executeOnLauncher(l -> {
+            l.getSharedPrefs().edit().putInt(WorkAdapterProvider.KEY_WORK_EDU_STEP, 0).commit();
+            ((AllAppsPagedView) l.getAppsView().getContentView()).setCurrentPage(WORK_PAGE);
+            l.getAppsView().getWorkManager().reset();
+        });
+
+        waitForLauncherCondition("Work profile education not shown",
+                l -> l.getAppsView().getActiveRecyclerView()
+                        .findViewHolderForAdapterPosition(0).itemView instanceof WorkEduCard,
+                LauncherInstrumentation.WAIT_TIME_MS);
+    }
+}
diff --git a/tests/src_disabled/WorkTabTest.java b/tests/src_disabled/WorkTabTest.java
deleted file mode 100644
index bfacc74..0000000
--- a/tests/src_disabled/WorkTabTest.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.ui;
-
-import static com.android.launcher3.LauncherState.ALL_APPS;
-import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import android.os.Process;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Log;
-import android.widget.TextView;
-
-import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
-import com.android.launcher3.allapps.AllAppsPagedView;
-import com.android.launcher3.allapps.WorkModeSwitch;
-import com.android.launcher3.dragndrop.DragLayer;
-import com.android.launcher3.tapl.LauncherInstrumentation;
-import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.views.WorkEduView;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.atomic.AtomicInteger;
-
-@LargeTest
-@RunWith(AndroidJUnit4.class)
-public class WorkTabTest extends AbstractLauncherUiTest {
-
-    private int mProfileUserId;
-
-    private static final int WORK_PAGE = AllAppsContainerView.AdapterHolder.WORK;
-
-    @Before
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        String output =
-                mDevice.executeShellCommand(
-                        "pm create-user --profileOf 0 --managed TestProfile");
-        assertTrue("Failed to create work profile", output.startsWith("Success"));
-
-        String[] tokens = output.split("\\s+");
-        mProfileUserId = Integer.parseInt(tokens[tokens.length - 1]);
-        Log.d(TestProtocol.WORK_PROFILE_REMOVED, "Created new user uid" + mProfileUserId);
-        mDevice.executeShellCommand("am start-user " + mProfileUserId);
-    }
-
-    @After
-    public void removeWorkProfile() throws Exception {
-        Log.d(TestProtocol.WORK_PROFILE_REMOVED, "(teardown) removing uid" + mProfileUserId,
-                new Exception());
-        mDevice.executeShellCommand("pm remove-user " + mProfileUserId);
-    }
-
-    @After
-    public void resumeAppStoreUpdate() {
-        executeOnLauncher(launcher -> {
-            if (launcher == null || launcher.getAppsView() == null) {
-                return;
-            }
-            launcher.getAppsView().getAppsStore().disableDeferUpdates(DEFER_UPDATES_TEST);
-            Log.d(TestProtocol.WORK_PROFILE_REMOVED, "resuming AppStore updates");
-        });
-    }
-
-    @Ignore("b/182844465")
-    @Test
-    public void workTabExists() {
-        mDevice.pressHome();
-        waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
-        executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
-        waitForState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS);
-        waitForLauncherCondition("Personal tab is missing",
-                launcher -> launcher.getAppsView().isPersonalTabVisible(), 60000);
-        waitForLauncherCondition("Work tab is missing",
-                launcher -> launcher.getAppsView().isWorkTabVisible(), 60000);
-    }
-
-    @Ignore("b/182844465")
-    @Test
-    public void toggleWorks() {
-        mDevice.pressHome();
-        waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
-        executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
-        waitForState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS);
-        getOnceNotNull("Apps view did not bind",
-                launcher -> launcher.getAppsView().getWorkModeSwitch(), 60000);
-
-        UserManager userManager = getFromLauncher(l -> l.getSystemService(UserManager.class));
-        assertEquals(2, userManager.getUserProfiles().size());
-        UserHandle workProfile = getFromLauncher(l -> {
-            UserHandle myHandle = Process.myUserHandle();
-            List<UserHandle> userProfiles = userManager.getUserProfiles();
-            return userProfiles.get(0) == myHandle ? userProfiles.get(1) : userProfiles.get(0);
-        });
-
-        waitForLauncherCondition("work profile can't be turned off",
-                l -> userManager.requestQuietModeEnabled(true, workProfile));
-
-        assertTrue(userManager.isQuietModeEnabled(workProfile));
-        executeOnLauncher(launcher -> {
-            WorkModeSwitch wf = launcher.getAppsView().getWorkModeSwitch();
-            ((AllAppsPagedView) launcher.getAppsView().getContentView()).snapToPageImmediately(
-                    AllAppsContainerView.AdapterHolder.WORK);
-            wf.toggle();
-        });
-        waitForLauncherCondition("Work toggle did not work",
-                l -> l.getSystemService(UserManager.class).isQuietModeEnabled(workProfile));
-    }
-
-    @Ignore("b/182844465")
-    @Test
-    public void testWorkEduFlow() {
-        mDevice.pressHome();
-        waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
-        executeOnLauncher(launcher -> launcher.getSharedPrefs().edit().remove(
-                WorkEduView.KEY_WORK_EDU_STEP).remove(
-                WorkEduView.KEY_LEGACY_WORK_EDU_SEEN).commit());
-
-        waitForLauncherCondition("Work tab not setup", launcher -> {
-            if (launcher.getAppsView().getContentView() instanceof AllAppsPagedView) {
-                launcher.getAppsView().getAppsStore().enableDeferUpdates(DEFER_UPDATES_TEST);
-                return true;
-            }
-            return false;
-        }, LauncherInstrumentation.WAIT_TIME_MS);
-
-        executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
-        WorkEduView workEduView = getEduView();
-        // verify personal app edu is seen first and click "next"
-        executeOnLauncher(l -> {
-            assertEquals(((TextView) workEduView.findViewById(R.id.content_text)).getText(),
-                    l.getResources().getString(R.string.work_profile_edu_personal_apps));
-            workEduView.findViewById(R.id.proceed).callOnClick();
-        });
-
-        AtomicInteger attempt = new AtomicInteger(0);
-        // verify work edu is seen next
-        waitForLauncherCondition("Launcher did not show the next edu screen", l -> {
-            Log.d(TestProtocol.WORK_PROFILE_REMOVED,
-                    "running test attempt" + attempt.getAndIncrement());
-            if (!(l.getAppsView().getContentView() instanceof AllAppsPagedView)) {
-                Log.d(TestProtocol.WORK_PROFILE_REMOVED, "Work tab not setup. Skipping test");
-                return false;
-            }
-            if (((AllAppsPagedView) l.getAppsView().getContentView()).getCurrentPage()
-                    != WORK_PAGE) {
-                Log.d(TestProtocol.WORK_PROFILE_REMOVED, "Work page not highlighted");
-            }
-            return ((TextView) workEduView.findViewById(R.id.content_text)).getText().equals(
-                    l.getResources().getString(R.string.work_profile_edu_work_apps));
-        });
-    }
-
-    @Ignore("b/182844465")
-    @Test
-    public void testWorkEduIntermittent() {
-        mDevice.pressHome();
-        waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
-        executeOnLauncher(launcher -> launcher.getSharedPrefs().edit().remove(
-                WorkEduView.KEY_WORK_EDU_STEP).remove(
-                WorkEduView.KEY_LEGACY_WORK_EDU_SEEN).commit());
-
-
-        waitForLauncherCondition("Work tab not setup",
-                launcher -> launcher.getAppsView().getContentView() instanceof AllAppsPagedView,
-                60000);
-        executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
-
-        // verify personal app edu is seen
-        getEduView();
-
-        // dismiss personal edu
-        mDevice.pressHome();
-        waitForState("Launcher did not go home", () -> NORMAL);
-
-        // open work tab
-        executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
-        waitForState("Launcher did not switch to all apps", () -> ALL_APPS);
-        waitForLauncherCondition("Work tab not setup",
-                launcher -> launcher.getAppsView().getContentView() instanceof AllAppsPagedView,
-                60000);
-
-        executeOnLauncher(launcher -> {
-            AllAppsPagedView pagedView = (AllAppsPagedView) launcher.getAppsView().getContentView();
-            pagedView.setCurrentPage(WORK_PAGE);
-        });
-
-        WorkEduView workEduView = getEduView();
-
-        // verify work tab edu is shown
-        waitForLauncherCondition("Launcher did not show the next edu screen",
-                l -> ((TextView) workEduView.findViewById(R.id.content_text)).getText().equals(
-                        l.getResources().getString(R.string.work_profile_edu_work_apps)));
-    }
-
-
-    private WorkEduView getEduView() {
-        waitForLauncherCondition("Edu did not show", l -> {
-            DragLayer dragLayer = l.getDragLayer();
-            return dragLayer.getChildCount() > 0 && dragLayer.getChildAt(
-                    dragLayer.getChildCount() - 1) instanceof WorkEduView;
-        }, 6000);
-        return getFromLauncher(launcher -> (WorkEduView) launcher.getDragLayer().getChildAt(
-                launcher.getDragLayer().getChildCount() - 1));
-    }
-
-}
\ No newline at end of file
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 7137c00..b037be4 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -57,7 +57,8 @@
                      mLauncher.addContextLayer("want to fling forward in overview")) {
             LauncherInstrumentation.log("Overview.flingForward before fling");
             final UiObject2 overview = verifyActiveContainer();
-            final int leftMargin = mLauncher.getTargetInsets().left;
+            final int leftMargin =
+                    mLauncher.getTargetInsets().left + mLauncher.getEdgeSensitivityWidth();
             mLauncher.scroll(
                     overview, Direction.LEFT, new Rect(leftMargin + 1, 0, 0, 0), 20, false);
             try (LauncherInstrumentation.Closable c2 =
@@ -97,7 +98,8 @@
                      mLauncher.addContextLayer("want to fling backward in overview")) {
             LauncherInstrumentation.log("Overview.flingBackward before fling");
             final UiObject2 overview = verifyActiveContainer();
-            final int rightMargin = mLauncher.getTargetInsets().right;
+            final int rightMargin =
+                    mLauncher.getTargetInsets().right + mLauncher.getEdgeSensitivityWidth();
             mLauncher.scroll(
                     overview, Direction.RIGHT, new Rect(0, 0, rightMargin + 1, 0), 20, false);
             try (LauncherInstrumentation.Closable c2 =
@@ -138,6 +140,10 @@
         }
     }
 
+    int getTaskCount() {
+        return getTasks().size();
+    }
+
     /**
      * Returns whether Overview has tasks.
      */
@@ -169,7 +175,7 @@
         }
         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                 "want to assert overview actions view visibility")) {
-            if (mLauncher.isTablet() && !isOverviewSnappedToFocusedTask()) {
+            if (mLauncher.isTablet() && !isOverviewSnappedToFocusedTaskForTablet()) {
                 mLauncher.waitUntilLauncherObjectGone("action_buttons");
             } else {
                 mLauncher.waitForLauncherObject("action_buttons");
@@ -178,14 +184,10 @@
     }
 
     /**
-     * Returns if focused task is currently snapped task in overview.
+     * Returns if focused task is currently snapped task in tablet grid overview.
      */
-    private boolean isOverviewSnappedToFocusedTask() {
-        if (!mLauncher.isTablet()) {
-            // Focused task only exists in tablet's grid-overview
-            return false;
-        }
-        UiObject2 focusedTask = getFocusedTask();
+    private boolean isOverviewSnappedToFocusedTaskForTablet() {
+        UiObject2 focusedTask = getFocusedTaskForTablet();
         if (focusedTask == null) {
             return false;
         }
@@ -197,14 +199,14 @@
     /**
      * Returns Overview focused task if it exists.
      */
-    private UiObject2 getFocusedTask() {
+    UiObject2 getFocusedTaskForTablet() {
         final List<UiObject2> taskViews = getTasks();
         if (taskViews.size() == 0) {
             return null;
         }
-        int focusedTaskWidth = mLauncher.getFocusedTaskWidth();
+        int focusedTaskHeight = mLauncher.getFocusedTaskHeightForTablet();
         for (UiObject2 task : taskViews) {
-            if (task.getVisibleBounds().width() == focusedTaskWidth) {
+            if (task.getVisibleBounds().height() == focusedTaskHeight) {
                 return task;
             }
         }
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index f83c031..55fb2c1 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -321,8 +321,8 @@
                 .getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD);
     }
 
-    int getFocusedTaskWidth() {
-        return getTestInfo(TestProtocol.REQUEST_GET_FOCUSED_TASK_WIDTH_FOR_TABLET).getInt(
+    int getFocusedTaskHeightForTablet() {
+        return getTestInfo(TestProtocol.REQUEST_GET_FOCUSED_TASK_HEIGHT_FOR_TABLET).getInt(
                 TestProtocol.TEST_INFO_RESPONSE_FIELD);
     }
 
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index 71c0abb..9419839 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -47,29 +47,53 @@
         mOverview.verifyActiveContainer();
     }
 
+    private int getVisibleHeight() {
+        return mTask.getVisibleBounds().height();
+    }
+
     /**
-     * Swipes the task up.
+     * Dismisses the task by swiping up.
      */
     public void dismiss() {
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
-                     "want to dismiss a task")) {
+                     "want to dismiss an overview task")) {
             verifyActiveContainer();
-            // Dismiss the task via flinging it up.
-            final Rect taskBounds = mLauncher.getVisibleBounds(mTask);
-            final int centerX = taskBounds.centerX();
-            final int centerY = taskBounds.centerY();
-            mLauncher.executeAndWaitForLauncherEvent(
-                    () -> mLauncher.linearGesture(centerX, centerY, centerX, 0, 10, false,
-                            LauncherInstrumentation.GestureScope.INSIDE),
-                    event -> TestProtocol.DISMISS_ANIMATION_ENDS_MESSAGE.equals(
-                            event.getClassName()),
-                    () -> "Didn't receive a dismiss animation ends message: " + centerX + ", "
-                            + centerY,
-                    "swiping to dismiss");
+            int taskCountBeforeDismiss = mOverview.getTaskCount();
+            mLauncher.assertNotEquals("Unable to find a task", 0, taskCountBeforeDismiss);
+            if (taskCountBeforeDismiss == 1) {
+                dismissBySwipingUp();
+                return;
+            }
+
+            boolean taskWasFocused = mLauncher.isTablet() && getVisibleHeight() == mLauncher
+                    .getFocusedTaskHeightForTablet();
+
+            dismissBySwipingUp();
+
+            try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("dismissed")) {
+                if (taskWasFocused) {
+                    mLauncher.assertNotNull("No task became focused",
+                            mOverview.getFocusedTaskForTablet());
+                }
+            }
         }
     }
 
+    private void dismissBySwipingUp() {
+        verifyActiveContainer();
+        // Dismiss the task via flinging it up.
+        final Rect taskBounds = mLauncher.getVisibleBounds(mTask);
+        final int centerX = taskBounds.centerX();
+        final int centerY = taskBounds.centerY();
+        mLauncher.executeAndWaitForLauncherEvent(
+                () -> mLauncher.linearGesture(centerX, centerY, centerX, 0, 10, false,
+                        LauncherInstrumentation.GestureScope.INSIDE),
+                event -> TestProtocol.DISMISS_ANIMATION_ENDS_MESSAGE.equals(event.getClassName()),
+                () -> "Didn't receive a dismiss animation ends message: " + centerX + ", "
+                        + centerY, "swiping to dismiss");
+    }
+
     /**
      * Clicks at the task.
      */