Merge "Invoke IME switcher for taskbar through SysUI" into sc-v2-dev
diff --git a/Android.bp b/Android.bp
index c8d9186..d04dca0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -152,9 +152,13 @@
     ],
     srcs: [
         "src/**/*.java",
+        "src/**/*.kt",
         "src_shortcuts_overrides/**/*.java",
+        "src_shortcuts_overrides/**/*.kt",
         "src_ui_overrides/**/*.java",
+        "src_ui_overrides/**/*.kt",
         "ext_tests/src/**/*.java",
+        "ext_tests/src/**/*.kt",
     ],
     resource_dirs: [
         "ext_tests/res",
@@ -211,7 +215,10 @@
 // Source code used for test helpers
 filegroup {
     name: "launcher-src-ext-tests",
-    srcs: ["ext_tests/src/**/*.java"],
+    srcs: [
+        "ext_tests/src/**/*.java",
+        "ext_tests/src/**/*.kt",
+    ],
 }
 
 // Common source files used to build launcher
@@ -219,8 +226,11 @@
     name: "launcher-src-no-build-config",
     srcs: [
         "src/**/*.java",
+        "src/**/*.kt",
         "src_shortcuts_overrides/**/*.java",
+        "src_shortcuts_overrides/**/*.kt",
         "quickstep/src/**/*.java",
+        "quickstep/src/**/*.kt",
     ],
 }
 
@@ -235,9 +245,13 @@
     name: "LauncherGoResLib",
     srcs: [
         "src/**/*.java",
+        "src/**/*.kt",
         "quickstep/src/**/*.java",
+        "quickstep/src/**/*.kt",
         "go/src/**/*.java",
+        "go/src/**/*.kt",
         "go/quickstep/src/**/*.java",
+        "go/quickstep/src/**/*.kt",
     ],
     resource_dirs: [
         "go/res",
diff --git a/Android.mk b/Android.mk
index c1dbc53..ceaaf13 100644
--- a/Android.mk
+++ b/Android.mk
@@ -105,7 +105,7 @@
   LOCAL_SDK_VERSION := system_current
   LOCAL_MIN_SDK_VERSION := 26
 endif
-LOCAL_STATIC_ANDROID_LIBRARIES := Launcher3CommonDepsLib
+LOCAL_STATIC_ANDROID_LIBRARIES := LauncherGoResLib
 
 LOCAL_SRC_FILES := \
     $(call all-java-files-under, src) \
diff --git a/quickstep/res/layout/rotate_suggestion.xml b/quickstep/res/layout/rotate_suggestion.xml
new file mode 100644
index 0000000..07cf0c8
--- /dev/null
+++ b/quickstep/res/layout/rotate_suggestion.xml
@@ -0,0 +1,30 @@
+<?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
+  -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+    <com.android.systemui.shared.rotation.FloatingRotationButtonView
+        android:id="@+id/rotate_suggestion"
+        android:layout_width="@dimen/floating_rotation_button_diameter"
+        android:layout_height="@dimen/floating_rotation_button_diameter"
+        android:paddingStart="@dimen/navigation_key_padding"
+        android:paddingEnd="@dimen/navigation_key_padding"
+        android:layout_gravity="bottom|left"
+        android:scaleType="center"
+        android:visibility="invisible" />
+</FrameLayout>
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index 459d32a..9597326 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Skermkiekie"</string>
     <string name="action_split" msgid="2098009717623550676">"Verdeel"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Probeer ander program om verdeelde skerm te gebruik"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Jou organisasie laat nie hierdie program toe nie"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Slaan navigasietutoriaal oor?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Jy kan dit later in die <xliff:g id="NAME">%1$s</xliff:g>-program kry"</string>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index 7961b28..bedad88 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"ቅጽበታዊ ገጽ እይታ"</string>
     <string name="action_split" msgid="2098009717623550676">"ክፈል"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"የተከፈለ ማያን ለመጠቀም ሌላ መተግበሪያ መታ ያድርጉ"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 a293124..93c256f 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"لقطة شاشة"</string>
     <string name="action_split" msgid="2098009717623550676">"تقسيم"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"انقر على تطبيق آخر لاستخدام وضع تقسيم الشاشة."</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 cc4347a..5612852 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -23,7 +23,7 @@
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
     <string name="recents_empty_message" msgid="7040467240571714191">"কোনো শেহতীয়া বস্তু নাই"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"এপে ব্যৱহাৰ কৰা ডেটাৰ ছেটিং"</string>
-    <string name="recents_clear_all" msgid="5328176793634888831">"সকলো মচক"</string>
+    <string name="recents_clear_all" msgid="5328176793634888831">"আটাইবোৰ মচক"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"শেহতীয়া এপসমূহ"</string>
     <string name="task_contents_description_with_remaining_time" msgid="4479688746574672685">"<xliff:g id="TASK_DESCRIPTION">%1$s</xliff:g>, <xliff:g id="REMAINING_TIME">%2$s</xliff:g>"</string>
     <string name="shorter_duration_less_than_one_minute" msgid="4722015666335015336">"&lt; ১ মিনিট"</string>
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"স্ক্ৰীনশ্বট"</string>
     <string name="action_split" msgid="2098009717623550676">"বিভাজন কৰক"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰিবলৈ অন্য এটা এপত টিপক"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-az/strings.xml b/quickstep/res/values-az/strings.xml
index e288b5d..4933a45 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Skrinşot"</string>
     <string name="action_split" msgid="2098009717623550676">"Ayırın"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Bölmə ekranını istifadə etmək üçün başqa tətbiqə toxunun"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Bu əməliyyata tətbiq və ya təşkilatınız tərəfindən icazə verilmir"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Naviqasiya dərsliyi ötürülsün?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Bunu sonra <xliff:g id="NAME">%1$s</xliff:g> tətbiqində tapa bilərsiniz"</string>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 3ebaa40..0ad0ad5 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Snimak ekrana"</string>
     <string name="action_split" msgid="2098009717623550676">"Podeli"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Dodirnite drugu aplikaciju za podeljeni ekran"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ili organizacija ne dozvoljavaju ovu radnju"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite da preskočite vodič za kretanje?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Možete da pronađete ovo kasnije u aplikaciji <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 bf21d81..9f8fdb3 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Здымак экрана"</string>
     <string name="action_split" msgid="2098009717623550676">"Падзелены экран"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Для падзеленага экрана націсніце на іншую праграму"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index 659dcb6..d78cd12 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Екранна снимка"</string>
     <string name="action_split" msgid="2098009717623550676">"Разделяне на екрана"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Докоснете друго прил., за да ползвате разд. екран"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 cc8e186..adf18f0 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"স্ক্রিনশট নিন"</string>
     <string name="action_split" msgid="2098009717623550676">"স্প্লিট"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"স্প্লিটস্ক্রিন ব্যবহার করতে অন্য অ্যাপে ট্যাপ করুন"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index bf2517f..17e4d82 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Snimak ekrana"</string>
     <string name="action_split" msgid="2098009717623550676">"Podijeli"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Dodirnite drugu apl. da koristite podijeljeni ekran"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Ovu radnju ne dozvoljava aplikacija ili vaša organizacija"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Preskočiti vodič za navigiranje?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"To možete pronaći kasnije u aplikaciji <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 1b1ed61..990b928 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Captura de pantalla"</string>
     <string name="action_split" msgid="2098009717623550676">"Divideix"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Toca una altra aplicació per dividir la pantalla"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 ae2e13f..4c08680 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Snímek obrazovky"</string>
     <string name="action_split" msgid="2098009717623550676">"Rozdělit"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Klepnutím na jinou aplikaci rozdělíte obrazovku"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-da/strings.xml b/quickstep/res/values-da/strings.xml
index 26de0c2..3bdadd5 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Opdel"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Tryk på en anden app for at bruge opdelt skærm"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller din organisation tillader ikke denne handling"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vil du springe selvstudiet for navigation over?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Du kan finde dette senere i appen <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 494f846..791df23 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Teilen"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Für „Bildschirm teilen“ auf weitere App tippen"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 a266ff8..4bc397f 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Στιγμιότυπο οθόνης"</string>
     <string name="action_split" msgid="2098009717623550676">"Διαχωρισμός"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Πατήστε άλλη εφαρμογή για χρήση διαχωρισμού οθόνης"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index b787fdf..c1e520b 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Split"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Tap another app to use split-screen"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organisation"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"You can find this later in the <xliff:g id="NAME">%1$s</xliff:g> app"</string>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index b787fdf..c1e520b 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Split"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Tap another app to use split-screen"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organisation"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"You can find this later in the <xliff:g id="NAME">%1$s</xliff:g> app"</string>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index b787fdf..c1e520b 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Split"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Tap another app to use split-screen"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organisation"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"You can find this later in the <xliff:g id="NAME">%1$s</xliff:g> app"</string>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index b787fdf..c1e520b 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Split"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Tap another app to use split-screen"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organisation"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"You can find this later in the <xliff:g id="NAME">%1$s</xliff:g> app"</string>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index c92af05..84727e5 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‎‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‎‏‎Screenshot‎‏‎‎‏‎"</string>
     <string name="action_split" msgid="2098009717623550676">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‎Split‎‏‎‎‏‎"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‏‎‎‎‏‎‎‏‎‏‏‎‎‏‏‎‏‎‏‎‎‎‏‎‏‎‏‏‎‏‏‎‏‎‎‎‏‏‎‎‎‎‎Tap another app to use splitscreen‎‏‎‎‏‎"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‏‎‎‏‏‎‎‏‏‏‎‏‎‏‏‏‎‎‎‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎This action isn\'t allowed by the app or your organization‎‏‎‎‏‎"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‎‎‏‎‎‏‏‎‎‏‎‎‏‏‏‎‏‎‎Skip navigation tutorial?‎‏‎‎‏‎"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‏‎‎‏‏‎‏‎‏‏‎‏‏‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‏‎‎You can find this later in the ‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ app‎‏‎‎‏‎"</string>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 118df33..4309453 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Captura de pantalla"</string>
     <string name="action_split" msgid="2098009717623550676">"Pantalla dividida"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Presiona otra app para usar la pantalla dividida"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"La app o tu organización no permiten realizar esta acción"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"¿Omitir el instructivo de navegación?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Puedes encontrarlo en la app de <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 5b2cee9..13bc0ee 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Hacer captura"</string>
     <string name="action_split" msgid="2098009717623550676">"Dividir"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Toca otra aplicación para usar la pantalla dividida"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"No puedes hacerlo porque la aplicación o tu organización no lo permiten"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"¿Saltar tutorial de navegación?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Puedes consultarlo en otro momento en la aplicación <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 7b2b3da..717afe2 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Ekraanipilt"</string>
     <string name="action_split" msgid="2098009717623550676">"Eralda"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Jagatud kuva kasutamiseks puudutage muud rakendust"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Rakendus või teie organisatsioon on selle toimingu keelanud"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Kas jätta navigeerimise õpetused vahele?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Leiate selle hiljem rakendusest <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index 8e26e20..bf6c04a 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Atera pantaila-argazki bat"</string>
     <string name="action_split" msgid="2098009717623550676">"Zatitu"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Sakatu beste aplikazio bat pantaila zatitzeko"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Aplikazioak edo erakundeak ez du eman ekintza hori gauzatzeko baimena"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Nabigazio-tutoriala saltatu nahi duzu?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> aplikazioan dago eskuragarri tutoriala"</string>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index c0a805c..ea65bdb 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"نماگرفت"</string>
     <string name="action_split" msgid="2098009717623550676">"دونیمه"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"برای استفاده از صفحهٔ دونیمه، روی برنامه دیگری ضربه بزنید"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index e6f6ab1..ac3a160 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Kuvakaappaus"</string>
     <string name="action_split" msgid="2098009717623550676">"Jaa"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Avaa jaettu näyttö napauttamalla toista sovellusta"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Sovellus tai organisaatio ei salli tätä toimintoa"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ohitetaanko navigointiohje?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Löydät tämän myöhemmin sovelluksesta: <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 3b611c4..423ca3f 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Capture d\'écran"</string>
     <string name="action_split" msgid="2098009717623550676">"Séparé"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Touchez une autre appli pour partager l\'écran"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 6f7149f..fa0dce1 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Capture d\'écran"</string>
     <string name="action_split" msgid="2098009717623550676">"Partager"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Appuyez sur autre appli pour utiliser écran partagé"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Cette action n\'est pas autorisée par l\'application ou par votre organisation"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorer le tutoriel de navigation ?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Vous le retrouverez dans l\'appli <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 db28634..c15a389 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Facer captura"</string>
     <string name="action_split" msgid="2098009717623550676">"Dividir"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Para usar a pantalla dividida, toca outra app"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 cc998b4..b54bc1c 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"સ્ક્રીનશૉટ"</string>
     <string name="action_split" msgid="2098009717623550676">"વિભાજિત કરો"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"સ્પલિટસ્ક્રીનના વપરાશ માટે, કોઈ અન્ય ઍપ પર ટૅપ કરો"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 fd06fca..d13e4d4 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट लें"</string>
     <string name="action_split" msgid="2098009717623550676">"स्प्लिट स्क्रीन मोड"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"स्प्लिट स्क्रीन मोड के लिए, दूसरे ऐप पर टैप करें"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index 2b31943..ab786da 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Snimka zaslona"</string>
     <string name="action_split" msgid="2098009717623550676">"Podijeli"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Dodirnite drugu aplikaciju za podijeljeni zaslon"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ili vaša organizacija ne dopuštaju ovu radnju"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite li preskočiti vodič za kretanje?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Kasnije ga možete pronaći u aplikaciji <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 06cfb71..b83d23a 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Képernyőkép"</string>
     <string name="action_split" msgid="2098009717623550676">"Felosztás"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Koppintson másik appra a képernyőmegosztáshoz"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Az alkalmazás vagy az Ön szervezete nem engedélyezi ezt a műveletet"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Kihagyja a navigáció bemutatóját?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Ezt később megtalálhatja a(z) <xliff:g id="NAME">%1$s</xliff:g> alkalmazásban"</string>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 18a2ddd..d192bad 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Սքրինշոթ անել"</string>
     <string name="action_split" msgid="2098009717623550676">"Տրոհել"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Հպեք այլ հավելվածի՝ էկրանը տրոհելու համար"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 5854104..9def0de 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Pisahkan"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Ketuk aplikasi lain untuk menggunakan layar terpisah"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-is/strings.xml b/quickstep/res/values-is/strings.xml
index c5a47b1..d475505 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Skjámynd"</string>
     <string name="action_split" msgid="2098009717623550676">"Skipta"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Ýttu á annað forrit til að nota skjáskiptingu"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Forritið eða fyrirtækið leyfir ekki þessa aðgerð"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Sleppa flettileiðsögn?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Þú getur fundið þetta síðar í forritinu <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 2a5b87d..b20f57d 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Dividi"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Tocca un\'altra app per usare lo schermo diviso"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Questa azione non è consentita dall\'app o dall\'organizzazione"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Saltare il tutorial di navigazione?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Puoi trovarlo in un secondo momento nell\'app <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 467f5b9..aef851f 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"צילום מסך"</string>
     <string name="action_split" msgid="2098009717623550676">"פיצול"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"צריך להקיש על אפליקציה אחרת כדי להשתמש במסך מפוצל"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 6b73a9b..a2eeccb 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"スクリーンショット"</string>
     <string name="action_split" msgid="2098009717623550676">"分割"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"分割画面を使用するには、他のアプリをタップします"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index 22ead5c..053607b 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"ეკრანის ანაბეჭდი"</string>
     <string name="action_split" msgid="2098009717623550676">"გაყოფა"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"შეეხეთ სხვა აპს ეკრანის გასაყოფად"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index cd86af4..76381fc 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
     <string name="action_split" msgid="2098009717623550676">"Бөлу"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Экранды бөлу режимін пайдалану үшін басқа қолданбаны түртіңіз."</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 1e677c2..df265c0 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"រូបថតអេក្រង់"</string>
     <string name="action_split" msgid="2098009717623550676">"បំបែក"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"ចុចកម្មវិធី​ផ្សេងទៀត ដើម្បីប្រើមុខងារ​បំបែកអេក្រង់"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 fa3f1f6..33a4c92 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್"</string>
     <string name="action_split" msgid="2098009717623550676">"ವಿಭಜಿಸಿ"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಬಳಸಲು ಬೇರೊಂದು ಆ್ಯಪ್ ಮೇಲೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index 085f194..088b2ce 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"스크린샷"</string>
     <string name="action_split" msgid="2098009717623550676">"분할"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"다른 앱을 탭하여 화면 분할 사용"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 ba23770..85df507 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
     <string name="action_split" msgid="2098009717623550676">"Бөлүү"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Экранды бөлүү үчүн башка колдонмону таптап коюңуз"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 796de14..3dde91d 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"ຮູບໜ້າຈໍ"</string>
     <string name="action_split" msgid="2098009717623550676">"ແບ່ງ"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"ແຕະແອັບອື່ນເພື່ອໃຊ້ການແຍກໜ້າຈໍ"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 e20a780..accaf44 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Ekrano kopija"</string>
     <string name="action_split" msgid="2098009717623550676">"Išskaidymo režimas"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Pal. kitą progr., kad gal. naud. išsk. ekr. rež."</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 148102f..f0fa5ef 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Veikt ekrānuzņēmumu"</string>
     <string name="action_split" msgid="2098009717623550676">"Sadalīt"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Piesk. citai lietotnei, lai izm. ekrāna sadalīšanu"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index e1bc7a6..878b13d 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Слика од екранот"</string>
     <string name="action_split" msgid="2098009717623550676">"Раздели"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Допрете друга апликација за да користите поделен екран"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index 7342c3c..6008acb 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"സ്ക്രീൻഷോട്ട്"</string>
     <string name="action_split" msgid="2098009717623550676">"വിഭജിക്കുക"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"സ്പ്ലിറ്റ് സ്ക്രീനിനായി മറ്റൊരു ആപ്പ് ടാപ്പുചെയ്യൂ"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 78ddb56..c3dc8be 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Дэлгэцийн агшин дарах"</string>
     <string name="action_split" msgid="2098009717623550676">"Хуваах"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Дэлгэц хуваахыг ашиглах бол өөр аппыг товшино уу"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 df94447..fd065cd 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट"</string>
     <string name="action_split" msgid="2098009717623550676">"स्प्लिट"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"स्प्लिटस्क्रीन वापरण्यासाठी दुसऱ्या ॲपवर टॅप करा"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index ba7a15e..baae5ae 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Tangkapan skrin"</string>
     <string name="action_split" msgid="2098009717623550676">"Pisah"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Ketik apl lain untuk menggunakan skrin pisah"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Tindakan ini tidak dibenarkan oleh apl atau organisasi anda"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Langkau tutorial navigasi?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Anda boleh mendapatkan tutorial ini kemudian dalam apl <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index 17cd498..2f003e3 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -23,7 +23,7 @@
     <string name="recent_task_option_freeform" msgid="48863056265284071">"အလွတ်ပုံစံ"</string>
     <string name="recents_empty_message" msgid="7040467240571714191">"မကြာမီကဖွင့်ထားသည်များ မရှိပါ"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"အက်ပ်အသုံးပြုမှု ဆက်တင်များ"</string>
-    <string name="recents_clear_all" msgid="5328176793634888831">"အားလုံးထုတ်ပစ်ရန်"</string>
+    <string name="recents_clear_all" msgid="5328176793634888831">"အားလုံးရှင်းရန်"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"လတ်တလောသုံး အက်ပ်များ"</string>
     <string name="task_contents_description_with_remaining_time" msgid="4479688746574672685">"<xliff:g id="TASK_DESCRIPTION">%1$s</xliff:g>၊ <xliff:g id="REMAINING_TIME">%2$s</xliff:g>"</string>
     <string name="shorter_duration_less_than_one_minute" msgid="4722015666335015336">"&lt; ၁ မိနစ်"</string>
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
     <string name="action_split" msgid="2098009717623550676">"ခွဲထုတ်ရန်"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"မျက်နှာပြင်ခွဲ၍ပြသရန် အက်ပ်နောက်တစ်ခုကို တို့ပါ"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 6e43cfb..e78ce8f 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Skjermdump"</string>
     <string name="action_split" msgid="2098009717623550676">"Del opp"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Trykk på en annen app for å bruke delt skjerm"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 f827bcc..bedbdde 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"स्क्रिनसट"</string>
     <string name="action_split" msgid="2098009717623550676">"स्प्लिट गर्नुहोस्"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"स्प्लिटक्रिन प्रयोग गर्न अर्को एपमा ट्याप गर्नुहोस्"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index 81cda4d..6d6cc38 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Splitsen"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Tik op nog een app om je scherm te splitsen"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Deze actie wordt niet toegestaan door de app of je organisatie"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Navigatietutorial overslaan?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Je vindt dit later terug in de app <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 3535427..2e66856 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"ସ୍କ୍ରିନସଟ୍"</string>
     <string name="action_split" msgid="2098009717623550676">"ସ୍ପ୍ଲିଟ୍"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"ସ୍ପ୍ଲିଟସ୍କ୍ରିନ ବ୍ୟବହାର କରିବାକୁ ଅନ୍ୟ ଏକ ଆପରେ ଟାପ କର"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index 5f070ce..e228b60 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
     <string name="action_split" msgid="2098009717623550676">"ਸਪਲਿਟ"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਵਰਤਣ ਲਈ ਕਿਸੇ ਹੋਰ ਐਪ \'ਤੇ ਟੈਪ ਕਰੋ"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 601aa4c..6e86c29 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Zrzut ekranu"</string>
     <string name="action_split" msgid="2098009717623550676">"Podziel"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Kliknij drugą aplikację, aby podzielić ekran"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Nie możesz wykonać tego działania, bo nie zezwala na to aplikacja lub Twoja organizacja"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Pominąć samouczek nawigacji?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Znajdziesz to później w aplikacji <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index 3f03537..beade90 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Fazer captura de ecrã"</string>
     <string name="action_split" msgid="2098009717623550676">"Dividir"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Toque noutra app para utilizar o ecrã dividido"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Esta ação não é permitida pela app ou a sua entidade."</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorar o tutorial de navegação?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Pode encontrar isto mais tarde na app <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index d725576..faa325f 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Capturar tela"</string>
     <string name="action_split" msgid="2098009717623550676">"Dividir"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Toque em outro app para dividir a tela"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Essa ação não é permitida pelo app ou pela organização"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Pular o tutorial de navegação?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Veja o tutorial mais tarde no app <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index 27fd511..95b6a78 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Captură de ecran"</string>
     <string name="action_split" msgid="2098009717623550676">"Împărțit"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Atingeți altă aplicație pentru a folosi ecranul împărțit"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Această acțiune nu este permisă de aplicație sau de organizația dvs."</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Omiteți tutorialul de navigare?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Îl puteți găsi mai târziu în aplicația <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 ab8b8cf..66c0f56 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
     <string name="action_split" msgid="2098009717623550676">"Разделить"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Для разделения экрана нажмите на другое приложение."</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-si/strings.xml b/quickstep/res/values-si/strings.xml
index f286b66..4aa9f02 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"තිර රුව"</string>
     <string name="action_split" msgid="2098009717623550676">"බෙදන්න"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"බෙදුම් තිරය භාවිත කිරීමට තවත් යෙදුමක් තට්ටු කරන්න"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index ce71b88..40d1ffc 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Snímka obrazovky"</string>
     <string name="action_split" msgid="2098009717623550676">"Rozdeliť"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Rozdel. obrazovku spustíte klepnutím na inú aplik."</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Aplikácia alebo vaša organizácia túto akciu nepovoľuje"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Chcete preskočiť návod na navigáciu?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Tento návod nájdete v aplikácii <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 13299f1..71c17b6 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Posnetek zaslona"</string>
     <string name="action_split" msgid="2098009717623550676">"Razdeli"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Za uporabo razdeljenega zaslona se dotaknite še ene aplikacije."</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 771eb13..e7a6d95 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Pamja e ekranit"</string>
     <string name="action_split" msgid="2098009717623550676">"Ndaj"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Trokit aplikacion tjetër e përdor ekranin e ndarë"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index 73d3bfa..d8cac25 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Снимак екрана"</string>
     <string name="action_split" msgid="2098009717623550676">"Подели"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Додирните другу апликацију за подељени екран"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index c741a39..d014e78 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Skärmbild"</string>
     <string name="action_split" msgid="2098009717623550676">"Delat"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Tryck på en annan app för att använda delad skärm"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 8302751..97cde71 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Picha ya skrini"</string>
     <string name="action_split" msgid="2098009717623550676">"Iliyogawanywa"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Gusa programu nyingine ili utumie skrini iliyogawanywa"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-sw600dp/dimens.xml b/quickstep/res/values-sw600dp/dimens.xml
new file mode 100644
index 0000000..5d9e059
--- /dev/null
+++ b/quickstep/res/values-sw600dp/dimens.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<resources>
+    <dimen name="navigation_key_padding">25dp</dimen>
+</resources>
diff --git a/quickstep/res/values-sw900dp/dimens.xml b/quickstep/res/values-sw900dp/dimens.xml
new file mode 100644
index 0000000..3efa5e3
--- /dev/null
+++ b/quickstep/res/values-sw900dp/dimens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<resources>
+    <!-- The maximum width of the navigation bar ripples. -->
+    <dimen name="key_button_ripple_max_width">76dp</dimen>
+
+    <!-- The padding around the navigation buttons -->
+    <dimen name="navigation_key_padding">0dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index 0de21e8..5abed08 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"ஸ்கிரீன்ஷாட்"</string>
     <string name="action_split" msgid="2098009717623550676">"பிரி"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"ஸ்பிளிட் ஸ்கிரீனுக்கு மற்றொரு ஆப்ஸைத் தட்டவும்"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-te/strings.xml b/quickstep/res/values-te/strings.xml
index 0f42271..7630444 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"స్క్రీన్‌షాట్"</string>
     <string name="action_split" msgid="2098009717623550676">"స్ప్లిట్ చేయండి"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"స్క్రీన్ విభజనను ఉపయోగించడానికి మరొక యాప్ నొక్కండి"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-th/strings.xml b/quickstep/res/values-th/strings.xml
index 435c774..5298f23 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"ภาพหน้าจอ"</string>
     <string name="action_split" msgid="2098009717623550676">"แยก"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"แตะที่แอปอื่นเพื่อใช้แบ่งหน้าจอ"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index 3ed75a9..6b68c3d 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Split"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Mag-tap ng ibang app para gamitin ang splitscreen"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Hindi pinapayagan ng app o ng iyong organisasyon ang pagkilos na ito"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Laktawan ang tutorial sa pag-navigate?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Makikita mo ito sa <xliff:g id="NAME">%1$s</xliff:g> app sa ibang pagkakataon"</string>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 910affe..23ed52b 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Ekran görüntüsü"</string>
     <string name="action_split" msgid="2098009717623550676">"Böl"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Bölünmüş ekran için başka bir uygulamaya dokunun"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Uygulamanız veya kuruluşunuz bu işleme izin vermiyor"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Gezinme eğitimi atlansın mı?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Bunu daha sonra <xliff:g id="NAME">%1$s</xliff:g> uygulamasında bulabilirsiniz"</string>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 466da29..adbe0e5 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Знімок екрана"</string>
     <string name="action_split" msgid="2098009717623550676">"Розділити"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Щоб розділити екран, виберіть ще один додаток"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 e0e9beb..2f26862 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"اسکرین شاٹ"</string>
     <string name="action_split" msgid="2098009717623550676">"اسپلٹ"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"اسپلٹ اسکرین کا استعمال کرنے کیلئے دوسری ایپ پر تھپتھپائیں"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index ffa8a2d..db18c8b 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Skrinshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Ajratish"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Ekranni ikkiga ajratish uchun boshqa ilovani bosing"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Bu amal ilova yoki tashkilotingiz tomonidan taqiqlangan"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Navigatsiya darsi yopilsinmi?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Bu darslar <xliff:g id="NAME">%1$s</xliff:g> ilovasida chiqadi"</string>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index 81d3dec..626ea97 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Chụp ảnh màn hình"</string>
     <string name="action_split" msgid="2098009717623550676">"Chia đôi màn hình"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Nhấn vào một ứng dụng khác để dùng màn hình chia đôi"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <string name="blocked_by_policy" msgid="2071401072261365546">"Ứng dụng hoặc tổ chức của bạn không cho phép thực hiện hành động này"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Bỏ qua phần hướng dẫn thao tác?"</string>
     <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Bạn có thể tìm lại phần hướng dẫn này trong ứng dụng <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 a55a44c..4e4090e 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"屏幕截图"</string>
     <string name="action_split" msgid="2098009717623550676">"拆分"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"点按另一个应用即可使用分屏"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index 42329eb..a7d344a 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"螢幕截圖"</string>
     <string name="action_split" msgid="2098009717623550676">"分割"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"輕按其他應用程式以使用分割螢幕"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index a014adb..e21b0e3 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"螢幕截圖"</string>
     <string name="action_split" msgid="2098009717623550676">"分割"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"輕觸另一個應用程式即可使用分割畫面"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 dfa67d0..ead9879 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -80,6 +80,8 @@
     <string name="action_screenshot" msgid="8171125848358142917">"Isithombe-skrini"</string>
     <string name="action_split" msgid="2098009717623550676">"Hlukanisa"</string>
     <string name="toast_split_select_app" msgid="5453865907322018352">"Thepha enye i-app ukuze usebenzise isikrini sokuhlukanisa"</string>
+    <!-- no translation found for toast_split_app_unsupported (3271526028981899666) -->
+    <skip />
     <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 fb2ee1c..f237d26 100644
--- a/quickstep/res/values/colors.xml
+++ b/quickstep/res/values/colors.xml
@@ -30,6 +30,9 @@
     <color name="taskbar_stashed_handle_light_color">#EBffffff</color>
     <color name="taskbar_stashed_handle_dark_color">#99000000</color>
 
+    <color name="rotation_button_light_color">#FFF</color>
+    <color name="rotation_button_dark_color">#99000000</color>
+
     <!-- Gesture navigation tutorial -->
     <color name="gesture_tutorial_back_arrow_color">#FFFFFFFF</color>
 
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 4ebf5cf..98d43f1 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -197,6 +197,19 @@
     <!-- Minimum distance to swipe to trigger accessibility gesture -->
     <dimen name="accessibility_gesture_min_swipe_distance">80dp</dimen>
 
+    <!-- The maximum width of the navigation bar ripples. -->
+    <dimen name="key_button_ripple_max_width">95dp</dimen>
+
+    <dimen name="rounded_corner_content_padding">0dp</dimen>
+
+    <dimen name="navigation_key_padding">0dp</dimen>
+
+    <!-- Floating rotation button -->
+    <dimen name="floating_rotation_button_diameter">40dp</dimen>
+    <dimen name="floating_rotation_button_min_margin">20dp</dimen>
+    <dimen name="floating_rotation_button_taskbar_left_margin">20dp</dimen>
+    <dimen name="floating_rotation_button_taskbar_bottom_margin">10dp</dimen>
+
     <!-- Taskbar -->
     <dimen name="taskbar_size">@*android:dimen/taskbar_frame_height</dimen>
     <dimen name="taskbar_icon_touch_size">48dp</dimen>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 88c98c0..151b8e4 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -208,6 +208,9 @@
     <!-- Button text shown on a button on the tutorial skip dialog to exit the tutorial. [CHAR LIMIT=14] -->
     <string name="gesture_tutorial_action_button_label_skip">Skip</string>
 
+    <!-- Accessibility label for the rotation suggestion button -->
+    <string name="accessibility_rotate_button">Rotate screen</string>
+
     <!-- ******* Taskbar Edu ******* -->
     <!-- Accessibility text spoken when the taskbar education panel appears [CHAR_LIMIT=NONE] -->
     <string name="taskbar_edu_opened">Taskbar education appeared</string>
diff --git a/quickstep/src/com/android/launcher3/LauncherInitListener.java b/quickstep/src/com/android/launcher3/LauncherInitListener.java
index 5fc79f0..35151f1 100644
--- a/quickstep/src/com/android/launcher3/LauncherInitListener.java
+++ b/quickstep/src/com/android/launcher3/LauncherInitListener.java
@@ -17,11 +17,8 @@
 
 import android.animation.AnimatorSet;
 import android.annotation.TargetApi;
-import android.content.Context;
-import android.content.Intent;
 import android.os.Build;
 import android.os.CancellationSignal;
-import android.os.Handler;
 
 import com.android.quickstep.util.ActivityInitListener;
 import com.android.quickstep.util.RemoteAnimationProvider;
@@ -78,11 +75,4 @@
         mRemoteAnimationProvider = null;
         super.unregister();
     }
-
-    @Override
-    public void registerAndStartActivity(Intent intent, RemoteAnimationProvider animProvider,
-            Context context, Handler handler, long duration) {
-        mRemoteAnimationProvider = animProvider;
-        super.registerAndStartActivity(intent, animProvider, context, handler, duration);
-    }
 }
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 8a05533..2ccec44 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -110,7 +110,6 @@
 import com.android.quickstep.RemoteAnimationTargets;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TaskViewUtils;
-import com.android.quickstep.util.AppCloseConfig;
 import com.android.quickstep.util.MultiValueUpdateListener;
 import com.android.quickstep.util.RectFSpringAnim;
 import com.android.quickstep.util.RemoteAnimationProvider;
@@ -286,7 +285,8 @@
         long statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION
                 - STATUS_BAR_TRANSITION_PRE_DELAY;
         RemoteAnimationAdapterCompat adapterCompat =
-                new RemoteAnimationAdapterCompat(runner, duration, statusBarTransitionDelay);
+                new RemoteAnimationAdapterCompat(runner, duration, statusBarTransitionDelay,
+                        mLauncher.getIApplicationThread());
         return new ActivityOptionsWrapper(
                 ActivityOptionsCompat.makeRemoteAnimation(adapterCompat), onEndCallback);
     }
@@ -1082,7 +1082,8 @@
                     new RemoteAnimationAdapterCompat(
                             new LauncherAnimationRunner(mHandler, mWallpaperOpenRunner,
                                     false /* startAtFrontOfQueue */),
-                            CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
+                            CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */,
+                            mLauncher.getIApplicationThread()));
 
             if (KEYGUARD_ANIMATION.get()) {
                 mKeyguardGoingAwayRunner = createWallpaperOpenRunner(true /* fromUnlock */);
@@ -1092,7 +1093,8 @@
                                 new LauncherAnimationRunner(
                                         mHandler, mKeyguardGoingAwayRunner,
                                         true /* startAtFrontOfQueue */),
-                                CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
+                                CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */,
+                                mLauncher.getIApplicationThread()));
             }
 
             new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
@@ -1110,7 +1112,7 @@
             mWallpaperOpenTransitionRunner = createWallpaperOpenRunner(false /* fromUnlock */);
             mLauncherOpenTransition = RemoteAnimationAdapterCompat.buildRemoteTransition(
                     new LauncherAnimationRunner(mHandler, mWallpaperOpenTransitionRunner,
-                            false /* startAtFrontOfQueue */));
+                            false /* startAtFrontOfQueue */), mLauncher.getIApplicationThread());
             mLauncherOpenTransition.addHomeOpenCheck(mLauncher.getComponentName());
             SystemUiProxy.INSTANCE.getNoCreate().registerRemoteTransition(mLauncherOpenTransition);
         }
@@ -1338,12 +1340,11 @@
 
             RectFSpringAnim.OnUpdateListener runner = new SpringAnimRunner(targets, targetRect) {
                 @Override
-                public void onUpdate(@Nullable AppCloseConfig values, RectF currentRectF,
-                        float progress) {
+                public void onUpdate(RectF currentRectF, float progress) {
                     finalFloatingIconView.update(1f, 255 /* fgAlpha */, currentRectF, progress,
                             windowAlphaThreshold, getCornerRadius(progress), false);
 
-                    super.onUpdate(values, currentRectF, progress);
+                    super.onUpdate(currentRectF, progress);
                 }
             };
             anim.addOnUpdateListener(runner);
@@ -1356,8 +1357,7 @@
             FloatingWidgetView finalFloatingWidget = floatingWidget;
             RectFSpringAnim.OnUpdateListener  runner = new SpringAnimRunner(targets, targetRect) {
                 @Override
-                public void onUpdate(@Nullable AppCloseConfig values, RectF currentRectF,
-                        float progress) {
+                public void onUpdate(RectF currentRectF, float progress) {
                     final float fallbackBackgroundAlpha =
                             1 - mapBoundToRange(progress, 0.8f, 1, 0, 1, EXAGGERATED_EASE);
                     final float foregroundAlpha =
@@ -1365,7 +1365,7 @@
                     finalFloatingWidget.update(currentRectF, floatingWidgetAlpha, foregroundAlpha,
                             fallbackBackgroundAlpha, 1 - progress);
 
-                    super.onUpdate(values, currentRectF, progress);
+                    super.onUpdate(currentRectF, progress);
                 }
             };
             anim.addOnUpdateListener(runner);
@@ -1776,7 +1776,7 @@
         }
 
         @Override
-        public void onUpdate(@Nullable AppCloseConfig values, RectF currentRectF, float progress) {
+        public void onUpdate(RectF currentRectF, float progress) {
             SurfaceParams[] params = new SurfaceParams[mAppTargets.length];
             for (int i = mAppTargets.length - 1; i >= 0; i--) {
                 RemoteAnimationTargetCompat target = mAppTargets[i];
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 648a16e..bc6348d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -345,7 +345,8 @@
      * @return Whether any Taskbar item could handle the given MotionEvent if given the chance.
      */
     public boolean isEventOverAnyTaskbarItem(MotionEvent ev) {
-        return mControllers.taskbarViewController.isEventOverAnyItem(ev);
+        return mControllers.taskbarViewController.isEventOverAnyItem(ev)
+                || mControllers.navbarButtonsViewController.isEventOverAnyItem(ev);
     }
 
     public boolean isDraggingItem() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 69804bd..4b6dacd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -15,6 +15,8 @@
  */
 package com.android.launcher3.taskbar;
 
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
+
 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;
@@ -38,6 +40,7 @@
 import android.annotation.DrawableRes;
 import android.annotation.IdRes;
 import android.annotation.LayoutRes;
+import android.content.Context;
 import android.content.res.ColorStateList;
 import android.graphics.Rect;
 import android.graphics.Region;
@@ -45,6 +48,7 @@
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.util.Property;
 import android.view.Gravity;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.View.OnHoverListener;
@@ -57,11 +61,12 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AlphaUpdateListener;
 import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton;
-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.Themes;
 import com.android.quickstep.AnimatedFloat;
+import com.android.systemui.shared.rotation.FloatingRotationButton;
+import com.android.systemui.shared.rotation.RotationButton;
+import com.android.systemui.shared.rotation.RotationButtonController;
 
 import java.util.ArrayList;
 import java.util.function.IntPredicate;
@@ -103,12 +108,16 @@
             this::updateNavButtonTranslationY);
     private final AnimatedFloat mNavButtonTranslationYMultiplier = new AnimatedFloat(
             this::updateNavButtonTranslationY);
+    private final RotationButtonListener mRotationButtonListener = new RotationButtonListener();
+
+    private final Rect mFloatingRotationButtonBounds = new Rect();
 
     // Initialized in init.
     private TaskbarControllers mControllers;
     private View mA11yButton;
     private int mSysuiStateFlags;
     private View mBackButton;
+    private FloatingRotationButton mFloatingRotationButton;
 
     public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) {
         mContext = context;
@@ -121,10 +130,9 @@
     /**
      * Initializes the controller
      */
-    public void init(TaskbarControllers controllers, TaskbarSharedState sharedState) {
+    public void init(TaskbarControllers controllers) {
         mControllers = controllers;
         mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize;
-        parseSystemUiFlags(sharedState.sysuiStateFlags);
         mNavButtonTranslationYMultiplier.value = 1;
 
         mA11yLongClickListener = view -> {
@@ -199,9 +207,21 @@
                     addButton(mEndContextualContainer, R.id.rotate_suggestion,
                             R.layout.taskbar_contextual_button));
             rotationButton.hide();
-            mControllers.rotationButtonController.setRotationButton(rotationButton);
+            mControllers.rotationButtonController.setRotationButton(rotationButton, null);
         } else {
-            mControllers.rotationButtonController.setRotationButton(new RotationButton() {});
+            mFloatingRotationButton = new FloatingRotationButton(mContext,
+                    R.string.accessibility_rotate_button,
+                    R.layout.rotate_suggestion,
+                    R.id.rotate_suggestion,
+                    R.dimen.floating_rotation_button_min_margin,
+                    R.dimen.rounded_corner_content_padding,
+                    R.dimen.floating_rotation_button_taskbar_left_margin,
+                    R.dimen.floating_rotation_button_taskbar_bottom_margin,
+                    R.dimen.floating_rotation_button_diameter,
+                    R.dimen.key_button_ripple_max_width);
+            mControllers.rotationButtonController.setRotationButton(mFloatingRotationButton,
+                    mRotationButtonListener);
+
             View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
                     mStartContextualContainer, mControllers.navButtonController, R.id.back);
             imeDownButton.setRotation(Utilities.isRtl(mContext.getResources()) ? 90 : -90);
@@ -290,12 +310,15 @@
         }
     }
 
-    public void updateStateForSysuiFlags(int systemUiStateFlags) {
+    public void updateStateForSysuiFlags(int systemUiStateFlags, boolean skipAnim) {
         if (systemUiStateFlags == mSysuiStateFlags) {
             return;
         }
         parseSystemUiFlags(systemUiStateFlags);
         applyState();
+        if (skipAnim) {
+            mPropertyHolders.forEach(StatePropertyHolder::endAnimation);
+        }
     }
 
     /**
@@ -403,8 +426,28 @@
         return buttonView;
     }
 
+    public boolean isEventOverAnyItem(MotionEvent ev) {
+        return mFloatingRotationButtonBounds.contains((int) ev.getX(), (int) ev.getY());
+    }
+
     public void onDestroy() {
         mPropertyHolders.clear();
+        mControllers.rotationButtonController.unregisterListeners();
+        if (mFloatingRotationButton != null) {
+            mFloatingRotationButton.hide();
+        }
+    }
+
+    private class RotationButtonListener implements RotationButton.RotationButtonUpdatesCallback {
+        @Override
+        public void onVisibilityChanged(boolean isVisible) {
+            if (isVisible) {
+                mFloatingRotationButton.getCurrentView()
+                        .getBoundsOnScreen(mFloatingRotationButtonBounds);
+            } else {
+                mFloatingRotationButtonBounds.setEmpty();
+            }
+        }
     }
 
     private class RotationButtonImpl implements RotationButton {
@@ -422,6 +465,8 @@
             mImageDrawable = (AnimatedVectorDrawable) mButton.getContext()
                     .getDrawable(rotationButtonController.getIconResId());
             mButton.setImageDrawable(mImageDrawable);
+            mButton.setContentDescription(mButton.getResources()
+                    .getString(R.string.accessibility_rotate_button));
             mImageDrawable.setCallback(mButton);
         }
 
@@ -431,17 +476,19 @@
         }
 
         @Override
-        public void show() {
+        public boolean show() {
             mButton.setVisibility(View.VISIBLE);
             mState |= FLAG_ROTATION_BUTTON_VISIBLE;
             applyState();
+            return true;
         }
 
         @Override
-        public void hide() {
+        public boolean hide() {
             mButton.setVisibility(View.GONE);
             mState &= ~FLAG_ROTATION_BUTTON_VISIBLE;
             applyState();
+            return true;
         }
 
         @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 172b396..5bc454e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -20,6 +20,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
+import static com.android.launcher3.testing.TestProtocol.TASKBAR_WINDOW_CRASH;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
 import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
@@ -60,7 +61,7 @@
 import com.android.launcher3.logger.LauncherAtom;
 import com.android.launcher3.model.data.FolderInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.taskbar.contextual.RotationButtonController;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.touch.ItemClickHandler;
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.SettingsCache;
@@ -71,6 +72,7 @@
 import com.android.quickstep.SysUINavigationMode;
 import com.android.quickstep.SysUINavigationMode.Mode;
 import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.rotation.RotationButtonController;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
@@ -147,8 +149,14 @@
                 new TaskbarDragController(this),
                 buttonController,
                 new NavbarButtonsViewController(this, navButtonsView),
-                new RotationButtonController(this, R.color.popup_color_primary_light,
-                        R.color.popup_color_primary_light),
+                new RotationButtonController(this,
+                        c.getColor(R.color.rotation_button_light_color),
+                        c.getColor(R.color.rotation_button_dark_color),
+                        R.drawable.ic_sysbar_rotate_button_ccw_start_0,
+                        R.drawable.ic_sysbar_rotate_button_ccw_start_90,
+                        R.drawable.ic_sysbar_rotate_button_cw_start_0,
+                        R.drawable.ic_sysbar_rotate_button_cw_start_90,
+                        () -> getDisplay().getRotation()),
                 new TaskbarDragLayerController(this, mDragLayer),
                 new TaskbarViewController(this, taskbarView),
                 new TaskbarScrimViewController(this, taskbarScrimView),
@@ -191,8 +199,12 @@
 
         // Initialize controllers after all are constructed.
         mControllers.init(sharedState);
+        updateSysuiStateFlags(sharedState.sysuiStateFlags, true /* fromInit */);
 
         mWindowManager.addView(mDragLayer, mWindowLayoutParams);
+        if (TestProtocol.sDebugTracing) {
+            Log.e(TASKBAR_WINDOW_CRASH, "Adding taskbar window");
+        }
     }
 
     public boolean isThreeButtonNav() {
@@ -323,28 +335,33 @@
         setUIController(TaskbarUIController.DEFAULT);
         mControllers.onDestroy();
         mWindowManager.removeViewImmediate(mDragLayer);
+        if (TestProtocol.sDebugTracing) {
+            Log.e(TASKBAR_WINDOW_CRASH, "Removing taskbar window");
+        }
     }
 
-    public void updateSysuiStateFlags(int systemUiStateFlags) {
-        mControllers.navbarButtonsViewController.updateStateForSysuiFlags(systemUiStateFlags);
+    public void updateSysuiStateFlags(int systemUiStateFlags, boolean fromInit) {
+        mControllers.navbarButtonsViewController.updateStateForSysuiFlags(systemUiStateFlags,
+                fromInit);
         mControllers.taskbarViewController.setImeIsVisible(
                 mControllers.navbarButtonsViewController.isImeVisible());
         int shadeExpandedFlags = SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
                 | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
-        onNotificationShadeExpandChanged((systemUiStateFlags & shadeExpandedFlags) != 0);
+        onNotificationShadeExpandChanged((systemUiStateFlags & shadeExpandedFlags) != 0, fromInit);
         mControllers.taskbarViewController.setRecentsButtonDisabled(
                 mControllers.navbarButtonsViewController.isRecentsDisabled());
         mControllers.stashedHandleViewController.setIsHomeButtonDisabled(
                 mControllers.navbarButtonsViewController.isHomeDisabled());
         mControllers.taskbarKeyguardController.updateStateForSysuiFlags(systemUiStateFlags);
-        mControllers.taskbarStashController.updateStateForSysuiFlags(systemUiStateFlags);
-        mControllers.taskbarScrimViewController.updateStateForSysuiFlags(systemUiStateFlags);
+        mControllers.taskbarStashController.updateStateForSysuiFlags(systemUiStateFlags, fromInit);
+        mControllers.taskbarScrimViewController.updateStateForSysuiFlags(systemUiStateFlags,
+                fromInit);
     }
 
     /**
      * Hides the taskbar icons and background when the notication shade is expanded.
      */
-    private void onNotificationShadeExpandChanged(boolean isExpanded) {
+    private void onNotificationShadeExpandChanged(boolean isExpanded, boolean skipAnim) {
         float alpha = isExpanded ? 0 : 1;
         AnimatorSet anim = new AnimatorSet();
         anim.play(mControllers.taskbarViewController.getTaskbarIconAlpha().getProperty(
@@ -354,6 +371,9 @@
                     .animateToValue(alpha));
         }
         anim.start();
+        if (skipAnim) {
+            anim.end();
+        }
     }
 
     public void onRotationProposal(int rotation, boolean isValid) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 7b0053e..08a79c0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -17,7 +17,7 @@
 
 import androidx.annotation.NonNull;
 
-import com.android.launcher3.taskbar.contextual.RotationButtonController;
+import com.android.systemui.shared.rotation.RotationButtonController;
 
 /**
  * Hosts various taskbar controllers to facilitate passing between one another.
@@ -79,10 +79,8 @@
      */
     public void init(TaskbarSharedState sharedState) {
         taskbarDragController.init(this);
-        navbarButtonsViewController.init(this, sharedState);
-        if (taskbarActivityContext.isThreeButtonNav()) {
-            rotationButtonController.init();
-        }
+        navbarButtonsViewController.init(this);
+        rotationButtonController.init();
         taskbarDragLayerController.init(this);
         taskbarViewController.init(this);
         taskbarScrimViewController.init(this);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 92cee04..53feaad 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -16,8 +16,9 @@
 package com.android.launcher3.taskbar;
 
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 
+import static com.android.launcher3.testing.TestProtocol.TASKBAR_WINDOW_CRASH;
 import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
 import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
 import static com.android.launcher3.util.DisplayController.CHANGE_SUPPORTED_BOUNDS;
@@ -30,6 +31,7 @@
 import android.hardware.display.DisplayManager;
 import android.net.Uri;
 import android.provider.Settings;
+import android.util.Log;
 import android.view.Display;
 
 import androidx.annotation.NonNull;
@@ -40,6 +42,7 @@
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.DisplayController.Info;
 import com.android.launcher3.util.SettingsCache;
@@ -91,7 +94,7 @@
         mSysUINavigationMode = SysUINavigationMode.INSTANCE.get(service);
         Display display =
                 service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
-        mContext = service.createWindowContext(display, TYPE_APPLICATION_OVERLAY, null);
+        mContext = service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null);
         mNavButtonController = new TaskbarNavButtonController(service);
         mUserSetupCompleteListener = isUserSetupComplete -> recreateTaskbar();
         mComponentCallbacks = new ComponentCallbacks() {
@@ -101,7 +104,7 @@
             public void onConfigurationChanged(Configuration newConfig) {
                 int configDiff = mOldConfig.diff(newConfig);
                 int configsRequiringRecreate = ActivityInfo.CONFIG_ASSETS_PATHS
-                        | ActivityInfo.CONFIG_LAYOUT_DIRECTION;
+                        | ActivityInfo.CONFIG_LAYOUT_DIRECTION | ActivityInfo.CONFIG_UI_MODE;
                 if ((configDiff & configsRequiringRecreate) != 0) {
                     // Color has changed, recreate taskbar to reload background color & icons.
                     recreateTaskbar();
@@ -204,6 +207,10 @@
     }
 
     private void recreateTaskbar() {
+        if (TestProtocol.sDebugTracing) {
+            Log.e(TASKBAR_WINDOW_CRASH, "Recreating taskbar: mTaskbarActivityContext="
+                    + mTaskbarActivityContext);
+        }
         destroyExistingTaskbar();
 
         DeviceProfile dp =
@@ -226,12 +233,15 @@
             mTaskbarActivityContext.setUIController(
                     createTaskbarUIControllerForActivity(mActivity));
         }
+        if (TestProtocol.sDebugTracing) {
+            Log.e(TASKBAR_WINDOW_CRASH, "Finished recreating taskbar");
+        }
     }
 
     public void onSystemUiFlagsChanged(int systemUiStateFlags) {
         mSharedState.sysuiStateFlags = systemUiStateFlags;
         if (mTaskbarActivityContext != null) {
-            mTaskbarActivityContext.updateSysuiStateFlags(systemUiStateFlags);
+            mTaskbarActivityContext.updateSysuiStateFlags(systemUiStateFlags, false /* fromInit */);
         }
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
index e7e55ef..4b4ee44 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -62,7 +62,7 @@
     /**
      * Updates the scrim state based on the flags.
      */
-    public void updateStateForSysuiFlags(int stateFlags) {
+    public void updateStateForSysuiFlags(int stateFlags, boolean skipAnim) {
         final boolean bubblesExpanded = (stateFlags & SYSUI_STATE_BUBBLES_EXPANDED) != 0;
         final boolean manageMenuExpanded =
                 (stateFlags & SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED) != 0;
@@ -73,15 +73,18 @@
                 // what the total transparency would be.
                 ? (SCRIM_ALPHA + (SCRIM_ALPHA * (1 - SCRIM_ALPHA)))
                 : showScrim ? SCRIM_ALPHA : 0;
-        showScrim(showScrim, scrimAlpha);
+        showScrim(showScrim, scrimAlpha, skipAnim);
     }
 
-    private void showScrim(boolean showScrim, float alpha) {
+    private void showScrim(boolean showScrim, float alpha, boolean skipAnim) {
         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();
+        if (skipAnim) {
+            anim.end();
+        }
     }
 
     private void updateScrimAlpha() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 0dd4ef1..acb4aa8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -94,6 +94,7 @@
     private final SharedPreferences mPrefs;
     private final int mStashedHeight;
     private final int mUnstashedHeight;
+    private final SystemUiProxy mSystemUiProxy;
 
     // Initialized in init.
     private TaskbarControllers mControllers;
@@ -127,6 +128,7 @@
         mPrefs = Utilities.getPrefs(mActivity);
         final Resources resources = mActivity.getResources();
         mStashedHeight = resources.getDimensionPixelSize(R.dimen.taskbar_stashed_size);
+        mSystemUiProxy = SystemUiProxy.INSTANCE.get(activity);
         mUnstashedHeight = mActivity.getDeviceProfile().taskbarSize;
     }
 
@@ -155,8 +157,7 @@
                 !mActivity.isUserSetupComplete() || sharedState.setupUIVisible);
         applyState();
 
-        SystemUiProxy.INSTANCE.get(mActivity)
-                .notifyTaskbarStatus(/* visible */ false, /* stashed */ isStashedInApp());
+        notifyStashChange(/* visible */ false, /* stashed */ isStashedInApp());
     }
 
     /**
@@ -408,10 +409,10 @@
     }
 
     /** Called when some system ui state has changed. (See SYSUI_STATE_... in QuickstepContract) */
-    public void updateStateForSysuiFlags(int systemUiStateFlags) {
+    public void updateStateForSysuiFlags(int systemUiStateFlags, boolean skipAnim) {
         updateStateForFlag(FLAG_STASHED_IN_APP_PINNED,
                 hasAnyFlag(systemUiStateFlags, SYSUI_STATE_SCREEN_PINNING));
-        applyState();
+        applyState(skipAnim ? 0 : TASKBAR_STASH_DURATION);
     }
 
     /**
@@ -440,8 +441,7 @@
             mControllers.uiController.onStashedInAppChanged();
         }
         if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP | FLAG_IN_APP)) {
-            SystemUiProxy.INSTANCE.get(mActivity)
-                    .notifyTaskbarStatus(/* visible */ hasAnyFlag(FLAG_IN_APP),
+            notifyStashChange(/* visible */ hasAnyFlag(FLAG_IN_APP),
                             /* stashed */ isStashedInApp());
         }
         if (hasAnyFlag(changedFlags, FLAG_STASHED_IN_APP_MANUAL)) {
@@ -453,6 +453,11 @@
         }
     }
 
+    private void notifyStashChange(boolean visible, boolean stashed) {
+        mSystemUiProxy.notifyTaskbarStatus(visible, stashed);
+        mControllers.rotationButtonController.onTaskbarStateChange(visible, stashed);
+    }
+
     private class StatePropertyHolder {
         private final IntPredicate mStashCondition;
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/contextual/RotationButton.java b/quickstep/src/com/android/launcher3/taskbar/contextual/RotationButton.java
deleted file mode 100644
index 4093097..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/contextual/RotationButton.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 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.contextual;
-
-import android.graphics.drawable.AnimatedVectorDrawable;
-import android.view.View;
-
-/**
- * Interface of a rotation button that interacts {@link RotationButtonController}.
- * This interface exists because of the two different styles of rotation button in Sysui,
- * one in contextual for 3 button nav and a floating rotation button for gestural.
- * Keeping the interface for eventual migration of floating button, so some methods are
- * pass through to "super" while others are trivially implemented.
- *
- * Changes:
- *  * Directly use AnimatedVectorDrawable instead of KeyButtonDrawable
- */
-public interface RotationButton {
-    default void setRotationButtonController(RotationButtonController rotationButtonController) { }
-
-    default View getCurrentView() {
-        return null;
-    }
-    default void show() { }
-    default void hide() { }
-    default boolean isVisible() {
-        return false;
-    }
-
-    default void updateIcon(int lightIconColor, int darkIconColor) { }
-    default void setOnClickListener(View.OnClickListener onClickListener) { }
-    default void setOnHoverListener(View.OnHoverListener onHoverListener) { }
-    default AnimatedVectorDrawable getImageDrawable() {
-        return null;
-    }
-    default void setDarkIntensity(float darkIntensity) { }
-    default boolean acceptRotationProposal() {
-        return getCurrentView() != null;
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/contextual/RotationButtonController.java b/quickstep/src/com/android/launcher3/taskbar/contextual/RotationButtonController.java
deleted file mode 100644
index c776f16..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/contextual/RotationButtonController.java
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * Copyright 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.contextual;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import static com.android.internal.view.RotationPolicy.NATURAL_ROTATION;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.annotation.ColorInt;
-import android.annotation.DrawableRes;
-import android.annotation.SuppressLint;
-import android.app.StatusBarManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.graphics.drawable.AnimatedVectorDrawable;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.IRotationWatcher;
-import android.view.MotionEvent;
-import android.view.Surface;
-import android.view.View;
-import android.view.WindowInsetsController;
-import android.view.WindowManagerGlobal;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.internal.logging.UiEvent;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.UiEventLoggerImpl;
-import com.android.internal.view.RotationPolicy;
-import com.android.launcher3.R;
-import com.android.launcher3.util.DisplayController;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.utilities.ViewRippler;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.TaskStackChangeListener;
-import com.android.systemui.shared.system.TaskStackChangeListeners;
-
-import java.util.Optional;
-
-/**
- * Copied over from the SysUI equivalent class. Known issues/things not ported over
- *  * When rotation button visible and in auto-hide mode, we ask auto-hide controller to
- *    keep the navbar around longer. Will need to implement if we use auto-hide on taskbar
- *
- * Contains logic that deals with showing a rotate suggestion button with animation.
- */
-public class RotationButtonController {
-
-    private static final String TAG = "StatusBar/RotationButtonController";
-    private static final int BUTTON_FADE_IN_OUT_DURATION_MS = 100;
-    private static final int NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS = 20000;
-
-    private static final int NUM_ACCEPTED_ROTATION_SUGGESTIONS_FOR_INTRODUCTION = 3;
-
-    private final Context mContext;
-    private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
-    private final UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
-    private final ViewRippler mViewRippler = new ViewRippler();
-    private final DisplayController mDisplayController;
-    private RotationButton mRotationButton;
-
-    private int mLastRotationSuggestion;
-    private boolean mPendingRotationSuggestion;
-    private boolean mHoveringRotationSuggestion;
-    private final AccessibilityManager mAccessibilityManager;
-    private final TaskStackListenerImpl mTaskStackListener;
-    private boolean mListenersRegistered = false;
-    private boolean mIsTaskbarShowing;
-    @SuppressLint("InlinedApi")
-    private @WindowInsetsController.Behavior
-    int mBehavior = WindowInsetsController.BEHAVIOR_DEFAULT;
-    private boolean mSkipOverrideUserLockPrefsOnce;
-    private final int mLightIconColor;
-    private final int mDarkIconColor;
-    private int mIconResId = R.drawable.ic_sysbar_rotate_button_ccw_start_90;
-
-    private final Runnable mRemoveRotationProposal =
-            () -> setRotateSuggestionButtonState(false /* visible */);
-    private final Runnable mCancelPendingRotationProposal =
-            () -> mPendingRotationSuggestion = false;
-    private Animator mRotateHideAnimator;
-
-
-    private final IRotationWatcher.Stub mRotationWatcher = new IRotationWatcher.Stub() {
-        @Override
-        public void onRotationChanged(final int rotation) {
-            // We need this to be scheduled as early as possible to beat the redrawing of
-            // window in response to the orientation change.
-            mMainThreadHandler.postAtFrontOfQueue(() -> {
-                // If the screen rotation changes while locked, potentially update lock to flow with
-                // new screen rotation and hide any showing suggestions.
-                if (isRotationLocked()) {
-                    if (shouldOverrideUserLockPrefs(rotation)) {
-                        setRotationLockedAtAngle(rotation);
-                    }
-                    setRotateSuggestionButtonState(false /* visible */, true /* forced */);
-                }
-            });
-        }
-    };
-
-    /**
-     * Determines if rotation suggestions disabled2 flag exists in flag
-     * @param disable2Flags see if rotation suggestion flag exists in this flag
-     * @return whether flag exists
-     */
-    static boolean hasDisable2RotateSuggestionFlag(int disable2Flags) {
-        return (disable2Flags & StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS) != 0;
-    }
-
-    public RotationButtonController(Context context, @ColorInt int lightIconColor,
-            @ColorInt int darkIconColor) {
-        mContext = context;
-        mLightIconColor = lightIconColor;
-        mDarkIconColor = darkIconColor;
-
-        mAccessibilityManager = AccessibilityManager.getInstance(context);
-        mTaskStackListener = new TaskStackListenerImpl();
-        mDisplayController = DisplayController.INSTANCE.get(context);
-    }
-
-    public void setRotationButton(RotationButton rotationButton) {
-        mRotationButton = rotationButton;
-        mRotationButton.setRotationButtonController(this);
-        mRotationButton.setOnClickListener(this::onRotateSuggestionClick);
-        mRotationButton.setOnHoverListener(this::onRotateSuggestionHover);
-    }
-
-    public void init() {
-        registerListeners();
-        if (mContext.getDisplay().getDisplayId() != DEFAULT_DISPLAY) {
-            // Currently there is no accelerometer sensor on non-default display, disable fixed
-            // rotation for non-default display
-            onDisable2FlagChanged(StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS);
-        }
-    }
-
-    public void onDestroy() {
-        unregisterListeners();
-    }
-
-    private void registerListeners() {
-        if (mListenersRegistered) {
-            return;
-        }
-
-        mListenersRegistered = true;
-        try {
-            WindowManagerGlobal.getWindowManagerService()
-                    .watchRotation(mRotationWatcher, DEFAULT_DISPLAY);
-        } catch (IllegalArgumentException e) {
-            mListenersRegistered = false;
-            Log.w(TAG, "RegisterListeners for the display failed");
-        } catch (RemoteException e) {
-            Log.e(TAG, "RegisterListeners caught a RemoteException", e);
-            return;
-        }
-
-        TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
-    }
-
-    void unregisterListeners() {
-        if (!mListenersRegistered) {
-            return;
-        }
-
-        mListenersRegistered = false;
-        try {
-            WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(mRotationWatcher);
-        } catch (RemoteException e) {
-            Log.e(TAG, "UnregisterListeners caught a RemoteException", e);
-            return;
-        }
-
-        TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
-    }
-
-    void setRotationLockedAtAngle(int rotationSuggestion) {
-        RotationPolicy.setRotationLockAtAngle(mContext, true, rotationSuggestion);
-    }
-
-    public boolean isRotationLocked() {
-        return RotationPolicy.isRotationLocked(mContext);
-    }
-
-    public void setRotateSuggestionButtonState(boolean visible) {
-        setRotateSuggestionButtonState(visible, false /* force */);
-    }
-
-    void setRotateSuggestionButtonState(final boolean visible, final boolean force) {
-        // At any point the button can become invisible because an a11y service became active.
-        // Similarly, a call to make the button visible may be rejected because an a11y service is
-        // active. Must account for this.
-        // Rerun a show animation to indicate change but don't rerun a hide animation
-        if (!visible && !mRotationButton.isVisible()) return;
-
-        final View view = mRotationButton.getCurrentView();
-        if (view == null) return;
-
-        final AnimatedVectorDrawable currentDrawable = mRotationButton.getImageDrawable();
-        if (currentDrawable == null) return;
-
-        // Clear any pending suggestion flag as it has either been nullified or is being shown
-        mPendingRotationSuggestion = false;
-        mMainThreadHandler.removeCallbacks(mCancelPendingRotationProposal);
-
-        // Handle the visibility change and animation
-        if (visible) { // Appear and change (cannot force)
-            // Stop and clear any currently running hide animations
-            if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) {
-                mRotateHideAnimator.cancel();
-            }
-            mRotateHideAnimator = null;
-
-            // Reset the alpha if any has changed due to hide animation
-            view.setAlpha(1f);
-
-            // Run the rotate icon's animation if it has one
-            currentDrawable.reset();
-            currentDrawable.start();
-
-            // TODO(b/187754252): No idea why this doesn't work. If we remove the "false"
-            //  we see the animation show the pressed state... but it only shows the first time.
-            if (!isRotateSuggestionIntroduced()) mViewRippler.start(view);
-
-            // Set visibility unless a11y service is active.
-            mRotationButton.show();
-        } else { // Hide
-            mViewRippler.stop(); // Prevent any pending ripples, force hide or not
-
-            if (force) {
-                // If a hide animator is running stop it and make invisible
-                if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) {
-                    mRotateHideAnimator.pause();
-                }
-                mRotationButton.hide();
-                return;
-            }
-
-            // Don't start any new hide animations if one is running
-            if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) return;
-
-            ObjectAnimator fadeOut = ObjectAnimator.ofFloat(view, "alpha", 0f);
-            fadeOut.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS);
-            fadeOut.setInterpolator(LINEAR);
-            fadeOut.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mRotationButton.hide();
-                }
-            });
-
-            mRotateHideAnimator = fadeOut;
-            fadeOut.start();
-        }
-    }
-
-    void setDarkIntensity(float darkIntensity) {
-        mRotationButton.setDarkIntensity(darkIntensity);
-    }
-
-    public void onRotationProposal(int rotation, boolean isValid) {
-        int windowRotation = mDisplayController.getInfo().rotation;
-
-        if (!mRotationButton.acceptRotationProposal()) {
-            return;
-        }
-
-        // This method will be called on rotation suggestion changes even if the proposed rotation
-        // is not valid for the top app. Use invalid rotation choices as a signal to remove the
-        // rotate button if shown.
-        if (!isValid) {
-            setRotateSuggestionButtonState(false /* visible */);
-            return;
-        }
-
-        // If window rotation matches suggested rotation, remove any current suggestions
-        if (rotation == windowRotation) {
-            mMainThreadHandler.removeCallbacks(mRemoveRotationProposal);
-            setRotateSuggestionButtonState(false /* visible */);
-            return;
-        }
-
-        // Prepare to show the navbar icon by updating the icon style to change anim params
-        mLastRotationSuggestion = rotation; // Remember rotation for click
-        final boolean rotationCCW = Utilities.isRotationAnimationCCW(windowRotation, rotation);
-        if (windowRotation == Surface.ROTATION_0 || windowRotation == Surface.ROTATION_180) {
-            mIconResId = rotationCCW
-                    ? R.drawable.ic_sysbar_rotate_button_ccw_start_90
-                    : R.drawable.ic_sysbar_rotate_button_cw_start_90;
-        } else { // 90 or 270
-            mIconResId = rotationCCW
-                    ? R.drawable.ic_sysbar_rotate_button_ccw_start_0
-                    : R.drawable.ic_sysbar_rotate_button_ccw_start_0;
-        }
-        mRotationButton.updateIcon(mLightIconColor, mDarkIconColor);
-
-        if (canShowRotationButton()) {
-            // The navbar is visible / it's in visual immersive mode, so show the icon right away
-            showAndLogRotationSuggestion();
-        } else {
-            // If the navbar isn't shown, flag the rotate icon to be shown should the navbar become
-            // visible given some time limit.
-            mPendingRotationSuggestion = true;
-            mMainThreadHandler.removeCallbacks(mCancelPendingRotationProposal);
-            mMainThreadHandler.postDelayed(mCancelPendingRotationProposal,
-                    NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS);
-        }
-    }
-
-    public void onDisable2FlagChanged(int state2) {
-        final boolean rotateSuggestionsDisabled = hasDisable2RotateSuggestionFlag(state2);
-        if (rotateSuggestionsDisabled) onRotationSuggestionsDisabled();
-    }
-
-    public void onBehaviorChanged(int displayId, @WindowInsetsController.Behavior int behavior) {
-        if (DEFAULT_DISPLAY != displayId) {
-            return;
-        }
-
-        if (mBehavior != behavior) {
-            mBehavior = behavior;
-            showPendingRotationButtonIfNeeded();
-        }
-    }
-
-    public void onTaskBarVisibilityChange(boolean showing) {
-        if (mIsTaskbarShowing != showing) {
-            mIsTaskbarShowing = showing;
-            showPendingRotationButtonIfNeeded();
-        }
-    }
-
-    private void showPendingRotationButtonIfNeeded() {
-        if (canShowRotationButton() && mPendingRotationSuggestion) {
-            showAndLogRotationSuggestion();
-        }
-    }
-
-    /** Return true when either the task bar is visible or it's in visual immersive mode. */
-    @SuppressLint("InlinedApi")
-    private boolean canShowRotationButton() {
-        return mIsTaskbarShowing || mBehavior == WindowInsetsController.BEHAVIOR_DEFAULT;
-    }
-
-    public @DrawableRes
-    int getIconResId() {
-        return mIconResId;
-    }
-
-    public @ColorInt int getLightIconColor() {
-        return mLightIconColor;
-    }
-
-    public @ColorInt int getDarkIconColor() {
-        return mDarkIconColor;
-    }
-
-    private void onRotateSuggestionClick(View v) {
-        mUiEventLogger.log(RotationButtonEvent.ROTATION_SUGGESTION_ACCEPTED);
-        incrementNumAcceptedRotationSuggestionsIfNeeded();
-        setRotationLockedAtAngle(mLastRotationSuggestion);
-    }
-
-    private boolean onRotateSuggestionHover(View v, MotionEvent event) {
-        final int action = event.getActionMasked();
-        mHoveringRotationSuggestion = (action == MotionEvent.ACTION_HOVER_ENTER)
-                || (action == MotionEvent.ACTION_HOVER_MOVE);
-        rescheduleRotationTimeout(true /* reasonHover */);
-        return false; // Must return false so a11y hover events are dispatched correctly.
-    }
-
-    private void onRotationSuggestionsDisabled() {
-        // Immediately hide the rotate button and clear any planned removal
-        setRotateSuggestionButtonState(false /* visible */, true /* force */);
-        mMainThreadHandler.removeCallbacks(mRemoveRotationProposal);
-    }
-
-    private void showAndLogRotationSuggestion() {
-        setRotateSuggestionButtonState(true /* visible */);
-        rescheduleRotationTimeout(false /* reasonHover */);
-        mUiEventLogger.log(RotationButtonEvent.ROTATION_SUGGESTION_SHOWN);
-    }
-
-    /**
-     * Makes {@link #shouldOverrideUserLockPrefs} always return {@code false} once. It is used to
-     * avoid losing original user rotation when display rotation is changed by entering the fixed
-     * orientation overview.
-     */
-    void setSkipOverrideUserLockPrefsOnce() {
-        mSkipOverrideUserLockPrefsOnce = true;
-    }
-
-    private boolean shouldOverrideUserLockPrefs(final int rotation) {
-        if (mSkipOverrideUserLockPrefsOnce) {
-            mSkipOverrideUserLockPrefsOnce = false;
-            return false;
-        }
-        // Only override user prefs when returning to the natural rotation (normally portrait).
-        // Don't let apps that force landscape or 180 alter user lock.
-        return rotation == NATURAL_ROTATION;
-    }
-
-    private void rescheduleRotationTimeout(final boolean reasonHover) {
-        // May be called due to a new rotation proposal or a change in hover state
-        if (reasonHover) {
-            // Don't reschedule if a hide animator is running
-            if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) return;
-            // Don't reschedule if not visible
-            if (!mRotationButton.isVisible()) return;
-        }
-
-        // Stop any pending removal
-        mMainThreadHandler.removeCallbacks(mRemoveRotationProposal);
-        // Schedule timeout
-        mMainThreadHandler.postDelayed(mRemoveRotationProposal,
-                computeRotationProposalTimeout());
-    }
-
-    private int computeRotationProposalTimeout() {
-        return mAccessibilityManager.getRecommendedTimeoutMillis(
-                mHoveringRotationSuggestion ? 16000 : 5000,
-                AccessibilityManager.FLAG_CONTENT_CONTROLS);
-    }
-
-    private boolean isRotateSuggestionIntroduced() {
-        ContentResolver cr = mContext.getContentResolver();
-        return Settings.Secure.getInt(cr, Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED, 0)
-                >= NUM_ACCEPTED_ROTATION_SUGGESTIONS_FOR_INTRODUCTION;
-    }
-
-    private void incrementNumAcceptedRotationSuggestionsIfNeeded() {
-        // Get the number of accepted suggestions
-        ContentResolver cr = mContext.getContentResolver();
-        final int numSuggestions = Settings.Secure.getInt(cr,
-                Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED, 0);
-
-        // Increment the number of accepted suggestions only if it would change intro mode
-        if (numSuggestions < NUM_ACCEPTED_ROTATION_SUGGESTIONS_FOR_INTRODUCTION) {
-            Settings.Secure.putInt(cr, Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED,
-                    numSuggestions + 1);
-        }
-    }
-
-    private class TaskStackListenerImpl extends TaskStackChangeListener {
-        // Invalidate any rotation suggestion on task change or activity orientation change
-        // Note: all callbacks happen on main thread
-
-        @Override
-        public void onTaskStackChanged() {
-            setRotateSuggestionButtonState(false /* visible */);
-        }
-
-        @Override
-        public void onTaskRemoved(int taskId) {
-            setRotateSuggestionButtonState(false /* visible */);
-        }
-
-        @Override
-        public void onTaskMovedToFront(int taskId) {
-            setRotateSuggestionButtonState(false /* visible */);
-        }
-
-        @Override
-        public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) {
-            // Only hide the icon if the top task changes its requestedOrientation
-            // Launcher can alter its requestedOrientation while it's not on top, don't hide on this
-            Optional.ofNullable(ActivityManagerWrapper.getInstance())
-                    .map(ActivityManagerWrapper::getRunningTask)
-                    .ifPresent(a -> {
-                        if (a.id == taskId) setRotateSuggestionButtonState(false /* visible */);
-                    });
-        }
-    }
-
-    enum RotationButtonEvent implements UiEventLogger.UiEventEnum {
-        @UiEvent(doc = "The rotation button was shown")
-        ROTATION_SUGGESTION_SHOWN(206),
-        @UiEvent(doc = "The rotation button was clicked")
-        ROTATION_SUGGESTION_ACCEPTED(207);
-
-        private final int mId;
-        RotationButtonEvent(int id) {
-            mId = id;
-        }
-        @Override public int getId() {
-            return mId;
-        }
-    }
-}
-
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index e8aa2fa..30a0fdf 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -677,6 +677,9 @@
     public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
         WindowInsets result = view.onApplyWindowInsets(windowInsets);
         buildAnimationController();
+        // Reapply the current shift to ensure it takes new insets into account, e.g. when long
+        // pressing to stash taskbar without moving the finger.
+        updateFinalShift();
         return result;
     }
 
@@ -961,8 +964,10 @@
                 } else {
                     mStateCallback.setState(STATE_RESUME_LAST_TASK);
                 }
-                TaskViewUtils.setSplitAuxiliarySurfacesShown(
-                        mRecentsAnimationTargets.nonApps, true);
+                if (mRecentsAnimationTargets != null) {
+                    TaskViewUtils.setSplitAuxiliarySurfacesShown(
+                            mRecentsAnimationTargets.nonApps, true);
+                }
                 break;
         }
         ActiveGestureLog.INSTANCE.addLog("onSettledOnEndTarget " + endTarget);
@@ -1447,7 +1452,7 @@
     }
 
     private void setupWindowAnimation(RectFSpringAnim[] anims) {
-        anims[0].addOnUpdateListener((v, r, p) -> {
+        anims[0].addOnUpdateListener((r, p) -> {
             updateSysUiFlags(Math.max(p, mCurrentShift.value));
         });
         anims[0].addAnimatorListener(new AnimationSuccessListener() {
@@ -1734,7 +1739,10 @@
         endLauncherTransitionController();
         mRecentsView.onSwipeUpAnimationSuccess();
         if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
-            mTaskAnimationManager.setLiveTileCleanUpHandler(mInputConsumerProxy::destroy);
+            mTaskAnimationManager.setLiveTileCleanUpHandler(() -> {
+                mRecentsView.cleanupRemoteTargets();
+                mInputConsumerProxy.destroy();
+            });
             mTaskAnimationManager.enableLiveTileRestartListener();
         }
 
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index c1b45e0..fed5ae5 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -50,7 +50,6 @@
 import android.view.SurfaceControl.Transaction;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Utilities;
@@ -59,7 +58,6 @@
 import com.android.launcher3.anim.SpringAnimationBuilder;
 import com.android.quickstep.fallback.FallbackRecentsView;
 import com.android.quickstep.fallback.RecentsState;
-import com.android.quickstep.util.AppCloseConfig;
 import com.android.quickstep.util.RectFSpringAnim;
 import com.android.quickstep.util.TransformParams;
 import com.android.quickstep.util.TransformParams.BuilderProxy;
@@ -317,8 +315,7 @@
         }
 
         @Override
-        public void update(@Nullable AppCloseConfig config, RectF currentRect, float progress,
-                 float radius) {
+        public void update(RectF currentRect, float progress, float radius) {
             if (mSurfaceControl != null) {
                 currentRect.roundOut(mTempRect);
                 Transaction t = new Transaction();
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index 0181cd7..8a30aad 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -18,18 +18,14 @@
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
 import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.Utilities.boundToRange;
 import static com.android.launcher3.Utilities.dpToPx;
 import static com.android.launcher3.Utilities.mapBoundToRange;
 import static com.android.launcher3.anim.Interpolators.EXAGGERATED_EASE;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.config.FeatureFlags.PROTOTYPE_APP_CLOSE;
 import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
 import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
 import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
 
-import static java.lang.Math.round;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -59,10 +55,8 @@
 import com.android.launcher3.views.FloatingIconView;
 import com.android.launcher3.views.FloatingView;
 import com.android.launcher3.widget.LauncherAppWidgetHostView;
-import com.android.quickstep.util.AppCloseConfig;
 import com.android.quickstep.util.RectFSpringAnim;
 import com.android.quickstep.util.StaggeredWorkspaceAnim;
-import com.android.quickstep.util.WorkspaceRevealAnim;
 import com.android.quickstep.views.FloatingWidgetView;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
@@ -167,15 +161,9 @@
             }
 
             @Override
-            public void update(@Nullable AppCloseConfig config, RectF currentRect,
-                    float progress, float radius) {
-                super.update(config, currentRect, progress, radius);
-                int fgAlpha = 255;
-                if (config != null && PROTOTYPE_APP_CLOSE.get()) {
-                    progress = config.getInterpolatedProgress();
-                    fgAlpha = config.getFgAlpha();
-                }
-                floatingIconView.update(1f, fgAlpha, currentRect, progress,
+            public void update(RectF currentRect, float progress, float radius) {
+                super.update(currentRect, progress, radius);
+                floatingIconView.update(1f /* alpha */, 255 /* fgAlpha */, currentRect, progress,
                         windowAlphaThreshold, radius, false);
             }
         };
@@ -232,9 +220,8 @@
             }
 
             @Override
-            public void update(@Nullable AppCloseConfig config, RectF currentRect, float progress,
-                    float radius) {
-                super.update(config, currentRect, progress, radius);
+            public void update(RectF currentRect, float progress, float radius) {
+                super.update(currentRect, progress, radius);
                 final float fallbackBackgroundAlpha =
                         1 - mapBoundToRange(progress, 0.8f, 1, 0, 1, EXAGGERATED_EASE);
                 final float foregroundAlpha =
@@ -293,27 +280,12 @@
         private final float mTransY;
         private final FloatingView mFloatingView;
         private ValueAnimator mBounceBackAnimator;
-        private final AnimatorSet mWorkspaceReveal;
 
         FloatingViewHomeAnimationFactory(FloatingView floatingView) {
             mFloatingView = floatingView;
 
             ResourceProvider rp = DynamicResource.provider(mActivity);
             mTransY = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp));
-
-            mWorkspaceReveal = PROTOTYPE_APP_CLOSE.get()
-                    ? new WorkspaceRevealAnim(mActivity, true /* animateScrim */).getAnimators()
-                    : null;
-        }
-
-        @Override
-        public @NonNull RectF getWindowTargetRect() {
-            if (PROTOTYPE_APP_CLOSE.get()) {
-                // We want the target rect to be at this offset position, so that all
-                // launcher content can spring back upwards.
-                mFloatingView.setPositionOffsetY(mTransY);
-            }
-            return super.getWindowTargetRect();
         }
 
         @Override
@@ -321,20 +293,6 @@
             return false;
         }
 
-        @Override
-        public void update(@Nullable AppCloseConfig config, RectF currentRect, float progress,
-                float radius) {
-            if (config != null && PROTOTYPE_APP_CLOSE.get()) {
-                DragLayer dl = mActivity.getDragLayer();
-                float translationY = config.getWorkspaceTransY();
-                dl.setTranslationY(translationY);
-
-                long duration = mWorkspaceReveal.getDuration();
-                long playTime = boundToRange(round(duration * progress), 0, duration);
-                mWorkspaceReveal.setCurrentPlayTime(playTime);
-            }
-        }
-
         protected void bounceBackToRestingPosition() {
             final float startValue = mTransY;
             final float endValue = 0;
@@ -369,31 +327,6 @@
         }
 
         @Override
-        public void setAnimation(RectFSpringAnim anim) {
-            if (PROTOTYPE_APP_CLOSE.get()) {
-                // Use a spring to put drag layer translation back to 0.
-                anim.addAnimatorListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        mFloatingView.setPositionOffsetY(0);
-                        bounceBackToRestingPosition();
-                    }
-                });
-
-                // Will be updated manually below so that the two animations are in sync.
-                mWorkspaceReveal.start();
-                mWorkspaceReveal.pause();
-
-                anim.addAnimatorListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        mWorkspaceReveal.end();
-                    }
-                });
-            }
-        }
-
-        @Override
         public void onCancel() {
             mFloatingView.fastFinish();
             if (mBounceBackAnimator != null) {
@@ -425,13 +358,9 @@
 
         @Override
         public void playAtomicAnimation(float velocity) {
-            if (!PROTOTYPE_APP_CLOSE.get()) {
-                new StaggeredWorkspaceAnim(mActivity, velocity, true /* animateOverviewScrim */,
-                        getViewIgnoredInWorkspaceRevealAnimation())
-                        .start();
-            } else if (shouldPlayAtomicWorkspaceReveal()) {
-                new WorkspaceRevealAnim(mActivity, true).start();
-            }
+            new StaggeredWorkspaceAnim(mActivity, velocity, true /* animateOverviewScrim */,
+                    getViewIgnoredInWorkspaceRevealAnimation())
+                    .start();
         }
 
         @Override
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index ad7e4df..09a0b7d 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -245,7 +245,7 @@
         RemoteAnimationAdapterCompat adapterCompat = new RemoteAnimationAdapterCompat(
                 wrapper, RECENTS_LAUNCH_DURATION,
                 RECENTS_LAUNCH_DURATION - STATUS_BAR_TRANSITION_DURATION
-                        - STATUS_BAR_TRANSITION_PRE_DELAY);
+                        - STATUS_BAR_TRANSITION_PRE_DELAY, getIApplicationThread());
         final ActivityOptionsWrapper activityOptions = new ActivityOptionsWrapper(
                 ActivityOptionsCompat.makeRemoteAnimation(adapterCompat),
                 onEndCallback);
@@ -394,7 +394,8 @@
         LauncherAnimationRunner runner = new LauncherAnimationRunner(
                 getMainThreadHandler(), mAnimationToHomeFactory, true);
         RemoteAnimationAdapterCompat adapterCompat =
-                new RemoteAnimationAdapterCompat(runner, HOME_APPEAR_DURATION, 0);
+                new RemoteAnimationAdapterCompat(runner, HOME_APPEAR_DURATION, 0,
+                        getIApplicationThread());
         startActivity(createHomeIntent(),
                 ActivityOptionsCompat.makeRemoteAnimation(adapterCompat).toBundle());
     }
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index 825abed..5f2b49d 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -17,7 +17,6 @@
 package com.android.quickstep;
 
 import android.content.Context;
-import android.util.Log;
 
 import androidx.annotation.Nullable;
 
@@ -33,8 +32,6 @@
  * {@link TaskViewSimulator}
  */
 public class RemoteTargetGluer {
-    private static final String TAG = "RemoteTargetGluer";
-
     private RemoteTargetHandle[] mRemoteTargetHandles;
     private SplitConfigurationOptions.StagedSplitBounds mStagedSplitBounds;
 
@@ -94,25 +91,18 @@
     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) {
             // If we're not in split screen, the splitIds count doesn't really matter since we
-            // should always hit this case. Right now there's no use case for multiple app targets
-            // without being in split screen
-            primaryTaskTarget = targets.apps[0];
+            // should always hit this case.
             mRemoteTargetHandles[0].mTransformParams.setTargetSet(targets);
-            mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(primaryTaskTarget, null);
+            if (targets.apps.length > 0) {
+                // Unclear why/when target.apps length == 0, but it sure does happen :(
+                primaryTaskTarget = targets.apps[0];
+                mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(primaryTaskTarget, null);
+            }
         } else {
             // split screen
             primaryTaskTarget = targets.findTask(splitIds[0]);
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index f64d506..b36cb0a 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -18,7 +18,6 @@
 import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_SELECT;
-import static com.android.launcher3.config.FeatureFlags.PROTOTYPE_APP_CLOSE;
 
 import android.animation.Animator;
 import android.content.Context;
@@ -28,7 +27,6 @@
 import android.graphics.RectF;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
 
 import com.android.launcher3.DeviceProfile;
@@ -39,10 +37,8 @@
 import com.android.launcher3.touch.PagedOrientationHandler;
 import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
 import com.android.quickstep.util.AnimatorControllerWithResistance;
-import com.android.quickstep.util.AppCloseConfig;
 import com.android.quickstep.util.LauncherSplitScreenListener;
 import com.android.quickstep.util.RectFSpringAnim;
-import com.android.quickstep.util.RectFSpringAnim2;
 import com.android.quickstep.util.TaskViewSimulator;
 import com.android.quickstep.util.TransformParams;
 import com.android.quickstep.util.TransformParams.BuilderProxy;
@@ -189,8 +185,7 @@
 
         public boolean keepWindowOpaque() { return false; }
 
-        public void update(@Nullable AppCloseConfig config, RectF currentRect, float progress,
-                float radius) { }
+        public void update(RectF currentRect, float progress, float radius) { }
 
         public void onCancel() { }
 
@@ -290,14 +285,7 @@
         homeToWindowPositionMap.invert(windowToHomePositionMap);
         windowToHomePositionMap.mapRect(startRect);
 
-        RectFSpringAnim anim;
-        if (PROTOTYPE_APP_CLOSE.get()) {
-            anim = new RectFSpringAnim2(startRect, targetRect, mContext,
-                    taskViewSimulator.getCurrentCornerRadius(),
-                    homeAnimationFactory.getEndRadius(cropRectF));
-        } else {
-            anim = new RectFSpringAnim(startRect, targetRect, mContext, mDp);
-        }
+        RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext, mDp);
         homeAnimationFactory.setAnimation(anim);
 
         SpringAnimationRunner runner = new SpringAnimationRunner(
@@ -343,17 +331,13 @@
         }
 
         @Override
-        public void onUpdate(@Nullable AppCloseConfig config, RectF currentRect, float progress) {
+        public void onUpdate(RectF currentRect, float progress) {
             mHomeAnim.setPlayFraction(progress);
             mHomeToWindowPositionMap.mapRect(mWindowCurrentRect, currentRect);
 
             mMatrix.setRectToRect(mCropRectF, mWindowCurrentRect, ScaleToFit.FILL);
             float cornerRadius = Utilities.mapRange(progress, mStartRadius, mEndRadius);
             float alpha = mAnimationFactory.getWindowAlpha(progress);
-            if (config != null && PROTOTYPE_APP_CLOSE.get()) {
-                alpha = config.getWindowAlpha();
-                cornerRadius = config.getCornerRadius();
-            }
             if (mAnimationFactory.keepWindowOpaque()) {
                 alpha = 1f;
             }
@@ -362,8 +346,7 @@
                     .setCornerRadius(cornerRadius);
             mLocalTransformParams.applySurfaceParams(mLocalTransformParams
                     .createSurfaceParams(this));
-            mAnimationFactory.update(config, currentRect, progress,
-                    mMatrix.mapRadius(cornerRadius));
+            mAnimationFactory.update(currentRect, progress, mMatrix.mapRadius(cornerRadius));
         }
 
         @Override
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 9fc557d..541af76 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -37,6 +37,7 @@
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
 
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -455,6 +456,8 @@
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed call handleImageBundleAsScreenshot");
             }
+        } else if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.NO_SCREENSHOT, "sysuiproxy, no proxy available");
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 4b89981..258a0c2 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -178,7 +178,8 @@
 
         if (ENABLE_SHELL_TRANSITIONS) {
             RemoteTransitionCompat transition = new RemoteTransitionCompat(mCallbacks,
-                    mController != null ? mController.getController() : null);
+                    mController != null ? mController.getController() : null,
+                    mCtx.getIApplicationThread());
             Bundle options = ActivityOptionsCompat.makeRemoteTransition(transition)
                     .setTransientLaunch().toBundle();
             mCtx.startActivity(intent, options);
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index ecc4b2b..b56c1b7 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -22,6 +22,7 @@
 
 import static com.android.launcher3.config.FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.launcher3.testing.TestProtocol.TASKBAR_WINDOW_CRASH;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.quickstep.GestureState.DEFAULT_STATE;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -350,6 +351,9 @@
     @Override
     public void onCreate() {
         super.onCreate();
+        if (TestProtocol.sDebugTracing) {
+            Log.e(TASKBAR_WINDOW_CRASH, "TIS created");
+        }
         // Initialize anything here that is needed in direct boot mode.
         // Everything else should be initialized in onUserUnlocked() below.
         mMainChoreographer = Choreographer.getInstance();
@@ -511,6 +515,9 @@
     @Override
     public void onDestroy() {
         Log.d(TAG, "Touch service destroyed: user=" + getUserId());
+        if (TestProtocol.sDebugTracing) {
+            Log.e(TASKBAR_WINDOW_CRASH, "TIS destroyed");
+        }
         sIsInitialized = false;
         if (mDeviceState.isUserUnlocked()) {
             mInputConsumer.unregisterInputConsumer();
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
index fb6cd8a..49d8203 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -43,6 +43,13 @@
     }
 
     @Override
+    public Integer getSuccessFeedbackSubtitle() {
+        return mTutorialFragment.isAtFinalStep()
+                ? R.string.back_gesture_feedback_complete_without_follow_up
+                : R.string.back_gesture_feedback_complete_with_overview_follow_up;
+    }
+
+    @Override
     protected int getMockAppTaskLayoutResId() {
         return getMockAppTaskCurrentPageLayoutResId();
     }
@@ -85,10 +92,7 @@
             case BACK_COMPLETED_FROM_RIGHT:
                 mTutorialFragment.releaseFeedbackAnimation();
                 updateFakeAppTaskViewLayout(getMockAppTaskPreviousPageLayoutResId());
-                int subtitleResId = mTutorialFragment.isAtFinalStep()
-                        ? R.string.back_gesture_feedback_complete_without_follow_up
-                        : R.string.back_gesture_feedback_complete_with_overview_follow_up;
-                showFeedback(subtitleResId, true);
+                showSuccessFeedback();
                 break;
             case BACK_CANCELLED_FROM_LEFT:
             case BACK_CANCELLED_FROM_RIGHT:
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index 7fb7d29..c2524b1 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -35,10 +35,9 @@
 /** Shows the gesture interactive sandbox in full screen mode. */
 public class GestureSandboxActivity extends FragmentActivity {
 
-    private static final String LOG_TAG = "GestureSandboxActivity";
-
     private static final String KEY_TUTORIAL_STEPS = "tutorial_steps";
     private static final String KEY_CURRENT_STEP = "current_step";
+    private static final String KEY_GESTURE_COMPLETE = "gesture_complete";
 
     private TutorialType[] mTutorialSteps;
     private TutorialType mCurrentTutorialStep;
@@ -56,7 +55,8 @@
         Bundle args = savedInstanceState == null ? getIntent().getExtras() : savedInstanceState;
         mTutorialSteps = getTutorialSteps(args);
         mCurrentTutorialStep = mTutorialSteps[mCurrentStep - 1];
-        mFragment = TutorialFragment.newInstance(mCurrentTutorialStep);
+        mFragment = TutorialFragment.newInstance(
+                mCurrentTutorialStep, args.getBoolean(KEY_GESTURE_COMPLETE, false));
         getSupportFragmentManager().beginTransaction()
                 .add(R.id.gesture_tutorial_fragment_container, mFragment)
                 .commit();
@@ -87,6 +87,7 @@
     protected void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
         savedInstanceState.putStringArray(KEY_TUTORIAL_STEPS, getTutorialStepNames());
         savedInstanceState.putInt(KEY_CURRENT_STEP, mCurrentStep);
+        savedInstanceState.putBoolean(KEY_GESTURE_COMPLETE, mFragment.isGestureComplete());
         super.onSaveInstanceState(savedInstanceState);
     }
 
@@ -121,7 +122,7 @@
             return;
         }
         mCurrentTutorialStep = mTutorialSteps[mCurrentStep];
-        mFragment = TutorialFragment.newInstance(mCurrentTutorialStep);
+        mFragment = TutorialFragment.newInstance(mCurrentTutorialStep, false);
         getSupportFragmentManager().beginTransaction()
                 .replace(R.id.gesture_tutorial_fragment_container, mFragment)
                 .runOnCommit(() -> mFragment.onAttachedToWindow())
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
index bbb22e6..0bc3691 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
@@ -42,6 +42,13 @@
     }
 
     @Override
+    public Integer getSuccessFeedbackSubtitle() {
+        return mTutorialFragment.isAtFinalStep()
+                ? R.string.home_gesture_feedback_complete_without_follow_up
+                : R.string.home_gesture_feedback_complete_with_follow_up;
+    }
+
+    @Override
     protected int getMockAppTaskLayoutResId() {
         return mTutorialFragment.isLargeScreen()
                 ? R.layout.gesture_tutorial_foldable_mock_webpage
@@ -84,10 +91,7 @@
                     case HOME_GESTURE_COMPLETED: {
                         mTutorialFragment.releaseFeedbackAnimation();
                         animateFakeTaskViewHome(finalVelocity, null);
-                        int subtitleResId = mTutorialFragment.isAtFinalStep()
-                                ? R.string.home_gesture_feedback_complete_without_follow_up
-                                : R.string.home_gesture_feedback_complete_with_follow_up;
-                        showFeedback(subtitleResId, true);
+                        showSuccessFeedback();
                         break;
                     }
                     case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE:
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
index 0fea0d7..f308f27 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -52,6 +52,13 @@
     }
 
     @Override
+    public Integer getSuccessFeedbackSubtitle() {
+        return mTutorialFragment.getNumSteps() > 1 && mTutorialFragment.isAtFinalStep()
+                ? R.string.overview_gesture_feedback_complete_with_follow_up
+                : R.string.overview_gesture_feedback_complete_without_follow_up;
+    }
+
+    @Override
     protected int getMockAppTaskLayoutResId() {
         return mTutorialFragment.isLargeScreen()
                 ? R.layout.gesture_tutorial_foldable_mock_conversation_list
@@ -106,11 +113,7 @@
                         mTutorialFragment.releaseFeedbackAnimation();
                         animateTaskViewToOverview();
                         onMotionPaused(true /*arbitrary value*/);
-                        int subtitleResId = mTutorialFragment.getNumSteps() > 1
-                                && mTutorialFragment.isAtFinalStep()
-                                ? R.string.overview_gesture_feedback_complete_with_follow_up
-                                : R.string.overview_gesture_feedback_complete_without_follow_up;
-                        showFeedback(subtitleResId, true);
+                        showSuccessFeedback();
                         break;
                     case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION:
                     case HOME_OR_OVERVIEW_CANCELLED:
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index 68df208..672687d 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -53,7 +53,6 @@
 import com.android.quickstep.RemoteTargetGluer;
 import com.android.quickstep.SwipeUpAnimationLogic;
 import com.android.quickstep.SwipeUpAnimationLogic.RunningWindowAnim;
-import com.android.quickstep.util.AppCloseConfig;
 import com.android.quickstep.util.RectFSpringAnim;
 import com.android.quickstep.util.TransformParams;
 import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
@@ -331,8 +330,7 @@
                 }
 
                 @Override
-                public void update(@Nullable AppCloseConfig config, RectF rect, float progress,
-                        float radius) {
+                public void update(RectF rect, float progress, float radius) {
                     mFakeIconView.setVisibility(View.VISIBLE);
                     mFakeIconView.update(rect, progress,
                             1f - SHAPE_PROGRESS_DURATION /* shapeProgressStart */,
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 81e18f6..4145393 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -223,6 +223,11 @@
         return null;
     }
 
+    @StringRes
+    public Integer getSuccessFeedbackSubtitle() {
+        return null;
+    }
+
     void showFeedback() {
         if (mGestureCompleted) {
             mFeedbackView.setTranslationY(0);
@@ -236,6 +241,13 @@
     }
 
     /**
+     * Show feedback reflecting a successful gesture attempt.
+     **/
+    void showSuccessFeedback() {
+        showFeedback(getSuccessFeedbackSubtitle(), true);
+    }
+
+    /**
      * Show feedback reflecting a failed gesture attempt.
      *
      * @param subtitleResId Resource of the text to display.
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 89be1a6..2fd7cde 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -49,8 +49,10 @@
 
     private static final String LOG_TAG = "TutorialFragment";
     static final String KEY_TUTORIAL_TYPE = "tutorial_type";
+    static final String KEY_GESTURE_COMPLETE = "gesture_complete";
 
     TutorialType mTutorialType;
+    boolean mGestureComplete = false;
     @Nullable TutorialController mTutorialController = null;
     RootSandboxLayout mRootView;
     View mFingerDotView;
@@ -67,7 +69,7 @@
 
     private boolean mIsLargeScreen;
 
-    public static TutorialFragment newInstance(TutorialType tutorialType) {
+    public static TutorialFragment newInstance(TutorialType tutorialType, boolean gestureComplete) {
         TutorialFragment fragment = getFragmentForTutorialType(tutorialType);
         if (fragment == null) {
             fragment = new BackGestureTutorialFragment();
@@ -76,6 +78,7 @@
 
         Bundle args = new Bundle();
         args.putSerializable(KEY_TUTORIAL_TYPE, tutorialType);
+        args.putBoolean(KEY_GESTURE_COMPLETE, gestureComplete);
         fragment.setArguments(args);
         return fragment;
     }
@@ -132,6 +135,7 @@
         super.onCreate(savedInstanceState);
         Bundle args = savedInstanceState != null ? savedInstanceState : getArguments();
         mTutorialType = (TutorialType) args.getSerializable(KEY_TUTORIAL_TYPE);
+        mGestureComplete = args.getBoolean(KEY_GESTURE_COMPLETE, false);
         mEdgeBackGestureHandler = new EdgeBackGestureHandler(getContext());
         mNavBarGestureHandler = new NavBarGestureHandler(getContext());
 
@@ -186,11 +190,13 @@
     }
 
     void initializeFeedbackVideoView() {
-        if (!updateFeedbackAnimation()) {
+        if (!updateFeedbackAnimation() || mTutorialController == null) {
             return;
         }
 
-        if (!mIntroductionShown && mTutorialController != null) {
+        if (isGestureComplete()) {
+            mTutorialController.showSuccessFeedback();
+        } else if (!mIntroductionShown) {
             Integer introTileStringResId = mTutorialController.getIntroductionTitle();
             Integer introSubtitleResId = mTutorialController.getIntroductionSubtitle();
             if (introTileStringResId != null && introSubtitleResId != null) {
@@ -372,6 +378,11 @@
         return getCurrentStep() == getNumSteps();
     }
 
+    boolean isGestureComplete() {
+        return mGestureComplete
+                || (mTutorialController != null && mTutorialController.isGestureCompleted());
+    }
+
     @Nullable
     private GestureSandboxActivity getGestureSandboxActivity() {
         Context context = getContext();
diff --git a/quickstep/src/com/android/quickstep/util/ActivityInitListener.java b/quickstep/src/com/android/quickstep/util/ActivityInitListener.java
index b9879ab..aeec36f 100644
--- a/quickstep/src/com/android/quickstep/util/ActivityInitListener.java
+++ b/quickstep/src/com/android/quickstep/util/ActivityInitListener.java
@@ -15,11 +15,6 @@
  */
 package com.android.quickstep.util;
 
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-
 import com.android.launcher3.BaseActivity;
 import com.android.launcher3.util.ActivityTracker;
 import com.android.launcher3.util.ActivityTracker.SchedulerCallback;
@@ -75,17 +70,4 @@
         mIsRegistered = false;
         mOnInitListener = null;
     }
-
-    /**
-     * Starts the given intent with the provided animation. Unlike {@link #register(Intent)}, this
-     * method will not call {@link #init} if the activity already exists, it will only call it when
-     * we get handleIntent() for the provided intent that we're starting.
-     */
-    public void registerAndStartActivity(Intent intent, RemoteAnimationProvider animProvider,
-            Context context, Handler handler, long duration) {
-        register();
-
-        Bundle options = animProvider.toActivityOptions(handler, duration, context).toBundle();
-        context.startActivity(new Intent(intent), options);
-    }
 }
diff --git a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
index de7dbd6..b0c68c5 100644
--- a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
+++ b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
@@ -49,6 +49,7 @@
 
 import com.android.internal.app.ChooserActivity;
 import com.android.launcher3.BuildConfig;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.quickstep.SystemUiProxy;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.utilities.BitmapUtil;
@@ -77,6 +78,9 @@
     public static void saveScreenshot(SystemUiProxy systemUiProxy, Bitmap screenshot,
             Rect screenshotBounds,
             Insets visibleInsets, Task.TaskKey task) {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.NO_SCREENSHOT, "image action utils calling into sysuiproxy");
+        }
         systemUiProxy.handleImageBundleAsScreenshot(BitmapUtil.hardwareBitmapToBundle(screenshot),
                 screenshotBounds, visibleInsets, task);
     }
diff --git a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
index 158fba9..c4909de 100644
--- a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
+++ b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
@@ -328,7 +328,7 @@
                     break;
             }
             for (OnUpdateListener onUpdateListener : mOnUpdateListeners) {
-                onUpdateListener.onUpdate(null, mCurrentRect, mCurrentScaleProgress);
+                onUpdateListener.onUpdate(mCurrentRect, mCurrentScaleProgress);
             }
         }
     }
@@ -353,7 +353,12 @@
     }
 
     public interface OnUpdateListener {
-        void onUpdate(@Nullable AppCloseConfig values, RectF currentRect, float progress);
+        /**
+         * Called when an update is made to the animation.
+         * @param currentRect The rect of the window.
+         * @param progress [0, 1] The progress of the rect scale animation.
+         */
+        void onUpdate(RectF currentRect, float progress);
 
         default void onCancel() { }
     }
diff --git a/quickstep/src/com/android/quickstep/util/RectFSpringAnim2.java b/quickstep/src/com/android/quickstep/util/RectFSpringAnim2.java
deleted file mode 100644
index cb35809..0000000
--- a/quickstep/src/com/android/quickstep/util/RectFSpringAnim2.java
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.util;
-
-import static com.android.launcher3.Utilities.dpToPx;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.graphics.PointF;
-import android.graphics.RectF;
-import android.util.PathParser;
-import android.util.Property;
-import android.view.animation.Interpolator;
-
-import androidx.core.view.animation.PathInterpolatorCompat;
-import androidx.dynamicanimation.animation.FloatPropertyCompat;
-import androidx.dynamicanimation.animation.SpringAnimation;
-import androidx.dynamicanimation.animation.SpringForce;
-
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.util.DynamicResource;
-import com.android.systemui.plugins.ResourceProvider;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Applies spring forces to animate from a starting rect to a target rect,
- * while providing update callbacks to the caller.
- */
-public class RectFSpringAnim2 extends RectFSpringAnim {
-
-    private static final FloatPropertyCompat<RectFSpringAnim2> RECT_CENTER_X =
-            new FloatPropertyCompat<RectFSpringAnim2>("rectCenterXSpring") {
-                @Override
-                public float getValue(RectFSpringAnim2 anim) {
-                    return anim.mCurrentCenterX;
-                }
-
-                @Override
-                public void setValue(RectFSpringAnim2 anim, float currentCenterX) {
-                    anim.mCurrentCenterX = currentCenterX;
-                    anim.onUpdate();
-                }
-            };
-
-    private static final FloatPropertyCompat<RectFSpringAnim2> RECT_Y =
-            new FloatPropertyCompat<RectFSpringAnim2>("rectYSpring") {
-                @Override
-                public float getValue(RectFSpringAnim2 anim) {
-                    return anim.mCurrentCenterY;
-                }
-
-                @Override
-                public void setValue(RectFSpringAnim2 anim, float y) {
-                    anim.mCurrentCenterY = y;
-                    anim.onUpdate();
-                }
-            };
-
-    private static final Property<RectFSpringAnim2, Float> PROGRESS =
-            new Property<RectFSpringAnim2, Float>(Float.class, "rectFProgress") {
-                @Override
-                public Float get(RectFSpringAnim2 rectFSpringAnim) {
-                    return rectFSpringAnim.mProgress;
-                }
-
-                @Override
-                public void set(RectFSpringAnim2 rectFSpringAnim, Float progress) {
-                    rectFSpringAnim.mProgress = progress;
-                    rectFSpringAnim.onUpdate();
-                }
-            };
-
-    private final RectF mStartRect;
-    private final RectF mTargetRect;
-    private final RectF mCurrentRect = new RectF();
-    private final List<OnUpdateListener> mOnUpdateListeners = new ArrayList<>();
-    private final List<Animator.AnimatorListener> mAnimatorListeners = new ArrayList<>();
-
-    private float mCurrentCenterX;
-    private float mCurrentCenterY;
-
-    private float mTargetX;
-    private float mTargetY;
-
-    // If true, tracking the bottom of the rects, else tracking the top.
-    private float mProgress;
-    private SpringAnimation mRectXAnim;
-    private SpringAnimation mRectYAnim;
-    private ValueAnimator mRectScaleAnim;
-    private boolean mAnimsStarted;
-    private boolean mRectXAnimEnded;
-    private boolean mRectYAnimEnded;
-    private boolean mRectScaleAnimEnded;
-
-    private final float mXDamping;
-    private final float mXStiffness;
-
-    private final float mYDamping;
-    private float mYStiffness;
-
-    private long mDuration;
-
-    private final Interpolator mCloseInterpolator;
-
-    private AppCloseConfig mValues;
-    final float mStartRadius;
-    final float mEndRadius;
-
-    final float mHomeTransYEnd;
-    final float mScaleStart;
-
-    public RectFSpringAnim2(RectF startRect, RectF targetRect, Context context, float startRadius,
-            float endRadius) {
-        super(startRect, targetRect, context, null);
-        mStartRect = startRect;
-        mTargetRect = targetRect;
-
-        mCurrentCenterY = mStartRect.centerY();
-        mCurrentCenterX = mStartRect.centerX();
-
-        mTargetY = mTargetRect.centerY();
-        mTargetX = mTargetRect.centerX();
-
-        ResourceProvider rp = DynamicResource.provider(context);
-        mXDamping = rp.getFloat(R.dimen.swipe_up_rect_2_x_damping_ratio);
-        mXStiffness = rp.getFloat(R.dimen.swipe_up_rect_2_x_stiffness);
-
-        mYDamping = rp.getFloat(R.dimen.swipe_up_rect_2_y_damping_ratio);
-        mYStiffness = rp.getFloat(R.dimen.swipe_up_rect_2_y_stiffness);
-        mDuration = Math.round(rp.getFloat(R.dimen.swipe_up_duration));
-
-        mHomeTransYEnd = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp));
-        mScaleStart = rp.getFloat(R.dimen.swipe_up_scale_start);
-
-        mCloseInterpolator = getAppCloseInterpolator(context);
-
-        // End on a "round-enough" radius so that the shape reveal doesn't have to do too much
-        // rounding at the end of the animation.
-        mStartRadius = startRadius;
-        mEndRadius = endRadius;
-
-        setCanRelease(true);
-    }
-
-    public void onTargetPositionChanged() {
-        if (mRectXAnim != null && mTargetX != mTargetRect.centerX()) {
-            mTargetX = mTargetRect.centerX();
-            mRectXAnim.animateToFinalPosition(mTargetX);
-        }
-
-        if (mRectYAnim != null) {
-            if (mTargetY != mTargetRect.centerY()) {
-                mTargetY = mTargetRect.centerY();
-                mRectYAnim.animateToFinalPosition(mTargetY);
-            }
-        }
-    }
-
-    public void addOnUpdateListener(OnUpdateListener onUpdateListener) {
-        mOnUpdateListeners.add(onUpdateListener);
-    }
-
-    public void addAnimatorListener(Animator.AnimatorListener animatorListener) {
-        mAnimatorListeners.add(animatorListener);
-    }
-
-    /**
-     * Starts the fling/spring animation.
-     * @param context The activity context.
-     * @param velocityPxPerMs Velocity of swipe in px/ms.
-     */
-    public void start(Context context, PointF velocityPxPerMs) {
-        mRectXAnim = new SpringAnimation(this, RECT_CENTER_X)
-                .setStartValue(mCurrentCenterX)
-                .setStartVelocity(velocityPxPerMs.x * 1000)
-                .setSpring(new SpringForce(mTargetX)
-                        .setStiffness(mXStiffness)
-                        .setDampingRatio(mXDamping));
-        mRectXAnim.addEndListener(((animation, canceled, centerX, velocityX) -> {
-            mRectXAnimEnded = true;
-            maybeOnEnd();
-        }));
-
-        mRectYAnim = new SpringAnimation(this, RECT_Y)
-                .setStartValue(mCurrentCenterY)
-                .setStartVelocity(velocityPxPerMs.y * 1000)
-                .setSpring(new SpringForce(mTargetY)
-                        .setStiffness(mYStiffness)
-                        .setDampingRatio(mYDamping));
-        mRectYAnim.addEndListener(((animation, canceled, centerY, velocityY) -> {
-            mRectYAnimEnded = true;
-            maybeOnEnd();
-        }));
-
-        mRectScaleAnim = ObjectAnimator.ofFloat(this, PROGRESS, 0, 1f)
-                .setDuration(mDuration);
-        mRectScaleAnim.setInterpolator(mCloseInterpolator);
-        mRectScaleAnim.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mRectScaleAnimEnded = true;
-                maybeOnEnd();
-            }
-        });
-
-        mValues = buildConfig();
-        mRectScaleAnim.addUpdateListener(mValues);
-
-        setCanRelease(false);
-        mAnimsStarted = true;
-
-        mRectXAnim.start();
-        mRectYAnim.start();
-        mRectScaleAnim.start();
-        for (Animator.AnimatorListener animatorListener : mAnimatorListeners) {
-            animatorListener.onAnimationStart(null);
-        }
-    }
-
-    private AppCloseConfig buildConfig() {
-        return new AppCloseConfig() {
-            FloatProp mHomeTransY = new FloatProp(0, mHomeTransYEnd, 0, mDuration, LINEAR);
-            FloatProp mHomeScale = new FloatProp(mScaleStart, 1f, 0, mDuration, LINEAR);
-            FloatProp mWindowFadeOut = new FloatProp(1f, 0f, 0, 116, LINEAR);
-            // There should be a slight overlap b/w window fading out and fg fading in.
-            // (fg startDelay < window fade out duration)
-            FloatProp mFgFadeIn = new FloatProp(0, 255f, 100, mDuration - 100, LINEAR);
-            FloatProp mRadius = new FloatProp(mStartRadius, mEndRadius, 0, mDuration, LINEAR);
-            FloatProp mThreePointInterpolation = new FloatProp(0, 1, 0, mDuration, LINEAR);
-
-            @Override
-            public float getWorkspaceTransY() {
-                return mHomeTransY.value;
-            }
-
-            @Override
-            public float getWorkspaceScale() {
-                return mHomeScale.value;
-            }
-
-            @Override
-            public float getWindowAlpha() {
-                return mWindowFadeOut.value;
-            }
-
-            @Override
-            public int getFgAlpha() {
-                return (int) mFgFadeIn.value;
-            }
-
-            @Override
-            public float getCornerRadius() {
-                return mRadius.value;
-            }
-
-            @Override
-            public float getInterpolatedProgress() {
-                return mThreePointInterpolation.value;
-            }
-
-            @Override
-            public void onUpdate(float percent, boolean initOnly) {}
-        };
-    }
-
-    public void end() {
-        if (mAnimsStarted) {
-            if (mRectXAnim.canSkipToEnd()) {
-                mRectXAnim.skipToEnd();
-            }
-            if (mRectYAnim.canSkipToEnd()) {
-                mRectYAnim.skipToEnd();
-            }
-            mRectScaleAnim.end();
-        }
-        mRectXAnimEnded = true;
-        mRectYAnimEnded = true;
-        mRectScaleAnimEnded = true;
-        maybeOnEnd();
-    }
-
-    private boolean isEnded() {
-        return mRectXAnimEnded && mRectYAnimEnded && mRectScaleAnimEnded;
-    }
-
-    private void onUpdate() {
-        if (isEnded()) {
-            // Prevent further updates from being called. This can happen between callbacks for
-            // ending the x/y/scale animations.
-            return;
-        }
-
-        if (!mOnUpdateListeners.isEmpty()) {
-            float rectProgress = mProgress;
-            float currentWidth = Utilities.mapRange(rectProgress, mStartRect.width(),
-                    mTargetRect.width());
-            float currentHeight = Utilities.mapRange(rectProgress, mStartRect.height(),
-                    mTargetRect.height());
-
-            mCurrentRect.set(mCurrentCenterX - currentWidth / 2,
-                    mCurrentCenterY - currentHeight / 2,
-                    mCurrentCenterX + currentWidth / 2,
-                    mCurrentCenterY + currentHeight / 2);
-
-            float currentPlayTime = mRectScaleAnimEnded ? mRectScaleAnim.getDuration()
-                    : mRectScaleAnim.getCurrentPlayTime();
-            float linearProgress = Math.min(1f, currentPlayTime / mRectScaleAnim.getDuration());
-            for (OnUpdateListener onUpdateListener : mOnUpdateListeners) {
-                onUpdateListener.onUpdate(mValues, mCurrentRect, linearProgress);
-            }
-        }
-    }
-
-    private void maybeOnEnd() {
-        if (mAnimsStarted && isEnded()) {
-            mAnimsStarted = false;
-            setCanRelease(true);
-            for (Animator.AnimatorListener animatorListener : mAnimatorListeners) {
-                animatorListener.onAnimationEnd(null);
-            }
-        }
-    }
-
-    public void cancel() {
-        if (mAnimsStarted) {
-            for (OnUpdateListener onUpdateListener : mOnUpdateListeners) {
-                onUpdateListener.onCancel();
-            }
-        }
-        end();
-    }
-
-    private Interpolator getAppCloseInterpolator(Context context) {
-        ResourceProvider rp = DynamicResource.provider(context);
-        String path = String.format(Locale.ENGLISH,
-                "M 0,0 C %f, %f, %f, %f, %f, %f C %f, %f, %f, %f, 1, 1",
-                rp.getFloat(R.dimen.c1_a),
-                rp.getFloat(R.dimen.c1_b),
-                rp.getFloat(R.dimen.c1_c),
-                rp.getFloat(R.dimen.c1_d),
-                rp.getFloat(R.dimen.mp_x),
-                rp.getFloat(R.dimen.mp_y),
-                rp.getFloat(R.dimen.c2_a),
-                rp.getFloat(R.dimen.c2_b),
-                rp.getFloat(R.dimen.c2_c),
-                rp.getFloat(R.dimen.c2_d));
-        return PathInterpolatorCompat.create(PathParser.createPathFromPathData(path));
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
index 98dbd47..ee82ae6 100644
--- a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
+++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
@@ -16,32 +16,14 @@
 package com.android.quickstep.util;
 
 import android.animation.AnimatorSet;
-import android.app.ActivityOptions;
-import android.content.Context;
-import android.os.Handler;
 
-import com.android.launcher3.LauncherAnimationRunner;
-import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory;
-import com.android.systemui.shared.system.ActivityOptionsCompat;
-import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 
 public abstract class RemoteAnimationProvider {
 
-    RemoteAnimationFactory mAnimationRunner;
-
     public abstract AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
             RemoteAnimationTargetCompat[] wallpaperTargets);
 
-    ActivityOptions toActivityOptions(Handler handler, long duration, Context context) {
-        mAnimationRunner = (transit, appTargets, wallpaperTargets, nonApps, result) ->
-                result.setAnimation(createWindowAnimation(appTargets, wallpaperTargets), context);
-        final LauncherAnimationRunner wrapper = new LauncherAnimationRunner(
-                handler, mAnimationRunner, false /* startAtFrontOfQueue */);
-        return ActivityOptionsCompat.makeRemoteAnimation(
-                new RemoteAnimationAdapterCompat(wrapper, duration, 0));
-    }
-
     /**
      * @return the target with the lowest opaque layer for a certain app animation, or null.
      */
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 1dae2c8..4c300ec 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -94,7 +94,8 @@
                     new RemoteSplitLaunchTransitionRunner(task1, task2);
             mSystemUiProxy.startTasks(taskIds[0], null /* mainOptions */, taskIds[1],
                     null /* sideOptions */, STAGE_POSITION_BOTTOM_OR_RIGHT,
-                    new RemoteTransitionCompat(animationRunner, MAIN_EXECUTOR));
+                    new RemoteTransitionCompat(animationRunner, MAIN_EXECUTOR,
+                            ActivityThread.currentActivityThread().getApplicationThread()));
         } else {
             RemoteSplitLaunchAnimationRunner animationRunner =
                     new RemoteSplitLaunchAnimationRunner(task1, task2, callback);
diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
index a30216c..a534450 100644
--- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
@@ -158,7 +158,7 @@
             t.reparent(mContentOverlay, mLeash);
             t.apply();
 
-            addOnUpdateListener((values, currentRect, progress) -> {
+            addOnUpdateListener((currentRect, progress) -> {
                 float alpha = progress < 0.5f
                         ? 0
                         : Utilities.mapToRange(Math.min(progress, 1f), 0.5f, 1f,
@@ -201,8 +201,7 @@
         addOnUpdateListener(this::onAnimationUpdate);
     }
 
-    private void onAnimationUpdate(@Nullable AppCloseConfig values, RectF currentRect,
-            float progress) {
+    private void onAnimationUpdate(RectF currentRect, float progress) {
         if (mHasAnimationEnded) return;
         final SurfaceControl.Transaction tx =
                 PipSurfaceTransactionHelper.newSurfaceControlTransaction();
diff --git a/quickstep/src/com/android/quickstep/util/TaskKeyLruCache.java b/quickstep/src/com/android/quickstep/util/TaskKeyLruCache.java
index d87feec..08a65fa 100644
--- a/quickstep/src/com/android/quickstep/util/TaskKeyLruCache.java
+++ b/quickstep/src/com/android/quickstep/util/TaskKeyLruCache.java
@@ -20,6 +20,7 @@
 import com.android.systemui.shared.recents.model.Task.TaskKey;
 
 import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.function.Predicate;
 
 /**
@@ -117,7 +118,7 @@
         }
 
         @Override
-        protected boolean removeEldestEntry(Entry<Integer, TaskKeyLruCache.Entry<V>> eldest) {
+        protected boolean removeEldestEntry(Map.Entry<Integer, TaskKeyLruCache.Entry<V>> eldest) {
             return size() > mMaxSize;
         }
     }
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 734c844..977c696 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -15,6 +15,7 @@
  */
 package com.android.quickstep.util;
 
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.states.RotationHelper.deltaRotation;
 import static com.android.launcher3.touch.PagedOrientationHandler.MATRIX_POST_TRANSLATE;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
@@ -99,6 +100,7 @@
     private boolean mLayoutValid = false;
     private int mOrientationStateId;
     private StagedSplitBounds mStagedSplitBounds;
+    private boolean mDrawsBelowRecents;
 
     public TaskViewSimulator(Context context, BaseActivityInterface sizeStrategy) {
         mContext = context;
@@ -198,6 +200,10 @@
         recentsViewScroll.value = scroll;
     }
 
+    public void setDrawsBelowRecents(boolean drawsBelowRecents) {
+        mDrawsBelowRecents = drawsBelowRecents;
+    }
+
     /**
      * Adds animation for all the components corresponding to transition from an app to overview.
      */
@@ -351,6 +357,12 @@
         builder.withMatrix(mMatrix)
                 .withWindowCrop(mTmpCropRect)
                 .withCornerRadius(getCurrentCornerRadius());
+
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && params.getRecentsSurface() != null) {
+            // When relativeLayer = 0, it reverts the surfaces back to the original order.
+            builder.withRelativeLayerTo(params.getRecentsSurface(),
+                    mDrawsBelowRecents ? Integer.MIN_VALUE : 0);
+        }
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 76d3591..5a8cbc1 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -20,6 +20,7 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.FrameLayout;
@@ -30,6 +31,7 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
 import com.android.quickstep.SysUINavigationMode;
@@ -110,6 +112,11 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         findViewById(R.id.action_screenshot).setOnClickListener(this);
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.NO_SCREENSHOT, "Inflated OverviewActionsView and added screenshot"
+                    + " listener.");
+        }
+
         mSplitButton = findViewById(R.id.action_split);
         mSplitButton.setOnClickListener(this);
     }
@@ -125,6 +132,11 @@
 
     @Override
     public void onClick(View view) {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.NO_SCREENSHOT, "OverviewActionsView - onClick"
+                    + " callbacks: " + mCallbacks + "  view id: " + view.getId() + " "
+                    + " is screenshot? " + (view.getId() == R.id.action_screenshot));
+        }
         if (mCallbacks == null) {
             return;
         }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 687a13a..96c5561 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -1911,8 +1911,10 @@
             }
         }
         setEnableDrawingLiveTile(false);
-        runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams()
-                .setTargetSet(null));
+        runActionOnRemoteHandles(remoteTargetHandle -> {
+            remoteTargetHandle.getTransformParams().setTargetSet(null);
+            remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(true);
+        });
 
         // These are relatively expensive and don't need to be done this frame (RecentsView isn't
         // visible anyway), so defer by a frame to get off the critical path, e.g. app to home.
@@ -4368,12 +4370,13 @@
             TaskViewSimulator tvs = remoteTargetHandle.getTaskViewSimulator();
             tvs.setOrientationState(mOrientationState);
             tvs.setDp(mActivity.getDeviceProfile());
+            tvs.setDrawsBelowRecents(true);
             tvs.recentsViewScale.value = 1;
         }
     }
 
     /** Helper to avoid writing some for-loops to iterate over {@link #mRemoteTargetHandles} */
-    private void runActionOnRemoteHandles(Consumer<RemoteTargetHandle> consumer) {
+    public void runActionOnRemoteHandles(Consumer<RemoteTargetHandle> consumer) {
         if (mRemoteTargetHandles == null) {
             return;
         }
@@ -4390,7 +4393,7 @@
     public void finishRecentsAnimation(boolean toRecents, boolean shouldPip,
             Runnable onFinishComplete) {
         // TODO(b/197232424#comment#10) Move this back into onRecentsAnimationComplete(). Maybe?
-        mRemoteTargetHandles = null;
+        cleanupRemoteTargets();
         if (!toRecents && ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             // Reset the minimized state since we force-toggled the minimized state when entering
             // overview, but never actually finished the recents animation.  This is a catch all for
@@ -4849,6 +4852,10 @@
                 && mCurrentGestureEndTarget != GestureState.GestureEndTarget.RECENTS;
     }
 
+    public void cleanupRemoteTargets() {
+        mRemoteTargetHandles = null;
+    }
+
     /**
      * Used to register callbacks for when our empty message state changes.
      *
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index 5c73fbb..77ac373 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -16,6 +16,7 @@
 
 package com.android.quickstep.views;
 
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
 import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
@@ -242,7 +243,17 @@
         LayoutParams lp = (LayoutParams) menuOptionView.getLayoutParams();
         mTaskView.getPagedOrientationHandler().setLayoutParamsForTaskMenuOptionItem(lp,
                 menuOptionView, mActivity.getDeviceProfile());
-        menuOptionView.setOnClickListener(menuOption::onClick);
+        menuOptionView.setOnClickListener(view -> {
+            if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+                RecentsView recentsView = mTaskView.getRecentsView();
+                recentsView.switchToScreenshot(null,
+                        () -> recentsView.finishRecentsAnimation(true /* toRecents */,
+                                false /* shouldPip */,
+                                () -> menuOption.onClick(view)));
+            } else {
+                menuOption.onClick(view);
+            }
+        });
         mOptionLayout.addView(menuOptionView);
     }
 
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
new file mode 100644
index 0000000..9b86c73
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
@@ -0,0 +1,14 @@
+package com.android.quickstep.views
+
+import android.util.Log
+
+// TODO(http://b/193432925)
+class TaskMenuViewWithArrow {
+    companion object {
+        const val TAG = "TaskMenuViewWithArrow"
+
+        fun logSomething() {
+            Log.d(TAG, "It worked!")
+        }
+    }
+}
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index a9db400..2d58ba5 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -31,6 +31,8 @@
 import android.graphics.Insets;
 import android.graphics.Matrix;
 import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Shader;
@@ -78,6 +80,7 @@
     private TaskOverlay mOverlay;
     private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     private final Paint mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+    private final Paint mClearPaint = new Paint();
     private final Paint mDimmingPaintAfterClearing = new Paint();
     private final int mDimColor;
 
@@ -107,6 +110,7 @@
         super(context, attrs, defStyleAttr);
         mPaint.setFilterBitmap(true);
         mBackgroundPaint.setColor(Color.WHITE);
+        mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
         mActivity = BaseActivity.fromContext(context);
         // Initialize with placeholder value. It is overridden later by TaskView
         mFullscreenParams = TEMP_PARAMS.get(context);
@@ -271,6 +275,7 @@
             float cornerRadius) {
         if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             if (mTask != null && getTaskView().isRunningTask() && !getTaskView().showScreenshot()) {
+                canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mClearPaint);
                 canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius,
                         mDimmingPaintAfterClearing);
                 return;
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 8d77e44..f88b243 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -94,6 +94,7 @@
 import com.android.quickstep.util.LauncherSplitScreenListener;
 import com.android.quickstep.util.RecentsOrientedState;
 import com.android.quickstep.util.TaskCornerRadius;
+import com.android.quickstep.util.TaskViewSimulator;
 import com.android.quickstep.util.TransformParams;
 import com.android.quickstep.views.TaskThumbnailView.PreviewPositionHelper;
 import com.android.systemui.shared.recents.model.Task;
@@ -115,6 +116,7 @@
 public class TaskView extends FrameLayout implements Reusable {
 
     private static final String TAG = TaskView.class.getSimpleName();
+    private static final boolean DEBUG = false;
 
     public static final int FLAG_UPDATE_ICON = 1;
     public static final int FLAG_UPDATE_THUMBNAIL = FLAG_UPDATE_ICON << 1;
@@ -624,7 +626,21 @@
                     recentsView.getDepthController());
             anim.addListener(new AnimatorListenerAdapter() {
                 @Override
+                public void onAnimationStart(Animator animator) {
+                    recentsView.runActionOnRemoteHandles(
+                            (Consumer<RemoteTargetHandle>) remoteTargetHandle ->
+                                    remoteTargetHandle
+                                            .getTaskViewSimulator()
+                                            .setDrawsBelowRecents(false));
+                }
+
+                @Override
                 public void onAnimationEnd(Animator animator) {
+                    recentsView.runActionOnRemoteHandles(
+                            (Consumer<RemoteTargetHandle>) remoteTargetHandle ->
+                                    remoteTargetHandle
+                                            .getTaskViewSimulator()
+                                            .setDrawsBelowRecents(true));
                     mIsClickableAsLiveTile = true;
                 }
             });
@@ -808,6 +824,8 @@
     }
 
     protected boolean showTaskMenuWithContainer(IconView iconView) {
+        // TODO(http://b/193432925)
+        if (DEBUG) TaskMenuViewWithArrow.Companion.logSomething();
         return TaskMenuView.showForTask(mTaskIdAttributeContainer[0]);
     }
 
@@ -818,15 +836,7 @@
                 if (confirmSecondSplitSelectApp()) {
                     return;
                 }
-                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) {
-                    RecentsView recentsView = getRecentsView();
-                    recentsView.switchToScreenshot(
-                            () -> recentsView.finishRecentsAnimation(true /* toRecents */,
-                                    false /* shouldPip */,
-                                    () -> showTaskMenu(iconView)));
-                } else {
-                    showTaskMenu(iconView);
-                }
+                showTaskMenu(iconView);
             });
             iconView.setOnLongClickListener(v -> {
                 requestDisallowInterceptTouchEvent(true);
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationBarRotationContextTest.java b/quickstep/tests/src/com/android/quickstep/NavigationBarRotationContextTest.java
index af5819a..de6740d 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationBarRotationContextTest.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationBarRotationContextTest.java
@@ -31,8 +31,8 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.launcher3.taskbar.contextual.RotationButton;
-import com.android.launcher3.taskbar.contextual.RotationButtonController;
+import com.android.systemui.shared.rotation.RotationButton;
+import com.android.systemui.shared.rotation.RotationButtonController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -55,8 +55,9 @@
         Context mTargetContext = InstrumentationRegistry.getTargetContext();
         final View view = new View(mTargetContext);
         RotationButton rotationButton = mock(RotationButton.class);
-        mRotationButtonController = new RotationButtonController(mTargetContext, 0, 0);
-        mRotationButtonController.setRotationButton(rotationButton);
+        mRotationButtonController = new RotationButtonController(mTargetContext, 0, 0, 0, 0, 0, 0,
+                () -> 0);
+        mRotationButtonController.setRotationButton(rotationButton, null);
         // Due to a mockito issue, only spy the object after setting the initial state
         mRotationButtonController = spy(mRotationButtonController);
         final AnimatedVectorDrawable kbd = mock(AnimatedVectorDrawable.class);
@@ -85,7 +86,7 @@
         // No navigation bar should not call to set visibility state
         mRotationButtonController.onBehaviorChanged(DEFAULT_DISPLAY,
                 WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
-        mRotationButtonController.onTaskBarVisibilityChange(false /* showing */);
+        mRotationButtonController.onNavigationBarWindowVisibilityChange(false /* showing */);
         verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
                 false /* visible */);
         verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
@@ -100,7 +101,7 @@
                 true /* visible */);
 
         // Since rotation has changed rotation should be pending, show mButton when showing nav bar
-        mRotationButtonController.onTaskBarVisibilityChange(true /* showing */);
+        mRotationButtonController.onNavigationBarWindowVisibilityChange(true /* showing */);
         verify(mRotationButtonController, times(1)).setRotateSuggestionButtonState(
                 true /* visible */);
     }
@@ -108,7 +109,7 @@
     @Test
     public void testOnRotationProposalShowButton() {
         // Navigation bar being visible should not call to set visibility state
-        mRotationButtonController.onTaskBarVisibilityChange(true /* showing */);
+        mRotationButtonController.onNavigationBarWindowVisibilityChange(true /* showing */);
         verify(mRotationButtonController, times(0))
                 .setRotateSuggestionButtonState(false /* visible */);
         verify(mRotationButtonController, times(0))
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 4895b10..ea65757 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -31,6 +31,7 @@
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
+import com.android.launcher3.tapl.AllApps;
 import com.android.launcher3.tapl.Background;
 import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel;
 import com.android.launcher3.tapl.Overview;
@@ -43,12 +44,16 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @LargeTest
 @RunWith(AndroidJUnit4.class)
 public class TaplTestsQuickstep extends AbstractQuickStepTest {
+
+    private static final String APP_NAME = "LauncherTestApp";
+
     @Before
     public void setUp() throws Exception {
         super.setUp();
@@ -286,6 +291,31 @@
         getAndAssertBackground();
     }
 
+    // TODO(b/204830798): test with all navigation modes(add @NavigationModeSwitch annotation)
+    //  after the bug resolved.
+    @Ignore("b/205027405")
+    @Test
+    @PortraitLandscape
+    @ScreenRecord
+    public void testPressBack() throws Exception {
+        mLauncher.getWorkspace().switchToAllApps();
+        mLauncher.pressBack();
+        mLauncher.getWorkspace();
+        waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
+
+        AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+        allApps.freeze();
+        try {
+            allApps.getAppIcon(APP_NAME).dragToWorkspace(false, false);
+        } finally {
+            allApps.unfreeze();
+        }
+        mLauncher.getWorkspace().getWorkspaceAppIcon(APP_NAME).launch(getAppPackageName());
+        mLauncher.pressBack();
+        mLauncher.getWorkspace();
+        waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
+    }
+
     @Test
     @PortraitLandscape
     public void testOverviewForTablet() throws Exception {
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 54da5f6..96d363a 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -57,8 +57,7 @@
     <string name="all_apps_no_search_results" msgid="3200346862396363786">"<xliff:g id="QUERY">%1$s</xliff:g> sorğusuna uyğun tətbiq tapılmadı"</string>
     <string name="all_apps_search_market_message" msgid="1366263386197059176">"Daha çox tətbiq üçün axtarış edin"</string>
     <string name="label_application" msgid="8531721983832654978">"Tətbiq"</string>
-    <!-- no translation found for all_apps_label (5015784846527570951) -->
-    <skip />
+    <string name="all_apps_label" msgid="5015784846527570951">"Bütün tətbiqlər"</string>
     <string name="notifications_header" msgid="1404149926117359025">"Bildirişlər"</string>
     <string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Qısayolu daşımaq üçün toxunub saxlayın."</string>
     <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Qısayolu daşımaq üçün iki dəfə toxunub saxlayın və ya fərdi əməliyyatlardan istifadə edin."</string>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 2cfa816..92be881 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -57,8 +57,7 @@
     <string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" এর সাথে মেলে এমন কোনো অ্যাপ পাওয়া যায়নি"</string>
     <string name="all_apps_search_market_message" msgid="1366263386197059176">"আরও অ্যাপ্লিকেশানের জন্য খুঁজুন"</string>
     <string name="label_application" msgid="8531721983832654978">"অ্যাপ"</string>
-    <!-- no translation found for all_apps_label (5015784846527570951) -->
-    <skip />
+    <string name="all_apps_label" msgid="5015784846527570951">"সব অ্যাপ"</string>
     <string name="notifications_header" msgid="1404149926117359025">"বিজ্ঞপ্তি"</string>
     <string name="long_press_shortcut_to_add" msgid="5405328730817637737">"একটি শর্টকাট সরাতে টাচ করে ধরে রাখুন।"</string>
     <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"একটি শর্টকাট সরাতে বা কাস্টম অ্যাকশন ব্যবহার করতে ডবল ট্যাপ করে ধরে রাখুন।"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 20e06e1..e884423 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -57,8 +57,7 @@
     <string name="all_apps_no_search_results" msgid="3200346862396363786">"Keine Apps für \"<xliff:g id="QUERY">%1$s</xliff:g>\" gefunden"</string>
     <string name="all_apps_search_market_message" msgid="1366263386197059176">"Weitere Apps suchen"</string>
     <string name="label_application" msgid="8531721983832654978">"App"</string>
-    <!-- no translation found for all_apps_label (5015784846527570951) -->
-    <skip />
+    <string name="all_apps_label" msgid="5015784846527570951">"Alle Apps"</string>
     <string name="notifications_header" msgid="1404149926117359025">"Benachrichtigungen"</string>
     <string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Zum Verschieben einer Verknüpfung berühren und halten"</string>
     <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Doppeltippen und halten, um eine Verknüpfung zu bewegen oder benutzerdefinierte Aktionen zu nutzen."</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 3b85234..e9988c6 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -57,8 +57,7 @@
     <string name="all_apps_no_search_results" msgid="3200346862396363786">"Aucune application trouvée correspondant à « <xliff:g id="QUERY">%1$s</xliff:g> »"</string>
     <string name="all_apps_search_market_message" msgid="1366263386197059176">"Rechercher plus d\'applications"</string>
     <string name="label_application" msgid="8531721983832654978">"Application"</string>
-    <!-- no translation found for all_apps_label (5015784846527570951) -->
-    <skip />
+    <string name="all_apps_label" msgid="5015784846527570951">"Toutes les applications"</string>
     <string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
     <string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Maintenez le doigt sur un raccourci pour le déplacer."</string>
     <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Touchez deux fois un raccourci et maintenez le doigt dessus pour le déplacer ou utiliser des actions personnalisées."</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 46c017c..094af61 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -57,8 +57,7 @@
     <string name="all_apps_no_search_results" msgid="3200346862396363786">"Non se atoparon aplicacións que coincidan con \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
     <string name="all_apps_search_market_message" msgid="1366263386197059176">"Buscar máis aplicacións"</string>
     <string name="label_application" msgid="8531721983832654978">"Aplicación"</string>
-    <!-- no translation found for all_apps_label (5015784846527570951) -->
-    <skip />
+    <string name="all_apps_label" msgid="5015784846527570951">"Todas as aplicacións"</string>
     <string name="notifications_header" msgid="1404149926117359025">"Notificacións"</string>
     <string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Mantén premido un atallo para movelo."</string>
     <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Toca dúas veces un atallo e manteno premido para movelo ou utiliza accións personalizadas."</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index ec8a708..de47dfb 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -57,8 +57,7 @@
     <string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\"થી મેળ ખાતી કોઈ ઍપ્લિકેશનો મળી નથી"</string>
     <string name="all_apps_search_market_message" msgid="1366263386197059176">"વધુ ઍપ્લિકેશનો શોધો"</string>
     <string name="label_application" msgid="8531721983832654978">"ઍપ"</string>
-    <!-- no translation found for all_apps_label (5015784846527570951) -->
-    <skip />
+    <string name="all_apps_label" msgid="5015784846527570951">"બધી ઍપ"</string>
     <string name="notifications_header" msgid="1404149926117359025">"નોટિફિકેશન"</string>
     <string name="long_press_shortcut_to_add" msgid="5405328730817637737">"શૉર્ટકટ ખસેડવા ટચ કરીને થોડી વાર દબાવી રાખો."</string>
     <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"શૉર્ટકટ ખસેડવા બે વાર ટૅપ કરીને દબાવી રાખો અથવા કસ્ટમ ક્રિયાઓનો ઉપયોગ કરો."</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index e6a5aaf..f5c0410 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -57,8 +57,7 @@
     <string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" сұрауына сәйкес келетін қолданбалар жоқ"</string>
     <string name="all_apps_search_market_message" msgid="1366263386197059176">"Қосымша қолданбалар іздеу"</string>
     <string name="label_application" msgid="8531721983832654978">"Қолданба"</string>
-    <!-- no translation found for all_apps_label (5015784846527570951) -->
-    <skip />
+    <string name="all_apps_label" msgid="5015784846527570951">"Барлық қолданба"</string>
     <string name="notifications_header" msgid="1404149926117359025">"Хабарландырулар"</string>
     <string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Таңбашаны жылжыту үшін басып тұрыңыз."</string>
     <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Таңбашаны жылжыту үшін екі рет түртіңіз де, ұстап тұрыңыз немесе арнаулы әрекеттерді пайдаланыңыз."</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index d28272b..fb2da8a 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -57,8 +57,7 @@
     <string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" ସହିତ ମେଳ ହେଉଥିବା କୌଣସି ଆପ୍‌ ମିଳିଲା ନାହିଁ"</string>
     <string name="all_apps_search_market_message" msgid="1366263386197059176">"ଅଧିକ ଆପ୍‌ ଖୋଜନ୍ତୁ"</string>
     <string name="label_application" msgid="8531721983832654978">"ଆପ୍"</string>
-    <!-- no translation found for all_apps_label (5015784846527570951) -->
-    <skip />
+    <string name="all_apps_label" msgid="5015784846527570951">"ସବୁ ଆପ"</string>
     <string name="notifications_header" msgid="1404149926117359025">"ବିଜ୍ଞପ୍ତି"</string>
     <string name="long_press_shortcut_to_add" msgid="5405328730817637737">"ଏକ ସର୍ଟକଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ।"</string>
     <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"ଏକ ସର୍ଟକଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ଦୁଇଥର-ଟାପ୍ କରି ଧରି ରଖନ୍ତୁ କିମ୍ବା କଷ୍ଟମ୍ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 7323c3f..994faf8 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -57,8 +57,7 @@
     <string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" ਨਾਲ ਮੇਲ ਖਾਂਦੀਆਂ ਕੋਈ ਐਪਾਂ ਨਹੀਂ ਮਿਲੀਆਂ"</string>
     <string name="all_apps_search_market_message" msgid="1366263386197059176">"ਹੋਰ ਐਪਾਂ ਖੋਜੋ"</string>
     <string name="label_application" msgid="8531721983832654978">"ਐਪ"</string>
-    <!-- no translation found for all_apps_label (5015784846527570951) -->
-    <skip />
+    <string name="all_apps_label" msgid="5015784846527570951">"ਸਾਰੀਆਂ ਐਪਾਂ"</string>
     <string name="notifications_header" msgid="1404149926117359025">"ਸੂਚਨਾਵਾਂ"</string>
     <string name="long_press_shortcut_to_add" msgid="5405328730817637737">"ਕਿਸੇ ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਲਿਜਾਉਣ ਲਈ ਸਪੱਰਸ਼ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ।"</string>
     <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"ਕਿਸੇ ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਲਿਜਾਉਣ ਲਈ ਡਬਲ ਟੈਪ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ ਜਾਂ ਵਿਉਂਤੀਆਂ ਕਾਰਵਾਈਆਂ ਵਰਤੋ।"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 472ea46..4cc63ed 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -57,8 +57,7 @@
     <string name="all_apps_no_search_results" msgid="3200346862396363786">"找不到與「<xliff:g id="QUERY">%1$s</xliff:g>」相符的應用程式"</string>
     <string name="all_apps_search_market_message" msgid="1366263386197059176">"搜尋更多應用程式"</string>
     <string name="label_application" msgid="8531721983832654978">"應用程式"</string>
-    <!-- no translation found for all_apps_label (5015784846527570951) -->
-    <skip />
+    <string name="all_apps_label" msgid="5015784846527570951">"所有應用程式"</string>
     <string name="notifications_header" msgid="1404149926117359025">"通知"</string>
     <string name="long_press_shortcut_to_add" msgid="5405328730817637737">"按住即可移動捷徑。"</string>
     <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"輕觸兩下並按住即可移動捷徑或使用自訂操作。"</string>
diff --git a/res/values/config.xml b/res/values/config.xml
index 6fdb4de..25911e6 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -136,7 +136,6 @@
     <item name="swipe_up_rect_xy_fling_friction" type="dimen" format="float">1.5</item>
 
     <item name="swipe_up_scale_start"  type="dimen" format="float">0.88</item>
-    <item name="swipe_up_duration"  type="dimen" format="float">400</item>
 
     <item name="swipe_up_trans_y_dp"  type="dimen" format="float">4.5</item>
     <item name="swipe_up_trans_y_dp_per_s" type="dimen" format="float">3</item>
@@ -147,33 +146,10 @@
     <item name="swipe_up_rect_xy_damping_ratio" type="dimen" format="float">0.8</item>
     <item name="swipe_up_rect_xy_stiffness" type="dimen" format="float">200</item>
 
-
-    <item name="swipe_up_rect_2_x_damping_ratio" type="dimen" format="float">1</item>
-    <item name="swipe_up_rect_2_x_stiffness" type="dimen" format="float">250</item>
-
-    <item name="swipe_up_rect_2_y_damping_ratio" type="dimen" format="float">1</item>
-    <item name="swipe_up_rect_2_y_stiffness" type="dimen" format="float">600</item>
-
-    <item name="swipe_up_rect_2_y_stiffness_low_swipe_multiplier" type="dimen" format="float">0.8</item>
     <item name="swipe_up_low_swipe_duration_multiplier"  type="dimen" format="float">1</item>
 
     <item name="swipe_up_launcher_alpha_max_progress" type="dimen" format="float">0.85</item>
 
-
-    <item name="c1_a" type="dimen" format="float">0.05</item>
-    <item name="c1_b" type="dimen" format="float">0</item>
-    <item name="c1_c" type="dimen" format="float">0.133333</item>
-    <item name="c1_d" type="dimen" format="float">0.06</item>
-
-    <item name="mp_x" type="dimen" format="float">0.166666</item>
-    <item name="mp_y" type="dimen" format="float">.4</item>
-
-    <item name="c2_a" type="dimen" format="float">0.208333</item>
-    <item name="c2_b" type="dimen" format="float">.82</item>
-    <item name="c2_c" type="dimen" format="float">.25</item>
-    <item name="c2_d" type="dimen" format="float">1</item>
-
-
     <item name="staggered_damping_ratio" type="dimen" format="float">0.7</item>
     <item name="staggered_stiffness" type="dimen" format="float">150</item>
     <dimen name="unlock_staggered_velocity_dp_per_s">2dp</dimen>
@@ -188,33 +164,14 @@
     <dimen name="swipe_up_max_velocity">7.619dp</dimen>
 
     <array name="dynamic_resources">
-        <item>@dimen/swipe_up_duration</item>
         <item>@dimen/swipe_up_scale_start</item>
         <item>@dimen/swipe_up_trans_y_dp</item>
         <item>@dimen/swipe_up_trans_y_dp_per_s</item>
         <item>@dimen/swipe_up_trans_y_damping</item>
         <item>@dimen/swipe_up_trans_y_stiffness</item>
-        <item>@dimen/swipe_up_rect_2_x_damping_ratio</item>
-        <item>@dimen/swipe_up_rect_2_x_stiffness</item>
-        <item>@dimen/swipe_up_rect_2_y_damping_ratio</item>
-        <item>@dimen/swipe_up_rect_2_y_stiffness</item>
         <item>@dimen/swipe_up_launcher_alpha_max_progress</item>
-        <item>@dimen/swipe_up_rect_2_y_stiffness_low_swipe_multiplier</item>
         <item>@dimen/swipe_up_low_swipe_duration_multiplier</item>
         <item>@dimen/swipe_up_max_velocity</item>
-
-        <item>@dimen/c1_a</item>
-        <item>@dimen/c1_b</item>
-        <item>@dimen/c1_c</item>
-        <item>@dimen/c1_d</item>
-
-        <item>@dimen/mp_x</item>
-        <item>@dimen/mp_y</item>
-
-        <item>@dimen/c2_a</item>
-        <item>@dimen/c2_b</item>
-        <item>@dimen/c2_c</item>
-        <item>@dimen/c2_d</item>
     </array>
 
     <string-array name="filtered_components" ></string-array>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d7a1506..e215c20 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -251,7 +251,7 @@
     <string name="wallpaper_button_text">Wallpapers</string>
     <!-- Text for wallpaper change button [CHAR LIMIT=30]-->
     <string name="styles_wallpaper_button_text">Wallpaper &amp; style</string>
-    <!-- Text for settings button [CHAR LIMIT=30]-->
+    <!-- Text for settings button [CHAR LIMIT=20]-->
     <string name="settings_button_text">Home settings</string>
     <!-- Message shown when a feature is disabled by the administrator -->
     <string name="msg_disabled_by_admin">Disabled by your admin</string>
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index fc717c9..ce06c6e 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -329,6 +329,7 @@
         }
 
         updateWorkspaceScreensPadding();
+        updateWorkspaceWidgetsSizes();
     }
 
     private void updateWorkspaceScreensPadding() {
@@ -360,6 +361,25 @@
         }
     }
 
+    private void updateWorkspaceWidgetsSizes() {
+        int numberOfScreens = mScreenOrder.size();
+        for (int i = 0; i < numberOfScreens; i++) {
+            ShortcutAndWidgetContainer shortcutAndWidgetContainer =
+                    mWorkspaceScreens.get(mScreenOrder.get(i)).getShortcutsAndWidgets();
+            int shortcutsAndWidgetCount = shortcutAndWidgetContainer.getChildCount();
+            for (int j = 0; j < shortcutsAndWidgetCount; j++) {
+                View view = shortcutAndWidgetContainer.getChildAt(j);
+                if (view instanceof LauncherAppWidgetHostView
+                        && view.getTag() instanceof LauncherAppWidgetInfo) {
+                    LauncherAppWidgetInfo launcherAppWidgetInfo =
+                            (LauncherAppWidgetInfo) view.getTag();
+                    WidgetSizes.updateWidgetSizeRanges((LauncherAppWidgetHostView) view,
+                            mLauncher, launcherAppWidgetInfo.spanX, launcherAppWidgetInfo.spanY);
+                }
+            }
+        }
+    }
+
     /**
      * Estimates the size of an item using spans: hSpan, vSpan.
      *
diff --git a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
index 97052b2..dd58123 100644
--- a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
+++ b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
@@ -41,11 +41,10 @@
     }
 
     /**
-     *
      * @param target The view the accessibility event is initialized on.
      *               If null, this method has no effect.
-     * @param type See TYPE_ constants defined in {@link AccessibilityEvent}.
-     * @param text Optional text to add to the event, which will be announced to the user.
+     * @param type   See TYPE_ constants defined in {@link AccessibilityEvent}.
+     * @param text   Optional text to add to the event, which will be announced to the user.
      */
     public static void sendCustomAccessibilityEvent(@Nullable View target, int type,
             @Nullable String text) {
@@ -97,6 +96,16 @@
                 null);
     }
 
+    /**
+     * Notify running tests of a folder opened.
+     */
+    public static void sendFolderOpenedEventToTest(Context context) {
+        final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
+        if (accessibilityManager == null) return;
+
+        sendEventToTest(accessibilityManager, context, TestProtocol.FOLDER_OPENED_MESSAGE, null);
+    }
+
     private static void sendEventToTest(
             AccessibilityManager accessibilityManager,
             Context context, String eventTag, Bundle data) {
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 796c912..1358387 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -233,9 +233,6 @@
     public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag("NOTIFY_CRASHES", false,
             "Sends a notification whenever launcher encounters an uncaught exception.");
 
-    public static final BooleanFlag PROTOTYPE_APP_CLOSE = getDebugFlag(
-            "PROTOTYPE_APP_CLOSE", false, "Enables new app close");
-
     public static final BooleanFlag ENABLE_WALLPAPER_SCRIM = getDebugFlag(
             "ENABLE_WALLPAPER_SCRIM", false,
             "Enables scrim over wallpaper for text protection.");
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 879739f..daef682 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -78,6 +78,7 @@
 import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
 import com.android.launcher3.accessibility.FolderAccessibilityHelper;
 import com.android.launcher3.anim.KeyboardInsetAnimationCallback;
+import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragController.DragListener;
@@ -687,6 +688,7 @@
             public void onAnimationEnd(Animator animation) {
                 mState = STATE_OPEN;
                 announceAccessibilityChanges();
+                AccessibilityManagerCompat.sendFolderOpenedEventToTest(getContext());
 
                 mContent.setFocusOnFirstChild();
             }
@@ -1265,7 +1267,8 @@
 
         PendingAddShortcutInfo pasi = d.dragInfo instanceof PendingAddShortcutInfo
                 ? (PendingAddShortcutInfo) d.dragInfo : null;
-        WorkspaceItemInfo pasiSi = pasi != null ? pasi.activityInfo.createWorkspaceItemInfo() : null;
+        WorkspaceItemInfo pasiSi =
+                pasi != null ? pasi.activityInfo.createWorkspaceItemInfo() : null;
         if (pasi != null && pasiSi == null) {
             // There is no WorkspaceItemInfo, so we have to go through a configuration activity.
             pasi.container = mInfo.id;
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index 97398de..b72f462 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -373,7 +373,7 @@
 
     protected LauncherAtom.ItemInfo.Builder getDefaultItemInfoBuilder() {
         LauncherAtom.ItemInfo.Builder itemBuilder = LauncherAtom.ItemInfo.newBuilder();
-        itemBuilder.setIsWork(user != Process.myUserHandle());
+        itemBuilder.setIsWork(!Process.myUserHandle().equals(user));
         return itemBuilder;
     }
 
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index 5a9c074..17d925c 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -21,6 +21,7 @@
 import android.annotation.TargetApi;
 import android.app.Activity;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Insets;
 import android.os.Build;
 import android.os.Bundle;
@@ -148,6 +149,14 @@
                         TestProtocol.TEST_INFO_RESPONSE_FIELD, TestLogging.sHadEventsNotFromTest);
                 return response;
 
+            case TestProtocol.REQUEST_START_DRAG_THRESHOLD: {
+                final Resources resources = mContext.getResources();
+                response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+                        resources.getDimensionPixelSize(R.dimen.deep_shortcuts_start_drag_threshold)
+                                + resources.getDimensionPixelSize(R.dimen.pre_drag_view_scale));
+                return response;
+            }
+
             default:
                 return null;
         }
@@ -193,6 +202,7 @@
 
     /**
      * Generic interface for setting a fiend in bundle
+     *
      * @param <T> the type of value being set
      */
     public interface BundleSetter<T> {
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 5bf0342..91c7221 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -25,6 +25,7 @@
     public static final String SCROLL_FINISHED_MESSAGE = "TAPL_SCROLL_FINISHED";
     public static final String PAUSE_DETECTED_MESSAGE = "TAPL_PAUSE_DETECTED";
     public static final String DISMISS_ANIMATION_ENDS_MESSAGE = "TAPL_DISMISS_ANIMATION_ENDS";
+    public static final String FOLDER_OPENED_MESSAGE = "TAPL_FOLDER_OPENED";
     public static final int NORMAL_STATE_ORDINAL = 0;
     public static final int SPRING_LOADED_STATE_ORDINAL = 1;
     public static final int OVERVIEW_STATE_ORDINAL = 2;
@@ -99,6 +100,7 @@
     public static final String REQUEST_CLEAR_DATA = "clear-data";
     public static final String REQUEST_IS_TABLET = "is-tablet";
     public static final String REQUEST_IS_TWO_PANELS = "is-two-panel";
+    public static final String REQUEST_START_DRAG_THRESHOLD = "start-drag-threshold";
     public static final String REQUEST_GET_ACTIVITIES_CREATED_COUNT =
             "get-activities-created-count";
     public static final String REQUEST_GET_ACTIVITIES = "get-activities";
@@ -119,7 +121,9 @@
     public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
 
     public static final String PERMANENT_DIAG_TAG = "TaplTarget";
+    public static final String TASKBAR_WINDOW_CRASH = "b/201305599";
     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";
+    public static final String NO_SCREENSHOT = "b/202414125";
 }
diff --git a/src/com/android/launcher3/widget/DeferredAppWidgetHostView.java b/src/com/android/launcher3/widget/DeferredAppWidgetHostView.java
index 9c32e42..57f8bc7 100644
--- a/src/com/android/launcher3/widget/DeferredAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/DeferredAppWidgetHostView.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3.widget;
 
+import android.annotation.SuppressLint;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.Context;
 import android.graphics.Canvas;
@@ -30,6 +31,9 @@
 
 import com.android.launcher3.R;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
 /**
  * A widget host views created while the host has not bind to the system service.
  */
@@ -75,8 +79,22 @@
                 && mSetupTextLayout.getWidth() == availableWidth) {
             return;
         }
-        mSetupTextLayout = new StaticLayout(info.label, mPaint, availableWidth,
-                Layout.Alignment.ALIGN_CENTER, 1, 0, true);
+        try {
+            mSetupTextLayout = new StaticLayout(info.label, mPaint, availableWidth,
+                    Layout.Alignment.ALIGN_CENTER, 1, 0, true);
+        } catch (IllegalArgumentException e) {
+            @SuppressLint("DrawAllocation") StringWriter stringWriter = new StringWriter();
+            @SuppressLint("DrawAllocation") PrintWriter printWriter = new PrintWriter(stringWriter);
+            mActivity.getDeviceProfile().dump(/*prefix=*/"", printWriter);
+            printWriter.flush();
+            String message = "b/203530620 "
+                    + "- availableWidth: " + availableWidth
+                    + ", getMeasuredWidth: " + getMeasuredWidth()
+                    + ", getPaddingLeft: " + getPaddingLeft()
+                    + ", getPaddingRight: " + getPaddingRight()
+                    + ", deviceProfile: " + stringWriter.toString();
+            throw new IllegalArgumentException(message, e);
+        }
     }
 
     @Override
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 0ffbeeb..b3457cd 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -211,7 +211,8 @@
     }
 
     protected TestRule getRulesInsideActivityMonitor() {
-        final RuleChain inner = RuleChain.outerRule(new PortraitLandscapeRunner(this))
+        final RuleChain inner = RuleChain
+                .outerRule(new PortraitLandscapeRunner(this))
                 .around(new FailureWatcher(mDevice, mLauncher));
 
         return TestHelpers.isInLauncherProcess()
@@ -345,13 +346,19 @@
     }
 
     // Cannot be used in TaplTests between a Tapl call injecting a gesture and a tapl call
-    // expecting
-    // the results of that gesture because the wait can hide flakeness.
+    // expecting the results of that gesture because the wait can hide flakeness.
     protected void waitForState(String message, Supplier<LauncherState> state) {
         waitForLauncherCondition(message,
                 launcher -> launcher.getStateManager().getCurrentStableState() == state.get());
     }
 
+    // Cannot be used in TaplTests between a Tapl call injecting a gesture and a tapl call
+    // expecting the results of that gesture because the wait can hide flakeness.
+    protected void waitForStableState(String message, Supplier<LauncherState> state) {
+        waitForLauncherCondition(message,
+                launcher -> launcher.getStateManager().isInStableState(state.get()));
+    }
+
     protected void waitForResumed(String message) {
         waitForLauncherCondition(message, launcher -> launcher.hasBeenResumed());
     }
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 881f50c..f29ac23 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -34,6 +34,8 @@
 import com.android.launcher3.tapl.AppIcon;
 import com.android.launcher3.tapl.AppIconMenu;
 import com.android.launcher3.tapl.AppIconMenuItem;
+import com.android.launcher3.tapl.Folder;
+import com.android.launcher3.tapl.FolderIcon;
 import com.android.launcher3.tapl.Widgets;
 import com.android.launcher3.tapl.Workspace;
 import com.android.launcher3.views.OptionsPopupView;
@@ -369,6 +371,71 @@
         }
     }
 
+    private AppIcon createShortcutIfNotExist(String name) {
+        AppIcon appIcon = mLauncher.getWorkspace().tryGetWorkspaceAppIcon(name);
+        if (appIcon == null) {
+            AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+            allApps.freeze();
+            try {
+                appIcon = allApps.getAppIcon(name);
+                appIcon.dragToWorkspace(false, false);
+            } finally {
+                allApps.unfreeze();
+            }
+            appIcon = mLauncher.getWorkspace().getWorkspaceAppIcon(name);
+        }
+        return appIcon;
+    }
+
+    @Ignore("b/205014516")
+    @Test
+    @PortraitLandscape
+    public void testDragToFolder() throws Exception {
+        final AppIcon playStoreIcon = createShortcutIfNotExist("Play Store");
+        final AppIcon gmailIcon = createShortcutIfNotExist("Gmail");
+
+        FolderIcon folderIcon = gmailIcon.dragToIcon(playStoreIcon);
+
+        Folder folder = folderIcon.open();
+        folder.getAppIcon("Play Store");
+        folder.getAppIcon("Gmail");
+        Workspace workspace = folder.close();
+
+        assertNull("Gmail should be moved to a folder.",
+                workspace.tryGetWorkspaceAppIcon("Gmail"));
+        assertNull("Play Store should be moved to a folder.",
+                workspace.tryGetWorkspaceAppIcon("Play Store"));
+
+        final AppIcon youTubeIcon = createShortcutIfNotExist("YouTube");
+
+        folderIcon = youTubeIcon.dragToIcon(folderIcon);
+        folder = folderIcon.open();
+        folder.getAppIcon("YouTube");
+        folder.close();
+    }
+
+    @Ignore("b/205027405")
+    @Test
+    @PortraitLandscape
+    public void testPressBack() throws Exception {
+        mLauncher.getWorkspace().switchToAllApps();
+        mLauncher.pressBack();
+        mLauncher.getWorkspace();
+        waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
+
+        AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+        allApps.freeze();
+        try {
+            allApps.getAppIcon(APP_NAME).dragToWorkspace(false, false);
+        } finally {
+            allApps.unfreeze();
+        }
+        mLauncher.getWorkspace().getWorkspaceAppIcon(APP_NAME).launch(getAppPackageName());
+        mLauncher.pressBack();
+        mLauncher.getWorkspace();
+        waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
+    }
+
     public static String getAppPackageName() {
         return getInstrumentation().getContext().getPackageName();
     }
diff --git a/tests/src/com/android/launcher3/ui/WorkProfileTest.java b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
index fcb0b7f..2087bfe 100644
--- a/tests/src/com/android/launcher3/ui/WorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import android.util.Log;
 import android.view.View;
 
 import com.android.launcher3.R;
@@ -31,6 +32,7 @@
 import com.android.launcher3.allapps.WorkEduCard;
 import com.android.launcher3.allapps.WorkProfileManager;
 import com.android.launcher3.tapl.LauncherInstrumentation;
+import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 
 import org.junit.After;
 import org.junit.Before;
@@ -51,6 +53,7 @@
         String output =
                 mDevice.executeShellCommand(
                         "pm create-user --profileOf 0 --managed TestProfile");
+        Log.d("b/203817455", "pm create-user; output: " + output);
         assertTrue("Failed to create work profile", output.startsWith("Success"));
 
         String[] tokens = output.split("\\s+");
@@ -84,12 +87,13 @@
     }
 
     @Test
+    @ScreenRecord // b/202735477
     public void workTabExists() {
         mDevice.pressHome();
         waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
-        waitForState("Launcher internal state didn't switch to Normal", () -> NORMAL);
+        waitForStableState("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);
+        waitForStableState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS);
         waitForLauncherCondition("Personal tab is missing",
                 launcher -> launcher.getAppsView().isPersonalTabVisible(),
                 LauncherInstrumentation.WAIT_TIME_MS);
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
index 21099b4..6da59da 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
@@ -16,8 +16,11 @@
 
 package com.android.launcher3.tapl;
 
+import android.graphics.Point;
+import android.graphics.Rect;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
 import androidx.test.uiautomator.By;
 import androidx.test.uiautomator.BySelector;
 import androidx.test.uiautomator.UiObject2;
@@ -29,7 +32,7 @@
 /**
  * App icon, whether in all apps or in workspace/
  */
-public final class AppIcon extends Launchable {
+public final class AppIcon extends Launchable implements FolderDragTarget {
 
     private static final Pattern LONG_CLICK_EVENT = Pattern.compile("onAllAppsItemLongClick");
 
@@ -61,6 +64,29 @@
         }
     }
 
+    /**
+     * Drag the AppIcon to the given position of other icon. The drag must result in a folder.
+     *
+     * @param target the destination icon.
+     */
+    @NonNull
+    public FolderIcon dragToIcon(FolderDragTarget target) {
+        try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+             LauncherInstrumentation.Closable c = mLauncher.addContextLayer("want to drag icon")) {
+            final Rect dropBounds = target.getDropLocationBounds();
+            Workspace.dragIconToWorkspace(
+                    mLauncher, this,
+                    () -> {
+                        final Rect bounds = target.getDropLocationBounds();
+                        return new Point(bounds.centerX(), bounds.centerY());
+                    },
+                    getLongPressIndicator());
+            FolderIcon result = target.getTargetFolder(dropBounds);
+            mLauncher.assertTrue("Can't find the target folder.", result != null);
+            return result;
+        }
+    }
+
     @Override
     protected void addExpectedEventsForLongClick() {
         mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT);
@@ -80,4 +106,20 @@
     protected String launchableType() {
         return "app icon";
     }
+
+    @Override
+    public Rect getDropLocationBounds() {
+        return mLauncher.getVisibleBounds(mObject);
+    }
+
+    @Override
+    public FolderIcon getTargetFolder(Rect bounds) {
+        for (FolderIcon folderIcon : mLauncher.getWorkspace().getFolderIcons()) {
+            final Rect folderIconBounds = folderIcon.getDropLocationBounds();
+            if (bounds.contains(folderIconBounds.centerX(), folderIconBounds.centerY())) {
+                return folderIcon;
+            }
+        }
+        return null;
+    }
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/Folder.java b/tests/tapl/com/android/launcher3/tapl/Folder.java
new file mode 100644
index 0000000..dba308d
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/Folder.java
@@ -0,0 +1,76 @@
+/*
+ * 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.tapl;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.view.MotionEvent;
+
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiObject2;
+
+public class Folder {
+
+    protected static final String FOLDER_CONTENT_RES_ID = "folder_content";
+
+    private final UiObject2 mContainer;
+    private final LauncherInstrumentation mLauncher;
+
+    Folder(LauncherInstrumentation launcher) {
+        this.mLauncher = launcher;
+        this.mContainer = launcher.waitForLauncherObject(FOLDER_CONTENT_RES_ID);
+    }
+
+    /**
+     * Find an app icon with given name or raise assertion error.
+     */
+    @NonNull
+    public AppIcon getAppIcon(String appName) {
+        try (LauncherInstrumentation.Closable ignored = mLauncher.addContextLayer(
+                "Want to get app icon in folder")) {
+            return new AppIcon(mLauncher,
+                    mLauncher.waitForObjectInContainer(
+                            mContainer,
+                            AppIcon.getAppIconSelector(appName, mLauncher)));
+        }
+    }
+
+    private void touchOutsideFolder() {
+        Rect containerBounds = mLauncher.getVisibleBounds(this.mContainer);
+        final long downTime = SystemClock.uptimeMillis();
+        Point containerLeftTopCorner = new Point(containerBounds.left - 1, containerBounds.top - 1);
+        mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN,
+                containerLeftTopCorner, LauncherInstrumentation.GestureScope.INSIDE);
+        mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP,
+                containerLeftTopCorner, LauncherInstrumentation.GestureScope.INSIDE);
+    }
+
+    /**
+     * CLose opened folder if possible. It throws assertion error if the folder is already closed.
+     */
+    public Workspace close() {
+        try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+             LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+                     "Want to close opened folder")) {
+            mLauncher.waitForLauncherObject(FOLDER_CONTENT_RES_ID);
+            touchOutsideFolder();
+            mLauncher.waitUntilLauncherObjectGone(FOLDER_CONTENT_RES_ID);
+            return mLauncher.getWorkspace();
+        }
+    }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/FolderDragTarget.java b/tests/tapl/com/android/launcher3/tapl/FolderDragTarget.java
new file mode 100644
index 0000000..d797418
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/FolderDragTarget.java
@@ -0,0 +1,25 @@
+/*
+ * 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.tapl;
+
+import android.graphics.Rect;
+
+public interface FolderDragTarget {
+    Rect getDropLocationBounds();
+
+    FolderIcon getTargetFolder(Rect bounds);
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/FolderIcon.java b/tests/tapl/com/android/launcher3/tapl/FolderIcon.java
new file mode 100644
index 0000000..2e79d70
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/FolderIcon.java
@@ -0,0 +1,64 @@
+/*
+ * 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.tapl;
+
+import android.graphics.Rect;
+
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiObject2;
+
+import com.android.launcher3.testing.TestProtocol;
+
+/**
+ * Folder Icon, an app folder in workspace.
+ */
+public class FolderIcon implements FolderDragTarget {
+
+    protected final UiObject2 mObject;
+    protected final LauncherInstrumentation mLauncher;
+
+    FolderIcon(LauncherInstrumentation launcher, UiObject2 icon) {
+        mObject = icon;
+        mLauncher = launcher;
+    }
+
+    /**
+     * Open and return a folder or raise assertion error.
+     */
+    @NonNull
+    public Folder open() {
+        try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+             LauncherInstrumentation.Closable c = mLauncher.addContextLayer("open folder")) {
+            mLauncher.executeAndWaitForLauncherEvent(() -> mLauncher.clickLauncherObject(mObject),
+                    event -> TestProtocol.FOLDER_OPENED_MESSAGE.equals(
+                            event.getClassName().toString()),
+                    () -> "Fail to open folder.",
+                    "open folder");
+        }
+        return new Folder(mLauncher);
+    }
+
+    @Override
+    public Rect getDropLocationBounds() {
+        return mLauncher.getVisibleBounds(mObject.getParent());
+    }
+
+    @Override
+    public FolderIcon getTargetFolder(Rect bounds) {
+        return this;
+    }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 7ffdf4c..e2d0238 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -21,6 +21,7 @@
 import static android.content.pm.PackageManager.MATCH_ALL;
 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
 
+import static com.android.launcher3.tapl.Folder.FOLDER_CONTENT_RES_ID;
 import static com.android.launcher3.tapl.TestHelpers.getOverviewPackageName;
 import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
 
@@ -75,11 +76,13 @@
 import java.io.IOException;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Deque;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.function.Consumer;
@@ -108,6 +111,9 @@
     static final Pattern EVENT_TOUCH_DOWN_TIS = getTouchEventPatternTIS("ACTION_DOWN");
     static final Pattern EVENT_TOUCH_UP_TIS = getTouchEventPatternTIS("ACTION_UP");
 
+    static final Pattern EVENT_KEY_BACK_DOWN = getKeyEventPattern("ACTION_DOWN", "KEYCODE_BACK");
+    static final Pattern EVENT_KEY_BACK_UP = getKeyEventPattern("ACTION_UP", "KEYCODE_BACK");
+
     private final String mLauncherPackage;
     private Boolean mIsLauncher3;
     private long mTestStartTime = -1;
@@ -123,7 +129,8 @@
     // Where the gesture happens: outside of Launcher, inside or from inside to outside and
     // whether the gesture recognition triggers pilfer.
     public enum GestureScope {
-        OUTSIDE_WITHOUT_PILFER, OUTSIDE_WITH_PILFER, INSIDE, INSIDE_TO_OUTSIDE
+        OUTSIDE_WITHOUT_PILFER, OUTSIDE_WITH_PILFER, INSIDE, INSIDE_TO_OUTSIDE,
+        INSIDE_TO_OUTSIDE_WITHOUT_PILFER,
     }
 
     // Base class for launcher containers.
@@ -193,6 +200,10 @@
         return getTouchEventPattern("TouchInteractionService.onInputEvent", action);
     }
 
+    private static Pattern getKeyEventPattern(String action, String keyCode) {
+        return Pattern.compile("Key event: KeyEvent.*action=" + action + ".*keyCode=" + keyCode);
+    }
+
     /**
      * Constructs the root of TAPL hierarchy. You get all other objects from it.
      */
@@ -768,6 +779,47 @@
     }
 
     /**
+     * Get the resource ID of visible floating view.
+     */
+    private Optional<String> getFloatingResId() {
+        if (hasLauncherObject(CONTEXT_MENU_RES_ID)) {
+            return Optional.of(CONTEXT_MENU_RES_ID);
+        }
+        if (hasLauncherObject(FOLDER_CONTENT_RES_ID)) {
+            return Optional.of(FOLDER_CONTENT_RES_ID);
+        }
+        return Optional.empty();
+    }
+
+    /**
+     * Using swiping up gesture to dismiss closable floating views, such as Menu or Folder Content.
+     */
+    private void swipeUpToCloseFloatingView(boolean gestureStartFromLauncher) {
+        final Point displaySize = getRealDisplaySize();
+
+        final Optional<String> floatingRes = getFloatingResId();
+
+        if (!floatingRes.isPresent()) {
+            return;
+        }
+
+        GestureScope gestureScope = gestureStartFromLauncher
+                ? (isTablet() ? GestureScope.INSIDE : GestureScope.INSIDE_TO_OUTSIDE)
+                : GestureScope.OUTSIDE_WITH_PILFER;
+        linearGesture(
+                displaySize.x / 2, displaySize.y - 1,
+                displaySize.x / 2, 0,
+                ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME,
+                false, gestureScope);
+
+        try (LauncherInstrumentation.Closable c1 = addContextLayer(
+                String.format("Swiped up from floating view %s to home", floatingRes.get()))) {
+            waitUntilLauncherObjectGone(floatingRes.get());
+            waitForLauncherObject(getAnyObjectSelector());
+        }
+    }
+
+    /**
      * Presses nav bar home button.
      *
      * @return the Workspace object.
@@ -791,21 +843,9 @@
                         ? !isLauncher3() || hasLauncherObject(WORKSPACE_RES_ID)
                         : isLauncherVisible();
 
-                if (hasLauncherObject(CONTEXT_MENU_RES_ID)) {
-                    GestureScope gestureScope = gestureStartFromLauncher
-                            ? (isTablet() ? GestureScope.INSIDE : GestureScope.INSIDE_TO_OUTSIDE)
-                            : GestureScope.OUTSIDE_WITH_PILFER;
-                    linearGesture(
-                            displaySize.x / 2, displaySize.y - 1,
-                            displaySize.x / 2, 0,
-                            ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME,
-                            false, gestureScope);
-                    try (LauncherInstrumentation.Closable c1 = addContextLayer(
-                            "Swiped up from context menu to home")) {
-                        waitUntilLauncherObjectGone(CONTEXT_MENU_RES_ID);
-                        waitForLauncherObject(getAnyObjectSelector());
-                    }
-                }
+                // CLose floating views before going back to home.
+                swipeUpToCloseFloatingView(gestureStartFromLauncher);
+
                 if (hasLauncherObject(WORKSPACE_RES_ID)) {
                     log(action = "already at home");
                 } else {
@@ -848,6 +888,38 @@
         }
     }
 
+    /**
+     * Press navbar back button or swipe back if in gesture navigation mode.
+     */
+    public void pressBack() {
+        try (Closable e = eventsCheck(); Closable c = addContextLayer("want to press back")) {
+            waitForLauncherInitialized();
+            final boolean launcherVisible =
+                    isTablet() ? isLauncherContainerVisible() : isLauncherVisible();
+            if (getNavigationModel() == NavigationModel.ZERO_BUTTON) {
+                final Point displaySize = getRealDisplaySize();
+                final GestureScope gestureScope =
+                        launcherVisible ? GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER
+                                : GestureScope.OUTSIDE_WITHOUT_PILFER;
+                linearGesture(0, displaySize.y / 2, displaySize.x / 2, displaySize.y / 2,
+                        10, false, gestureScope);
+            } else {
+                waitForNavigationUiObject("back").click();
+                if (isTablet()) {
+                    expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
+                    expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_UP);
+                } else if (!isLauncher3() && getNavigationModel() == NavigationModel.TWO_BUTTON) {
+                    expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
+                    expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
+                }
+            }
+            if (launcherVisible) {
+                expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_KEY_BACK_DOWN);
+                expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_KEY_BACK_UP);
+            }
+        }
+    }
+
     private static BySelector getAnyObjectSelector() {
         return By.textStartsWith("");
     }
@@ -857,6 +929,11 @@
         return hasLauncherObject(getAnyObjectSelector());
     }
 
+    boolean isLauncherContainerVisible() {
+        final String[] containerResources = {WORKSPACE_RES_ID, OVERVIEW_RES_ID, APPS_RES_ID};
+        return Arrays.stream(containerResources).anyMatch(r -> hasLauncherObject(r));
+    }
+
     /**
      * Gets the Workspace object if the current state is "active home", i.e. workspace. Fails if the
      * launcher is not in that state.
@@ -1383,6 +1460,7 @@
                 break;
             case MotionEvent.ACTION_UP:
                 if (notLauncher3 && gestureScope != GestureScope.INSIDE
+                        && gestureScope != GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER
                         && (gestureScope == GestureScope.OUTSIDE_WITH_PILFER
                         || gestureScope == GestureScope.INSIDE_TO_OUTSIDE)) {
                     expectEvent(TestProtocol.SEQUENCE_PILFER, EVENT_PILFER_POINTERS);
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 288c853..0145690 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -36,7 +36,10 @@
 
 import com.android.launcher3.testing.TestProtocol;
 
+import java.util.List;
+import java.util.function.Supplier;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 /**
  * Operations on the workspace screen.
@@ -170,40 +173,100 @@
                 mHotseat, AppIcon.getAppIconSelector(appName, mLauncher)));
     }
 
-    static void dragIconToWorkspace(
-            LauncherInstrumentation launcher, Launchable launchable, Point dest,
-            String longPressIndicator, boolean startsActivity, boolean isWidgetShortcut,
-            Runnable expectLongClickEvents) {
-        LauncherInstrumentation.log("dragIconToWorkspace: begin");
-        final Point launchableCenter = launchable.getObject().getVisibleCenter();
-        final long downTime = SystemClock.uptimeMillis();
-        launcher.runToState(
-                () -> {
-                    launcher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN,
-                            launchableCenter, LauncherInstrumentation.GestureScope.INSIDE);
-                    LauncherInstrumentation.log("dragIconToWorkspace: sent down");
-                    expectLongClickEvents.run();
-                    launcher.waitForLauncherObject(longPressIndicator);
-                    LauncherInstrumentation.log("dragIconToWorkspace: indicator");
-                    launcher.movePointer(launchableCenter, dest, 10, downTime, true,
-                            LauncherInstrumentation.GestureScope.INSIDE);
-                },
-                SPRING_LOADED_STATE_ORDINAL,
-                "long-pressing and moving");
-        LauncherInstrumentation.log("dragIconToWorkspace: moved pointer");
+    private static int getStartDragThreshold(LauncherInstrumentation launcher) {
+        return launcher.getTestInfo(TestProtocol.REQUEST_START_DRAG_THRESHOLD).getInt(
+                TestProtocol.TEST_INFO_RESPONSE_FIELD);
+    }
+
+    /**
+     * Finds folder icons in the current workspace.
+     *
+     * @return a list of folder icons.
+     */
+    List<FolderIcon> getFolderIcons() {
+        final UiObject2 workspace = verifyActiveContainer();
+        return mLauncher.getObjectsInContainer(workspace, "folder_icon_name").stream().map(
+                o -> new FolderIcon(mLauncher, o)).collect(Collectors.toList());
+    }
+
+    /**
+     * Drag an icon up with a short distance that makes workspace go to spring loaded state.
+     *
+     * @return the position after dragging.
+     */
+    private static Point dragIconToSpringLoaded(LauncherInstrumentation launcher, long downTime,
+            UiObject2 icon,
+            String longPressIndicator, Runnable expectLongClickEvents) {
+        final Point iconCenter = icon.getVisibleCenter();
+        final Point dragStartCenter = new Point(iconCenter.x,
+                iconCenter.y - getStartDragThreshold(launcher));
+
+        launcher.runToState(() -> {
+            launcher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN,
+                    iconCenter, LauncherInstrumentation.GestureScope.INSIDE);
+            LauncherInstrumentation.log("dragIconToSpringLoaded: sent down");
+            expectLongClickEvents.run();
+            launcher.waitForLauncherObject(longPressIndicator);
+            LauncherInstrumentation.log("dragIconToSpringLoaded: indicator");
+            launcher.movePointer(iconCenter, dragStartCenter, 10, downTime, true,
+                    LauncherInstrumentation.GestureScope.INSIDE);
+        }, SPRING_LOADED_STATE_ORDINAL, "long-pressing and triggering drag start");
+        return dragStartCenter;
+    }
+
+    private static void dropDraggedIcon(LauncherInstrumentation launcher, Point dest, long downTime,
+            @Nullable Runnable expectedEvents) {
         launcher.runToState(
                 () -> launcher.sendPointer(
                         downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, dest,
                         LauncherInstrumentation.GestureScope.INSIDE),
                 NORMAL_STATE_ORDINAL,
                 "sending UP event");
-        if (startsActivity || isWidgetShortcut) {
-            launcher.expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START);
+        if (expectedEvents != null) {
+            expectedEvents.run();
         }
-        LauncherInstrumentation.log("dragIconToWorkspace: end");
+        LauncherInstrumentation.log("dropIcon: end");
         launcher.waitUntilLauncherObjectGone("drop_target_bar");
     }
 
+    static void dragIconToWorkspace(LauncherInstrumentation launcher, Launchable launchable,
+            Point dest, String longPressIndicator, boolean startsActivity, boolean isWidgetShortcut,
+            Runnable expectLongClickEvents) {
+        Runnable expectDropEvents = null;
+        if (startsActivity || isWidgetShortcut) {
+            expectDropEvents = () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN,
+                    LauncherInstrumentation.EVENT_START);
+        }
+        dragIconToWorkspace(launcher, launchable, () -> dest, longPressIndicator,
+                expectLongClickEvents, expectDropEvents);
+    }
+
+    /**
+     * Drag icon in workspace to else where.
+     * This function expects the launchable is inside the workspace and there is no drop event.
+     */
+    static void dragIconToWorkspace(LauncherInstrumentation launcher, Launchable launchable,
+            Supplier<Point> destSupplier, String longPressIndicator) {
+        dragIconToWorkspace(launcher, launchable, destSupplier, longPressIndicator,
+                () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT), null);
+    }
+
+    static void dragIconToWorkspace(
+            LauncherInstrumentation launcher, Launchable launchable, Supplier<Point> dest,
+            String longPressIndicator, Runnable expectLongClickEvents,
+            @Nullable Runnable expectDropEvents) {
+        try (LauncherInstrumentation.Closable ignored = launcher.addContextLayer(
+                "want to drag icon to workspace")) {
+            final long downTime = SystemClock.uptimeMillis();
+            final Point dragStartCenter = dragIconToSpringLoaded(launcher, downTime,
+                    launchable.getObject(), longPressIndicator, expectLongClickEvents);
+            final Point targetDest = dest.get();
+            launcher.movePointer(dragStartCenter, targetDest, 10, downTime, true,
+                    LauncherInstrumentation.GestureScope.INSIDE);
+            dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents);
+        }
+    }
+
     /**
      * Flings to get to screens on the right. Waits for scrolling and a possible overscroll
      * recoil to complete.