Merge "Utilities.trim never returns null."
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index 382ef36..dd6ad48 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Programgebruikinstellings"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Vee alles uit"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Onlangse programme"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minuut"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> oor vandag"</string>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index a80bcb8..1577335 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"የመተግበሪያ አጠቃቀም ቅንብሮች"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ሁሉንም አጽዳ"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"የቅርብ ጊዜ መተግበሪያዎች"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 ደቂቃ"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"ዛሬ <xliff:g id="TIME">%1$s</xliff:g> ቀርቷል"</string>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index fd34873..602b3e1 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"إعدادات استخدام التطبيق"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"محو الكل"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"التطبيقات المستخدمة مؤخرًا"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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">"أقل من دقيقة"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"يتبقى اليوم <xliff:g id="TIME">%1$s</xliff:g>."</string>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index a10a0fc..adb4bae 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"এপে ব্যৱহাৰ কৰা ডেটাৰ ছেটিং"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"আটাইবোৰ মচক"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"শেহতীয়া এপসমূহ"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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>
     <string name="time_left_for_app" msgid="3111996412933644358">"আজি <xliff:g id="TIME">%1$s</xliff:g> বাকী আছ"</string>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index d3b8e5a..a2050f3 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Tətbiq istifadə ayarları"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Hamısını silin"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Son tətbiqlər"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 dəq"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Bu gün <xliff:g id="TIME">%1$s</xliff:g> qaldı"</string>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index dc95a00..b064af9 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Podešavanja korišćenja aplikacije"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Obriši sve"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedavne aplikacije"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Još <xliff:g id="TIME">%1$s</xliff:g> danas"</string>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 82b4c30..672e901 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Налады выкарыстання праграмы"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Ачысціць усё"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Нядаўнія праграмы"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 хв"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Сёння засталося <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index 3ee50dc..65a1f07 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Настройки за използването на приложенията"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Изчистване на всички"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Скорошни приложения"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 мин"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Оставащо време днес: <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index e05a495..5f05f4e 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"অ্যাপ ব্যবহারের সেটিংস"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"সবকিছু খালি করুন"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"সম্প্রতি ব্যবহৃত অ্যাপ"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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>
     <string name="time_left_for_app" msgid="3111996412933644358">"আজকে <xliff:g id="TIME">%1$s</xliff:g> বাকি আছে"</string>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 3a2cc55..7de9d91 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Postavke korištenja aplikacije"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Obriši sve"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedavne aplikacije"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Preostalo vrijeme: <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index 2c1ccd1..a83c8d9 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuració d\'ús d\'aplicacions"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Esborra-ho tot"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplicacions recents"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minut"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"temps restant avui: <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index ccf0dbb..92f8cc4 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Nastavení využití aplikací"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Vymazat vše"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Poslední aplikace"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minuta"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"dnes zbývá: <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index e21899a..9f2af7f 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Indstillinger for appforbrug"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Ryd alt"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Seneste apps"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> tilbage i dag"</string>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 2d7da93..75fee4b 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Einstellungen zur App-Nutzung"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Alle Apps schließen"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Kürzlich geöffnete Apps"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 Min."</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Heute noch <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 89c1ff2..9f49b99 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ρυθμίσεις χρήσης εφαρμογής"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Διαγραφή όλων"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Πρόσφατες εφαρμογές"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 λ."</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> σήμερα"</string>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index adeb2ea..9acc708 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minute"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> left today"</string>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index adeb2ea..9acc708 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minute"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> left today"</string>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index adeb2ea..9acc708 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minute"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> left today"</string>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index adeb2ea..9acc708 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minute"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> left today"</string>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index 31a637a..9f1cfe2 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -25,6 +25,7 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‏‎‎‏‏‎‏‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎App usage settings‎‏‎‎‏‎"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎Clear all‎‏‎‎‏‎"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‏‏‎Recent apps‎‏‎‎‏‎"</string>
+    <string name="task_view_closed" msgid="9170038230110856166">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎Task Closed‎‏‎‎‏‎"</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; 1 minute‎‏‎‎‏‎"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left today‎‏‎‎‏‎"</string>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 39f4645..0fe634c 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuración de uso de la app"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Borrar todo"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Apps recientes"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minuto"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Tiempo restante: <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index aea3c48..667dd99 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ajustes de uso de la aplicación"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Borrar todo"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplicaciones recientes"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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;1 minuto"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"tiempo restante: <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index d637aae..212976c 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Rakenduse kasutuse seaded"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Sule kõik"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Hiljutised rakendused"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minut"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Tääna jäänud <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index 60698fc..c6b0688 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Aplikazioen erabileraren ezarpenak"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Garbitu guztiak"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Azken aplikazioak"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> gelditzen dira gaur"</string>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index 2f046f7..5f6b278 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"تنظیمات استفاده از برنامه"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"پاک کردن همه"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"برنامه‌های اخیر"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> باقی‌مانده برای امروز"</string>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index 0e0542c..866e2d0 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Sovelluksen käyttöasetukset"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Poista kaikki"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Viimeisimmät sovellukset"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> jäljellä tänään"</string>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 0d0324d..27b22ee 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Paramètres d\'utilisation de l\'application"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Tout effacer"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Applications récentes"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Il reste <xliff:g id="TIME">%1$s</xliff:g> aujourd\'hui"</string>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 041b801..fdfb9f2 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Paramètres de consommation de l\'application"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Tout effacer"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Applications récentes"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Encore <xliff:g id="TIME">%1$s</xliff:g> aujourd\'hui"</string>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 46f92c8..ab3382f 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuración do uso de aplicacións"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Borrar todo"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Apps recentes"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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;1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Tempo restante hoxe <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 0148a36..d965ff8 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ઍપ વપરાશનું સેટિંગ"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"બધું સાફ કરો"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"તાજેતરની ઍપ"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 મિનિટ"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> આજે બાકી"</string>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index 72a0faa..b79cb02 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ऐप्लिकेशन इस्तेमाल की सेटिंग"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"सभी ऐप्लिकेशन बंद करें"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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;1 मिनट"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"आज <xliff:g id="TIME">%1$s</xliff:g> और चलेगा"</string>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index bbc0e90..1767c8f 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Postavke upotrebe aplikacija"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Izbriši sve"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedavne aplikacije"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Još <xliff:g id="TIME">%1$s</xliff:g> danas"</string>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 2674937..3ac0128 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Alkalmazáshasználati beállítások"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Összes törlése"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Legutóbbi alkalmazások"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 perc"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Ma még <xliff:g id="TIME">%1$s</xliff:g> van hátra"</string>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 2183662..b478137 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Հավելվածի օգտագործման կարգավորումներ"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Փակել բոլորը"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Վերջին օգտագործած հավելվածները"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 ր"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Այսօր մնացել է՝ <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 0960537..1ac69c1 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Setelan penggunaan aplikasi"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Hapus semua"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplikasi terbaru"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 menit"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> tersisa hari ini"</string>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 50231b1..3ef2f31 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Notkunarstillingar forrits"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Hreinsa allt"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Nýleg forrit"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 mín."</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> eftir í dag"</string>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index b4b2803..e44175d 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Impostazioni di utilizzo delle app"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Cancella tutto"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"App recenti"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Rimanente oggi: <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 19de478..5313280 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"הגדרות שימוש באפליקציה"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ניקוי הכול"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"אפליקציות אחרונות"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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>
     <string name="time_left_for_app" msgid="3111996412933644358">"הזמן שנותר להיום: <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index bd86a92..3d91d05 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"アプリの使用状況の設定"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"すべてクリア"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"最近使ったアプリ"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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">"1 分未満"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"今日はあと <xliff:g id="TIME">%1$s</xliff:g>です"</string>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index 536ed38..eb2dc94 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"აპების გამოყენების პარამეტრები"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ყველას გასუფთავება"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"ბოლოდროინდელი აპები"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 წუთი"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"დღეს დარჩენილია <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index ac56c89..538fb59 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Қолданбаны пайдалану параметрлері"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Барлығын өшіру"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Соңғы пайдаланылған қолданбалар"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 мин"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Бүгін <xliff:g id="TIME">%1$s</xliff:g> қалды"</string>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index 2926611..7402776 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ការកំណត់​ការប្រើប្រាស់​កម្មវិធី"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"សម្អាត​ទាំងអស់"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"កម្មវិធី​ថ្មីៗ"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 នាទី"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"នៅសល់ <xliff:g id="TIME">%1$s</xliff:g> ទៀត​នៅថ្ងៃនេះ"</string>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index d1e247e..5ec6df7 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ಆ್ಯಪ್‌ ಬಳಕೆಯ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"ಇತ್ತೀಚಿನ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 ನಿ"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"ಇಂದು <xliff:g id="TIME">%1$s</xliff:g> ಸಮಯ ಉಳಿದಿದೆ"</string>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index aa29046..45643e7 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"앱 사용 설정"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"모두 삭제"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"최근 앱"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1분"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"오늘 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index ba6094f..e562f93 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Колдонмону пайдалануу жөндөөлөрү"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Баарын тазалоо"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Акыркы колдонмолор"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 мүнөт"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Бүгүн <xliff:g id="TIME">%1$s</xliff:g> мүнөт калды"</string>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index 02aaed0..04939fc 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ການຕັ້ງຄ່າການນຳໃຊ້ແອັບ"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ລຶບລ້າງທັງໝົດ"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"ແອັບຫຼ້າສຸດ"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 ນາທີ"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"ເຫຼືອ <xliff:g id="TIME">%1$s</xliff:g> ມື້ນີ້"</string>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index a83e2f6..c9b0919 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Programos naudojimo nustatymai"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Išvalyti viską"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Naujausios programos"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min."</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Šiandien liko: <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index a054f41..6bd8f5e 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Lietotņu izmantošanas iestatījumi"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Notīrīt visu"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Pēdējās izmantotās lietotnes"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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;1 minūte"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Šodien atlicis: <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index 5d1dde8..250c11c 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Поставки за користење на апликациите"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Избриши ги сите"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Неодамнешни апликации"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 минута"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Уште <xliff:g id="TIME">%1$s</xliff:g> за денес"</string>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index 10ef7f9..19c3985 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ആപ്പ് ഉപയോഗ ക്രമീകരണം"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"എല്ലാം മായ്‌ക്കുക"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"സമീപകാല ആപ്പുകൾ"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 മിനിറ്റ്"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"ഇന്ന് <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 2b61e8c..4ac7c17 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Апп ашиглалтын тохиргоо"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Бүгдийг устгах"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Саяхны аппууд"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 минут"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Өнөөдөр <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index d31a070..8b505dd 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"अ‍ॅप वापर सेटिंग्ज"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"सर्व साफ करा"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"अलीकडील अ‍ॅप्स"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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">"१मिहून कमी"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"आज <xliff:g id="TIME">%1$s</xliff:g>शिल्लक आहे"</string>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 6ef116a..da81382 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Tetapan penggunaan apl"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Kosongkan semua"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Apl terbaharu"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minit"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> lagi hari ini"</string>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index 921252f..675a53e 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"အက်ပ်အသုံးပြုမှု ဆက်တင်များ"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"အားလုံးရှင်းရန်"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"လတ်တလောသုံး အက်ပ်များ"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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>
     <string name="time_left_for_app" msgid="3111996412933644358">"ယနေ့ <xliff:g id="TIME">%1$s</xliff:g> ခု ကျန်သည်"</string>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index 5065a2d..8a789e1 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Innstillinger for appbruk"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Fjern alt"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Nylige apper"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minutt"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> gjenstår i dag"</string>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index b90a573..6e7e6e8 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"एपको उपयोगका सेटिङहरू"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"सबै मेटाउनुहोस्"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"हालसालैका एपहरू"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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>
     <string name="time_left_for_app" msgid="3111996412933644358">"आज: <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index da36ff5..e7af211 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Instellingen voor app-gebruik"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Alles wissen"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Recente apps"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minuut"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Nog <xliff:g id="TIME">%1$s</xliff:g> vandaag"</string>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 1ec4804..e3f1f77 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ଆପ୍‍ ବ୍ୟବହାର ସେଟିଂସ୍‍"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ସବୁ ଖାଲି କରନ୍ତୁ"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"ବର୍ତ୍ତମାନର ଆପ୍‌"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 ମିନିଟ୍"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"ଆଜି <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index d42ac0d..48098a5 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ਐਪ ਵਰਤੋਂ ਦੀਆਂ ਸੈਟਿੰਗਾਂ"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ਸਭ ਕਲੀਅਰ ਕਰੋ"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"ਹਾਲੀਆ ਐਪਾਂ"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 ਮਿੰਟ"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"ਅੱਜ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 00c9a18..f0b9566 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ustawienia użycia aplikacji"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Wyczyść wszystko"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Ostatnie aplikacje"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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">"&gt; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Na dziś zostało <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index f58971a..407edb7 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Definições de utilização de aplicações"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Limpar tudo"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Apps recentes"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minuto"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Resta(m) <xliff:g id="TIME">%1$s</xliff:g> hoje."</string>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index 893795c..eb9e794 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configurações de uso do app"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Limpar tudo"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Apps recentes"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> restante(s) hoje"</string>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index cb82841..89589a1 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Setări de utilizare a aplicației"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Ștergeți tot"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplicații recente"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minut"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Au mai rămas <xliff:g id="TIME">%1$s</xliff:g> astăzi"</string>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index d07308d..0baa02c 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Настройки использования приложения"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Очистить все"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Недавние приложения"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 мин."</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Осталось сегодня: <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index eff3541..b72aca4 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"යෙදුම් භාවිත සැකසීම්"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"සියල්ල හිස් කරන්න"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"මෑත යෙදුම්"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 විනාඩියක්"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"අද <xliff:g id="TIME">%1$s</xliff:g>ක් ඉතුරුයි"</string>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index dc4b4c6..c03ffd5 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Nastavenia využívania aplikácie"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Vymazať všetko"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedávne aplikácie"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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">"Menej ako 1 minúta"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Dnes ešte zostáva: <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index ed2b5e5..61368f5 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Nastavitve uporabe aplikacij"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Počisti vse"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedavne aplikacije"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Danes je ostalo še <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index 0145239..6dbf712 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Cilësimet e përdorimit të aplikacionit"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Pastroji të gjitha"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplikacionet e fundit"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 minutë"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura sot"</string>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index cf7c6be..db6c2b4 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Подешавања коришћења апликације"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Обриши све"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Недавне апликације"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 мин"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Још <xliff:g id="TIME">%1$s</xliff:g> данас"</string>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index dc49054..0ae3ca0 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Inställningar för appanvändning"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Rensa alla"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Senaste apparna"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> kvar i dag"</string>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index 0e901bf..287635a 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Mipangilio ya matumizi ya programu"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Ondoa zote"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Programu za hivi karibuni"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; dak 1"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Umebakisha <xliff:g id="TIME">%1$s</xliff:g> leo"</string>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index 41c8df3..c67b6b7 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ஆப்ஸ் உபயோக அமைப்புகள்"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"எல்லாம் அழி"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"சமீபத்திய ஆப்ஸ்"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 நி"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"இன்று <xliff:g id="TIME">%1$s</xliff:g> மீதமுள்ளது"</string>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index 64b4b37..19236e9 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"యాప్ వినియోగ సెట్టింగ్‌లు"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"అన్నీ తీసివేయండి"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"ఇటీవలి యాప్‌లు"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 నిమిషం"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"నేటికి <xliff:g id="TIME">%1$s</xliff:g> మిగిలి ఉంది"</string>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 834b751..d91c016 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"การตั้งค่าการใช้แอป"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ล้างทั้งหมด"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"แอปล่าสุด"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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;1 นาที"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"วันนี้เหลืออีก <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index 6449bed..cc457c0 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Mga setting ng paggamit ng app"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"I-clear lahat"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Mga kamakailang app"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 min"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> na lang ngayon"</string>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 8933000..e0ef9b7 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Uygulama kullanım ayarları"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Tümünü temizle"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Son uygulamalar"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 dk."</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Bugün <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 1a521b8..e376938 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Налаштування використання додатка"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Очистити все"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Нещодавні додатки"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 хв"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Сьогодні залишилося <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index f5e51a8..380d470 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ایپ کے استعمال کی ترتیبات"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"سبھی کو صاف کریں"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"حالیہ ایپس"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 منٹ"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"آج <xliff:g id="TIME">%1$s</xliff:g> بچا ہے"</string>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 1e22693..9374fc7 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ilovadan foydalanish sozlamalari"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Hammasini tozalash"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Yaqinda ishlatilgan ilovalar"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 daqiqa"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Bugun <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index ad79a32..12cf3cb 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Cài đặt mức sử dụng ứng dụng"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Xóa tất cả"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Ứng dụng gần đây"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 phút"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"Hôm nay còn <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index 34d4bc8..8c05499 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"应用使用设置"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"全部清除"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"最近用过的应用"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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">"不到 1 分钟"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"今天还可使用 <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index 1487051..a0d95c9 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"應用程式使用情況設定"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"全部清除"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"最近使用的應用程式"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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">"少於 1 分鐘"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"今天剩餘時間:<xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index 67906d1..45e2f75 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"應用程式使用情況設定"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"全部清除"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"最近使用的應用程式"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 分鐘"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"今天還能使用 <xliff:g id="TIME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index ccb9341..85c43ed 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -25,6 +25,8 @@
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Izilungiselelo zokusetshenziswa kohlelo lokusebenza"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Sula konke"</string>
     <string name="accessibility_recent_apps" msgid="4058661986695117371">"Izinhlelo zokusebenza zakamuva"</string>
+    <!-- no translation found for task_view_closed (9170038230110856166) -->
+    <skip />
     <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; 1 iminithi"</string>
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> esele namhlanje"</string>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 0e5ba2f..a52e480 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -234,7 +234,7 @@
     <dimen name="taskbar_nav_buttons_width_kids">88dp</dimen>
     <dimen name="taskbar_nav_buttons_height_kids">40dp</dimen>
     <dimen name="taskbar_nav_buttons_corner_radius_kids">40dp</dimen>
-    <dimen name="taskbar_back_button_left_margin_kids">96dp</dimen>
+    <dimen name="taskbar_back_button_left_margin_kids">48dp</dimen>
     <dimen name="taskbar_home_button_left_margin_kids">48dp</dimen>
     <dimen name="taskbar_icon_size_kids">32dp</dimen>
 </resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 59997e9..3ee2af0 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -39,6 +39,9 @@
     <!-- Accessibility title for the list of recent apps [CHAR_LIMIT=none] -->
     <string name="accessibility_recent_apps">Recent apps</string>
 
+    <!-- Accessibility confirmation for task closed -->
+    <string name="task_view_closed">Task Closed</string>
+
     <!-- Accessibility title for an app card in Recents for apps that have time limit set
      [CHAR_LIMIT=none] -->
     <string name="task_contents_description_with_remaining_time"><xliff:g id="task_description" example="GMail">%1$s</xliff:g>, <xliff:g id="remaining_time" example="7 minutes left today">%2$s</xliff:g></string>
@@ -243,6 +246,10 @@
     <string name="taskbar_button_ime_switcher">IME switcher</string>
     <!-- Content description for recents button [CHAR_LIMIT=16] -->
     <string name="taskbar_button_recents">Recents</string>
+    <!-- Content description for notifications button [CHAR_LIMIT=16] -->
+    <string name="taskbar_button_notifications">Notifications</string>
+    <!-- Content description for quick settings button [CHAR_LIMIT=16] -->
+    <string name="taskbar_button_quick_settings">Quick Settings</string>
 
     <!-- Label for moving drop target to the top or left side of the screen, depending on orientation (from the taskbar only). -->
     <string name="move_drop_target_top_or_left">Move to top&#47;left</string>
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 65b346a..51c2294 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -39,6 +39,7 @@
 import android.hardware.devicestate.DeviceStateManager;
 import android.os.Bundle;
 import android.os.CancellationSignal;
+import android.view.Display;
 import android.view.View;
 import android.view.WindowInsets;
 import android.window.SplashScreen;
@@ -385,8 +386,7 @@
 
     @Override
     public boolean supportsAdaptiveIconAnimation(View clickedView) {
-        return mAppTransitionManager.hasControlRemoteAppTransitionPermission()
-                && FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM.get();
+        return mAppTransitionManager.hasControlRemoteAppTransitionPermission();
     }
 
     @Override
@@ -509,6 +509,9 @@
                     activityOptions.options, mLastTouchUpTime);
         }
         activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+        activityOptions.options.setLaunchDisplayId(
+                (v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
+                        : Display.DEFAULT_DISPLAY);
         addLaunchCookie(item, activityOptions.options);
         return activityOptions;
     }
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 6e2fadd..49b2cc5 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -367,7 +367,7 @@
         if (launcherClosing) {
             // Delay animation by a frame to avoid jank.
             Pair<AnimatorSet, Runnable> launcherContentAnimator =
-                    getLauncherContentAnimator(true /* isAppOpening */, startDelay);
+                    getLauncherContentAnimator(true /* isAppOpening */, startDelay, false);
             anim.play(launcherContentAnimator.first);
             anim.addListener(new AnimatorListenerAdapter() {
                 @Override
@@ -464,9 +464,10 @@
      * @param isAppOpening True when this is called when an app is opening.
      *                     False when this is called when an app is closing.
      * @param startDelay   Start delay duration.
+     * @param skipAllAppsScale True if we want to avoid scaling All Apps
      */
     private Pair<AnimatorSet, Runnable> getLauncherContentAnimator(boolean isAppOpening,
-            int startDelay) {
+            int startDelay, boolean skipAllAppsScale) {
         AnimatorSet launcherAnimator = new AnimatorSet();
         Runnable endListener;
 
@@ -484,7 +485,6 @@
             final float startAlpha = appsView.getAlpha();
             final float startScale = SCALE_PROPERTY.get(appsView);
             appsView.setAlpha(alphas[0]);
-            SCALE_PROPERTY.set(appsView, scales[0]);
 
             ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, alphas);
             alpha.setDuration(CONTENT_ALPHA_DURATION);
@@ -496,12 +496,16 @@
                     appsView.setLayerType(View.LAYER_TYPE_NONE, null);
                 }
             });
-            ObjectAnimator scale = ObjectAnimator.ofFloat(appsView, SCALE_PROPERTY, scales);
-            scale.setInterpolator(AGGRESSIVE_EASE);
-            scale.setDuration(CONTENT_SCALE_DURATION);
+
+            if (!skipAllAppsScale) {
+                SCALE_PROPERTY.set(appsView, scales[0]);
+                ObjectAnimator scale = ObjectAnimator.ofFloat(appsView, SCALE_PROPERTY, scales);
+                scale.setInterpolator(AGGRESSIVE_EASE);
+                scale.setDuration(CONTENT_SCALE_DURATION);
+                launcherAnimator.play(scale);
+            }
 
             launcherAnimator.play(alpha);
-            launcherAnimator.play(scale);
 
             endListener = () -> {
                 appsView.setAlpha(startAlpha);
@@ -1565,6 +1569,7 @@
                         || mLauncher.getWorkspace().isOverlayShown();
 
                 boolean playWorkspaceReveal = true;
+                boolean skipAllAppsScale = false;
                 if (mFromUnlock) {
                     anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets));
                 } else if (ENABLE_BACK_SWIPE_HOME_ANIMATION.get()
@@ -1579,6 +1584,10 @@
                                 true /* animateOverviewScrim */, launcherView).getAnimators());
                         // We play StaggeredWorkspaceAnim as a part of the closing window animation.
                         playWorkspaceReveal = false;
+                    } else {
+                        // Skip scaling all apps, otherwise FloatingIconView will get wrong
+                        // layout bounds.
+                        skipAllAppsScale = true;
                     }
                 } else {
                     anim.play(getFallbackClosingWindowAnimators(appTargets));
@@ -1600,7 +1609,8 @@
 
                     if (mLauncher.isInState(LauncherState.ALL_APPS)) {
                         Pair<AnimatorSet, Runnable> contentAnimator =
-                                getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY);
+                                getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY,
+                                        skipAllAppsScale);
                         anim.play(contentAnimator.first);
                         anim.addListener(new AnimatorListenerAdapter() {
                             @Override
diff --git a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
index 1b0f967..4f987d2 100644
--- a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
@@ -209,7 +209,7 @@
     private Layout getAllAppsLabelLayout() {
         if (mAllAppsLabelLayout == null) {
             mPaint.setAntiAlias(true);
-            mPaint.setTypeface(Typeface.create("sans-serif-medium", Typeface.NORMAL));
+            mPaint.setTypeface(Typeface.create("google-sans", Typeface.NORMAL));
             mPaint.setTextSize(
                     getResources().getDimensionPixelSize(R.dimen.all_apps_label_text_size));
 
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index e1d89a1..3242d42 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -289,9 +289,8 @@
         if (Float.compare(mDepth, depthF) == 0) {
             return;
         }
-        if (dispatchTransactionSurface(depthF)) {
-            mDepth = depthF;
-        }
+        dispatchTransactionSurface(depthF);
+        mDepth = depthF;
     }
 
     public void onOverlayScrollChanged(float progress) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
new file mode 100644
index 0000000..0ab3cfd
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar;
+
+import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_NOTIFICATIONS;
+import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_QUICK_SETTINGS;
+
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.launcher3.R;
+
+/**
+ * Controller for managing buttons and status icons in taskbar in a desktop environment.
+ */
+public class DesktopNavbarButtonsViewController extends NavbarButtonsViewController {
+
+    private final TaskbarActivityContext mContext;
+    private final FrameLayout mNavButtonsView;
+    private final ViewGroup mNavButtonContainer;
+
+    private TaskbarControllers mControllers;
+
+    public DesktopNavbarButtonsViewController(TaskbarActivityContext context,
+            FrameLayout navButtonsView) {
+        super(context, navButtonsView);
+        mContext = context;
+        mNavButtonsView = navButtonsView;
+        mNavButtonContainer = mNavButtonsView.findViewById(R.id.end_nav_buttons);
+    }
+
+    /**
+     * Initializes the controller
+     */
+    @Override
+    public void init(TaskbarControllers controllers) {
+        mControllers = controllers;
+        mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize;
+
+        // Quick settings and notifications buttons
+        addButton(R.drawable.ic_sysbar_quick_settings, BUTTON_QUICK_SETTINGS,
+                mNavButtonContainer, mControllers.navButtonController,
+                R.id.quick_settings_button);
+        addButton(R.drawable.ic_sysbar_notifications, BUTTON_NOTIFICATIONS,
+                mNavButtonContainer, mControllers.navButtonController,
+                R.id.notifications_button);
+    }
+
+    /** Cleans up on destroy */
+    @Override
+    public void onDestroy() { }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 5e8db69..d2ac7c1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -113,6 +113,11 @@
         return !mTaskbarLauncherStateController.isAnimatingToLauncher();
     }
 
+    public void setShouldDelayLauncherStateAnim(boolean shouldDelayLauncherStateAnim) {
+        mTaskbarLauncherStateController.setShouldDelayLauncherStateAnim(
+                shouldDelayLauncherStateAnim);
+    }
+
     /**
      * Should be called from onResume() and onPause(), and animates the Taskbar accordingly.
      */
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 002a86c..b145861 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -15,15 +15,11 @@
  */
 package com.android.launcher3.taskbar;
 
-import static android.content.pm.PackageManager.FEATURE_PC;
-
 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_BACK;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_IME_SWITCH;
-import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_NOTIFICATIONS;
-import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_QUICK_SETTINGS;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_RECENTS;
 import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_KEYGUARD;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
@@ -36,6 +32,7 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
+import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION;
 
 import android.animation.ArgbEvaluator;
 import android.animation.ObjectAnimator;
@@ -51,13 +48,16 @@
 import android.graphics.Region.Op;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.PaintDrawable;
+import android.inputmethodservice.InputMethodService;
 import android.util.Property;
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
 import android.view.View.OnClickListener;
 import android.view.View.OnHoverListener;
 import android.view.ViewGroup;
+import android.view.WindowManager;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -68,18 +68,24 @@
 import com.android.launcher3.anim.AlphaUpdateListener;
 import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton;
 import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.TouchController;
+import com.android.launcher3.views.BaseDragLayer;
 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 com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.ViewTreeObserverWrapper;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.StringJoiner;
 import java.util.function.IntPredicate;
 
 /**
  * Controller for managing nav bar buttons in taskbar
  */
-public class NavbarButtonsViewController {
+public class NavbarButtonsViewController implements TaskbarControllers.LoggableTaskbarController {
 
     private final Rect mTempRect = new Rect();
 
@@ -98,6 +104,8 @@
 
     private static final int MASK_IME_SWITCHER_VISIBLE = FLAG_SWITCHER_SUPPORTED | FLAG_IME_VISIBLE;
 
+    private static final String NAV_BUTTONS_SEPARATE_WINDOW_TITLE = "Taskbar Nav Buttons";
+
     private final ArrayList<StatePropertyHolder> mPropertyHolders = new ArrayList<>();
     private final ArrayList<ImageView> mAllButtons = new ArrayList<>();
     private int mState;
@@ -128,12 +136,19 @@
 
     // Initialized in init.
     private TaskbarControllers mControllers;
+    private boolean mIsImeRenderingNavButtons;
     private View mA11yButton;
     private int mSysuiStateFlags;
     private View mBackButton;
     private View mHomeButton;
     private FloatingRotationButton mFloatingRotationButton;
 
+    // Variables for moving nav buttons to a separate window above IME
+    private boolean mAreNavButtonsInSeparateWindow = false;
+    private BaseDragLayer<TaskbarActivityContext> mSeparateWindowParent; // Initialized in init.
+    private final ViewTreeObserverWrapper.OnComputeInsetsListener mSeparateWindowInsetsComputer =
+            this::onComputeInsetsForSeparateWindow;
+
     public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) {
         mContext = context;
         mNavButtonsView = navButtonsView;
@@ -154,13 +169,17 @@
         mNavButtonTranslationYMultiplier.value = 1;
 
         boolean isThreeButtonNav = mContext.isThreeButtonNav();
-        // IME switcher
-        View imeSwitcherButton = addButton(R.drawable.ic_ime_switcher, BUTTON_IME_SWITCH,
-                isThreeButtonNav ? mStartContextualContainer : mEndContextualContainer,
-                mControllers.navButtonController, R.id.ime_switcher);
-        mPropertyHolders.add(new StatePropertyHolder(imeSwitcherButton,
-                flags -> ((flags & MASK_IME_SWITCHER_VISIBLE) == MASK_IME_SWITCHER_VISIBLE)
-                        && ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)));
+        mIsImeRenderingNavButtons =
+                InputMethodService.canImeRenderGesturalNavButtons() && mContext.isGestureNav();
+        if (!mIsImeRenderingNavButtons) {
+            // IME switcher
+            View imeSwitcherButton = addButton(R.drawable.ic_ime_switcher, BUTTON_IME_SWITCH,
+                    isThreeButtonNav ? mStartContextualContainer : mEndContextualContainer,
+                    mControllers.navButtonController, R.id.ime_switcher);
+            mPropertyHolders.add(new StatePropertyHolder(imeSwitcherButton,
+                    flags -> ((flags & MASK_IME_SWITCHER_VISIBLE) == MASK_IME_SWITCHER_VISIBLE)
+                            && ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)));
+        }
 
         mPropertyHolders.add(new StatePropertyHolder(
                 mControllers.taskbarViewController.getTaskbarIconAlpha()
@@ -300,27 +319,34 @@
             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);
-            // Rotate when Ime visible
-            mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
-                    flags -> (flags & FLAG_IME_VISIBLE) != 0));
+            if (!mIsImeRenderingNavButtons) {
+                View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
+                        mStartContextualContainer, mControllers.navButtonController, R.id.back);
+                imeDownButton.setRotation(Utilities.isRtl(mContext.getResources()) ? 90 : -90);
+                // Only show when IME is visible.
+                mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
+                        flags -> (flags & FLAG_IME_VISIBLE) != 0));
+            }
         }
 
         applyState();
         mPropertyHolders.forEach(StatePropertyHolder::endAnimation);
 
-        // quick setting and notification buttons
-        if (mContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
-            addButton(R.drawable.ic_sysbar_quick_settings, BUTTON_QUICK_SETTINGS,
-                    mNavButtonContainer, mControllers.navButtonController,
-                    R.id.quick_settings_button);
-            addButton(R.drawable.ic_sysbar_notifications, BUTTON_NOTIFICATIONS,
-                    mNavButtonContainer, mControllers.navButtonController,
-                    R.id.notifications_button);
-        }
+        // Initialize things needed to move nav buttons to separate window.
+        mSeparateWindowParent = new BaseDragLayer<TaskbarActivityContext>(mContext, null, 0) {
+            @Override
+            public void recreateControllers() {
+                mControllers = new TouchController[0];
+            }
 
+            @Override
+            protected boolean canFindActiveController() {
+                // We don't have any controllers, but we don't want any floating views such as
+                // folder to intercept, either. This ensures nav buttons can always be pressed.
+                return false;
+            }
+        };
+        mSeparateWindowParent.recreateControllers();
     }
 
     private void initButtons(ViewGroup navContainer, ViewGroup endContainer,
@@ -456,7 +482,7 @@
     /**
      * Adds the bounds corresponding to all visible buttons to provided region
      */
-    public void addVisibleButtonsRegion(TaskbarDragLayer parent, Region outRegion) {
+    public void addVisibleButtonsRegion(BaseDragLayer<?> parent, Region outRegion) {
         int count = mAllButtons.size();
         for (int i = 0; i < count; i++) {
             View button = mAllButtons.get(i);
@@ -517,7 +543,7 @@
         }
     }
 
-    private ImageView addButton(@DrawableRes int drawableId, @TaskbarButton int buttonType,
+    protected ImageView addButton(@DrawableRes int drawableId, @TaskbarButton int buttonType,
             ViewGroup parent, TaskbarNavButtonController navButtonController, @IdRes int id) {
         return addButton(drawableId, buttonType, parent, navButtonController, id,
                 R.layout.taskbar_nav_button);
@@ -561,6 +587,100 @@
         if (mFloatingRotationButton != null) {
             mFloatingRotationButton.hide();
         }
+
+        moveNavButtonsBackToTaskbarWindow();
+    }
+
+    /**
+     * Moves mNavButtonsView from TaskbarDragLayer to a placeholder BaseDragLayer on a new window.
+     */
+    public void moveNavButtonsToNewWindow() {
+        if (mAreNavButtonsInSeparateWindow) {
+            return;
+        }
+
+        if (mIsImeRenderingNavButtons) {
+            // IME is rendering the nav buttons, so we don't need to create a new layer for them.
+            return;
+        }
+
+        mSeparateWindowParent.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+            @Override
+            public void onViewAttachedToWindow(View view) {
+                ViewTreeObserverWrapper.addOnComputeInsetsListener(
+                        mSeparateWindowParent.getViewTreeObserver(), mSeparateWindowInsetsComputer);
+            }
+
+            @Override
+            public void onViewDetachedFromWindow(View view) {
+                mSeparateWindowParent.removeOnAttachStateChangeListener(this);
+                ViewTreeObserverWrapper.removeOnComputeInsetsListener(
+                        mSeparateWindowInsetsComputer);
+            }
+        });
+
+        mAreNavButtonsInSeparateWindow = true;
+        mContext.getDragLayer().removeView(mNavButtonsView);
+        mSeparateWindowParent.addView(mNavButtonsView);
+        WindowManager.LayoutParams windowLayoutParams = mContext.createDefaultWindowLayoutParams();
+        windowLayoutParams.setTitle(NAV_BUTTONS_SEPARATE_WINDOW_TITLE);
+        mContext.addWindowView(mSeparateWindowParent, windowLayoutParams);
+
+    }
+
+    /**
+     * Moves mNavButtonsView from its temporary window and reattaches it to TaskbarDragLayer.
+     */
+    public void moveNavButtonsBackToTaskbarWindow() {
+        if (!mAreNavButtonsInSeparateWindow) {
+            return;
+        }
+
+        mAreNavButtonsInSeparateWindow = false;
+        mContext.removeWindowView(mSeparateWindowParent);
+        mSeparateWindowParent.removeView(mNavButtonsView);
+        mContext.getDragLayer().addView(mNavButtonsView);
+    }
+
+    private void onComputeInsetsForSeparateWindow(ViewTreeObserverWrapper.InsetsInfo insetsInfo) {
+        addVisibleButtonsRegion(mSeparateWindowParent, insetsInfo.touchableRegion);
+        insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
+    }
+
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "NavbarButtonsViewController:");
+
+        pw.println(String.format("%s\tmState=%s", prefix, getStateString(mState)));
+        pw.println(String.format(
+                "%s\tmLightIconColor=0x%s", prefix, Integer.toHexString(mLightIconColor)));
+        pw.println(String.format(
+                "%s\tmDarkIconColor=0x%s", prefix, Integer.toHexString(mDarkIconColor)));
+        pw.println(String.format(
+                "%s\tmFloatingRotationButtonBounds=%s", prefix, mFloatingRotationButtonBounds));
+        pw.println(String.format(
+                "%s\tmSysuiStateFlags=%s",
+                prefix,
+                QuickStepContract.getSystemUiStateString(mSysuiStateFlags)));
+    }
+
+    private static String getStateString(int flags) {
+        StringJoiner str = new StringJoiner("|");
+        str.add((flags & FLAG_SWITCHER_SUPPORTED) != 0 ? "FLAG_SWITCHER_SUPPORTED" : "");
+        str.add((flags & FLAG_IME_VISIBLE) != 0 ? "FLAG_IME_VISIBLE" : "");
+        str.add((flags & FLAG_ROTATION_BUTTON_VISIBLE) != 0 ? "FLAG_ROTATION_BUTTON_VISIBLE" : "");
+        str.add((flags & FLAG_A11Y_VISIBLE) != 0 ? "FLAG_A11Y_VISIBLE" : "");
+        str.add((flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0
+                ? "FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE" : "");
+        str.add((flags & FLAG_KEYGUARD_VISIBLE) != 0 ? "FLAG_KEYGUARD_VISIBLE" : "");
+        str.add((flags & FLAG_KEYGUARD_OCCLUDED) != 0 ? "FLAG_KEYGUARD_OCCLUDED" : "");
+        str.add((flags & FLAG_DISABLE_HOME) != 0 ? "FLAG_DISABLE_HOME" : "");
+        str.add((flags & FLAG_DISABLE_RECENTS) != 0 ? "FLAG_DISABLE_RECENTS" : "");
+        str.add((flags & FLAG_DISABLE_BACK) != 0 ? "FLAG_DISABLE_BACK" : "");
+        str.add((flags & FLAG_NOTIFICATION_SHADE_EXPANDED) != 0
+                ? "FLAG_NOTIFICATION_SHADE_EXPANDED" : "");
+        str.add((flags & FLAG_SCREEN_PINNING_ACTIVE) != 0 ? "FLAG_SCREEN_PINNING_ACTIVE" : "");
+        return str.toString();
     }
 
     private class RotationButtonListener implements RotationButton.RotationButtonUpdatesCallback {
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index 22ca63f..a9ae7bd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -34,10 +34,12 @@
 import com.android.quickstep.AnimatedFloat;
 import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
 
+import java.io.PrintWriter;
+
 /**
  * Handles properties/data collection, then passes the results to our stashed handle View to render.
  */
-public class StashedHandleViewController {
+public class StashedHandleViewController implements TaskbarControllers.LoggableTaskbarController {
 
     public static final int ALPHA_INDEX_STASHED = 0;
     public static final int ALPHA_INDEX_HOME_DISABLED = 1;
@@ -200,4 +202,15 @@
     public boolean isStashedHandleVisible() {
         return mStashedHandleView.getVisibility() == View.VISIBLE;
     }
+
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "StashedHandleViewController:");
+
+        pw.println(String.format(
+                "%s\tisStashedHandleVisible=%b", prefix, isStashedHandleVisible()));
+        pw.println(String.format("%s\tmStashedHandleWidth=%dpx", prefix, mStashedHandleWidth));
+        pw.println(String.format("%s\tmStashedHandleHeight=%dpx", prefix, mStashedHandleHeight));
+        mRegionSamplingHelper.dump(prefix, pw);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 1198dc5..e37bd21 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -15,7 +15,9 @@
  */
 package com.android.launcher3.taskbar;
 
+import static android.content.pm.PackageManager.FEATURE_PC;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 
@@ -81,6 +83,8 @@
 import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
 
+import java.io.PrintWriter;
+
 /**
  * The {@link ActivityContext} with which we inflate Taskbar-related Views. This allows UI elements
  * that are used by both Launcher and Taskbar (such as Folder) to reference a generic
@@ -94,11 +98,12 @@
 
     private static final String WINDOW_TITLE = "Taskbar";
 
-    private final DeviceProfile mDeviceProfile;
     private final LayoutInflater mLayoutInflater;
     private final TaskbarDragLayer mDragLayer;
     private final TaskbarControllers mControllers;
 
+    private DeviceProfile mDeviceProfile;
+
     private final WindowManager mWindowManager;
     private final @Nullable RoundedCorner mLeftCorner, mRightCorner;
     private final int mTaskbarHeightForIme;
@@ -134,10 +139,7 @@
                 Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE), 0);
 
         final Resources resources = getResources();
-        float taskbarIconSize = resources.getDimension(R.dimen.taskbar_icon_size);
-        mDeviceProfile.updateIconSize(1, resources);
-        float iconScale = taskbarIconSize / mDeviceProfile.iconSizePx;
-        mDeviceProfile.updateIconSize(iconScale, resources);
+        updateIconSize(resources);
 
         mTaskbarHeightForIme = resources.getDimensionPixelSize(R.dimen.taskbar_ime_size);
 
@@ -165,7 +167,9 @@
         mControllers = new TaskbarControllers(this,
                 new TaskbarDragController(this),
                 buttonController,
-                new NavbarButtonsViewController(this, navButtonsView),
+                getPackageManager().hasSystemFeature(FEATURE_PC)
+                        ? new DesktopNavbarButtonsViewController(this, navButtonsView) :
+                        new NavbarButtonsViewController(this, navButtonsView),
                 new RotationButtonController(this,
                         c.getColor(R.color.taskbar_nav_icon_light_color),
                         c.getColor(R.color.taskbar_nav_icon_dark_color),
@@ -189,21 +193,7 @@
 
     public void init(TaskbarSharedState sharedState) {
         mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight();
-        mWindowLayoutParams = new WindowManager.LayoutParams(
-                MATCH_PARENT,
-                mLastRequestedNonFullscreenHeight,
-                TYPE_NAVIGATION_BAR_PANEL,
-                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                        | WindowManager.LayoutParams.FLAG_SLIPPERY,
-                PixelFormat.TRANSLUCENT);
-        mWindowLayoutParams.setTitle(WINDOW_TITLE);
-        mWindowLayoutParams.packageName = getPackageName();
-        mWindowLayoutParams.gravity = Gravity.BOTTOM;
-        mWindowLayoutParams.setFitInsetsTypes(0);
-        mWindowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
-        mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        mWindowLayoutParams.privateFlags =
-                WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+        mWindowLayoutParams = createDefaultWindowLayoutParams();
 
         WindowManagerWrapper wmWrapper = WindowManagerWrapper.getInstance();
         wmWrapper.setProvidesInsetsTypes(
@@ -224,6 +214,40 @@
         mWindowManager.addView(mDragLayer, mWindowLayoutParams);
     }
 
+    /** Updates the Device profile instance to the latest representation of the screen. */
+    public void updateDeviceProfile(DeviceProfile dp) {
+        mDeviceProfile = dp;
+        updateIconSize(getResources());
+    }
+
+    private void updateIconSize(Resources resources) {
+        float taskbarIconSize = resources.getDimension(R.dimen.taskbar_icon_size);
+        mDeviceProfile.updateIconSize(1, resources);
+        float iconScale = taskbarIconSize / mDeviceProfile.iconSizePx;
+        mDeviceProfile.updateIconSize(iconScale, resources);
+    }
+
+    /** Creates LayoutParams for adding a view directly to WindowManager as a new window */
+    public WindowManager.LayoutParams createDefaultWindowLayoutParams() {
+        WindowManager.LayoutParams windowLayoutParams = new WindowManager.LayoutParams(
+                MATCH_PARENT,
+                mLastRequestedNonFullscreenHeight,
+                TYPE_NAVIGATION_BAR_PANEL,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_SLIPPERY,
+                PixelFormat.TRANSLUCENT);
+        windowLayoutParams.setTitle(WINDOW_TITLE);
+        windowLayoutParams.packageName = getPackageName();
+        windowLayoutParams.gravity = Gravity.BOTTOM;
+        windowLayoutParams.setFitInsetsTypes(0);
+        windowLayoutParams.receiveInsetsIgnoringZOrder = true;
+        windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+        windowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+        windowLayoutParams.privateFlags =
+                WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+        return windowLayoutParams;
+    }
+
     public void onConfigurationChanged(@Config int configChanges) {
         mControllers.onConfigurationChanged(configChanges);
     }
@@ -232,6 +256,10 @@
         return mNavMode == Mode.THREE_BUTTONS;
     }
 
+    public boolean isGestureNav() {
+        return mNavMode == Mode.NO_BUTTON;
+    }
+
     public int getLeftCornerRadius() {
         return mLeftCorner == null ? 0 : mLeftCorner.getRadius();
     }
@@ -271,14 +299,6 @@
     }
 
     @Override
-    public boolean supportsIme() {
-        // Currently we don't support IME because we have FLAG_NOT_FOCUSABLE. We can remove that
-        // flag when opening a floating view that needs IME (such as Folder), but then that means
-        // Taskbar will be below IME and thus users can't click the back button.
-        return false;
-    }
-
-    @Override
     public View.OnClickListener getItemOnClickListener() {
         return this::onTaskbarIconClicked;
     }
@@ -505,6 +525,42 @@
         return mTaskbarHeightForIme;
     }
 
+    /**
+     * Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar
+     * window.
+     */
+    public void setTaskbarWindowFocusable(boolean focusable) {
+        if (focusable) {
+            mWindowLayoutParams.flags &= ~FLAG_NOT_FOCUSABLE;
+        } else {
+            mWindowLayoutParams.flags |= FLAG_NOT_FOCUSABLE;
+        }
+        mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
+    }
+
+    /**
+     * Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar
+     * window. If we're now focusable, also move nav buttons to a separate window above IME.
+     */
+    public void setTaskbarWindowFocusableForIme(boolean focusable) {
+        if (focusable) {
+            mControllers.navbarButtonsViewController.moveNavButtonsToNewWindow();
+        } else {
+            mControllers.navbarButtonsViewController.moveNavButtonsBackToTaskbarWindow();
+        }
+        setTaskbarWindowFocusable(focusable);
+    }
+
+    /** Adds the given view to WindowManager with the provided LayoutParams (creates new window). */
+    public void addWindowView(View view, WindowManager.LayoutParams windowLayoutParams) {
+        mWindowManager.addView(view, windowLayoutParams);
+    }
+
+    /** Removes the given view from WindowManager. See {@link #addWindowView}. */
+    public void removeWindowView(View view) {
+        mWindowManager.removeViewImmediate(view);
+    }
+
     protected void onTaskbarIconClicked(View view) {
         Object tag = view.getTag();
         if (tag instanceof Task) {
@@ -514,6 +570,17 @@
         } else if (tag instanceof FolderInfo) {
             FolderIcon folderIcon = (FolderIcon) view;
             Folder folder = folderIcon.getFolder();
+
+            folder.setOnFolderStateChangedListener(newState -> {
+                if (newState == Folder.STATE_OPEN) {
+                    setTaskbarWindowFocusableForIme(true);
+                } else if (newState == Folder.STATE_CLOSED) {
+                    // Defer by a frame to ensure we're no longer fullscreen and thus won't jump.
+                    getDragLayer().post(() -> setTaskbarWindowFocusableForIme(false));
+                    folder.setOnFolderStateChangedListener(null);
+                }
+            });
+
             setTaskbarWindowFullscreen(true);
 
             getDragLayer().post(() -> {
@@ -620,4 +687,16 @@
         setTaskbarWindowFullscreen(true);
         btv.post(() -> mControllers.taskbarPopupController.showForIcon(btv));
     }
+
+    protected void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarActivityContext:");
+
+        pw.println(String.format(
+                "%s\tmNavMode=%s", prefix, mNavMode));
+        pw.println(String.format(
+                "%s\tmIsUserSetupComplete=%b", prefix, mIsUserSetupComplete));
+        pw.println(String.format(
+                "%s\tmWindowLayoutParams.height=%dpx", prefix, mWindowLayoutParams.height));
+        mControllers.dumpLogs(prefix + "\t", pw);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
index e42f83d..31a6aa6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
@@ -19,17 +19,21 @@
 
 import com.android.quickstep.SystemUiProxy;
 
+import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.StringJoiner;
 
 /**
  * Normally Taskbar will auto-hide when entering immersive (fullscreen) apps. This controller allows
  * us to suspend that behavior in certain cases (e.g. opening a Folder or dragging an icon).
  */
-public class TaskbarAutohideSuspendController {
+public class TaskbarAutohideSuspendController implements
+        TaskbarControllers.LoggableTaskbarController {
 
     public static final int FLAG_AUTOHIDE_SUSPEND_FULLSCREEN = 1 << 0;
     public static final int FLAG_AUTOHIDE_SUSPEND_DRAGGING = 1 << 1;
+
     @IntDef(flag = true, value = {
             FLAG_AUTOHIDE_SUSPEND_FULLSCREEN,
             FLAG_AUTOHIDE_SUSPEND_DRAGGING,
@@ -60,4 +64,21 @@
         }
         mSystemUiProxy.notifyTaskbarAutohideSuspend(mAutohideSuspendFlags != 0);
     }
+
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarAutohideSuspendController:");
+
+        pw.println(String.format(
+                "%s\tmAutohideSuspendFlags=%s", prefix, getStateString(mAutohideSuspendFlags)));
+    }
+
+    private static String getStateString(int flags) {
+        StringJoiner str = new StringJoiner("|");
+        str.add((flags & FLAG_AUTOHIDE_SUSPEND_FULLSCREEN) != 0
+                ? "FLAG_AUTOHIDE_SUSPEND_FULLSCREEN" : "");
+        str.add((flags & FLAG_AUTOHIDE_SUSPEND_DRAGGING) != 0
+                ? "FLAG_AUTOHIDE_SUSPEND_DRAGGING" : "");
+        return str.toString();
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 488c822..f491669 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -18,9 +18,11 @@
 import android.content.pm.ActivityInfo.Config;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import com.android.systemui.shared.rotation.RotationButtonController;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -30,6 +32,7 @@
 public class TaskbarControllers {
 
     public final TaskbarActivityContext taskbarActivityContext;
+
     public final TaskbarDragController taskbarDragController;
     public final TaskbarNavButtonController navButtonController;
     public final NavbarButtonsViewController navbarButtonsViewController;
@@ -45,6 +48,8 @@
     public final TaskbarAutohideSuspendController taskbarAutohideSuspendController;
     public final TaskbarPopupController taskbarPopupController;
 
+    @Nullable private LoggableTaskbarController[] mControllersToLog = null;
+
     /** Do not store this controller, as it may change at runtime. */
     @NonNull public TaskbarUIController uiController = TaskbarUIController.DEFAULT;
 
@@ -104,6 +109,14 @@
         taskbarEduController.init(this);
         taskbarPopupController.init(this);
 
+        mControllersToLog = new LoggableTaskbarController[] {
+                taskbarDragController, navButtonController, navbarButtonsViewController,
+                taskbarDragLayerController, taskbarScrimViewController, taskbarViewController,
+                taskbarUnfoldAnimationController, taskbarKeyguardController,
+                stashedHandleViewController, taskbarStashController, taskbarEduController,
+                taskbarAutohideSuspendController, taskbarPopupController
+        };
+
         mAreAllControllersInitialized = true;
         for (Runnable postInitCallback : mPostInitCallbacks) {
             postInitCallback.run();
@@ -129,6 +142,8 @@
         stashedHandleViewController.onDestroy();
         taskbarAutohideSuspendController.onDestroy();
         taskbarPopupController.onDestroy();
+
+        mControllersToLog = null;
     }
 
     /**
@@ -143,4 +158,23 @@
             mPostInitCallbacks.add(callback);
         }
     }
+
+    protected void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarControllers:");
+
+        if (mControllersToLog == null) {
+            pw.println(String.format(
+                    "%s\t%s", prefix, "All taskbar controllers have already been destroyed."));
+            return;
+        }
+
+        for (LoggableTaskbarController controller : mControllersToLog) {
+            controller.dumpLogs(prefix + "\t", pw);
+        }
+        rotationButtonController.dumpLogs(prefix + "\t", pw);
+    }
+
+    protected interface LoggableTaskbarController {
+        void dumpLogs(String prefix, PrintWriter pw);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 3315f8c..3323104 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -57,10 +57,14 @@
 import com.android.systemui.shared.system.ClipDescriptionCompat;
 import com.android.systemui.shared.system.LauncherAppsCompat;
 
+import java.io.PrintWriter;
+import java.util.Arrays;
+
 /**
  * Handles long click on Taskbar items to start a system drag and drop operation.
  */
-public class TaskbarDragController extends DragController<TaskbarActivityContext>  {
+public class TaskbarDragController extends DragController<TaskbarActivityContext> implements
+        TaskbarControllers.LoggableTaskbarController {
 
     private final int mDragIconSize;
     private final int[] mTempXY = new int[2];
@@ -167,7 +171,7 @@
             PopupContainerWithArrow<TaskbarActivityContext> popupContainer =
                     mControllers.taskbarPopupController.showForIcon(btv);
             if (popupContainer != null) {
-                dragOptions.preDragCondition = popupContainer.createPreDragCondition();
+                dragOptions.preDragCondition = popupContainer.createPreDragCondition(false);
             }
         }
 
@@ -415,4 +419,18 @@
     protected DropTarget getDefaultDropTarget(int[] dropCoordinates) {
         return null;
     }
+
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarDragController:");
+
+        pw.println(String.format("%s\tmDragIconSize=%dpx", prefix, mDragIconSize));
+        pw.println(String.format("%s\tmTempXY=%s", prefix, Arrays.toString(mTempXY)));
+        pw.println(String.format("%s\tmRegistrationX=%d", prefix, mRegistrationX));
+        pw.println(String.format("%s\tmRegistrationY=%d", prefix, mRegistrationY));
+        pw.println(String.format(
+                "%s\tmIsSystemDragInProgress=%b", prefix, mIsSystemDragInProgress));
+        pw.println(String.format(
+                "%s\tisInternalDragInProgess=%b", prefix, super.isDragging()));
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index b42a60c..df004ef 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -15,17 +15,22 @@
  */
 package com.android.launcher3.taskbar;
 
+import static android.view.KeyEvent.ACTION_UP;
+import static android.view.KeyEvent.KEYCODE_BACK;
+
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.util.AttributeSet;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.R;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.TestProtocol;
@@ -187,4 +192,17 @@
         TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev);
         return super.dispatchTouchEvent(ev);
     }
+
+    /** Called while Taskbar window is focusable, e.g. when pressing back while a folder is open */
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
+            AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
+            if (topView != null && topView.onBackPressed()) {
+                // Handled by the floating view.
+                return true;
+            }
+        }
+        return super.dispatchKeyEvent(event);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index a918016..fa40992 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -29,10 +29,12 @@
 import com.android.quickstep.AnimatedFloat;
 import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo;
 
+import java.io.PrintWriter;
+
 /**
  * Handles properties/data collection, then passes the results to TaskbarDragLayer to render.
  */
-public class TaskbarDragLayerController {
+public class TaskbarDragLayerController implements TaskbarControllers.LoggableTaskbarController {
 
     private final TaskbarActivityContext mActivity;
     private final TaskbarDragLayer mTaskbarDragLayer;
@@ -144,6 +146,16 @@
         mNavButtonDarkIntensityMultiplier.updateValue(1 - effectiveBgAlpha);
     }
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarDragLayerController:");
+
+        pw.println(String.format("%s\tmBgOffset=%.2f", prefix, mBgOffset.value));
+        pw.println(String.format("%s\tmFolderMargin=%dpx", prefix, mFolderMargin));
+        pw.println(String.format(
+                "%s\tmLastSetBackgroundAlpha=%.2f", prefix, mLastSetBackgroundAlpha));
+    }
+
     /**
      * Callbacks for {@link TaskbarDragLayer} to interact with its controller.
      */
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
index fd5c2ea..e29b14b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
@@ -37,12 +37,13 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.uioverrides.PredictedAppIcon;
 
+import java.io.PrintWriter;
 import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 
 /** Handles the Taskbar Education flow. */
-public class TaskbarEduController {
+public class TaskbarEduController implements TaskbarControllers.LoggableTaskbarController {
 
     private static final long WAVE_ANIM_DELAY = 250;
     private static final long WAVE_ANIM_STAGGER = 50;
@@ -186,6 +187,18 @@
         return waveAnim;
     }
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarEduController:");
+
+        pw.println(String.format("%s\tisShowingEdu=%b", prefix, mTaskbarEduView != null));
+        pw.println(String.format("%s\tmWaveAnimTranslationY=%.2f", prefix, mWaveAnimTranslationY));
+        pw.println(String.format(
+                "%s\tmWaveAnimTranslationYReturnOvershoot=%.2f",
+                prefix,
+                mWaveAnimTranslationYReturnOvershoot));
+    }
+
     /**
      * Callbacks for {@link TaskbarEduView} to interact with its controller.
      */
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
index 5fc0695..991bcec 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
@@ -14,10 +14,14 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 
+import com.android.systemui.shared.system.QuickStepContract;
+
+import java.io.PrintWriter;
+
 /**
  * Controller for managing keyguard state for taskbar
  */
-public class TaskbarKeyguardController {
+public class TaskbarKeyguardController implements TaskbarControllers.LoggableTaskbarController {
 
     private static final int KEYGUARD_SYSUI_FLAGS = SYSUI_STATE_BOUNCER_SHOWING |
             SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING | SYSUI_STATE_DEVICE_DOZING |
@@ -95,4 +99,16 @@
     public void onDestroy() {
         mContext.unregisterReceiver(mScreenOffReceiver);
     }
+
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarKeyguardController:");
+
+        pw.println(String.format(
+                "%s\tmKeyguardSysuiFlags=%s",
+                prefix,
+                QuickStepContract.getSystemUiStateString(mKeyguardSysuiFlags)));
+        pw.println(String.format("%s\tmBouncerShowing=%b", prefix, mBouncerShowing));
+        pw.println(String.format("%s\tmIsScreenOff=%b", prefix, mIsScreenOff));
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 7a50d0b..ebe6a04 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -27,6 +27,7 @@
 
 import androidx.annotation.NonNull;
 
+import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BaseQuickstepLauncher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.statemanager.StateManager;
@@ -73,6 +74,8 @@
     private boolean mIsAnimatingToLauncherViaGesture;
     private boolean mIsAnimatingToLauncherViaResume;
 
+    private boolean mShouldDelayLauncherStateAnim;
+
     private final StateManager.StateListener<LauncherState> mStateListener =
             new StateManager.StateListener<LauncherState>() {
 
@@ -85,7 +88,9 @@
                         mLauncherState = toState;
                     }
                     updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, true);
-                    applyState();
+                    if (!mShouldDelayLauncherStateAnim) {
+                        applyState();
+                    }
                 }
 
                 @Override
@@ -158,6 +163,15 @@
         return mIsAnimatingToLauncherViaResume || mIsAnimatingToLauncherViaGesture;
     }
 
+    public void setShouldDelayLauncherStateAnim(boolean shouldDelayLauncherStateAnim) {
+        if (!shouldDelayLauncherStateAnim && mShouldDelayLauncherStateAnim) {
+            // Animate the animation we have delayed immediately. This is usually triggered when
+            // the user has released their finger.
+            applyState();
+        }
+        mShouldDelayLauncherStateAnim = shouldDelayLauncherStateAnim;
+    }
+
     /**
      * Updates the proper flag to change the state of the task bar.
      *
@@ -207,59 +221,10 @@
 
     private Animator onStateChangeApplied(int changedFlags, long duration, boolean start) {
         AnimatorSet animatorSet = new AnimatorSet();
-        if (hasAnyFlag(changedFlags, FLAG_RESUMED)) {
-            boolean isResumed = isResumed();
-            ObjectAnimator anim = mIconAlignmentForResumedState
-                    .animateToValue(isResumed && goingToUnstashedLauncherState()
-                            ? 1 : 0)
-                    .setDuration(duration);
 
-            anim.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mIsAnimatingToLauncherViaResume = false;
-                }
-
-                @Override
-                public void onAnimationStart(Animator animation) {
-                    mIsAnimatingToLauncherViaResume = isResumed;
-
-                    TaskbarStashController stashController = mControllers.taskbarStashController;
-                    stashController.updateStateForFlag(FLAG_IN_APP, !isResumed);
-                    stashController.applyState(duration);
-                }
-            });
-            animatorSet.play(anim);
-        }
-
-        if (hasAnyFlag(changedFlags, FLAG_RECENTS_ANIMATION_RUNNING)) {
-            boolean isRecentsAnimationRunning = isRecentsAnimationRunning();
-            Animator animator = mIconAlignmentForGestureState
-                    .animateToValue(isRecentsAnimationRunning && goingToUnstashedLauncherState()
-                            ? 1 : 0);
-            if (isRecentsAnimationRunning) {
-                animator.setDuration(duration);
-            }
-            animator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mIsAnimatingToLauncherViaGesture = false;
-                }
-
-                @Override
-                public void onAnimationStart(Animator animation) {
-                    mIsAnimatingToLauncherViaGesture = isRecentsAnimationRunning();
-                }
-            });
-            animatorSet.play(animator);
-        }
-
-        if (hasAnyFlag(changedFlags, FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING)) {
-            boolean goingToLauncher = hasAnyFlag(FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING);
-            animatorSet.play(mTaskbarBackgroundAlpha.animateToValue(goingToLauncher ? 0 : 1)
-                    .setDuration(duration));
-        }
-
+        // Add the state animation first to ensure FLAG_IN_STASHED_LAUNCHER_STATE is set and we can
+        // determine whether goingToUnstashedLauncherStateChanged.
+        boolean wasGoingToUnstashedLauncherState = goingToUnstashedLauncherState();
         if (hasAnyFlag(changedFlags, FLAG_TRANSITION_STATE_RUNNING)) {
             boolean committed = !hasAnyFlag(FLAG_TRANSITION_STATE_RUNNING);
             playStateTransitionAnim(animatorSet, duration, committed);
@@ -270,6 +235,80 @@
                 applyState(0 /* duration */);
             }
         }
+        boolean goingToUnstashedLauncherStateChanged = wasGoingToUnstashedLauncherState
+                != goingToUnstashedLauncherState();
+
+        boolean launcherStateChangedDuringAnimToResumeAlignment =
+                mIconAlignmentForResumedState.isAnimating() && goingToUnstashedLauncherStateChanged;
+        if (hasAnyFlag(changedFlags, FLAG_RESUMED)
+                || launcherStateChangedDuringAnimToResumeAlignment) {
+            boolean isResumed = isResumed();
+            float toAlignmentForResumedState = isResumed && goingToUnstashedLauncherState() ? 1 : 0;
+            // If we're already animating to the value, just leave it be instead of restarting it.
+            if (!mIconAlignmentForResumedState.isAnimatingToValue(toAlignmentForResumedState)) {
+                ObjectAnimator resumeAlignAnim = mIconAlignmentForResumedState
+                        .animateToValue(toAlignmentForResumedState)
+                        .setDuration(duration);
+
+                resumeAlignAnim.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        mIsAnimatingToLauncherViaResume = false;
+                    }
+
+                    @Override
+                    public void onAnimationStart(Animator animation) {
+                        mIsAnimatingToLauncherViaResume = isResumed;
+
+                        TaskbarStashController stashController =
+                                mControllers.taskbarStashController;
+                        stashController.updateStateForFlag(FLAG_IN_APP, !isResumed);
+                        stashController.applyState(duration);
+                    }
+                });
+                animatorSet.play(resumeAlignAnim);
+            }
+        }
+
+
+        boolean launcherStateChangedDuringAnimToGestureAlignment =
+                mIconAlignmentForGestureState.isAnimating() && goingToUnstashedLauncherStateChanged;
+        if (hasAnyFlag(changedFlags, FLAG_RECENTS_ANIMATION_RUNNING)
+                || launcherStateChangedDuringAnimToGestureAlignment) {
+            boolean isRecentsAnimationRunning = isRecentsAnimationRunning();
+            float toAlignmentForGestureState = isRecentsAnimationRunning
+                    && goingToUnstashedLauncherState() ? 1 : 0;
+            // If we're already animating to the value, just leave it be instead of restarting it.
+            if (!mIconAlignmentForGestureState.isAnimatingToValue(toAlignmentForGestureState)) {
+                Animator gestureAlignAnim = mIconAlignmentForGestureState
+                        .animateToValue(toAlignmentForGestureState);
+                if (isRecentsAnimationRunning) {
+                    gestureAlignAnim.setDuration(duration);
+                }
+                gestureAlignAnim.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        mIsAnimatingToLauncherViaGesture = false;
+                    }
+
+                    @Override
+                    public void onAnimationStart(Animator animation) {
+                        mIsAnimatingToLauncherViaGesture = isRecentsAnimationRunning();
+                    }
+                });
+                animatorSet.play(gestureAlignAnim);
+            }
+        }
+
+        if (hasAnyFlag(changedFlags, FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING)) {
+            boolean goingToLauncher = hasAnyFlag(FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING);
+            if (goingToLauncher) {
+                // Handle closing open popups when going home/overview
+                AbstractFloatingView.closeAllOpenViews(mControllers.taskbarActivityContext);
+            }
+            animatorSet.play(mTaskbarBackgroundAlpha.animateToValue(goingToLauncher ? 0 : 1)
+                    .setDuration(duration));
+        }
 
         if (start) {
             animatorSet.start();
@@ -310,8 +349,11 @@
             animatorSet.play(stashAnimator);
         }
 
-        animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment)
-                .setDuration(duration));
+        // If we're already animating to the value, just leave it be instead of restarting it.
+        if (!mIconAlignmentForLauncherState.isAnimatingToValue(toAlignment)) {
+            animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment)
+                    .setDuration(duration));
+        }
     }
 
     private boolean isResumed() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index a262674..50be430 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -54,6 +54,8 @@
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
 
+import java.io.PrintWriter;
+
 /**
  * Class to manage taskbar lifecycle
  */
@@ -116,6 +118,13 @@
                 } else {
                     // Config change might be handled without re-creating the taskbar
                     if (mTaskbarActivityContext != null) {
+                        DeviceProfile dp = mUserUnlocked
+                                ? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext)
+                                : null;
+
+                        if (dp != null && dp.isTaskbarPresent) {
+                            mTaskbarActivityContext.updateDeviceProfile(dp.copy(mContext));
+                        }
                         mTaskbarActivityContext.onConfigurationChanged(configDiff);
                     }
                 }
@@ -305,4 +314,13 @@
     public @Nullable TaskbarActivityContext getCurrentActivityContext() {
         return mTaskbarActivityContext;
     }
+
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarManager:");
+        if (mTaskbarActivityContext == null) {
+            pw.println(prefix + "\tTaskbarActivityContext: null");
+        } else {
+            mTaskbarActivityContext.dumpLogs(prefix + "\t", pw);
+        }
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
index 37a9b5e..910752a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
@@ -29,6 +29,7 @@
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.LauncherBindableItemsContainer;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -196,4 +197,15 @@
     public void bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMapCopy) {
         mControllers.taskbarPopupController.setDeepShortcutMap(deepShortcutMapCopy);
     }
+
+    protected void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarModelCallbacks:");
+
+        pw.println(String.format("%s\thotseat items count=%s", prefix, mHotseatItems.size()));
+        if (mPredictedItems != null) {
+            pw.println(
+                    String.format("%s\tpredicted items count=%s", prefix, mPredictedItems.size()));
+        }
+        pw.println(String.format("%s\tmBindInProgress=%b", prefix, mBindInProgress));
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index a601984..d72c3d2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -33,6 +33,7 @@
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TouchInteractionService;
 
+import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -41,7 +42,7 @@
  * Handles all the functionality of the various buttons, making/routing the right calls into
  * launcher or sysui/system.
  */
-public class TaskbarNavButtonController {
+public class TaskbarNavButtonController implements TaskbarControllers.LoggableTaskbarController {
 
     /** Allow some time in between the long press for back and recents. */
     static final int SCREEN_PIN_LONG_PRESS_THRESHOLD = 200;
@@ -50,6 +51,15 @@
     private long mLastScreenPinLongPress;
     private boolean mScreenPinned;
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarNavButtonController:");
+
+        pw.println(String.format(
+                "%s\tmLastScreenPinLongPress=%dms", prefix, mLastScreenPinLongPress));
+        pw.println(String.format("%s\tmScreenPinned=%b", prefix, mScreenPinned));
+    }
+
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(value = {
             BUTTON_BACK,
@@ -143,6 +153,10 @@
                 return R.string.taskbar_button_ime_switcher;
             case BUTTON_RECENTS:
                 return R.string.taskbar_button_recents;
+            case BUTTON_NOTIFICATIONS:
+                return R.string.taskbar_button_notifications;
+            case BUTTON_QUICK_SETTINGS:
+                return R.string.taskbar_button_quick_settings;
             default:
                 return 0;
         }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 2dee506..68459ab 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -40,6 +40,7 @@
 import com.android.launcher3.util.PackageUserKey;
 import com.android.launcher3.views.ActivityContext;
 
+import java.io.PrintWriter;
 import java.util.HashMap;
 import java.util.Objects;
 import java.util.function.Predicate;
@@ -49,7 +50,7 @@
 /**
  * Implements interfaces required to show and allow interacting with a PopupContainerWithArrow.
  */
-public class TaskbarPopupController {
+public class TaskbarPopupController implements TaskbarControllers.LoggableTaskbarController {
 
     private static final SystemShortcut.Factory<TaskbarActivityContext>
             APP_INFO = SystemShortcut.AppInfo::new;
@@ -154,9 +155,25 @@
                         .filter(Objects::nonNull)
                         .collect(Collectors.toList()));
         container.requestFocus();
+
+        // Make focusable to receive back events
+        mControllers.taskbarActivityContext.setTaskbarWindowFocusable(true);
+        container.setOnCloseCallback(() -> {
+            mControllers.taskbarActivityContext.getDragLayer().post(
+                    () -> mControllers.taskbarActivityContext.setTaskbarWindowFocusable(false));
+            container.setOnCloseCallback(null);
+        });
+
         return container;
     }
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarPopupController:");
+
+        mPopupDataProvider.dump(prefix + "\t", pw);
+    }
+
     private class TaskbarPopupItemDragHandler implements
             PopupContainerWithArrow.PopupItemDragHandler {
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
index 4b4ee44..02bbae4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -25,10 +25,12 @@
 import com.android.quickstep.AnimatedFloat;
 import com.android.quickstep.SystemUiProxy;
 
+import java.io.PrintWriter;
+
 /**
  * Handles properties/data collection, and passes the results to {@link TaskbarScrimView} to render.
  */
-public class TaskbarScrimViewController {
+public class TaskbarScrimViewController implements TaskbarControllers.LoggableTaskbarController {
 
     private static final float SCRIM_ALPHA = 0.6f;
 
@@ -94,4 +96,11 @@
     private void onClick() {
         SystemUiProxy.INSTANCE.get(mActivity).onBackPressed();
     }
+
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarScrimViewController:");
+
+        pw.println(String.format("%s\tmScrimAlpha.value=%.2f", prefix, mScrimAlpha.value));
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 076eea1..748557b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -36,13 +36,15 @@
 import com.android.quickstep.AnimatedFloat;
 import com.android.quickstep.SystemUiProxy;
 
+import java.io.PrintWriter;
+import java.util.StringJoiner;
 import java.util.function.IntPredicate;
 
 /**
  * Coordinates between controllers such as TaskbarViewController and StashedHandleViewController to
  * create a cohesive animation between stashed/unstashed states.
  */
-public class TaskbarStashController {
+public class TaskbarStashController implements TaskbarControllers.LoggableTaskbarController {
 
     public static final int FLAG_IN_APP = 1 << 0;
     public static final int FLAG_STASHED_IN_APP_MANUAL = 1 << 1; // long press, persisted
@@ -544,6 +546,34 @@
         mControllers.rotationButtonController.onTaskbarStateChange(visible, stashed);
     }
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarStashController:");
+
+        pw.println(String.format("%s\tmStashedHeight=%dpx", prefix, mStashedHeight));
+        pw.println(String.format("%s\tmUnstashedHeight=%dpx", prefix, mUnstashedHeight));
+        pw.println(String.format("%s\tmIsStashed=%b", prefix, mIsStashed));
+        pw.println(String.format(
+                "%s\tappliedState=%s", prefix, getStateString(mStatePropertyHolder.mPrevFlags)));
+        pw.println(String.format("%s\tmState=%s", prefix, getStateString(mState)));
+        pw.println(String.format(
+                "%s\tmIsSystemGestureInProgress=%b", prefix, mIsSystemGestureInProgress));
+        pw.println(String.format("%s\tmIsImeShowing=%b", prefix, mIsImeShowing));
+    }
+
+    private static String getStateString(int flags) {
+        StringJoiner str = new StringJoiner("|");
+        str.add((flags & FLAG_IN_APP) != 0 ? "FLAG_IN_APP" : "");
+        str.add((flags & FLAG_STASHED_IN_APP_MANUAL) != 0 ? "FLAG_STASHED_IN_APP_MANUAL" : "");
+        str.add((flags & FLAG_STASHED_IN_APP_PINNED) != 0 ? "FLAG_STASHED_IN_APP_PINNED" : "");
+        str.add((flags & FLAG_STASHED_IN_APP_EMPTY) != 0 ? "FLAG_STASHED_IN_APP_EMPTY" : "");
+        str.add((flags & FLAG_STASHED_IN_APP_SETUP) != 0 ? "FLAG_STASHED_IN_APP_SETUP" : "");
+        str.add((flags & FLAG_STASHED_IN_APP_IME) != 0 ? "FLAG_STASHED_IN_APP_IME" : "");
+        str.add((flags & FLAG_IN_STASHED_LAUNCHER_STATE) != 0
+                ? "FLAG_IN_STASHED_LAUNCHER_STATE" : "");
+        return str.toString();
+    }
+
     private class StatePropertyHolder {
         private final IntPredicate mStashCondition;
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
index c785186..d5ea570 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
@@ -23,10 +23,13 @@
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
 
+import java.io.PrintWriter;
+
 /**
  * Controls animation of taskbar icons when unfolding foldable devices
  */
-public class TaskbarUnfoldAnimationController {
+public class TaskbarUnfoldAnimationController implements
+        TaskbarControllers.LoggableTaskbarController {
 
     private final ScopedUnfoldTransitionProgressProvider mUnfoldTransitionProgressProvider;
     private final UnfoldMoveFromCenterAnimator mMoveFromCenterAnimator;
@@ -59,6 +62,11 @@
         mUnfoldTransitionProgressProvider.removeCallback(mTransitionListener);
     }
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarUnfoldAnimationController:");
+    }
+
     private class TransitionListener implements TransitionProgressListener {
 
         @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index e00d177..0508994 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -39,10 +39,12 @@
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.quickstep.AnimatedFloat;
 
+import java.io.PrintWriter;
+
 /**
  * Handles properties/data collection, then passes the results to TaskbarView to render.
  */
-public class TaskbarViewController {
+public class TaskbarViewController implements TaskbarControllers.LoggableTaskbarController {
     private static final Runnable NO_OP = () -> { };
 
     public static final int ALPHA_INDEX_HOME = 0;
@@ -258,6 +260,12 @@
         return mTaskbarView.isEventOverAnyItem(ev);
     }
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarViewController:");
+        mModelCallbacks.dumpLogs(prefix + "\t", pw);
+    }
+
     /**
      * Callbacks for {@link TaskbarView} to interact with its controller.
      */
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index 8f89d30..26d8f30 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -23,7 +23,6 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
 import com.android.launcher3.util.Themes;
 
 /**
@@ -33,13 +32,6 @@
 
     private static final int STATE_FLAGS = FLAG_WORKSPACE_INACCESSIBLE | FLAG_CLOSE_POPUPS;
 
-    private static final PageAlphaProvider PAGE_ALPHA_PROVIDER = new PageAlphaProvider(DEACCEL_2) {
-        @Override
-        public float getPageAlpha(int pageIndex) {
-            return 0;
-        }
-    };
-
     public AllAppsState(int id) {
         super(id, LAUNCHER_STATE_ALLAPPS, STATE_FLAGS);
     }
@@ -51,8 +43,7 @@
 
     @Override
     public String getDescription(Launcher launcher) {
-        AllAppsContainerView appsView = launcher.getAppsView();
-        return appsView.getDescription();
+        return launcher.getAppsView().getDescription();
     }
 
     @Override
@@ -82,7 +73,15 @@
 
     @Override
     public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
-        return PAGE_ALPHA_PROVIDER;
+        PageAlphaProvider superPageAlphaProvider = super.getWorkspacePageAlphaProvider(launcher);
+        return new PageAlphaProvider(DEACCEL_2) {
+            @Override
+            public float getPageAlpha(int pageIndex) {
+                return launcher.getDeviceProfile().isTablet
+                        ? superPageAlphaProvider.getPageAlpha(pageIndex)
+                        : 0;
+            }
+        };
     }
 
     @Override
@@ -97,6 +96,8 @@
 
     @Override
     public int getWorkspaceScrimColor(Launcher launcher) {
-        return Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
+        return launcher.getDeviceProfile().isTablet
+                ? launcher.getResources().getColor(R.color.widgets_picker_scrim)
+                : Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
     }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index ef6f53e..7ec1243 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -18,6 +18,7 @@
 
 import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
 import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
+import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.HINT_STATE;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
@@ -33,11 +34,13 @@
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 
+import com.android.launcher3.BaseQuickstepLauncher;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.taskbar.LauncherTaskbarUIController;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.AnimatorControllerWithResistance;
 import com.android.quickstep.util.MotionPauseDetector;
@@ -109,6 +112,14 @@
 
     @Override
     public void onDragStart(boolean start, float startDisplacement) {
+        if (mLauncher.isInState(ALL_APPS)) {
+            LauncherTaskbarUIController controller =
+                    ((BaseQuickstepLauncher) mLauncher).getTaskbarUIController();
+            if (controller != null) {
+                controller.setShouldDelayLauncherStateAnim(true);
+            }
+        }
+
         super.onDragStart(start, startDisplacement);
 
         mMotionPauseDetector.clear();
@@ -139,6 +150,12 @@
 
     @Override
     public void onDragEnd(float velocity) {
+        LauncherTaskbarUIController controller =
+                ((BaseQuickstepLauncher) mLauncher).getTaskbarUIController();
+        if (controller != null) {
+            controller.setShouldDelayLauncherStateAnim(false);
+        }
+
         if (mStartedOverview) {
             goToOverviewOrHomeOnDragEnd(velocity);
         } else {
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 9f1e47f..bc06944 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -1410,7 +1410,7 @@
                 .setContext(mContext)
                 .setTaskId(runningTaskTarget.taskId)
                 .setComponentName(taskInfo.topActivity)
-                .setLeash(runningTaskTarget.leash.getSurfaceControl())
+                .setLeash(runningTaskTarget.leash)
                 .setSourceRectHint(
                         runningTaskTarget.taskInfo.pictureInPictureParams.getSourceRectHint())
                 .setAppBounds(taskInfo.configuration.windowConfiguration.getBounds())
diff --git a/quickstep/src/com/android/quickstep/AnimatedFloat.java b/quickstep/src/com/android/quickstep/AnimatedFloat.java
index 95c8710..6a7d066 100644
--- a/quickstep/src/com/android/quickstep/AnimatedFloat.java
+++ b/quickstep/src/com/android/quickstep/AnimatedFloat.java
@@ -42,6 +42,8 @@
 
     private final Runnable mUpdateCallback;
     private ObjectAnimator mValueAnimator;
+    // Only non-null when an animation is playing to this value.
+    private Float mEndValue;
 
     public float value;
 
@@ -68,9 +70,17 @@
         mValueAnimator = ObjectAnimator.ofFloat(this, VALUE, start, end);
         mValueAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
+            public void onAnimationStart(Animator animator) {
+                if (mValueAnimator == animator) {
+                    mEndValue = end;
+                }
+            }
+
+            @Override
             public void onAnimationEnd(Animator animator) {
                 if (mValueAnimator == animator) {
                     mValueAnimator = null;
+                    mEndValue = null;
                 }
             }
         });
@@ -103,4 +113,15 @@
     public ObjectAnimator getCurrentAnimation() {
         return mValueAnimator;
     }
+
+    public boolean isAnimating() {
+        return mValueAnimator != null;
+    }
+
+    /**
+     * Returns whether we are currently animating, and the animation's end value matches the given.
+     */
+    public boolean isAnimatingToValue(float endValue) {
+        return isAnimating() && mEndValue != null && mEndValue == endValue;
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 1d4ed4c..0cf9b4c 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -167,7 +167,7 @@
     public abstract boolean allowMinimizeSplitScreen();
 
     public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
-        return deviceState.isInDeferredGestureRegion(ev);
+        return deviceState.isInDeferredGestureRegion(ev) || deviceState.isImeRenderingNavButtons();
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/InputConsumer.java b/quickstep/src/com/android/quickstep/InputConsumer.java
index 0b09323..c455dc7 100644
--- a/quickstep/src/com/android/quickstep/InputConsumer.java
+++ b/quickstep/src/com/android/quickstep/InputConsumer.java
@@ -99,6 +99,8 @@
 
     default void onMotionEvent(MotionEvent ev) { }
 
+    default void onHoverEvent(MotionEvent ev) { }
+
     default void onKeyEvent(KeyEvent ev) { }
 
     default void onInputEvent(InputEvent ev) {
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 719c2ae..38331a9 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -326,7 +326,8 @@
         if (uiController == null) {
             return super.deferStartingActivity(deviceState, ev);
         }
-        return uiController.isEventOverAnyTaskbarItem(ev);
+        return uiController.isEventOverAnyTaskbarItem(ev)
+                || super.deferStartingActivity(deviceState, ev);
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index a72935b..af6cb84 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -15,10 +15,7 @@
  */
 package com.android.quickstep;
 
-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.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;
@@ -26,10 +23,7 @@
 import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
 import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
-import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -42,15 +36,9 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.BaseQuickstepLauncher;
-import com.android.launcher3.Hotseat;
 import com.android.launcher3.LauncherState;
-import com.android.launcher3.R;
-import com.android.launcher3.Workspace;
 import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.SpringAnimationBuilder;
-import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.states.StateAnimationConfig;
-import com.android.launcher3.util.DynamicResource;
 import com.android.launcher3.util.ObjectWrapper;
 import com.android.launcher3.views.FloatingIconView;
 import com.android.launcher3.views.FloatingView;
@@ -60,7 +48,6 @@
 import com.android.quickstep.views.FloatingWidgetView;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
-import com.android.systemui.plugins.ResourceProvider;
 import com.android.systemui.shared.system.InputConsumerController;
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 
@@ -257,61 +244,15 @@
 
     private class FloatingViewHomeAnimationFactory extends LauncherHomeAnimationFactory {
 
-        private final float mTransY;
         private final FloatingView mFloatingView;
-        private ValueAnimator mBounceBackAnimator;
 
         FloatingViewHomeAnimationFactory(FloatingView floatingView) {
             mFloatingView = floatingView;
-
-            ResourceProvider rp = DynamicResource.provider(mActivity);
-            mTransY = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp));
-        }
-
-        @Override
-        public boolean shouldPlayAtomicWorkspaceReveal() {
-            return false;
-        }
-
-        protected void bounceBackToRestingPosition() {
-            final float startValue = mTransY;
-            final float endValue = 0;
-            // Ensures the velocity is always aligned with the direction.
-            float pixelPerSecond = Math.abs(mSwipeVelocity) * Math.signum(endValue - mTransY);
-
-            DragLayer dl = mActivity.getDragLayer();
-            Workspace workspace = mActivity.getWorkspace();
-            Hotseat hotseat = mActivity.getHotseat();
-
-            ResourceProvider rp = DynamicResource.provider(mActivity);
-            ValueAnimator springTransY = new SpringAnimationBuilder(dl.getContext())
-                    .setStiffness(rp.getFloat(R.dimen.swipe_up_trans_y_stiffness))
-                    .setDampingRatio(rp.getFloat(R.dimen.swipe_up_trans_y_damping))
-                    .setMinimumVisibleChange(1f)
-                    .setStartValue(startValue)
-                    .setEndValue(endValue)
-                    .setStartVelocity(pixelPerSecond)
-                    .build(dl, VIEW_TRANSLATE_Y);
-            springTransY.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    dl.setTranslationY(0f);
-                    dl.setAlpha(1f);
-                    SCALE_PROPERTY.set(workspace, 1f);
-                    SCALE_PROPERTY.set(hotseat, 1f);
-                }
-            });
-
-            mBounceBackAnimator = springTransY;
-            mBounceBackAnimator.start();
         }
 
         @Override
         public void onCancel() {
             mFloatingView.fastFinish();
-            if (mBounceBackAnimator != null) {
-                mBounceBackAnimator.cancel();
-            }
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 75e8dd1..17baa3a 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -38,6 +38,7 @@
 import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
 
@@ -271,6 +272,14 @@
         scheduleNextTask(cmd);
     }
 
+    public void dump(PrintWriter pw) {
+        pw.println("OverviewCommandHelper:");
+        pw.println("  mPendingCommands=" + mPendingCommands.size());
+        if (!mPendingCommands.isEmpty()) {
+            pw.println("    pendingCommandType=" + mPendingCommands.get(0).type);
+        }
+    }
+
     private static class CommandInfo {
         public final long createTime = SystemClock.elapsedRealtime();
         public final int type;
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 306e864..db92e33 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -38,6 +38,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.view.Display;
 import android.view.SurfaceControl.Transaction;
 import android.view.View;
 import android.window.SplashScreen;
@@ -99,6 +100,7 @@
     private Handler mUiHandler = new Handler(Looper.getMainLooper());
 
     private static final long HOME_APPEAR_DURATION = 250;
+    private static final long RECENTS_ANIMATION_TIMEOUT = 1000;
 
     private RecentsDragLayer mDragLayer;
     private ScrimView mScrimView;
@@ -115,6 +117,11 @@
     // Strong refs to runners which are cleared when the activity is destroyed
     private RemoteAnimationFactory mActivityLaunchAnimationRunner;
 
+    // For handling degenerate cases where starting an activity doesn't actually trigger the remote
+    // animation callback
+    private final Handler mHandler = new Handler();
+    private final Runnable mAnimationStartTimeoutRunnable = this::onAnimationStartTimeout;
+
     /**
      * Init drag layer and overview panel views.
      */
@@ -219,6 +226,16 @@
         // TODO(b/137318995) This should go home, but doing so removes freeform windows
     }
 
+    /**
+     * Called if the remote animation callback from #getActivityLaunchOptions() hasn't called back
+     * in a reasonable time due to a conflict with the recents animation.
+     */
+    private void onAnimationStartTimeout() {
+        if (mActivityLaunchAnimationRunner != null) {
+            mActivityLaunchAnimationRunner.onAnimationCancelled();
+        }
+    }
+
     @Override
     public ActivityOptionsWrapper getActivityLaunchOptions(final View v, @Nullable ItemInfo item) {
         if (!(v instanceof TaskView)) {
@@ -233,6 +250,7 @@
             public void onCreateAnimation(int transit, RemoteAnimationTargetCompat[] appTargets,
                     RemoteAnimationTargetCompat[] wallpaperTargets,
                     RemoteAnimationTargetCompat[] nonAppTargets, AnimationResult result) {
+                mHandler.removeCallbacks(mAnimationStartTimeoutRunnable);
                 AnimatorSet anim = composeRecentsLaunchAnimator(taskView, appTargets,
                         wallpaperTargets, nonAppTargets);
                 anim.addListener(resetStateListener());
@@ -242,6 +260,7 @@
 
             @Override
             public void onAnimationCancelled() {
+                mHandler.removeCallbacks(mAnimationStartTimeoutRunnable);
                 onEndCallback.executeAllAndDestroy();
             }
         };
@@ -256,6 +275,10 @@
                 ActivityOptionsCompat.makeRemoteAnimation(adapterCompat),
                 onEndCallback);
         activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+        activityOptions.options.setLaunchDisplayId(
+                (v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
+                        : Display.DEFAULT_DISPLAY);
+        mHandler.postDelayed(mAnimationStartTimeoutRunnable, RECENTS_ANIMATION_TIMEOUT);
         return activityOptions;
     }
 
@@ -419,7 +442,7 @@
             RemoteAnimationTargets targets = new RemoteAnimationTargets(
                     appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
             for (RemoteAnimationTargetCompat app : targets.apps) {
-                new Transaction().setAlpha(app.leash.getSurfaceControl(), 1).apply();
+                new Transaction().setAlpha(app.leash, 1).apply();
             }
             AnimatorSet anim = new AnimatorSet();
             anim.play(controller.getAnimationPlayer());
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 19baaf1..4d79202 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -34,6 +34,7 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_GLOBAL_ACTIONS_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
@@ -52,6 +53,7 @@
 import android.content.IntentFilter;
 import android.content.res.Resources;
 import android.graphics.Region;
+import android.inputmethodservice.InputMethodService;
 import android.net.Uri;
 import android.os.Process;
 import android.os.RemoteException;
@@ -101,6 +103,9 @@
     private final RotationTouchHelper mRotationTouchHelper;
     private final TaskStackChangeListener mPipListener;
     private final List<ComponentName> mGestureBlockedActivities;
+    // Cache for better performance since it doesn't change at runtime.
+    private final boolean mCanImeRenderGesturalNavButtons =
+            InputMethodService.canImeRenderGesturalNavButtons();
 
     private final ArrayList<Runnable> mOnDestroyActions = new ArrayList<>();
 
@@ -592,6 +597,12 @@
         return mRotationTouchHelper;
     }
 
+    /** Returns whether IME is rendering nav buttons, and IME is currently showing. */
+    public boolean isImeRenderingNavButtons() {
+        return mCanImeRenderGesturalNavButtons && mMode == NO_BUTTON
+                && ((mSystemUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0);
+    }
+
     public void dump(PrintWriter pw) {
         pw.println("DeviceState:");
         pw.println("  canStartSystemGesture=" + canStartSystemGesture());
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index 8e2b566..afb4d4d 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -27,6 +27,8 @@
 import com.android.quickstep.util.TransformParams;
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 
+import java.util.ArrayList;
+
 /**
  * Glues together the necessary components to animate a remote target using a
  * {@link TaskViewSimulator}
@@ -144,20 +146,29 @@
      */
     private RemoteAnimationTargets createRemoteAnimationTargetsForTarget(
             RemoteAnimationTargets targets,
-            @Nullable RemoteAnimationTargetCompat targetToExclude) {
-        int finalLength = targets.unfilteredApps.length - (targetToExclude == null ? 0 : 1);
-        RemoteAnimationTargetCompat[] targetsWithoutExcluded =
-                new RemoteAnimationTargetCompat[finalLength];
-        int i = 0;
+            RemoteAnimationTargetCompat targetToExclude) {
+        ArrayList<RemoteAnimationTargetCompat> targetsWithoutExcluded =
+                new ArrayList<RemoteAnimationTargetCompat>();
+
         for (RemoteAnimationTargetCompat targetCompat : targets.unfilteredApps) {
             if (targetCompat == targetToExclude) {
                 continue;
             }
-            targetsWithoutExcluded[i] = targetCompat;
-            i++;
+            if (targetToExclude != null
+                    && targetToExclude.taskInfo != null
+                    && targetCompat.taskInfo != null
+                    && targetToExclude.taskInfo.parentTaskId == targetCompat.taskInfo.taskId) {
+                // Also exclude corresponding parent task
+                continue;
+            }
+
+            targetsWithoutExcluded.add(targetCompat);
         }
-        return new RemoteAnimationTargets(targetsWithoutExcluded,
-                targets.wallpapers, targets.nonApps, targets.targetMode);
+        final RemoteAnimationTargetCompat[] filteredApps =
+                targetsWithoutExcluded.toArray(
+                        new RemoteAnimationTargetCompat[targetsWithoutExcluded.size()]);
+        return new RemoteAnimationTargets(
+                filteredApps, targets.wallpapers, targets.nonApps, targets.targetMode);
     }
 
     public RemoteTargetHandle[] getRemoteTargetHandles() {
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index 8e9b668..8d9a685 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -177,10 +177,6 @@
             // No-op
         }
 
-        public boolean shouldPlayAtomicWorkspaceReveal() {
-            return true;
-        }
-
         public void setAnimation(RectFSpringAnim anim) { }
 
         public void update(RectF currentRect, float progress, float radius) { }
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index b428b67..22a30e9 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -44,8 +44,9 @@
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.system.RemoteTransitionCompat;
-import com.android.systemui.shared.system.smartspace.ISmartspaceCallback;
-import com.android.systemui.shared.system.smartspace.ISmartspaceTransitionController;
+import com.android.systemui.shared.system.smartspace.ILauncherUnlockAnimationController;
+import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
+import com.android.systemui.shared.system.smartspace.SmartspaceState;
 import com.android.wm.shell.onehanded.IOneHanded;
 import com.android.wm.shell.pip.IPip;
 import com.android.wm.shell.pip.IPipAnimationListener;
@@ -73,7 +74,7 @@
 
     private ISystemUiProxy mSystemUiProxy;
     private IPip mPip;
-    private ISmartspaceTransitionController mSmartspaceTransitionController;
+    private ISysuiUnlockAnimationController mSysuiUnlockAnimationController;
     private ISplitScreen mSplitScreen;
     private IOneHanded mOneHanded;
     private IShellTransitions mShellTransitions;
@@ -90,7 +91,7 @@
     private IPipAnimationListener mPipAnimationListener;
     private ISplitScreenListener mSplitScreenListener;
     private IStartingWindowListener mStartingWindowListener;
-    private ISmartspaceCallback mSmartspaceCallback;
+    private ILauncherUnlockAnimationController mPendingLauncherUnlockAnimationController;
     private IRecentTasksListener mRecentTasksListener;
     private final ArrayList<RemoteTransitionCompat> mRemoteTransitions = new ArrayList<>();
 
@@ -157,7 +158,8 @@
     public void setProxy(ISystemUiProxy proxy, IPip pip, ISplitScreen splitScreen,
             IOneHanded oneHanded, IShellTransitions shellTransitions,
             IStartingWindow startingWindow, IRecentTasks recentTasks,
-            ISmartspaceTransitionController smartSpaceTransitionController) {
+            ISysuiUnlockAnimationController sysuiUnlockAnimationController) {
+
         unlinkToDeath();
         mSystemUiProxy = proxy;
         mPip = pip;
@@ -165,7 +167,7 @@
         mOneHanded = oneHanded;
         mShellTransitions = shellTransitions;
         mStartingWindow = startingWindow;
-        mSmartspaceTransitionController = smartSpaceTransitionController;
+        mSysuiUnlockAnimationController = sysuiUnlockAnimationController;
         mRecentTasks = recentTasks;
         linkToDeath();
         // re-attach the listeners once missing due to setProxy has not been initialized yet.
@@ -178,8 +180,10 @@
         if (mStartingWindowListener != null && mStartingWindow != null) {
             setStartingWindowListener(mStartingWindowListener);
         }
-        if (mSmartspaceCallback != null && mSmartspaceTransitionController != null) {
-            setSmartspaceCallback(mSmartspaceCallback);
+        if (mPendingLauncherUnlockAnimationController != null
+                && mSysuiUnlockAnimationController != null) {
+            setLauncherUnlockAnimationController(mPendingLauncherUnlockAnimationController);
+            mPendingLauncherUnlockAnimationController = null;
         }
         for (int i = mRemoteTransitions.size() - 1; i >= 0; --i) {
             registerRemoteTransition(mRemoteTransitions.get(i));
@@ -731,15 +735,42 @@
     // SmartSpace transitions
     //
 
-    public void setSmartspaceCallback(ISmartspaceCallback callback) {
-        if (mSmartspaceTransitionController != null) {
+    /**
+     * Sets the instance of {@link ILauncherUnlockAnimationController} that System UI should use to
+     * control the launcher side of the unlock animation. This will also cause us to dispatch the
+     * current state of the smartspace to System UI (this will subsequently happen if the state
+     * changes).
+     */
+    public void setLauncherUnlockAnimationController(
+            ILauncherUnlockAnimationController controller) {
+        if (mSysuiUnlockAnimationController != null) {
             try {
-                mSmartspaceTransitionController.setSmartspace(callback);
+                mSysuiUnlockAnimationController.setLauncherUnlockController(controller);
+
+                if (controller != null) {
+                    controller.dispatchSmartspaceStateToSysui();
+                }
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed call setStartingWindowListener", e);
             }
+        } else {
+            mPendingLauncherUnlockAnimationController = controller;
         }
-        mSmartspaceCallback = callback;
+    }
+
+    /**
+     * Tells System UI that the Launcher's smartspace state has been updated, so that it can prepare
+     * the unlock animation accordingly.
+     */
+    public void notifySysuiSmartspaceStateUpdated(SmartspaceState state) {
+        if (mSysuiUnlockAnimationController != null) {
+            try {
+                mSysuiUnlockAnimationController.onLauncherSmartspaceStateUpdated(state);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call notifySysuiSmartspaceStateUpdated", e);
+                e.printStackTrace();
+            }
+        }
     }
 
     //
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 1af1532..914c939 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -220,6 +220,22 @@
         return mCallbacks;
     }
 
+    public void endLiveTile() {
+        if (mLastGestureState == null) {
+            return;
+        }
+        BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode()
+                && activityInterface.getCreatedActivity() != null) {
+            RecentsView recentsView = activityInterface.getCreatedActivity().getOverviewPanel();
+            if (recentsView != null) {
+                recentsView.switchToScreenshot(null,
+                        () -> recentsView.finishRecentsAnimation(true /* toRecents */,
+                                false /* shouldPip */, null));
+            }
+        }
+    }
+
     public void setLiveTileCleanUpHandler(Runnable cleanUpHandler) {
         mLiveTileCleanUpHandler = cleanUpHandler;
     }
diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.java b/quickstep/src/com/android/quickstep/TaskIconCache.java
index b5d6fae..6c71da9 100644
--- a/quickstep/src/com/android/quickstep/TaskIconCache.java
+++ b/quickstep/src/com/android/quickstep/TaskIconCache.java
@@ -28,6 +28,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.util.SparseArray;
 import android.view.accessibility.AccessibilityManager;
 
 import androidx.annotation.WorkerThread;
@@ -62,7 +63,9 @@
 
     private final Context mContext;
     private final TaskKeyLruCache<TaskCacheEntry> mIconCache;
-    private final BitmapInfo[] mDefaultIcons = new BitmapInfo[1];
+    private final SparseArray<BitmapInfo> mDefaultIcons = new SparseArray<>();
+    private BitmapInfo mDefaultIconBase = null;
+
     private final IconProvider mIconProvider;
 
     private BaseIconFactory mIconFactory;
@@ -208,12 +211,23 @@
     @WorkerThread
     private Drawable getDefaultIcon(int userId) {
         synchronized (mDefaultIcons) {
-            if (mDefaultIcons[0] == null) {
+            if (mDefaultIconBase == null) {
                 try (BaseIconFactory bif = getIconFactory()) {
-                    mDefaultIcons[0] = bif.makeDefaultIcon();
+                    mDefaultIconBase = bif.makeDefaultIcon();
                 }
             }
-            return mDefaultIcons[0].clone().withUser(UserHandle.of(userId)).newIcon(mContext);
+
+            int index;
+            if ((index = mDefaultIcons.indexOfKey(userId)) >= 0) {
+                return mDefaultIcons.valueAt(index).newIcon(mContext);
+            } else {
+                try (BaseIconFactory li = getIconFactory()) {
+                    BitmapInfo info = mDefaultIconBase.withFlags(
+                            li.getBitmapFlagOp(new IconOptions().setUser(UserHandle.of(userId))));
+                    mDefaultIcons.put(userId, info);
+                    return info.newIcon(mContext);
+                }
+            }
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 5d9a537..db1d7e7 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -36,6 +36,7 @@
 import static com.android.launcher3.anim.Interpolators.clampToProgress;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.statehandlers.DepthController.DEPTH;
+import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
 
@@ -168,7 +169,7 @@
                 ENABLE_QUICKSTEP_LIVE_TILE.get() && v.getRecentsView().getRunningTaskIndex() != -1;
         final RemoteAnimationTargets targets =
                 new RemoteAnimationTargets(appTargets, wallpaperTargets, nonAppTargets,
-                        inLiveTileMode ? MODE_CLOSING : MODE_OPENING);
+                        !ENABLE_SHELL_TRANSITIONS && inLiveTileMode ? MODE_CLOSING : MODE_OPENING);
         final RemoteAnimationTargetCompat navBarTarget = targets.getNavBarRemoteAnimationTarget();
 
         SurfaceTransactionApplier applier = new SurfaceTransactionApplier(v);
@@ -282,7 +283,8 @@
             topMostSimulators = remoteTargetHandles;
         }
 
-        if (!skipViewChanges && parallaxCenterAndAdjacentTask && topMostSimulators.length > 0) {
+        if (!skipViewChanges && parallaxCenterAndAdjacentTask && topMostSimulators != null
+                && topMostSimulators.length > 0) {
             out.addFloat(v, VIEW_ALPHA, 1, 0, clampToProgress(LINEAR, 0.2f, 0.4f));
 
             RemoteTargetHandle[] simulatorCopies = topMostSimulators;
@@ -469,7 +471,7 @@
         for (RemoteAnimationTargetCompat appTarget : appTargets) {
             final int taskId = appTarget.taskInfo != null ? appTarget.taskInfo.taskId : -1;
             final int mode = appTarget.mode;
-            final SurfaceControl leash = appTarget.leash.getSurfaceControl();
+            final SurfaceControl leash = appTarget.leash;
             if (leash == null) {
                 continue;
             }
@@ -484,7 +486,7 @@
         }
 
         for (int i = 0; i < nonAppTargets.length; ++i) {
-            final SurfaceControl leash = appTargets[i].leash.getSurfaceControl();
+            final SurfaceControl leash = appTargets[i].leash;
             if (nonAppTargets[i].windowType == TYPE_DOCK_DIVIDER && leash != null) {
                 openingTargets.add(leash);
             }
@@ -611,7 +613,7 @@
         boolean hasSurfaceToAnimate = false;
         for (int i = 0; i < nonApps.length; ++i) {
             final RemoteAnimationTargetCompat targ = nonApps[i];
-            final SurfaceControl leash = targ.leash.getSurfaceControl();
+            final SurfaceControl leash = targ.leash;
             if (targ.windowType == TYPE_DOCK_DIVIDER && leash != null) {
                 auxiliarySurfaces.add(leash);
                 hasSurfaceToAnimate = true;
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index f620b62..0c34ead 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -31,8 +31,9 @@
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SPLIT_SCREEN;
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_STARTING_WINDOW;
-import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER;
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
 
 import android.annotation.TargetApi;
@@ -104,7 +105,7 @@
 import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
 import com.android.systemui.shared.system.InputConsumerController;
 import com.android.systemui.shared.system.InputMonitorCompat;
-import com.android.systemui.shared.system.smartspace.ISmartspaceTransitionController;
+import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
 import com.android.systemui.shared.tracing.ProtoTraceable;
 import com.android.wm.shell.onehanded.IOneHanded;
 import com.android.wm.shell.pip.IPip;
@@ -161,15 +162,15 @@
                     bundle.getBinder(KEY_EXTRA_SHELL_SHELL_TRANSITIONS));
             IStartingWindow startingWindow = IStartingWindow.Stub.asInterface(
                     bundle.getBinder(KEY_EXTRA_SHELL_STARTING_WINDOW));
-            ISmartspaceTransitionController smartspaceTransitionController =
-                    ISmartspaceTransitionController.Stub.asInterface(
-                            bundle.getBinder(KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER));
+            ISysuiUnlockAnimationController launcherUnlockAnimationController =
+                    ISysuiUnlockAnimationController.Stub.asInterface(
+                            bundle.getBinder(KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER));
             IRecentTasks recentTasks = IRecentTasks.Stub.asInterface(
                     bundle.getBinder(KEY_EXTRA_RECENT_TASKS));
             MAIN_EXECUTOR.execute(() -> {
                 SystemUiProxy.INSTANCE.get(TouchInteractionService.this).setProxy(proxy, pip,
                         splitscreen, onehanded, shellTransitions, startingWindow, recentTasks,
-                        smartspaceTransitionController);
+                        launcherUnlockAnimationController);
                 TouchInteractionService.this.initInputMonitor();
                 preloadOverview(true /* fromInit */);
             });
@@ -479,6 +480,15 @@
             mOverviewComponentObserver.onSystemUiStateChanged();
             mTaskbarManager.onSystemUiFlagsChanged(systemUiStateFlags);
 
+            boolean wasExpanded = (lastSysUIFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
+            boolean isExpanded =
+                    (systemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
+            if (wasExpanded != isExpanded && isExpanded) {
+                // End live tile when expanding the notification panel for the first time from
+                // overview.
+                mTaskAnimationManager.endLiveTile();
+            }
+
             if ((lastSysUIFlags & SYSUI_STATE_TRACING_ENABLED) !=
                     (systemUiStateFlags & SYSUI_STATE_TRACING_ENABLED)) {
                 // Update the tracing state
@@ -932,6 +942,9 @@
             if (mOverviewComponentObserver != null) {
                 mOverviewComponentObserver.dump(pw);
             }
+            if (mOverviewCommandHelper != null) {
+                mOverviewCommandHelper.dump(pw);
+            }
             if (mGestureState != null) {
                 mGestureState.dump(pw);
             }
@@ -951,6 +964,7 @@
             RecentsModel.INSTANCE.get(this).dump("", pw);
             pw.println("ProtoTrace:");
             pw.println("  file=" + ProtoTracer.INSTANCE.get(this).getTraceFile());
+            mTaskbarManager.dumpLogs("", pw);
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
index b0df286..02ac48e 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
@@ -101,6 +101,13 @@
     }
 
     @Override
+    public void onHoverEvent(MotionEvent ev) {
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+            mActivity.dispatchGenericMotionEvent(ev);
+        }
+    }
+
+    @Override
     public void onKeyEvent(KeyEvent ev) {
         if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             switch (ev.getKeyCode()) {
diff --git a/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java b/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java
index c2101a8..91b53c7 100644
--- a/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java
+++ b/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java
@@ -71,7 +71,16 @@
 
     private boolean onInputConsumerEvent(InputEvent ev) {
         if (ev instanceof MotionEvent) {
-            onInputConsumerMotionEvent((MotionEvent) ev);
+            MotionEvent event = (MotionEvent) ev;
+            int action = event.getActionMasked();
+            boolean isHoverEvent = action == MotionEvent.ACTION_HOVER_ENTER
+                    || action == MotionEvent.ACTION_HOVER_MOVE
+                    || action == MotionEvent.ACTION_HOVER_EXIT;
+            if (isHoverEvent) {
+                onInputConsumerHoverEvent(event);
+            } else {
+                onInputConsumerMotionEvent(event);
+            }
         } else if (ev instanceof KeyEvent) {
             initInputConsumerIfNeeded();
             mInputConsumer.onKeyEvent((KeyEvent) ev);
@@ -113,6 +122,15 @@
         return true;
     }
 
+    private void onInputConsumerHoverEvent(MotionEvent ev) {
+        initInputConsumerIfNeeded();
+        if (mInputConsumer != null) {
+            SimpleOrientationTouchTransformer.INSTANCE.get(mContext).transform(ev,
+                    mRotationSupplier.get());
+            mInputConsumer.onHoverEvent(ev);
+        }
+    }
+
     public void destroy() {
         if (mTouchInProgress) {
             mDestroyPending = true;
diff --git a/quickstep/src/com/android/quickstep/util/TransformParams.java b/quickstep/src/com/android/quickstep/util/TransformParams.java
index 03d7a37..75d6001 100644
--- a/quickstep/src/com/android/quickstep/util/TransformParams.java
+++ b/quickstep/src/com/android/quickstep/util/TransformParams.java
@@ -174,10 +174,10 @@
             RemoteAnimationTargetCompat app = targets.unfilteredApps[i];
             if (app.mode == targets.targetMode) {
                 if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_RECENTS) {
-                    return app.leash.getSurfaceControl();
+                    return app.leash;
                 }
             } else {
-                return app.leash.getSurfaceControl();
+                return app.leash;
             }
         }
         return null;
diff --git a/quickstep/src/com/android/quickstep/util/WorkspaceUnlockAnim.java b/quickstep/src/com/android/quickstep/util/WorkspaceUnlockAnim.java
new file mode 100644
index 0000000..b01447e
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/WorkspaceUnlockAnim.java
@@ -0,0 +1,82 @@
+/*
+ * 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 com.android.launcher3.Launcher;
+import com.android.launcher3.Utilities;
+
+/**
+ * Animation to animate in a workspace during the unlock transition.
+ */
+public class WorkspaceUnlockAnim {
+    /** Scale for the workspace icons at the beginning of the animation. */
+    private static final float START_SCALE = 0.9f;
+
+    /**
+     * Starting translation Y values for the animation. We use a larger value if we're animating in
+     * from a swipe, since there is more perceived upward movement when we unlock from a swipe.
+     */
+    private static final int START_TRANSLATION_DP = 15;
+    private static final int START_TRANSLATION_SWIPE_DP = 60;
+
+    private Launcher mLauncher;
+    private float mUnlockAmount = 0f;
+
+    public WorkspaceUnlockAnim(Launcher launcher) {
+        mLauncher = launcher;
+    }
+
+    /**
+     * Called when we're about to make the Launcher window visible and play the unlock animation.
+     *
+     * This is a blocking call so that System UI knows it's safe to show the Launcher window without
+     * causing the Launcher contents to flicker on screen. Do not do anything expensive here.
+     */
+    public void prepareForUnlock() {
+        mLauncher.getWorkspace().setAlpha(0f);
+        mLauncher.getHotseat().setAlpha(0f);
+
+        mUnlockAmount = 0f;
+    }
+
+    public void setUnlockAmount(float amount, boolean fromSwipe) {
+        mUnlockAmount = amount;
+
+        final float amountInverse = 1f - amount;
+        final float scale = START_SCALE + (1f - START_SCALE) * amount;
+
+        mLauncher.getWorkspace().setScaleX(scale);
+        mLauncher.getWorkspace().setScaleY(scale);
+        mLauncher.getWorkspace().setAlpha(amount);
+        mLauncher.getWorkspace().setPivotToScaleWithSelf(mLauncher.getHotseat());
+
+        mLauncher.getHotseat().setScaleX(scale);
+        mLauncher.getHotseat().setScaleY(scale);
+        mLauncher.getHotseat().setAlpha(amount);
+
+        if (fromSwipe) {
+            mLauncher.getWorkspace().setTranslationY(
+                    Utilities.dpToPx(START_TRANSLATION_SWIPE_DP) * amountInverse);
+            mLauncher.getHotseat().setTranslationY(
+                    Utilities.dpToPx(START_TRANSLATION_SWIPE_DP) * amountInverse);
+        } else {
+            mLauncher.getWorkspace().setTranslationY(
+                    Utilities.dpToPx(START_TRANSLATION_DP) * amountInverse);
+            mLauncher.getHotseat().setTranslationY(
+                    Utilities.dpToPx(START_TRANSLATION_DP) * amountInverse);
+        }
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 0294828..fcc6272 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -16,6 +16,8 @@
 
 package com.android.quickstep.views;
 
+import static com.android.quickstep.SysUINavigationMode.Mode.THREE_BUTTONS;
+
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Rect;
@@ -33,6 +35,7 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
+import com.android.launcher3.uioverrides.ApiWrapper;
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
 import com.android.quickstep.SysUINavigationMode;
@@ -152,7 +155,7 @@
     public void setInsets(Rect insets) {
         mInsets.set(insets);
         updateVerticalMargin(SysUINavigationMode.getMode(getContext()));
-        updateHorizontalPadding();
+        updatePaddingAndTranslations();
     }
 
     public void updateHiddenFlags(@ActionsHiddenFlags int visibilityFlags, boolean enable) {
@@ -195,8 +198,37 @@
         return mMultiValueAlpha.getProperty(INDEX_FULLSCREEN_ALPHA);
     }
 
-    private void updateHorizontalPadding() {
-        setPadding(mInsets.left, 0, mInsets.right, 0);
+    /**
+     * Aligns OverviewActionsView vertically with and offsets horizontal position based on
+     * 3 button nav container in taskbar.
+     */
+    private void updatePaddingAndTranslations() {
+        boolean alignFor3ButtonTaskbar = mDp.isTaskbarPresent &&
+                SysUINavigationMode.getMode(getContext()) == THREE_BUTTONS;
+        if (alignFor3ButtonTaskbar) {
+            // Add extra horizontal spacing
+            int additionalPadding = ApiWrapper.getHotseatEndOffset(getContext());
+            if (isLayoutRtl()) {
+                setPadding(mInsets.left + additionalPadding, 0, mInsets.right, 0);
+            } else {
+                setPadding(mInsets.left, 0, mInsets.right + additionalPadding, 0);
+            }
+
+            // Align vertically, using taskbar height + mDp.taskbarOffsetY() to guestimate
+            // where the button nav top is
+            View startActionView = findViewById(R.id.action_screenshot);
+            int marginBottom = getOverviewActionsBottomMarginPx(
+                    SysUINavigationMode.getMode(getContext()), mDp);
+            int actionsTop = (mDp.heightPx - marginBottom - mInsets.bottom);
+            int navTop = mDp.heightPx - (mDp.taskbarSize + mDp.getTaskbarOffsetY());
+            int transY = navTop - actionsTop
+                    + ((mDp.taskbarSize - startActionView.getHeight()) / 2);
+            setTranslationY(transY);
+        } else {
+            setPadding(mInsets.left, 0, mInsets.right, 0);
+            setTranslationX(0);
+            setTranslationY(0);
+        }
     }
 
     /** Updates vertical margins for different navigation mode or configuration changes. */
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index e863a89..13a2bda 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -2783,6 +2783,8 @@
             }
         }
 
+        announceForAccessibility(getResources().getString(R.string.task_view_closed));
+
         float dismissTranslationInterpolationEnd = 1;
         boolean closeGapBetweenClearAll = false;
         boolean isClearAllHidden = isClearAllHidden();
@@ -4137,8 +4139,10 @@
             anim.play(ObjectAnimator.ofFloat(getPageAt(centerTaskIndex),
                     mOrientationHandler.getPrimaryViewTranslate(), primaryTranslation));
             int runningTaskIndex = recentsView.getRunningTaskIndex();
-            if (ENABLE_QUICKSTEP_LIVE_TILE.get() && runningTaskIndex != -1
-                    && runningTaskIndex != taskIndex) {
+            if (ENABLE_QUICKSTEP_LIVE_TILE.get()
+                    && runningTaskIndex != -1
+                    && runningTaskIndex != taskIndex
+                    && recentsView.getRemoteTargetHandles() != null) {
                 for (RemoteTargetHandle remoteHandle : recentsView.getRemoteTargetHandles()) {
                     anim.play(ObjectAnimator.ofFloat(
                             remoteHandle.getTaskViewSimulator().taskPrimaryTranslation,
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 3e0eb91..2a442a7 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -16,6 +16,7 @@
 
 package com.android.quickstep.views;
 
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.widget.Toast.LENGTH_SHORT;
 
 import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
@@ -51,6 +52,7 @@
 import android.util.AttributeSet;
 import android.util.FloatProperty;
 import android.util.Log;
+import android.view.Display;
 import android.view.MotionEvent;
 import android.view.TouchDelegate;
 import android.view.View;
@@ -638,6 +640,7 @@
                 // If the recents animation is cancelled somehow between the parent if block and
                 // here, try to launch the task as a non live tile task.
                 launchTaskAnimated();
+                mIsClickableAsLiveTile = true;
                 return;
             }
 
@@ -659,6 +662,9 @@
 
                 @Override
                 public void onAnimationEnd(Animator animator) {
+                    if (mTask != null && mTask.key.displayId != getRootViewDisplayId()) {
+                        launchTaskAnimated();
+                    }
                     mIsClickableAsLiveTile = true;
                 }
             });
@@ -1519,7 +1525,8 @@
 
 
     private int getRootViewDisplayId() {
-        return getRootView().getDisplay().getDisplayId();
+        Display  display = getRootView().getDisplay();
+        return display != null ? display.getDisplayId() : DEFAULT_DISPLAY;
     }
 
     /**
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index 318f04e..1cb7529 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -20,9 +20,7 @@
 
 import static com.android.quickstep.NavigationModeSwitchRule.Mode.ALL;
 import static com.android.quickstep.NavigationModeSwitchRule.Mode.THREE_BUTTON;
-import static com.android.quickstep.NavigationModeSwitchRule.Mode.TWO_BUTTON;
 import static com.android.quickstep.NavigationModeSwitchRule.Mode.ZERO_BUTTON;
-import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_2BUTTON_OVERLAY;
 import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_3BUTTON_OVERLAY;
 import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_GESTURAL_OVERLAY;
 
@@ -61,7 +59,7 @@
     public static final int WAIT_TIME_MS = 10000;
 
     public enum Mode {
-        THREE_BUTTON, TWO_BUTTON, ZERO_BUTTON, ALL
+        THREE_BUTTON, ZERO_BUTTON, ALL
     }
 
     // Annotation for tests that need to be run with quickstep enabled and disabled.
@@ -99,9 +97,6 @@
                         if (mode == ZERO_BUTTON || mode == ALL) {
                             evaluateWithZeroButtons();
                         }
-                        if (mode == TWO_BUTTON || mode == ALL) {
-                            evaluateWithTwoButtons();
-                        }
                         if (mode == THREE_BUTTON || mode == ALL) {
                             evaluateWithThreeButtons();
                         }
@@ -123,13 +118,6 @@
                     }
                 }
 
-                private void evaluateWithTwoButtons() throws Throwable {
-                    if (setActiveOverlay(mLauncher, NAV_BAR_MODE_2BUTTON_OVERLAY,
-                            LauncherInstrumentation.NavigationModel.TWO_BUTTON, description)) {
-                        base.evaluate();
-                    }
-                }
-
                 private void evaluateWithZeroButtons() throws Throwable {
                     if (setActiveOverlay(mLauncher, NAV_BAR_MODE_GESTURAL_OVERLAY,
                             LauncherInstrumentation.NavigationModel.ZERO_BUTTON, description)) {
@@ -145,9 +133,7 @@
     public static String getCurrentOverlayPackage(int currentInteractionMode) {
         return QuickStepContract.isGesturalMode(currentInteractionMode)
                 ? NAV_BAR_MODE_GESTURAL_OVERLAY
-                : QuickStepContract.isSwipeUpMode(currentInteractionMode)
-                        ? NAV_BAR_MODE_2BUTTON_OVERLAY
-                        : NAV_BAR_MODE_3BUTTON_OVERLAY;
+                : NAV_BAR_MODE_3BUTTON_OVERLAY;
     }
 
     private static LauncherInstrumentation.NavigationModel currentSysUiNavigationMode() {
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
index f44a812..75d057e 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -16,23 +16,16 @@
 
 package com.android.quickstep;
 
-import static com.android.launcher3.util.RaceConditionReproducer.enterEvt;
-import static com.android.launcher3.util.RaceConditionReproducer.exitEvt;
-
 import android.content.Intent;
 
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.launcher3.Launcher;
 import com.android.launcher3.ui.TaplTestsLauncher3;
 import com.android.launcher3.util.RaceConditionReproducer;
-import com.android.quickstep.NavigationModeSwitchRule.Mode;
 import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
-import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -66,21 +59,6 @@
     }
 
     @Test
-    @Ignore // Ignoring until race condition repro framework is changes for multi-process case.
-    @NavigationModeSwitch(mode = Mode.TWO_BUTTON)
-    public void testPressHome() {
-        runTest(enterEvt(Launcher.ON_CREATE_EVT),
-                exitEvt(Launcher.ON_CREATE_EVT),
-                enterEvt(OtherActivityInputConsumer.DOWN_EVT),
-                exitEvt(OtherActivityInputConsumer.DOWN_EVT));
-
-        runTest(enterEvt(OtherActivityInputConsumer.DOWN_EVT),
-                exitEvt(OtherActivityInputConsumer.DOWN_EVT),
-                enterEvt(Launcher.ON_CREATE_EVT),
-                exitEvt(Launcher.ON_CREATE_EVT));
-    }
-
-    @Test
     @NavigationModeSwitch
     public void testStressPressHome() {
         for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
diff --git a/res/drawable/bg_all_apps_bottom_sheet.xml b/res/drawable/bg_all_apps_bottom_sheet.xml
new file mode 100644
index 0000000..dba2fee
--- /dev/null
+++ b/res/drawable/bg_all_apps_bottom_sheet.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2022 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ripple android:color="?android:attr/colorControlHighlight"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+    <item>
+        <shape android:shape="rectangle"
+            android:tint="?colorButtonNormal">
+            <corners
+                android:topLeftRadius="@dimen/dialogCornerRadius"
+                android:topRightRadius="@dimen/dialogCornerRadius"/>
+            <solid android:color="?attr/allAppsScrimColor" />
+        </shape>
+    </item>
+</ripple>
\ No newline at end of file
diff --git a/res/layout/secondary_launcher.xml b/res/layout/secondary_launcher.xml
index b15a320..3ccd4f2 100644
--- a/res/layout/secondary_launcher.xml
+++ b/res/layout/secondary_launcher.xml
@@ -41,7 +41,8 @@
         android:contentDescription="@string/all_apps_button_label"
         android:onClick="onAppsButtonClicked" />
 
-    <com.android.launcher3.allapps.AllAppsContainerView
+    <view
+        class="com.android.launcher3.allapps.ActivityAllAppsContainerView"
         android:id="@+id/apps_view"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
@@ -121,5 +122,5 @@
             android:textSize="16sp" />
 
         <include layout="@layout/all_apps_fast_scroller" />
-    </com.android.launcher3.allapps.AllAppsContainerView>
+    </view>
 </com.android.launcher3.secondarydisplay.SecondaryDragLayer>
\ No newline at end of file
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 3727932..157cefa 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -20,4 +20,7 @@
 
 <!-- Widgets pickers -->
     <dimen name="widget_list_horizontal_margin">32dp</dimen>
+
+<!-- AllApps -->
+    <dimen name="all_apps_bottom_sheet_horizontal_padding">32dp</dimen>
 </resources>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
new file mode 100644
index 0000000..9d7941f
--- /dev/null
+++ b/res/values-sw720dp/dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at`
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+<!-- AllApps -->
+    <dimen name="all_apps_bottom_sheet_horizontal_padding">41dp</dimen>
+</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 6db0af3..0b04b86 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -187,6 +187,10 @@
         <attr name="minCellHeight" format="float" />
         <attr name="minCellWidth" format="float" />
         <!-- defaults to minCellHeight, if not specified -->
+        <attr name="minCellHeightLandscape" format="float" />
+        <!-- defaults to minCellWidth, if not specified -->
+        <attr name="minCellWidthLandscape" format="float" />
+        <!-- defaults to minCellHeight, if not specified -->
         <attr name="minCellHeightTwoPanelPortrait" format="float" />
         <!-- defaults to minCellWidth, if not specified -->
         <attr name="minCellWidthTwoPanelPortrait" format="float" />
@@ -244,6 +248,8 @@
         <!-- defaults to borderSpaceDps, if not specified -->
         <attr name="hotseatBorderSpace" format="float" />
         <!-- defaults to hotseatBorderSpace, if not specified -->
+        <attr name="hotseatBorderSpaceLandscape" format="float" />
+        <!-- defaults to hotseatBorderSpace, if not specified -->
         <attr name="hotseatBorderSpaceTwoPanelLandscape" format="float" />
         <!-- defaults to hotseatBorderSpace, if not specified -->
         <attr name="hotseatBorderSpaceTwoPanelPortrait" format="float" />
@@ -270,6 +276,8 @@
         <!-- Margin on left and right of the workspace when GridDisplayOption#isScalable is true -->
         <attr name="horizontalMargin" format="float"/>
         <!-- defaults to horizontalMargin if not specified -->
+        <attr name="horizontalMarginLandscape" format="float"/>
+        <!-- defaults to horizontalMargin if not specified -->
         <attr name="horizontalMarginTwoPanelLandscape" format="float"/>
         <!-- defaults to horizontalMargin if not specified -->
         <attr name="horizontalMarginTwoPanelPortrait" format="float"/>
diff --git a/res/values/config.xml b/res/values/config.xml
index d5629b5..1c996eb 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -139,19 +139,9 @@
 
     <item name="swipe_up_scale_start"  type="dimen" format="float">0.88</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>
-
-    <item name="swipe_up_trans_y_damping" type="dimen" format="float">0.45</item>
-    <item name="swipe_up_trans_y_stiffness" type="dimen" format="float">200</item>
-
     <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_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="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>
@@ -167,12 +157,6 @@
 
     <array name="dynamic_resources">
         <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_launcher_alpha_max_progress</item>
-        <item>@dimen/swipe_up_low_swipe_duration_multiplier</item>
         <item>@dimen/swipe_up_max_velocity</item>
     </array>
 
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 086a254..e215db9 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -33,6 +33,7 @@
     <dimen name="dynamic_grid_hotseat_top_padding">8dp</dimen>
     <dimen name="dynamic_grid_hotseat_bottom_padding">2dp</dimen>
     <dimen name="dynamic_grid_hotseat_bottom_tall_padding">0dp</dimen>
+    <dimen name="inline_qsb_bottom_margin">0dp</dimen>
 
     <!-- Qsb -->
     <!-- Used for adjusting the position of QSB when placed in hotseat. This is a ratio and a higher
@@ -114,6 +115,7 @@
     <dimen name="all_apps_content_fade_in_offset">150dp</dimen>
     <dimen name="all_apps_tip_bottom_margin">8dp</dimen>
     <dimen name="all_apps_height_extra">6dp</dimen>
+    <dimen name="all_apps_bottom_sheet_horizontal_padding">0dp</dimen>
 
     <!-- The size of corner radius of the arrow in the arrow toast. -->
     <dimen name="arrow_toast_corner_radius">2dp</dimen>
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index dd56ca3..b47554f 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -49,7 +49,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
 import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider;
 import com.android.launcher3.allapps.search.SearchAdapterProvider;
 import com.android.launcher3.logging.InstanceId;
@@ -182,6 +182,10 @@
         }
         ActivityOptions options =
                 ActivityOptions.makeClipRevealAnimation(v, left, top, width, height);
+
+        options.setLaunchDisplayId(
+                (v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
+                        : Display.DEFAULT_DISPLAY);
         RunnableList callback = new RunnableList();
         addOnResumeCallback(callback::executeAllAndDestroy);
         return new ActivityOptionsWrapper(options, callback);
@@ -336,7 +340,8 @@
      * Creates and returns {@link SearchAdapterProvider} for build variant specific search result
      * views
      */
-    public SearchAdapterProvider createSearchAdapterProvider(AllAppsContainerView allapps) {
-        return new DefaultSearchAdapterProvider(this, allapps);
+    public SearchAdapterProvider<?> createSearchAdapterProvider(
+            ActivityAllAppsContainerView<?> allApps) {
+        return new DefaultSearchAdapterProvider(this);
     }
 }
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index adb1613..11f58e7 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -238,9 +238,19 @@
         mActivity = ActivityContext.lookupContext(context);
         DeviceProfile deviceProfile = mActivity.getDeviceProfile();
 
-        mBorderSpace = mContainerType == FOLDER
-                ? new Point(deviceProfile.folderCellLayoutBorderSpacePx)
-                : new Point(deviceProfile.cellLayoutBorderSpacePx);
+        switch (mContainerType) {
+            case FOLDER:
+                mBorderSpace = new Point(deviceProfile.folderCellLayoutBorderSpacePx);
+                break;
+            case HOTSEAT:
+                mBorderSpace = new Point(deviceProfile.hotseatBorderSpace,
+                        deviceProfile.hotseatBorderSpace);
+                break;
+            case WORKSPACE:
+            default:
+                mBorderSpace = new Point(deviceProfile.cellLayoutBorderSpacePx);
+                break;
+        }
 
         mCellWidth = mCellHeight = -1;
         mFixedCellWidth = mFixedCellHeight = -1;
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index ab8e5e7..d348602 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -61,6 +61,7 @@
     public final boolean isPhone;
     public final boolean transposeLayoutWithOrientation;
     public final boolean isTwoPanels;
+    public final boolean isQsbInline;
 
     // Device properties in current orientation
     public final boolean isLandscape;
@@ -161,10 +162,11 @@
     public final int hotseatBarSidePaddingStartPx;
     public final int hotseatBarSidePaddingEndPx;
     public final int hotseatQsbHeight;
-    public final int hotseatBorderSpace;
+    public int hotseatBorderSpace;
 
     public final float qsbBottomMarginOriginalPx;
     public int qsbBottomMarginPx;
+    public int qsbWidth; // only used when isQsbInline
 
     // All apps
     public Point allAppsBorderSpacePx;
@@ -174,6 +176,7 @@
     public int allAppsIconSizePx;
     public int allAppsIconDrawablePaddingPx;
     public int allAppsLeftRightPadding;
+    public int allAppsLeftRightMargin;
     public final int numShownAllAppsColumns;
     public float allAppsIconTextSizePx;
 
@@ -235,26 +238,35 @@
 
         isScalableGrid = inv.isScalable && !isVerticalBarLayout() && !isMultiWindowMode;
 
-        // Determine sizes.
-        widthPx = windowBounds.bounds.width();
-        heightPx = windowBounds.bounds.height();
-        availableWidthPx = windowBounds.availableSize.x;
-        availableHeightPx = windowBounds.availableSize.y;
-
+        // Determine device posture.
         mInfo = info;
         isTablet = info.isTablet(windowBounds);
         isPhone = !isTablet;
         isTwoPanels = isTablet && useTwoPanels;
+        isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS
+                && FeatureFlags.ENABLE_TASKBAR.get();
 
-        aspectRatio = ((float) Math.max(widthPx, heightPx)) / Math.min(widthPx, heightPx);
-        boolean isTallDevice = Float.compare(aspectRatio, TALL_DEVICE_ASPECT_RATIO_THRESHOLD) >= 0;
-        mQsbCenterFactor = context.getResources().getFloat(R.dimen.qsb_center_factor);
-        // Some more constants
+        // Some more constants.
         context = getContext(context, info, isVerticalBarLayout()
                 ? Configuration.ORIENTATION_LANDSCAPE
                 : Configuration.ORIENTATION_PORTRAIT);
-        mMetrics = context.getResources().getDisplayMetrics();
         final Resources res = context.getResources();
+        mMetrics = res.getDisplayMetrics();
+
+        // Determine sizes.
+        widthPx = windowBounds.bounds.width();
+        heightPx = windowBounds.bounds.height();
+        availableWidthPx = windowBounds.availableSize.x;
+        int taskbarInset = isTaskbarPresent
+                ? ResourceUtils.getNavbarSize(
+                        isLandscape ? "navigation_bar_height_landscape" : "navigation_bar_height",
+                        res)
+                : 0;
+        availableHeightPx =  windowBounds.availableSize.y - taskbarInset;
+
+        aspectRatio = ((float) Math.max(widthPx, heightPx)) / Math.min(widthPx, heightPx);
+        boolean isTallDevice = Float.compare(aspectRatio, TALL_DEVICE_ASPECT_RATIO_THRESHOLD) >= 0;
+        mQsbCenterFactor = res.getFloat(R.dimen.qsb_center_factor);
 
         if (isTwoPanels) {
             if (isLandscape) {
@@ -270,9 +282,6 @@
             }
         }
 
-        hotseatQsbHeight = res.getDimensionPixelSize(R.dimen.qsb_widget_height);
-        isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS
-                && FeatureFlags.ENABLE_TASKBAR.get();
         if (isTaskbarPresent) {
             taskbarSize = res.getDimensionPixelSize(R.dimen.taskbar_size);
         }
@@ -333,6 +342,8 @@
 
         workspaceCellPaddingXPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_x);
 
+        hotseatQsbHeight = res.getDimensionPixelSize(R.dimen.qsb_widget_height);
+        isQsbInline = isTablet && isLandscape && !isTwoPanels && hotseatQsbHeight > 0;
         numShownHotseatIcons =
                 isTwoPanels ? inv.numDatabaseHotseatIcons : inv.numShownHotseatIcons;
         numShownAllAppsColumns =
@@ -340,10 +351,17 @@
         hotseatBarSizeExtraSpacePx = 0;
         hotseatBarTopPaddingPx =
                 res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding);
-        hotseatBarBottomPaddingPx = (isTallDevice ? res.getDimensionPixelSize(
-                R.dimen.dynamic_grid_hotseat_bottom_tall_padding)
-                : res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_non_tall_padding))
-                + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
+        if (isQsbInline) {
+            hotseatBarBottomPaddingPx = res.getDimensionPixelSize(R.dimen.inline_qsb_bottom_margin);
+            qsbWidth = calculateQsbWidth();
+        } else {
+            hotseatBarBottomPaddingPx = (isTallDevice ? res.getDimensionPixelSize(
+                    R.dimen.dynamic_grid_hotseat_bottom_tall_padding)
+                    : res.getDimensionPixelSize(
+                            R.dimen.dynamic_grid_hotseat_bottom_non_tall_padding))
+                    + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
+            qsbWidth = 0;
+        }
         hotseatBarSidePaddingEndPx =
                 res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_side_padding);
         // Add a bit of space between nav bar and hotseat in vertical bar layout.
@@ -472,6 +490,14 @@
                 new DotRenderer(allAppsIconSizePx, dotPath, DEFAULT_DOT_SIZE);
     }
 
+    private int calculateQsbWidth() {
+        return cellWidthPx * inv.numColumns
+                + cellLayoutBorderSpacePx.x * (inv.numColumns - 1)
+                - (cellWidthPx - iconSizePx) // left and right cell space
+                - iconSizePx * numShownHotseatIcons
+                - hotseatBorderSpace * numShownHotseatIcons;
+    }
+
     private int getHorizontalMarginPx(InvariantDeviceProfile idp, Resources res) {
         if (isVerticalBarLayout()) {
             return 0;
@@ -595,11 +621,16 @@
                 + textHeight + (topBottomPadding * 2);
     }
 
-    private void updateAllAppsWidth() {
-        if (isTwoPanels) {
+    private void updateAllAppsWidth(Resources res) {
+
+        if (isTablet) {
+            allAppsLeftRightPadding =
+                    res.getDimensionPixelSize(R.dimen.all_apps_bottom_sheet_horizontal_padding)
+                            + cellLayoutPaddingLeftRightPx;
             int usedWidth = (allAppsCellWidthPx * numShownAllAppsColumns)
-                    + (allAppsBorderSpacePx.x * (numShownAllAppsColumns + 1));
-            allAppsLeftRightPadding = Math.max(1, (availableWidthPx - usedWidth) / 2);
+                    + (allAppsBorderSpacePx.x * (numShownAllAppsColumns + 1))
+                    + allAppsLeftRightPadding * 2;
+            allAppsLeftRightMargin = Math.max(1, (availableWidthPx - usedWidth) / 2);
         } else {
             allAppsLeftRightPadding =
                     desiredWorkspaceHorizontalMarginPx + cellLayoutPaddingLeftRightPx;
@@ -709,13 +740,19 @@
             allAppsCellHeightPx = getCellSize().y;
         }
         allAppsCellWidthPx = allAppsIconSizePx + (2 * allAppsIconDrawablePaddingPx);
-        updateAllAppsWidth();
+        updateAllAppsWidth(res);
 
         if (isVerticalLayout) {
             hideWorkspaceLabelsIfNotEnoughSpace();
         }
 
         // Hotseat
+        hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics, scale);
+        if (isQsbInline) {
+            qsbWidth = calculateQsbWidth();
+        } else {
+            qsbWidth = 0;
+        }
         updateHotseatIconSize(iconSizePx);
 
         if (!isVerticalLayout) {
@@ -894,15 +931,24 @@
         } else if (isTaskbarPresent) {
             int hotseatHeight = workspacePadding.bottom;
             int taskbarOffset = getTaskbarOffsetY();
+            int additionalLeftSpace = 0;
+
+            // Center the QSB with hotseat and push icons to the right
+            if (isQsbInline) {
+                additionalLeftSpace = qsbWidth + hotseatBorderSpace;
+            }
+
             int hotseatTopDiff = hotseatHeight - taskbarOffset;
 
             int endOffset = ApiWrapper.getHotseatEndOffset(context);
             int requiredWidth = iconSizePx * numShownHotseatIcons
-                    + hotseatBorderSpace * (numShownHotseatIcons - 1);
+                    + hotseatBorderSpace * (numShownHotseatIcons - 1)
+                    + additionalLeftSpace;
 
             int hotseatSize = Math.min(requiredWidth, availableWidthPx - endOffset);
             int sideSpacing = (availableWidthPx - hotseatSize) / 2;
-            mHotseatPadding.set(sideSpacing, hotseatTopDiff, sideSpacing, taskbarOffset);
+            mHotseatPadding.set(sideSpacing + additionalLeftSpace, hotseatTopDiff, sideSpacing,
+                    taskbarOffset);
 
             if (endOffset > sideSpacing) {
                 int diff = Utilities.isRtl(context.getResources())
@@ -935,6 +981,10 @@
      * Returns the number of pixels the QSB is translated from the bottom of the screen.
      */
     public int getQsbOffsetY() {
+        if (isQsbInline) {
+            return hotseatBarBottomPaddingPx;
+        }
+
         int freeSpace = isTaskbarPresent
                 ? workspacePadding.bottom
                 : hotseatBarSizePx - hotseatCellHeightPx - hotseatQsbHeight;
@@ -952,7 +1002,11 @@
      * Returns the number of pixels the taskbar is translated from the bottom of the screen.
      */
     public int getTaskbarOffsetY() {
-        return (getQsbOffsetY() - taskbarSize) / 2;
+        if (isQsbInline) {
+            return getQsbOffsetY() + (Math.abs(hotseatQsbHeight - iconSizePx) / 2);
+        } else {
+            return (getQsbOffsetY() - taskbarSize) / 2;
+        }
     }
 
     /**
@@ -1101,7 +1155,10 @@
         writer.println(prefix + pxToDpStr("allAppsIconDrawablePaddingPx",
                 allAppsIconDrawablePaddingPx));
         writer.println(prefix + pxToDpStr("allAppsCellHeightPx", allAppsCellHeightPx));
+        writer.println(prefix + pxToDpStr("allAppsCellWidthPx", allAppsCellWidthPx));
         writer.println(prefix + "\tnumShownAllAppsColumns: " + numShownAllAppsColumns);
+        writer.println(prefix + pxToDpStr("allAppsLeftRightPadding", allAppsLeftRightPadding));
+        writer.println(prefix + pxToDpStr("allAppsLeftRightMargin", allAppsLeftRightMargin));
 
         writer.println(prefix + pxToDpStr("hotseatBarSizePx", hotseatBarSizePx));
         writer.println(prefix + pxToDpStr("hotseatCellHeightPx", hotseatCellHeightPx));
@@ -1112,6 +1169,8 @@
         writer.println(prefix + pxToDpStr("hotseatBarSidePaddingEndPx",
                 hotseatBarSidePaddingEndPx));
         writer.println(prefix + "\tnumShownHotseatIcons: " + numShownHotseatIcons);
+        writer.println(prefix + "\tisQsbInline: " + isQsbInline);
+        writer.println(prefix + pxToDpStr("qsbWidth", qsbWidth));
 
         writer.println(prefix + "\tisTaskbarPresent:" + isTaskbarPresent);
         writer.println(prefix + "\tisTaskbarPresentInApps:" + isTaskbarPresentInApps);
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index ffe3816..cb0cc11 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -173,7 +173,10 @@
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
-        int width = getShortcutsAndWidgets().getMeasuredWidth();
+        int width = mActivity.getDeviceProfile().isQsbInline
+                ? mActivity.getDeviceProfile().qsbWidth
+                : getShortcutsAndWidgets().getMeasuredWidth();
+
         mQsb.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                 MeasureSpec.makeMeasureSpec(mQsbHeight, MeasureSpec.EXACTLY));
     }
@@ -183,7 +186,13 @@
         super.onLayout(changed, l, t, r, b);
 
         int qsbWidth = mQsb.getMeasuredWidth();
-        int left = (r - l - qsbWidth) / 2;
+        int left;
+        if (mActivity.getDeviceProfile().isQsbInline) {
+            int qsbSpace = mActivity.getDeviceProfile().hotseatBorderSpace;
+            left = l + getPaddingLeft() - qsbWidth - qsbSpace;
+        } else {
+            left = (r - l - qsbWidth) / 2;
+        }
         int right = left + qsbWidth;
 
         int bottom = b - t - mActivity.getDeviceProfile().getQsbOffsetY();
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 94325d0..0b168a5 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -794,6 +794,11 @@
             x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidth, 0);
             y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeight, 0);
             minCellSize[INDEX_DEFAULT] = new PointF(x, y);
+
+            x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthLandscape,
+                    minCellSize[INDEX_DEFAULT].x);
+            y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightLandscape,
+                    minCellSize[INDEX_DEFAULT].y);
             minCellSize[INDEX_LANDSCAPE] = new PointF(x, y);
 
             x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthTwoPanelPortrait,
@@ -896,7 +901,9 @@
 
             horizontalMargin[INDEX_DEFAULT] = a.getFloat(
                     R.styleable.ProfileDisplayOption_horizontalMargin, 0);
-            horizontalMargin[INDEX_LANDSCAPE] = horizontalMargin[INDEX_DEFAULT];
+            horizontalMargin[INDEX_LANDSCAPE] = a.getFloat(
+                    R.styleable.ProfileDisplayOption_horizontalMarginLandscape,
+                    horizontalMargin[INDEX_DEFAULT]);
             horizontalMargin[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
                     R.styleable.ProfileDisplayOption_horizontalMarginTwoPanelLandscape,
                     horizontalMargin[INDEX_DEFAULT]);
@@ -906,7 +913,9 @@
 
             hotseatBorderSpaces[INDEX_DEFAULT] = a.getFloat(
                     R.styleable.ProfileDisplayOption_hotseatBorderSpace, borderSpace);
-            hotseatBorderSpaces[INDEX_LANDSCAPE] = hotseatBorderSpaces[INDEX_DEFAULT];
+            hotseatBorderSpaces[INDEX_LANDSCAPE] = a.getFloat(
+                    R.styleable.ProfileDisplayOption_hotseatBorderSpaceLandscape,
+                    hotseatBorderSpaces[INDEX_DEFAULT]);
             hotseatBorderSpaces[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
                     R.styleable.ProfileDisplayOption_hotseatBorderSpaceTwoPanelLandscape,
                     hotseatBorderSpaces[INDEX_DEFAULT]);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index bed4fa9..84c4783 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -40,7 +40,6 @@
 import static com.android.launcher3.LauncherState.SPRING_LOADED;
 import static com.android.launcher3.Utilities.postAsyncCallback;
 import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.getSupportedActions;
-import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
 import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
@@ -122,7 +121,7 @@
 import com.android.launcher3.DropTarget.DragObject;
 import com.android.launcher3.accessibility.BaseAccessibilityDelegate.LauncherAction;
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
 import com.android.launcher3.allapps.AllAppsStore;
 import com.android.launcher3.allapps.AllAppsTransitionController;
 import com.android.launcher3.allapps.DiscoveryBounce;
@@ -315,7 +314,7 @@
 
     // Main container view for the all apps screen.
     @Thunk
-    AllAppsContainerView mAppsView;
+    ActivityAllAppsContainerView<Launcher> mAppsView;
     AllAppsTransitionController mAllAppsController;
 
     // Scrim view for the all apps and overview state.
@@ -1490,7 +1489,8 @@
         return mDragLayer;
     }
 
-    public AllAppsContainerView getAppsView() {
+    @Override
+    public ActivityAllAppsContainerView<Launcher> getAppsView() {
         return mAppsView;
     }
 
@@ -2366,6 +2366,9 @@
                 CellLayout cl = mWorkspace.getScreenWithId(item.screenId);
                 if (cl != null && cl.isOccupied(item.cellX, item.cellY)) {
                     View v = cl.getChildAt(item.cellX, item.cellY);
+                    if (v == null) {
+                        Log.e(TAG, "bindItems failed when removing colliding item=" + item);
+                    }
                     Object tag = v.getTag();
                     String desc = "Collision while binding workspace item: " + item
                             + ". Collides with " + tag;
@@ -2730,14 +2733,8 @@
                     -> containers.add(((CellLayout) page).getShortcutsAndWidgets()));
 
             // Order: Preferred item by itself or in folder, then by matching package/user
-            if (ADAPTIVE_ICON_WINDOW_ANIM.get()) {
-                return getFirstMatch(containers, preferredItem, forFolderMatch(preferredItem),
-                        packageAndUserAndApp, forFolderMatch(packageAndUserAndApp));
-            } else {
-                // Do not use Folder as a criteria, since it'll cause a crash when trying to draw
-                // FolderAdaptiveIcon as the background.
-                return getFirstMatch(containers, preferredItem, packageAndUserAndApp);
-            }
+            return getFirstMatch(containers, preferredItem, forFolderMatch(preferredItem),
+                    packageAndUserAndApp, forFolderMatch(packageAndUserAndApp));
         }
     }
 
@@ -2787,6 +2784,17 @@
     }
 
     /**
+     * Informs us that the overlay (-1 screen, typically), has either become visible or invisible.
+     */
+    public void onOverlayVisibilityChanged(boolean visible) {}
+
+    /**
+     * Informs us that the page transition has ended, so that we can react to the newly selected
+     * page if we want to.
+     */
+    public void onPageEndTransition() {}
+
+    /**
      * Add the icons for all apps.
      *
      * Implementation of the method from LauncherModel.Callbacks.
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index fec1d68..5583eae 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -19,6 +19,7 @@
 import static android.view.MotionEvent.ACTION_DOWN;
 
 import static com.android.launcher3.CellLayout.FOLDER;
+import static com.android.launcher3.CellLayout.HOTSEAT;
 import static com.android.launcher3.CellLayout.WORKSPACE;
 
 import android.app.WallpaperManager;
@@ -146,7 +147,8 @@
             // No need to add padding when cell layout border spacing is present.
             boolean noPaddingX =
                     (dp.cellLayoutBorderSpacePx.x > 0 && mContainerType == WORKSPACE)
-                            || (dp.folderCellLayoutBorderSpacePx.x > 0 && mContainerType == FOLDER);
+                            || (dp.folderCellLayoutBorderSpacePx.x > 0 && mContainerType == FOLDER)
+                            || (dp.hotseatBorderSpace > 0 && mContainerType == HOTSEAT);
             int cellPaddingX = noPaddingX
                     ? 0
                     : mContainerType == WORKSPACE
@@ -251,7 +253,7 @@
         CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
         // While the folder is open, the position of the icon cannot change.
         lp.canReorder = false;
-        if (mContainerType == CellLayout.HOTSEAT) {
+        if (mContainerType == HOTSEAT) {
             CellLayout cl = (CellLayout) getParent();
             cl.setFolderLeaveBehindCell(lp.cellX, lp.cellY);
         }
@@ -260,7 +262,7 @@
     @Override
     public void clearFolderLeaveBehind(FolderIcon child) {
         ((CellLayout.LayoutParams) child.getLayoutParams()).canReorder = true;
-        if (mContainerType == CellLayout.HOTSEAT) {
+        if (mContainerType == HOTSEAT) {
             CellLayout cl = (CellLayout) getParent();
             cl.clearFolderLeaveBehind();
         }
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index e0bb351..cbc21eb 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -229,7 +229,7 @@
             offsetPoints(coord, v.getLeft(), v.getTop());
             scale *= v.getScaleX();
 
-            v = (View) v.getParent();
+            v = v.getParent() instanceof View ? (View) v.getParent() : null;
         }
         return scale;
     }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 65006ff..16fecde 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1135,6 +1135,10 @@
             stripEmptyScreens();
             mStripScreensOnPageStopMoving = false;
         }
+
+        // Inform the Launcher activity that the page transition ended so that it can react to the
+        // newly visible page if it wants to.
+        mLauncher.onPageEndTransition();
     }
 
     public void setLauncherOverlay(LauncherOverlay overlay) {
@@ -1211,6 +1215,10 @@
                         .log(LAUNCHER_SWIPELEFT);
             }
             mOverlayShown = true;
+
+            // Let the Launcher activity know that the overlay is now visible.
+            mLauncher.onOverlayVisibilityChanged(mOverlayShown);
+
             // Not announcing the overlay page for accessibility since it announces itself.
         } else if (Float.compare(scroll, 0f) == 0) {
             if (mOverlayShown) {
@@ -1234,6 +1242,10 @@
                 announcePageForAccessibility();
             }
             mOverlayShown = false;
+
+            // Let the Launcher activity know that the overlay is no longer visible.
+            mLauncher.onOverlayVisibilityChanged(mOverlayShown);
+
             tryRunOverlayCallback();
         }
 
@@ -1686,7 +1698,7 @@
             PopupContainerWithArrow<Launcher> popupContainer = PopupContainerWithArrow
                     .showForIcon((BubbleTextView) child);
             if (popupContainer != null) {
-                dragOptions.preDragCondition = popupContainer.createPreDragCondition();
+                dragOptions.preDragCondition = popupContainer.createPreDragCondition(true);
             }
         }
 
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
new file mode 100644
index 0000000..070b98e
--- /dev/null
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps;
+
+import android.content.Context;
+import android.content.Intent;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+
+import androidx.core.graphics.ColorUtils;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.allapps.search.SearchAdapterProvider;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.PackageManagerHelper;
+
+import java.util.Objects;
+
+/**
+ * All apps container view with search support for use in a dragging activity.
+ *
+ * @param <T> Type of context inflating all apps.
+ */
+public class ActivityAllAppsContainerView<T extends BaseDraggingActivity> extends
+        BaseAllAppsContainerView<T> {
+
+    protected SearchUiManager mSearchUiManager;
+    /**
+     * View that defines the search box. Result is rendered inside the recycler view defined in the
+     * base class.
+     */
+    private View mSearchContainer;
+    /** {@code true} when rendered view is in search state instead of the scroll state. */
+    private boolean mIsSearching;
+
+    public ActivityAllAppsContainerView(Context context) {
+        this(context, null);
+    }
+
+    public ActivityAllAppsContainerView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public ActivityAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        mActivityContext.addOnDeviceProfileChangeListener(this);
+    }
+
+    public SearchUiManager getSearchUiManager() {
+        return mSearchUiManager;
+    }
+
+    public View getSearchView() {
+        return mSearchContainer;
+    }
+
+    /** Updates all apps container with the latest search query. */
+    public void setLastSearchQuery(String query) {
+        Intent marketSearchIntent = PackageManagerHelper.getMarketSearchIntent(
+                mActivityContext, query);
+        OnClickListener marketSearchClickListener = (v) -> mActivityContext.startActivitySafely(v,
+                marketSearchIntent, null);
+        for (int i = 0; i < mAH.size(); i++) {
+            mAH.get(i).adapter.setLastSearchQuery(query, marketSearchClickListener);
+        }
+        mIsSearching = true;
+        rebindAdapters();
+        mHeader.setCollapsed(true);
+    }
+
+    /** Invoke when the current search session is finished. */
+    public void onClearSearchResult() {
+        mIsSearching = false;
+        mHeader.setCollapsed(false);
+        rebindAdapters();
+        mHeader.reset(false);
+    }
+
+    /** Invoke when the search results change. */
+    public void onSearchResultsChanged() {
+        for (int i = 0; i < mAH.size(); i++) {
+            if (mAH.get(i).mRecyclerView != null) {
+                mAH.get(i).mRecyclerView.onSearchResultsChanged();
+            }
+        }
+    }
+
+    /** Handles selection on focused view and returns {@code true} on success. */
+    public boolean launchHighlightedItem() {
+        return getMainAdapterProvider().launchHighlightedItem();
+    }
+
+    @Override
+    protected SearchAdapterProvider<?> createMainAdapterProvider() {
+        return mActivityContext.createSearchAdapterProvider(this);
+    }
+
+    @Override
+    public boolean shouldContainerScroll(MotionEvent ev) {
+        // IF the MotionEvent is inside the search box, and the container keeps on receiving
+        // touch input, container should move down.
+        if (mActivityContext.getDragLayer().isEventOverView(mSearchContainer, ev)) {
+            return true;
+        }
+        return super.shouldContainerScroll(ev);
+    }
+
+    @Override
+    public void reset(boolean animate) {
+        super.reset(animate);
+        // Reset the search bar after transitioning home.
+        mSearchUiManager.resetSearch();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mSearchContainer = findViewById(R.id.search_container_all_apps);
+        mSearchUiManager = (SearchUiManager) mSearchContainer;
+        mSearchUiManager.initializeSearch(this);
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        mSearchUiManager.preDispatchKeyEvent(event);
+        return super.dispatchKeyEvent(event);
+    }
+
+    @Override
+    public String getDescription() {
+        if (!mUsingTabs && mIsSearching) {
+            return getContext().getString(R.string.all_apps_search_results);
+        } else {
+            return super.getDescription();
+        }
+    }
+
+    @Override
+    protected boolean showTabs() {
+        return super.showTabs() && !mIsSearching;
+    }
+
+    @Override
+    protected void rebindAdapters(boolean force) {
+        super.rebindAdapters(force);
+        if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()
+                || getMainAdapterProvider().getDecorator() == null) {
+            return;
+        }
+
+        RecyclerView.ItemDecoration decoration = getMainAdapterProvider().getDecorator();
+        mAH.stream()
+                .map(adapterHolder -> adapterHolder.mRecyclerView)
+                .filter(Objects::nonNull)
+                .forEach(v -> {
+                    v.removeItemDecoration(decoration); // Remove in case it is already added.
+                    v.addItemDecoration(decoration);
+                });
+    }
+
+    @Override
+    protected void updateHeaderScroll(int scrolledOffset) {
+        super.updateHeaderScroll(scrolledOffset);
+        if (mSearchUiManager.getEditText() == null) {
+            return;
+        }
+
+        float prog = Utilities.boundToRange((float) scrolledOffset / mHeaderThreshold, 0f, 1f);
+        boolean bgVisible = mSearchUiManager.getBackgroundVisibility();
+        if (scrolledOffset == 0 && !mIsSearching) {
+            bgVisible = true;
+        } else if (scrolledOffset > mHeaderThreshold) {
+            bgVisible = false;
+        }
+        mSearchUiManager.setBackgroundVisibility(bgVisible, 1 - prog);
+    }
+
+    @Override
+    protected int getHeaderColor(float blendRatio) {
+        return ColorUtils.setAlphaComponent(
+                super.getHeaderColor(blendRatio),
+                (int) (mSearchContainer.getAlpha() * 255));
+    }
+
+    @Override
+    protected int getHeaderBottom() {
+        return super.getHeaderBottom() + mSearchContainer.getBottom();
+    }
+}
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index d5c9a53..f1ca9c0 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -18,7 +18,6 @@
 import static com.android.launcher3.touch.ItemLongClickListener.INSTANCE_ALL_APPS;
 
 import android.content.Context;
-import android.content.Intent;
 import android.content.res.Resources;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -38,21 +37,22 @@
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.R;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
-import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.views.ActivityContext;
 
 import java.util.Arrays;
 import java.util.List;
 
 /**
  * The grid view adapter of all the apps.
+ *
+ * @param <T> Type of context inflating all apps.
  */
-public class AllAppsGridAdapter extends
+public class AllAppsGridAdapter<T extends Context & ActivityContext> extends
         RecyclerView.Adapter<AllAppsGridAdapter.ViewHolder> {
 
     public static final String TAG = "AppsGridAdapter";
@@ -256,9 +256,9 @@
         }
     }
 
-    private final BaseDraggingActivity mLauncher;
+    private final T mActivityContext;
     private final LayoutInflater mLayoutInflater;
-    private final AlphabeticalAppsList mApps;
+    private final AlphabeticalAppsList<T> mApps;
     private final GridLayoutManager mGridLayoutMgr;
     private final GridSpanSizer mGridSizer;
 
@@ -271,27 +271,28 @@
 
     // The text to show when there are no search results and no market search handler.
     protected String mEmptySearchMessage;
-    // The intent to send off to the market app, updated each time the search query changes.
-    private Intent mMarketSearchIntent;
+    // The click listener to send off to the market app, updated each time the search query changes.
+    private OnClickListener mMarketSearchClickListener;
 
     private final int mExtraHeight;
 
-    public AllAppsGridAdapter(BaseDraggingActivity launcher, LayoutInflater inflater,
-            AlphabeticalAppsList apps, BaseAdapterProvider[] adapterProviders) {
-        Resources res = launcher.getResources();
-        mLauncher = launcher;
+    public AllAppsGridAdapter(T activityContext, LayoutInflater inflater,
+            AlphabeticalAppsList<T> apps, BaseAdapterProvider[] adapterProviders) {
+        Resources res = activityContext.getResources();
+        mActivityContext = activityContext;
         mApps = apps;
         mEmptySearchMessage = res.getString(R.string.all_apps_loading_message);
         mGridSizer = new GridSpanSizer();
-        mGridLayoutMgr = new AppsGridLayoutManager(launcher);
+        mGridLayoutMgr = new AppsGridLayoutManager(mActivityContext);
         mGridLayoutMgr.setSpanSizeLookup(mGridSizer);
         mLayoutInflater = inflater;
 
-        mOnIconClickListener = launcher.getItemOnClickListener();
+        mOnIconClickListener = mActivityContext.getItemOnClickListener();
 
         mAdapterProviders = adapterProviders;
-        setAppsPerRow(mLauncher.getDeviceProfile().numShownAllAppsColumns);
-        mExtraHeight = launcher.getResources().getDimensionPixelSize(R.dimen.all_apps_height_extra);
+        setAppsPerRow(mActivityContext.getDeviceProfile().numShownAllAppsColumns);
+        mExtraHeight = mActivityContext.getResources().getDimensionPixelSize(
+                R.dimen.all_apps_height_extra);
     }
 
     public void setAppsPerRow(int appsPerRow) {
@@ -334,10 +335,10 @@
      * Sets the last search query that was made, used to show when there are no results and to also
      * seed the intent for searching the market.
      */
-    public void setLastSearchQuery(String query) {
-        Resources res = mLauncher.getResources();
+    public void setLastSearchQuery(String query, OnClickListener marketSearchClickListener) {
+        Resources res = mActivityContext.getResources();
         mEmptySearchMessage = res.getString(R.string.all_apps_no_search_results, query);
-        mMarketSearchIntent = PackageManagerHelper.getMarketSearchIntent(mLauncher, query);
+        mMarketSearchClickListener = marketSearchClickListener;
     }
 
     /**
@@ -360,7 +361,8 @@
                 icon.setOnClickListener(mOnIconClickListener);
                 icon.setOnLongClickListener(mOnIconLongClickListener);
                 // Ensure the all apps icon height matches the workspace icons in portrait mode.
-                icon.getLayoutParams().height = mLauncher.getDeviceProfile().allAppsCellHeightPx;
+                icon.getLayoutParams().height =
+                        mActivityContext.getDeviceProfile().allAppsCellHeightPx;
                 if (FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get()) {
                     icon.getLayoutParams().height += mExtraHeight;
                 }
@@ -371,8 +373,7 @@
             case VIEW_TYPE_SEARCH_MARKET:
                 View searchMarketView = mLayoutInflater.inflate(R.layout.all_apps_search_market,
                         parent, false);
-                searchMarketView.setOnClickListener(v -> mLauncher.startActivitySafely(
-                        v, mMarketSearchIntent, null));
+                searchMarketView.setOnClickListener(mMarketSearchClickListener);
                 return new ViewHolder(searchMarketView);
             case VIEW_TYPE_ALL_APPS_DIVIDER:
                 return new ViewHolder(mLayoutInflater.inflate(
@@ -407,7 +408,7 @@
                 break;
             case VIEW_TYPE_SEARCH_MARKET:
                 TextView searchView = (TextView) holder.itemView;
-                if (mMarketSearchIntent != null) {
+                if (mMarketSearchClickListener != null) {
                     searchView.setVisibility(View.VISIBLE);
                 } else {
                     searchView.setVisibility(View.GONE);
diff --git a/src/com/android/launcher3/allapps/AllAppsPagedView.java b/src/com/android/launcher3/allapps/AllAppsPagedView.java
index 3cc9ce6..872503a 100644
--- a/src/com/android/launcher3/allapps/AllAppsPagedView.java
+++ b/src/com/android/launcher3/allapps/AllAppsPagedView.java
@@ -21,13 +21,13 @@
 import android.content.Context;
 import android.util.AttributeSet;
 
-import com.android.launcher3.Launcher;
 import com.android.launcher3.PagedView;
+import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.workprofile.PersonalWorkPagedView;
 
 /**
- *  A {@link PagedView} for showing different views for the personal and work profile respectively
- *  in the {@link AllAppsContainerView}.
+ * A {@link PagedView} for showing different views for the personal and work profile respectively
+ * in the {@link BaseAllAppsContainerView}.
  */
 public class AllAppsPagedView extends PersonalWorkPagedView {
 
@@ -47,7 +47,7 @@
     protected boolean snapToPageWithVelocity(int whichPage, int velocity) {
         boolean resp = super.snapToPageWithVelocity(whichPage, velocity);
         if (resp && whichPage != mCurrentPage) {
-            Launcher.getLauncher(getContext()).getStatsLogManager().logger()
+            ActivityContext.lookupContext(getContext()).getStatsLogManager().logger()
                     .log(mCurrentPage < whichPage
                             ? LAUNCHER_ALLAPPS_SWIPE_TO_WORK_TAB
                             : LAUNCHER_ALLAPPS_SWIPE_TO_PERSONAL_TAB);
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index bccd9b4..c2cb845 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -36,7 +36,6 @@
 
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.BaseRecyclerView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherAppState;
@@ -58,7 +57,7 @@
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_LATENCY = Utilities.isPropertyEnabled(SEARCH_LOGGING);
 
-    private AlphabeticalAppsList mApps;
+    private AlphabeticalAppsList<?> mApps;
     private final int mNumAppsPerRow;
 
     // The specific view heights that we use to calculate scroll
@@ -104,16 +103,16 @@
     /**
      * Sets the list of apps in this view, used to determine the fastscroll position.
      */
-    public void setApps(AlphabeticalAppsList apps) {
+    public void setApps(AlphabeticalAppsList<?> apps) {
         mApps = apps;
     }
 
-    public AlphabeticalAppsList getApps() {
+    public AlphabeticalAppsList<?> getApps() {
         return mApps;
     }
 
     private void updatePoolSize() {
-        DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
+        DeviceProfile grid = ActivityContext.lookupContext(getContext()).getDeviceProfile();
         RecyclerView.RecycledViewPool pool = getRecycledViewPool();
         int approxRows = (int) Math.ceil(grid.availableHeightPx / grid.allAppsIconSizePx);
         pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH, 1);
@@ -201,7 +200,7 @@
     public void onScrollStateChanged(int state) {
         super.onScrollStateChanged(state);
 
-        StatsLogManager mgr = BaseDraggingActivity.fromContext(getContext()).getStatsLogManager();
+        StatsLogManager mgr = ActivityContext.lookupContext(getContext()).getStatsLogManager();
         switch (state) {
             case SCROLL_STATE_DRAGGING:
                 requestFocus();
@@ -470,7 +469,7 @@
      * Returns distance between left and right app icons
      */
     public int getTabWidth() {
-        DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
+        DeviceProfile grid = ActivityContext.lookupContext(getContext()).getDeviceProfile();
         int totalWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
         int iconPadding = totalWidth / grid.numShownAllAppsColumns - grid.allAppsIconSizePx;
         return totalWidth - iconPadding - grid.allAppsIconDrawablePaddingPx;
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index fc78bea..b6a2459 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -75,7 +75,7 @@
                 }
             };
 
-    private AllAppsContainerView mAppsView;
+    private ActivityAllAppsContainerView<Launcher> mAppsView;
 
     private final Launcher mLauncher;
     private boolean mIsVerticalLayout;
@@ -201,7 +201,7 @@
     /**
      * see Launcher#setupViews
      */
-    public void setupViews(ScrimView scrimView, AllAppsContainerView appsView) {
+    public void setupViews(ScrimView scrimView, ActivityAllAppsContainerView<Launcher> appsView) {
         mScrimView = scrimView;
         mAppsView = appsView;
         if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && Utilities.ATLEAST_R) {
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index ce5c589..1a1d521 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -18,12 +18,12 @@
 
 import android.content.Context;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.LabelComparator;
+import com.android.launcher3.views.ActivityContext;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -35,8 +35,11 @@
 
 /**
  * The alphabetically sorted list of applications.
+ *
+ * @param <T> Type of context inflating this view.
  */
-public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
+public class AlphabeticalAppsList<T extends Context & ActivityContext> implements
+        AllAppsStore.OnUpdateListener {
 
     public static final String TAG = "AlphabeticalAppsList";
 
@@ -64,7 +67,7 @@
     }
 
 
-    private final BaseDraggingActivity mLauncher;
+    private final T mActivityContext;
 
     // The set of apps from the system
     private final List<AppInfo> mApps = new ArrayList<>();
@@ -79,7 +82,7 @@
 
     // The of ordered component names as a result of a search query
     private ArrayList<AdapterItem> mSearchResults;
-    private AllAppsGridAdapter mAdapter;
+    private AllAppsGridAdapter<T> mAdapter;
     private AppInfoComparator mAppNameComparator;
     private final int mNumAppsPerRow;
     private int mNumAppRowsInAdapter;
@@ -88,10 +91,10 @@
     public AlphabeticalAppsList(Context context, AllAppsStore appsStore,
             WorkAdapterProvider adapterProvider) {
         mAllAppsStore = appsStore;
-        mLauncher = BaseDraggingActivity.fromContext(context);
+        mActivityContext = ActivityContext.lookupContext(context);
         mAppNameComparator = new AppInfoComparator(context);
         mWorkAdapterProvider = adapterProvider;
-        mNumAppsPerRow = mLauncher.getDeviceProfile().inv.numColumns;
+        mNumAppsPerRow = mActivityContext.getDeviceProfile().inv.numColumns;
         mAllAppsStore.addUpdateListener(this);
     }
 
@@ -103,7 +106,7 @@
     /**
      * Sets the adapter to notify when this dataset changes.
      */
-    public void setAdapter(AllAppsGridAdapter adapter) {
+    public void setAdapter(AllAppsGridAdapter<T> adapter) {
         mAdapter = adapter;
     }
 
@@ -229,7 +232,7 @@
 
         // As a special case for some languages (currently only Simplified Chinese), we may need to
         // coalesce sections
-        Locale curLocale = mLauncher.getResources().getConfiguration().locale;
+        Locale curLocale = mActivityContext.getResources().getConfiguration().locale;
         boolean localeRequiresSectionSorting = curLocale.equals(Locale.SIMPLIFIED_CHINESE);
         if (localeRequiresSectionSorting) {
             // Compute the section headers. We use a TreeMap with the section name comparator to
diff --git a/src/com/android/launcher3/allapps/AppInfoComparator.java b/src/com/android/launcher3/allapps/AppInfoComparator.java
index 823f98e..311a40e 100644
--- a/src/com/android/launcher3/allapps/AppInfoComparator.java
+++ b/src/com/android/launcher3/allapps/AppInfoComparator.java
@@ -43,7 +43,9 @@
     @Override
     public int compare(AppInfo a, AppInfo b) {
         // Order by the title in the current locale
-        int result = mLabelComparator.compare(a.title.toString(), b.title.toString());
+        int result = mLabelComparator.compare(
+                a.title == null ? "" : a.title.toString(),
+                b.title == null ? "" : b.title.toString());
         if (result != 0) {
             return result;
         }
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
similarity index 66%
rename from src/com/android/launcher3/allapps/AllAppsContainerView.java
rename to src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index 3ba6ea4..c1f0e06 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -31,15 +31,12 @@
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.UserManager;
-import android.text.SpannableStringBuilder;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.SparseArray;
-import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.WindowInsets;
 
 import androidx.annotation.NonNull;
@@ -50,7 +47,6 @@
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
 import com.android.launcher3.DragSource;
@@ -60,22 +56,27 @@
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.search.SearchAdapterProvider;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.keyboard.FocusedItemDecorator;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.Themes;
+import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.views.RecyclerViewFastScroller;
 import com.android.launcher3.views.ScrimView;
 import com.android.launcher3.views.SpringRelativeLayout;
 import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePageChangedListener;
 
+import java.util.Arrays;
+import java.util.List;
+
 /**
- * The all apps view container.
+ * Base all apps view container.
+ *
+ * @param <T> Type of context inflating all apps.
  */
-public class AllAppsContainerView extends SpringRelativeLayout implements DragSource,
-        Insettable, OnDeviceProfileChangeListener, OnActivePageChangedListener,
-        ScrimView.ScrimDrawingController {
+public abstract class BaseAllAppsContainerView<T extends Context & ActivityContext> extends
+        SpringRelativeLayout implements DragSource, Insettable, OnDeviceProfileChangeListener,
+        OnActivePageChangedListener, ScrimView.ScrimDrawingController {
 
     private static final String BUNDLE_KEY_CURRENT_PAGE = "launcher.allapps.current_page";
 
@@ -85,10 +86,12 @@
     private final Paint mHeaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     private final Rect mInsets = new Rect();
 
-    protected final BaseDraggingActivity mLauncher;
-    protected final AdapterHolder[] mAH;
+    /** Context of an activity or window that is inflating this container. */
+    protected final T mActivityContext;
+    protected final List<AdapterHolder> mAH;
     protected final ItemInfoMatcher mPersonalMatcher = ItemInfoMatcher.ofUser(
             Process.myUserHandle());
+    private final SearchAdapterProvider<?> mMainAdapterProvider;
     private final AllAppsStore mAllAppsStore = new AllAppsStore();
 
     private final RecyclerView.OnScrollListener mScrollListener =
@@ -100,67 +103,58 @@
             };
     private final WorkProfileManager mWorkManager;
 
-
     private final Paint mNavBarScrimPaint;
     private int mNavBarScrimHeight = 0;
 
-    protected SearchUiManager mSearchUiManager;
-    private View mSearchContainer;
     private AllAppsPagedView mViewPager;
 
     protected FloatingHeaderView mHeader;
 
-
-    private SpannableStringBuilder mSearchQueryBuilder = null;
-
     protected boolean mUsingTabs;
-    private boolean mIsSearching;
     private boolean mHasWorkApps;
 
     protected RecyclerViewFastScroller mTouchHandler;
     protected final Point mFastScrollerOffset = new Point();
 
-    private SearchAdapterProvider mSearchAdapterProvider;
     private final int mScrimColor;
     private final int mHeaderProtectionColor;
-    private final float mHeaderThreshold;
+    protected final float mHeaderThreshold;
     private ScrimView mScrimView;
     private int mHeaderColor;
     private int mTabsProtectionAlpha;
 
-    public AllAppsContainerView(Context context) {
-        this(context, null);
-    }
-
-    public AllAppsContainerView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public AllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
+    protected BaseAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-
-        mLauncher = BaseDraggingActivity.fromContext(context);
+        mActivityContext = ActivityContext.lookupContext(context);
+        mMainAdapterProvider = createMainAdapterProvider();
 
         mScrimColor = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
         mHeaderThreshold = getResources().getDimensionPixelSize(
                 R.dimen.dynamic_grid_cell_border_spacing);
         mHeaderProtectionColor = Themes.getAttrColor(context, R.attr.allappsHeaderProtectionColor);
 
-        mLauncher.addOnDeviceProfileChangeListener(this);
-
-        mSearchAdapterProvider = mLauncher.createSearchAdapterProvider(this);
-
-        mAH = new AdapterHolder[2];
-
-        mWorkManager = new WorkProfileManager(mLauncher.getSystemService(UserManager.class), this,
-                Utilities.getPrefs(mLauncher));
-        mAH[AdapterHolder.MAIN] = new AdapterHolder(false /* isWork */);
-        mAH[AdapterHolder.WORK] = new AdapterHolder(true /* isWork */);
+        mWorkManager = new WorkProfileManager(
+                mActivityContext.getSystemService(UserManager.class),
+                this,
+                Utilities.getPrefs(mActivityContext));
+        mAH = Arrays.asList(null, null);
+        mAH.set(AdapterHolder.MAIN, new AdapterHolder(false /* isWork */));
+        mAH.set(AdapterHolder.WORK, new AdapterHolder(true /* isWork */));
 
         mNavBarScrimPaint = new Paint();
         mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
 
         mAllAppsStore.addUpdateListener(this::onAppsUpdated);
+
+        updateBackground(mActivityContext.getDeviceProfile());
+    }
+
+    /** Creates the adapter provider for the main section. */
+    protected abstract SearchAdapterProvider<?> createMainAdapterProvider();
+
+    /** The adapter provider for the main section. */
+    public final SearchAdapterProvider<?> getMainAdapterProvider() {
+        return mMainAdapterProvider;
     }
 
     @Override
@@ -217,13 +211,20 @@
     public void onDeviceProfileChanged(DeviceProfile dp) {
         for (AdapterHolder holder : mAH) {
             holder.adapter.setAppsPerRow(dp.numShownAllAppsColumns);
-            if (holder.recyclerView != null) {
+            if (holder.mRecyclerView != null) {
                 // Remove all views and clear the pool, while keeping the data same. After this
                 // call, all the viewHolders will be recreated.
-                holder.recyclerView.swapAdapter(holder.recyclerView.getAdapter(), true);
-                holder.recyclerView.getRecycledViewPool().clear();
+                holder.mRecyclerView.swapAdapter(holder.mRecyclerView.getAdapter(), true);
+                holder.mRecyclerView.getRecycledViewPool().clear();
             }
         }
+        updateBackground(dp);
+    }
+
+    private void updateBackground(DeviceProfile deviceProfile) {
+        setBackground(deviceProfile.isTablet
+                ? getContext().getDrawable(R.drawable.bg_all_apps_bottom_sheet)
+                : null);
     }
 
     private void onAppsUpdated() {
@@ -235,7 +236,7 @@
             }
         }
         mHasWorkApps = hasWorkApps;
-        if (!mAH[AdapterHolder.MAIN].appsList.hasFilter()) {
+        if (!mAH.get(AdapterHolder.MAIN).mAppsList.hasFilter()) {
             rebindAdapters();
             if (hasWorkApps) {
                 mWorkManager.reset();
@@ -247,28 +248,24 @@
      * Returns whether the view itself will handle the touch event or not.
      */
     public boolean shouldContainerScroll(MotionEvent ev) {
-        // IF the MotionEvent is inside the search box, and the container keeps on receiving
-        // touch input, container should move down.
-        if (mLauncher.getDragLayer().isEventOverView(mSearchContainer, ev)) {
-            return true;
-        }
+        // TODO(b/216203409) Support dragging down from bottom sheet divider, if present.
         AllAppsRecyclerView rv = getActiveRecyclerView();
         if (rv == null) {
             return true;
         }
-        if (rv.getScrollbar().getThumbOffsetY() >= 0 &&
-                mLauncher.getDragLayer().isEventOverView(rv.getScrollbar(), ev)) {
+        if (rv.getScrollbar().getThumbOffsetY() >= 0
+                && mActivityContext.getDragLayer().isEventOverView(rv.getScrollbar(), ev)) {
             return false;
         }
-        return rv.shouldContainerScroll(ev, mLauncher.getDragLayer());
+        return rv.shouldContainerScroll(ev, mActivityContext.getDragLayer());
     }
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
             AllAppsRecyclerView rv = getActiveRecyclerView();
-            if (rv != null &&
-                    rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(), mFastScrollerOffset)) {
+            if (rv != null && rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(),
+                    mFastScrollerOffset)) {
                 mTouchHandler = rv.getScrollbar();
             } else {
                 mTouchHandler = null;
@@ -299,6 +296,7 @@
         return false;
     }
 
+    /** Description of the container view based on its current state. */
     public String getDescription() {
         @StringRes int descriptionRes;
         if (mUsingTabs) {
@@ -306,19 +304,18 @@
                     mViewPager.getNextPage() == 0
                             ? R.string.all_apps_button_personal_label
                             : R.string.all_apps_button_work_label;
-        } else if (mIsSearching) {
-            descriptionRes = R.string.all_apps_search_results;
         } else {
             descriptionRes = R.string.all_apps_button_label;
         }
         return getContext().getString(descriptionRes);
     }
 
+    /** The current recycler view visible in the container. */
     public AllAppsRecyclerView getActiveRecyclerView() {
         if (!mUsingTabs || mViewPager.getNextPage() == 0) {
-            return mAH[AdapterHolder.MAIN].recyclerView;
+            return mAH.get(AdapterHolder.MAIN).mRecyclerView;
         } else {
-            return mAH[AdapterHolder.WORK].recyclerView;
+            return mAH.get(AdapterHolder.WORK).mRecyclerView;
         }
     }
 
@@ -330,16 +327,15 @@
      * Resets the state of AllApps.
      */
     public void reset(boolean animate) {
-        for (int i = 0; i < mAH.length; i++) {
-            if (mAH[i].recyclerView != null) {
-                mAH[i].recyclerView.scrollToTop();
+        for (int i = 0; i < mAH.size(); i++) {
+            if (mAH.get(i).mRecyclerView != null) {
+                mAH.get(i).mRecyclerView.scrollToTop();
             }
         }
         if (isHeaderVisible()) {
             mHeader.reset(animate);
         }
-        // Reset the search bar and base recycler view after transitioning home
-        mSearchUiManager.resetSearch();
+        // Reset the base recycler view after transitioning home.
         updateHeaderScroll(0);
     }
 
@@ -357,20 +353,6 @@
 
         mHeader = findViewById(R.id.all_apps_header);
         rebindAdapters(true /* force */);
-
-        mSearchContainer = findViewById(R.id.search_container_all_apps);
-        mSearchUiManager = (SearchUiManager) mSearchContainer;
-        mSearchUiManager.initializeSearch(this);
-    }
-
-    public SearchUiManager getSearchUiManager() {
-        return mSearchUiManager;
-    }
-
-    @Override
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        mSearchUiManager.preDispatchKeyEvent(event);
-        return super.dispatchKeyEvent(event);
     }
 
     @Override
@@ -380,17 +362,19 @@
     @Override
     public void setInsets(Rect insets) {
         mInsets.set(insets);
-        DeviceProfile grid = mLauncher.getDeviceProfile();
+        DeviceProfile grid = mActivityContext.getDeviceProfile();
 
-        for (int i = 0; i < mAH.length; i++) {
-            mAH[i].padding.bottom = insets.bottom;
-            mAH[i].padding.left = mAH[i].padding.right = grid.allAppsLeftRightPadding;
-            mAH[i].applyPadding();
+        for (int i = 0; i < mAH.size(); i++) {
+            mAH.get(i).mPadding.bottom = insets.bottom;
+            mAH.get(i).mPadding.left = mAH.get(i).mPadding.right = grid.allAppsLeftRightPadding;
+            mAH.get(i).applyPadding();
         }
 
-        ViewGroup.MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
-        mlp.leftMargin = insets.left;
-        mlp.rightMargin = insets.right;
+        MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
+        mlp.topMargin = grid.isTablet ? insets.top : 0;
+        int leftRightMargin = grid.allAppsLeftRightMargin;
+        mlp.leftMargin = insets.left + leftRightMargin;
+        mlp.rightMargin = insets.right + leftRightMargin;
         setLayoutParams(mlp);
 
         if (grid.isVerticalBarLayout()) {
@@ -422,57 +406,60 @@
         }
     }
 
-    private void rebindAdapters() {
+    protected void rebindAdapters() {
         rebindAdapters(false /* force */);
     }
 
     protected void rebindAdapters(boolean force) {
-        boolean showTabs = mHasWorkApps && !mIsSearching;
+        boolean showTabs = showTabs();
         if (showTabs == mUsingTabs && !force) {
             return;
         }
         replaceRVContainer(showTabs);
         mUsingTabs = showTabs;
 
-        mAllAppsStore.unregisterIconContainer(mAH[AdapterHolder.MAIN].recyclerView);
-        mAllAppsStore.unregisterIconContainer(mAH[AdapterHolder.WORK].recyclerView);
+        mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
+        mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
 
         if (mUsingTabs) {
-            mAH[AdapterHolder.MAIN].setup(mViewPager.getChildAt(0), mPersonalMatcher);
-            mAH[AdapterHolder.WORK].setup(mViewPager.getChildAt(1), mWorkManager.getMatcher());
-            mAH[AdapterHolder.WORK].recyclerView.setId(R.id.apps_list_view_work);
+            mAH.get(AdapterHolder.MAIN).setup(mViewPager.getChildAt(0), mPersonalMatcher);
+            mAH.get(AdapterHolder.WORK).setup(mViewPager.getChildAt(1), mWorkManager.getMatcher());
+            mAH.get(AdapterHolder.WORK).mRecyclerView.setId(R.id.apps_list_view_work);
             mViewPager.getPageIndicator().setActiveMarker(AdapterHolder.MAIN);
             findViewById(R.id.tab_personal)
                     .setOnClickListener((View view) -> {
                         if (mViewPager.snapToPage(AdapterHolder.MAIN)) {
-                            mLauncher.getStatsLogManager().logger()
+                            mActivityContext.getStatsLogManager().logger()
                                     .log(LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB);
                         }
                     });
             findViewById(R.id.tab_work)
                     .setOnClickListener((View view) -> {
                         if (mViewPager.snapToPage(AdapterHolder.WORK)) {
-                            mLauncher.getStatsLogManager().logger()
+                            mActivityContext.getStatsLogManager().logger()
                                     .log(LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB);
                         }
                     });
             onActivePageChanged(mViewPager.getNextPage());
         } else {
-            mAH[AdapterHolder.MAIN].setup(findViewById(R.id.apps_list_view), null);
-            mAH[AdapterHolder.WORK].recyclerView = null;
+            mAH.get(AdapterHolder.MAIN).setup(findViewById(R.id.apps_list_view), null);
+            mAH.get(AdapterHolder.WORK).mRecyclerView = null;
         }
         setupHeader();
 
-        mAllAppsStore.registerIconContainer(mAH[AdapterHolder.MAIN].recyclerView);
-        mAllAppsStore.registerIconContainer(mAH[AdapterHolder.WORK].recyclerView);
+        mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
+        mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
     }
 
+    protected boolean showTabs() {
+        return mHasWorkApps;
+    }
 
     private void replaceRVContainer(boolean showTabs) {
         for (AdapterHolder adapterHolder : mAH) {
-            if (adapterHolder.recyclerView != null) {
-                adapterHolder.recyclerView.setLayoutManager(null);
-                adapterHolder.recyclerView.setAdapter(null);
+            if (adapterHolder.mRecyclerView != null) {
+                adapterHolder.mRecyclerView.setLayoutManager(null);
+                adapterHolder.mRecyclerView.setAdapter(null);
             }
         }
         View oldView = getRecyclerViewContainer();
@@ -486,7 +473,8 @@
             mViewPager.initParentViews(this);
             mViewPager.getPageIndicator().setOnActivePageChangedListener(this);
             if (mWorkManager.attachWorkModeSwitch()) {
-                mWorkManager.getWorkModeSwitch().post(() -> mAH[AdapterHolder.WORK].applyPadding());
+                mWorkManager.getWorkModeSwitch().post(
+                        () -> mAH.get(AdapterHolder.WORK).applyPadding());
             }
         } else {
             mWorkManager.detachWorkModeSwitch();
@@ -501,8 +489,8 @@
     @Override
     public void onActivePageChanged(int currentActivePage) {
         mHeader.setMainActive(currentActivePage == AdapterHolder.MAIN);
-        if (mAH[currentActivePage].recyclerView != null) {
-            mAH[currentActivePage].recyclerView.bindFastScrollbar();
+        if (mAH.get(currentActivePage).mRecyclerView != null) {
+            mAH.get(currentActivePage).mRecyclerView.bindFastScrollbar();
         }
         reset(true /* animate */);
 
@@ -524,95 +512,53 @@
         return isDescendantViewVisible(R.id.tab_personal);
     }
 
-    // Used by tests only
+    @VisibleForTesting
     public boolean isWorkTabVisible() {
         return isDescendantViewVisible(R.id.tab_work);
     }
 
-    public AlphabeticalAppsList getApps() {
-        return mAH[AdapterHolder.MAIN].appsList;
+    public AlphabeticalAppsList<T> getApps() {
+        return mAH.get(AdapterHolder.MAIN).mAppsList;
     }
 
     public FloatingHeaderView getFloatingHeaderView() {
         return mHeader;
     }
 
-    public View getSearchView() {
-        return mSearchContainer;
-    }
-
+    @VisibleForTesting
     public View getContentView() {
         return mViewPager == null ? getActiveRecyclerView() : mViewPager;
     }
 
+    /** The current page visible in all apps. */
     public int getCurrentPage() {
         return mViewPager != null ? mViewPager.getCurrentPage() : AdapterHolder.MAIN;
     }
 
-    /**
-     * Handles selection on focused view and returns success
-     */
-    public boolean launchHighlightedItem() {
-        if (mSearchAdapterProvider == null) return false;
-        return mSearchAdapterProvider.launchHighlightedItem();
-    }
-
-    public SearchAdapterProvider getSearchAdapterProvider() {
-        return mSearchAdapterProvider;
-    }
-
+    /** The scroll bar for the active recycler view. */
     public RecyclerViewFastScroller getScrollBar() {
         AllAppsRecyclerView rv = getActiveRecyclerView();
         return rv == null ? null : rv.getScrollbar();
     }
 
-    public void setupHeader() {
+    void setupHeader() {
         mHeader.setVisibility(View.VISIBLE);
-        mHeader.setup(mAH, mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView == null);
+        mHeader.setup(mAH, mAH.get(AdapterHolder.WORK).mRecyclerView == null);
 
         int padding = mHeader.getMaxTranslation();
-        for (int i = 0; i < mAH.length; i++) {
-            mAH[i].padding.top = padding;
-            mAH[i].applyPadding();
-            if (mAH[i].recyclerView != null) {
-                mAH[i].recyclerView.scrollToTop();
+        for (int i = 0; i < mAH.size(); i++) {
+            mAH.get(i).mPadding.top = padding;
+            mAH.get(i).applyPadding();
+            if (mAH.get(i).mRecyclerView != null) {
+                mAH.get(i).mRecyclerView.scrollToTop();
             }
         }
     }
 
-    public void setLastSearchQuery(String query) {
-        for (int i = 0; i < mAH.length; i++) {
-            mAH[i].adapter.setLastSearchQuery(query);
-        }
-        mIsSearching = true;
-        rebindAdapters();
-        mHeader.setCollapsed(true);
-    }
-
-    public void onClearSearchResult() {
-        mIsSearching = false;
-        mHeader.setCollapsed(false);
-        rebindAdapters();
-        mHeader.reset(false);
-    }
-
-    public void onSearchResultsChanged() {
-        for (int i = 0; i < mAH.length; i++) {
-            if (mAH[i].recyclerView != null) {
-                mAH[i].recyclerView.onSearchResultsChanged();
-            }
-        }
-    }
-
+    /** @see View#setVerticalFadingEdgeEnabled(boolean). */
     public void setRecyclerViewVerticalFadingEdgeEnabled(boolean enabled) {
-        for (int i = 0; i < mAH.length; i++) {
-            mAH[i].applyVerticalFadingEdgeEnabled(enabled);
-        }
-    }
-
-    public void addElevationController(RecyclerView.OnScrollListener scrollListener) {
-        if (!mUsingTabs) {
-            mAH[AdapterHolder.MAIN].recyclerView.addOnScrollListener(scrollListener);
+        for (int i = 0; i < mAH.size(); i++) {
+            mAH.get(i).applyVerticalFadingEdgeEnabled(enabled);
         }
     }
 
@@ -621,7 +567,7 @@
     }
 
     /**
-     * Adds an update listener to {@param animator} that adds springs to the animation.
+     * Adds an update listener to animator that adds springs to the animation.
      */
     public void addSpringFromFlingUpdateListener(ValueAnimator animator,
             float velocity /* release velocity */,
@@ -639,6 +585,7 @@
         });
     }
 
+    /** Invoked when the container is pulled. */
     public void onPull(float deltaDistance, float displacement) {
         absorbPullDeltaDistance(PULL_MULTIPLIER * deltaDistance, PULL_MULTIPLIER * displacement);
         // Current motion spec is to actually push and not pull
@@ -668,7 +615,7 @@
         mHeaderPaint.setColor(mHeaderColor);
         mHeaderPaint.setAlpha((int) (getAlpha() * Color.alpha(mHeaderColor)));
         if (mHeaderPaint.getColor() != mScrimColor && mHeaderPaint.getColor() != 0) {
-            int bottom = (int) (mSearchContainer.getBottom() + getTranslationY());
+            int bottom = getHeaderBottom();
             canvas.drawRect(0, 0, canvas.getWidth(), bottom, mHeaderPaint);
             int tabsHeight = getFloatingHeaderView().getPeripheralProtectionHeight();
             if (mTabsProtectionAlpha > 0 && tabsHeight != 0) {
@@ -678,81 +625,18 @@
         }
     }
 
-    public class AdapterHolder {
-        public static final int MAIN = 0;
-        public static final int WORK = 1;
-
-        private final boolean mIsWork;
-        public final AllAppsGridAdapter adapter;
-        final LinearLayoutManager layoutManager;
-        final AlphabeticalAppsList appsList;
-        final Rect padding = new Rect();
-        AllAppsRecyclerView recyclerView;
-        boolean verticalFadingEdge;
-
-
-        AdapterHolder(boolean isWork) {
-            mIsWork = isWork;
-            appsList = new AlphabeticalAppsList(mLauncher, mAllAppsStore,
-                    isWork ? mWorkManager.getAdapterProvider() : null);
-
-            BaseAdapterProvider[] adapterProviders =
-                    isWork ? new BaseAdapterProvider[]{mSearchAdapterProvider,
-                            mWorkManager.getAdapterProvider()}
-                            : new BaseAdapterProvider[]{mSearchAdapterProvider};
-
-            adapter = new AllAppsGridAdapter(mLauncher, getLayoutInflater(), appsList,
-                    adapterProviders);
-            appsList.setAdapter(adapter);
-            layoutManager = adapter.getLayoutManager();
-        }
-
-        void setup(@NonNull View rv, @Nullable ItemInfoMatcher matcher) {
-            appsList.updateItemFilter(matcher);
-            recyclerView = (AllAppsRecyclerView) rv;
-            recyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
-            recyclerView.setApps(appsList);
-            recyclerView.setLayoutManager(layoutManager);
-            recyclerView.setAdapter(adapter);
-            recyclerView.setHasFixedSize(true);
-            // No animations will occur when changes occur to the items in this RecyclerView.
-            recyclerView.setItemAnimator(null);
-            recyclerView.addOnScrollListener(mScrollListener);
-            FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(recyclerView);
-            recyclerView.addItemDecoration(focusedItemDecorator);
-            adapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
-            applyVerticalFadingEdgeEnabled(verticalFadingEdge);
-            applyPadding();
-            if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
-                recyclerView.addItemDecoration(mSearchAdapterProvider.getDecorator());
-            }
-        }
-
-        void applyPadding() {
-            if (recyclerView != null) {
-                int bottomOffset = 0;
-                if (mIsWork && mWorkManager.getWorkModeSwitch() != null) {
-                    bottomOffset = mInsets.bottom + mWorkManager.getWorkModeSwitch().getHeight();
-                }
-                recyclerView.setPadding(padding.left, padding.top, padding.right,
-                        padding.bottom + bottomOffset);
-            }
-        }
-
-        public void applyVerticalFadingEdgeEnabled(boolean enabled) {
-            verticalFadingEdge = enabled;
-            mAH[AdapterHolder.MAIN].recyclerView.setVerticalFadingEdgeEnabled(!mUsingTabs
-                    && verticalFadingEdge);
+    /**
+     * redraws header protection
+     */
+    public void invalidateHeader() {
+        if (mScrimView != null && mHeader.isHeaderProtectionSupported()) {
+            mScrimView.invalidate();
         }
     }
 
-
     protected void updateHeaderScroll(int scrolledOffset) {
-
         float prog = Utilities.boundToRange((float) scrolledOffset / mHeaderThreshold, 0f, 1f);
-        int viewBG = ColorUtils.blendARGB(mScrimColor, mHeaderProtectionColor, prog);
-        int headerColor = ColorUtils.setAlphaComponent(viewBG,
-                (int) (getSearchView().getAlpha() * 255));
+        int headerColor = getHeaderColor(prog);
         int tabsAlpha = mHeader.getPeripheralProtectionHeight() == 0 ? 0
                 : (int) (Utilities.boundToRange(
                         (scrolledOffset + mHeader.mSnappedScrolledY) / mHeaderThreshold, 0f, 1f)
@@ -762,23 +646,78 @@
             mTabsProtectionAlpha = tabsAlpha;
             invalidateHeader();
         }
-        if (mSearchUiManager.getEditText() != null) {
-            boolean bgVisible = mSearchUiManager.getBackgroundVisibility();
-            if (scrolledOffset == 0 && !mIsSearching) {
-                bgVisible = true;
-            } else if (scrolledOffset > mHeaderThreshold) {
-                bgVisible = false;
-            }
-            mSearchUiManager.setBackgroundVisibility(bgVisible, 1 - prog);
-        }
     }
 
-    /**
-     * redraws header protection
-     */
-    public void invalidateHeader() {
-        if (mScrimView != null && mHeader.isHeaderProtectionSupported()) {
-            mScrimView.invalidate();
+    protected int getHeaderColor(float blendRatio) {
+        return ColorUtils.blendARGB(mScrimColor, mHeaderProtectionColor, blendRatio);
+    }
+
+    protected int getHeaderBottom() {
+        return (int) getTranslationY();
+    }
+
+    /** Holds a {@link AllAppsGridAdapter} and related fields. */
+    public class AdapterHolder {
+        public static final int MAIN = 0;
+        public static final int WORK = 1;
+
+        private final boolean mIsWork;
+        public final AllAppsGridAdapter<T> adapter;
+        final LinearLayoutManager mLayoutManager;
+        final AlphabeticalAppsList<T> mAppsList;
+        final Rect mPadding = new Rect();
+        AllAppsRecyclerView mRecyclerView;
+        boolean mVerticalFadingEdge;
+
+        AdapterHolder(boolean isWork) {
+            mIsWork = isWork;
+            mAppsList = new AlphabeticalAppsList<>(mActivityContext, mAllAppsStore,
+                    isWork ? mWorkManager.getAdapterProvider() : null);
+
+            BaseAdapterProvider[] adapterProviders =
+                    isWork ? new BaseAdapterProvider[]{mMainAdapterProvider,
+                            mWorkManager.getAdapterProvider()}
+                            : new BaseAdapterProvider[]{mMainAdapterProvider};
+
+            adapter = new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), mAppsList,
+                    adapterProviders);
+            mAppsList.setAdapter(adapter);
+            mLayoutManager = adapter.getLayoutManager();
+        }
+
+        void setup(@NonNull View rv, @Nullable ItemInfoMatcher matcher) {
+            mAppsList.updateItemFilter(matcher);
+            mRecyclerView = (AllAppsRecyclerView) rv;
+            mRecyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
+            mRecyclerView.setApps(mAppsList);
+            mRecyclerView.setLayoutManager(mLayoutManager);
+            mRecyclerView.setAdapter(adapter);
+            mRecyclerView.setHasFixedSize(true);
+            // No animations will occur when changes occur to the items in this RecyclerView.
+            mRecyclerView.setItemAnimator(null);
+            mRecyclerView.addOnScrollListener(mScrollListener);
+            FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(mRecyclerView);
+            mRecyclerView.addItemDecoration(focusedItemDecorator);
+            adapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
+            applyVerticalFadingEdgeEnabled(mVerticalFadingEdge);
+            applyPadding();
+        }
+
+        void applyPadding() {
+            if (mRecyclerView != null) {
+                int bottomOffset = 0;
+                if (mIsWork && mWorkManager.getWorkModeSwitch() != null) {
+                    bottomOffset = mInsets.bottom + mWorkManager.getWorkModeSwitch().getHeight();
+                }
+                mRecyclerView.setPadding(mPadding.left, mPadding.top, mPadding.right,
+                        mPadding.bottom + bottomOffset);
+            }
+        }
+
+        private void applyVerticalFadingEdgeEnabled(boolean enabled) {
+            mVerticalFadingEdge = enabled;
+            mAH.get(AdapterHolder.MAIN).mRecyclerView.setVerticalFadingEdgeEnabled(!mUsingTabs
+                    && mVerticalFadingEdge);
         }
     }
 }
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 85ee636..059d4b8 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -30,17 +30,18 @@
 import androidx.annotation.Nullable;
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
+import com.android.launcher3.views.ActivityContext;
 import com.android.systemui.plugins.AllAppsRow;
 import com.android.systemui.plugins.AllAppsRow.OnHeightUpdatedListener;
 import com.android.systemui.plugins.PluginListener;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 public class FloatingHeaderView extends LinearLayout implements
@@ -72,7 +73,8 @@
                     moved(current);
                     applyVerticalMove();
                     if (headerCollapsed != mHeaderCollapsed) {
-                        AllAppsContainerView parent = (AllAppsContainerView) getParent();
+                        BaseAllAppsContainerView<?> parent =
+                                (BaseAllAppsContainerView<?>) getParent();
                         parent.invalidateHeader();
                     }
                 }
@@ -118,7 +120,9 @@
         mHeaderTopPadding = context.getResources()
                 .getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
         mHeaderProtectionSupported = context.getResources().getBoolean(
-                R.bool.config_header_protection_supported);
+                R.bool.config_header_protection_supported)
+                // TODO(b/208599118) Support header protection for bottom sheet.
+                && !ActivityContext.lookupContext(context).getDeviceProfile().isTablet;
     }
 
     @Override
@@ -193,7 +197,7 @@
         updateExpectedHeight();
 
         if (mMaxTranslation != oldMaxHeight) {
-            AllAppsContainerView parent = (AllAppsContainerView) getParent();
+            BaseAllAppsContainerView<?> parent = (BaseAllAppsContainerView<?>) getParent();
             if (parent != null) {
                 parent.setupHeader();
             }
@@ -222,7 +226,8 @@
         return super.getFocusedChild();
     }
 
-    public void setup(AllAppsContainerView.AdapterHolder[] mAH, boolean tabsHidden) {
+    <T extends Context & ActivityContext> void setup(
+            List<BaseAllAppsContainerView<T>.AdapterHolder> mAH, boolean tabsHidden) {
         for (FloatingHeaderRow row : mAllRows) {
             row.setup(this, mAllRows, tabsHidden);
         }
@@ -230,8 +235,10 @@
 
         mTabsHidden = tabsHidden;
         mTabLayout.setVisibility(tabsHidden ? View.GONE : View.VISIBLE);
-        mMainRV = setupRV(mMainRV, mAH[AllAppsContainerView.AdapterHolder.MAIN].recyclerView);
-        mWorkRV = setupRV(mWorkRV, mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView);
+        mMainRV = setupRV(mMainRV,
+                mAH.get(BaseAllAppsContainerView.AdapterHolder.MAIN).mRecyclerView);
+        mWorkRV = setupRV(mWorkRV,
+                mAH.get(BaseAllAppsContainerView.AdapterHolder.WORK).mRecyclerView);
         mParent = (ViewGroup) mMainRV.getParent();
         setMainActive(mMainRVActive || mWorkRV == null);
         reset(false);
@@ -413,7 +420,7 @@
 
     @Override
     public void setInsets(Rect insets) {
-        DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
+        DeviceProfile grid = ActivityContext.lookupContext(getContext()).getDeviceProfile();
         for (FloatingHeaderRow row : mAllRows) {
             row.setInsets(insets, grid);
         }
diff --git a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
index b6dcec6..30d33f9 100644
--- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
@@ -26,9 +26,7 @@
 /**
  * AllAppsContainerView with launcher specific callbacks
  */
-public class LauncherAllAppsContainerView extends AllAppsContainerView {
-
-    private final Launcher mLauncher;
+public class LauncherAllAppsContainerView extends ActivityAllAppsContainerView<Launcher> {
 
     public LauncherAllAppsContainerView(Context context) {
         this(context, null);
@@ -40,14 +38,13 @@
 
     public LauncherAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        mLauncher = Launcher.getLauncher(context);
     }
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         // The AllAppsContainerView houses the QSB and is hence visible from the Workspace
         // Overview states. We shouldn't intercept for the scrubber in these cases.
-        if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
+        if (!mActivityContext.isInState(LauncherState.ALL_APPS)) {
             mTouchHandler = null;
             return false;
         }
@@ -57,7 +54,7 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
+        if (!mActivityContext.isInState(LauncherState.ALL_APPS)) {
             return false;
         }
         return super.onTouchEvent(ev);
@@ -66,13 +63,8 @@
     @Override
     public void setInsets(Rect insets) {
         super.setInsets(insets);
-        int allAppsStartingPositionY = mLauncher.getDeviceProfile().availableHeightPx
-                - mLauncher.getDeviceProfile().allAppsOpenVerticalTranslate;
-        mLauncher.getAllAppsController().setScrollRangeDelta(allAppsStartingPositionY);
-    }
-
-    @Override
-    public void onActivePageChanged(int currentActivePage) {
-        super.onActivePageChanged(currentActivePage);
+        int allAppsStartingPositionY = mActivityContext.getDeviceProfile().availableHeightPx
+                - mActivityContext.getDeviceProfile().allAppsOpenVerticalTranslate;
+        mActivityContext.getAllAppsController().setScrollRangeDelta(allAppsStartingPositionY);
     }
 }
diff --git a/src/com/android/launcher3/allapps/SearchUiManager.java b/src/com/android/launcher3/allapps/SearchUiManager.java
index 7478b53..f9055ee 100644
--- a/src/com/android/launcher3/allapps/SearchUiManager.java
+++ b/src/com/android/launcher3/allapps/SearchUiManager.java
@@ -29,7 +29,7 @@
     /**
      * Initializes the search manager.
      */
-    void initializeSearch(AllAppsContainerView containerView);
+    void initializeSearch(ActivityAllAppsContainerView<?> containerView);
 
     /**
      * Notifies the search manager to close any active search session.
diff --git a/src/com/android/launcher3/allapps/WorkEduCard.java b/src/com/android/launcher3/allapps/WorkEduCard.java
index 9db7bf0..c336496 100644
--- a/src/com/android/launcher3/allapps/WorkEduCard.java
+++ b/src/com/android/launcher3/allapps/WorkEduCard.java
@@ -23,16 +23,18 @@
 import android.view.animation.AnimationUtils;
 import android.widget.FrameLayout;
 
-import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.views.ActivityContext;
 
 /**
  * Work profile toggle switch shown at the bottom of AllApps work tab
  */
-public class WorkEduCard extends FrameLayout implements View.OnClickListener,
+public class WorkEduCard extends FrameLayout implements
+        View.OnClickListener,
         Animation.AnimationListener {
 
-    private final Launcher mLauncher;
+    private final ActivityContext mActivityContext;
     Animation mDismissAnim;
     private int mPosition = -1;
 
@@ -46,7 +48,7 @@
 
     public WorkEduCard(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        mLauncher = Launcher.getLauncher(getContext());
+        mActivityContext = ActivityContext.lookupContext(getContext());
         mDismissAnim = AnimationUtils.loadAnimation(context, android.R.anim.fade_out);
         mDismissAnim.setDuration(500);
         mDismissAnim.setAnimationListener(this);
@@ -69,13 +71,14 @@
         super.onFinishInflate();
         findViewById(R.id.action_btn).setOnClickListener(this);
         MarginLayoutParams lp = ((MarginLayoutParams) findViewById(R.id.wrapper).getLayoutParams());
-        lp.width = mLauncher.getAppsView().getActiveRecyclerView().getTabWidth();
+        lp.width = mActivityContext.getAppsView().getActiveRecyclerView().getTabWidth();
     }
 
     @Override
     public void onClick(View view) {
         startAnimation(mDismissAnim);
-        mLauncher.getSharedPrefs().edit().putInt(WorkAdapterProvider.KEY_WORK_EDU_STEP, 1).apply();
+        Utilities.getPrefs(getContext()).edit().putInt(WorkAdapterProvider.KEY_WORK_EDU_STEP,
+                1).apply();
     }
 
     @Override
@@ -97,8 +100,8 @@
         if (mPosition == -1) {
             if (getParent() != null) ((ViewGroup) getParent()).removeView(WorkEduCard.this);
         } else {
-            AllAppsRecyclerView rv = mLauncher.getAppsView()
-                    .mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView;
+            AllAppsRecyclerView rv = mActivityContext.getAppsView().mAH.get(
+                    ActivityAllAppsContainerView.AdapterHolder.WORK).mRecyclerView;
             rv.getApps().getAdapterItems().remove(mPosition);
             rv.getAdapter().notifyItemRemoved(mPosition);
         }
diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java
index be01581..4598690 100644
--- a/src/com/android/launcher3/allapps/WorkModeSwitch.java
+++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java
@@ -26,12 +26,11 @@
 import android.view.WindowInsets;
 import android.widget.Button;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Insettable;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.KeyboardInsetAnimationCallback;
+import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
 
 /**
@@ -73,7 +72,7 @@
                     new KeyboardInsetAnimationCallback(this);
             setWindowInsetsAnimationCallback(keyboardInsetAnimationCallback);
         }
-        DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
+        DeviceProfile grid = ActivityContext.lookupContext(getContext()).getDeviceProfile();
         setInsets(grid.getInsets());
     }
 
@@ -91,7 +90,7 @@
 
     @Override
     public void onActivePageChanged(int page) {
-        mOnWorkTab = page == AllAppsContainerView.AdapterHolder.WORK;
+        mOnWorkTab = page == ActivityAllAppsContainerView.AdapterHolder.WORK;
         updateVisibility();
     }
 
@@ -99,9 +98,9 @@
     public void onClick(View view) {
         if (Utilities.ATLEAST_P && isEnabled()) {
             setFlag(FLAG_PROFILE_TOGGLE_ONGOING);
-            Launcher launcher = Launcher.getLauncher(getContext());
-            launcher.getStatsLogManager().logger().log(LAUNCHER_TURN_OFF_WORK_APPS_TAP);
-            launcher.getAppsView().getWorkManager().setWorkProfileEnabled(false);
+            ActivityContext activityContext = ActivityContext.lookupContext(getContext());
+            activityContext.getStatsLogManager().logger().log(LAUNCHER_TURN_OFF_WORK_APPS_TAP);
+            activityContext.getAppsView().getWorkManager().setWorkProfileEnabled(false);
         }
     }
 
diff --git a/src/com/android/launcher3/allapps/WorkPausedCard.java b/src/com/android/launcher3/allapps/WorkPausedCard.java
index 7593ca7..729622f 100644
--- a/src/com/android/launcher3/allapps/WorkPausedCard.java
+++ b/src/com/android/launcher3/allapps/WorkPausedCard.java
@@ -24,16 +24,16 @@
 import android.widget.Button;
 import android.widget.LinearLayout;
 
-import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.views.ActivityContext;
 
 /**
  * Work profile toggle switch shown at the bottom of AllApps work tab
  */
 public class WorkPausedCard extends LinearLayout implements View.OnClickListener {
 
-    private final Launcher mLauncher;
+    private final ActivityContext mActivityContext;
     private Button mBtn;
 
     public WorkPausedCard(Context context) {
@@ -46,7 +46,7 @@
 
     public WorkPausedCard(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        mLauncher = Launcher.getLauncher(getContext());
+        mActivityContext = ActivityContext.lookupContext(getContext());
     }
 
 
@@ -61,8 +61,8 @@
     public void onClick(View view) {
         if (Utilities.ATLEAST_P) {
             setEnabled(false);
-            mLauncher.getAppsView().getWorkManager().setWorkProfileEnabled(true);
-            mLauncher.getStatsLogManager().logger().log(LAUNCHER_TURN_ON_WORK_APPS_TAP);
+            mActivityContext.getAppsView().getWorkManager().setWorkProfileEnabled(true);
+            mActivityContext.getStatsLogManager().logger().log(LAUNCHER_TURN_ON_WORK_APPS_TAP);
         }
     }
 
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index e223248..bcaf1f4 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -39,7 +39,8 @@
 import java.lang.annotation.RetentionPolicy;
 
 /**
- * Companion class for {@link AllAppsContainerView} to manage work tab and personal tab related
+ * Companion class for {@link BaseAllAppsContainerView} to manage work tab and personal tab
+ * related
  * logic based on {@link WorkProfileState}?
  */
 public class WorkProfileManager implements PersonalWorkSlidingTabStrip.OnActivePageChangedListener {
@@ -50,7 +51,6 @@
     public static final int STATE_DISABLED = 2;
     public static final int STATE_TRANSITION = 3;
 
-
     private final UserManager mUserManager;
 
     /**
@@ -65,7 +65,7 @@
     public @interface WorkProfileState {
     }
 
-    private final AllAppsContainerView mAllApps;
+    private final BaseAllAppsContainerView<?> mAllApps;
     private final WorkAdapterProvider mAdapterProvider;
     private final ItemInfoMatcher mMatcher;
 
@@ -75,7 +75,7 @@
     private int mCurrentState;
 
 
-    public WorkProfileManager(UserManager userManager, AllAppsContainerView allApps,
+    public WorkProfileManager(UserManager userManager, BaseAllAppsContainerView<?> allApps,
             SharedPreferences preferences) {
         mUserManager = userManager;
         mAllApps = allApps;
@@ -118,7 +118,7 @@
         mCurrentState = currentState;
         mAdapterProvider.updateCurrentState(currentState);
         if (getAH() != null) {
-            getAH().appsList.updateAdapterItems();
+            getAH().mAppsList.updateAdapterItems();
         }
         if (mWorkModeSwitch != null) {
             mWorkModeSwitch.updateCurrentState(currentState == STATE_ENABLED);
@@ -126,7 +126,7 @@
     }
 
     /**
-     * Creates and attaches for profile toggle button to {@link AllAppsContainerView}
+     * Creates and attaches for profile toggle button to {@link BaseAllAppsContainerView}
      */
     public boolean attachWorkModeSwitch() {
         if (!mAllApps.getAppsStore().hasModelFlag(
@@ -149,7 +149,7 @@
     }
 
     /**
-     * Removes work profile toggle button from {@link AllAppsContainerView}
+     * Removes work profile toggle button from {@link BaseAllAppsContainerView}
      */
     public void detachWorkModeSwitch() {
         if (mWorkModeSwitch != null && mWorkModeSwitch.getParent() == mAllApps) {
@@ -172,8 +172,8 @@
         return mWorkModeSwitch;
     }
 
-    private AllAppsContainerView.AdapterHolder getAH() {
-        return mAllApps.mAH[AllAppsContainerView.AdapterHolder.WORK];
+    private BaseAllAppsContainerView<?>.AdapterHolder getAH() {
+        return mAllApps.mAH.get(BaseAllAppsContainerView.AdapterHolder.WORK);
     }
 
     public int getCurrentState() {
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index 4c5a9e6..ffc049b 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -37,7 +37,7 @@
 import com.android.launcher3.ExtendedEditText;
 import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
 import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
 import com.android.launcher3.allapps.AllAppsStore;
 import com.android.launcher3.allapps.AlphabeticalAppsList;
@@ -57,8 +57,8 @@
     private final AllAppsSearchBarController mSearchBarController;
     private final SpannableStringBuilder mSearchQueryBuilder;
 
-    private AlphabeticalAppsList mApps;
-    private AllAppsContainerView mAppsView;
+    private AlphabeticalAppsList<?> mApps;
+    private ActivityAllAppsContainerView<?> mAppsView;
 
     // The amount of pixels to shift down and overlap with the rest of the content.
     private final int mContentOverlap;
@@ -130,7 +130,7 @@
     }
 
     @Override
-    public void initializeSearch(AllAppsContainerView appsView) {
+    public void initializeSearch(ActivityAllAppsContainerView<?> appsView) {
         mApps = appsView.getApps();
         mAppsView = appsView;
         mSearchBarController.initialize(
diff --git a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
index 7abd555..2fe4915 100644
--- a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
@@ -25,21 +25,19 @@
 
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.allapps.AllAppsContainerView;
 import com.android.launcher3.allapps.AllAppsGridAdapter;
 import com.android.launcher3.model.data.ItemInfo;
 
 /**
  * Provides views for local search results
  */
-public class DefaultSearchAdapterProvider extends SearchAdapterProvider {
+public class DefaultSearchAdapterProvider extends SearchAdapterProvider<BaseDraggingActivity> {
 
     private final RecyclerView.ItemDecoration mDecoration;
     private View mHighlightedView;
 
-    public DefaultSearchAdapterProvider(BaseDraggingActivity launcher,
-            AllAppsContainerView appsContainerView) {
-        super(launcher, appsContainerView);
+    public DefaultSearchAdapterProvider(BaseDraggingActivity launcher) {
+        super(launcher);
         mDecoration = new RecyclerView.ItemDecoration() {
             @Override
             public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent,
diff --git a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
index 7af0406..bc52784 100644
--- a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
@@ -21,18 +21,19 @@
 
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.allapps.AllAppsContainerView;
 import com.android.launcher3.allapps.BaseAdapterProvider;
+import com.android.launcher3.views.ActivityContext;
 
 /**
  * A UI expansion wrapper providing for search results
+ *
+ * @param <T> Context for this adapter provider.
  */
-public abstract class SearchAdapterProvider extends BaseAdapterProvider {
+public abstract class SearchAdapterProvider<T extends ActivityContext> extends BaseAdapterProvider {
 
-    protected final BaseDraggingActivity mLauncher;
+    protected final T mLauncher;
 
-    public SearchAdapterProvider(BaseDraggingActivity launcher, AllAppsContainerView appsView) {
+    public SearchAdapterProvider(T launcher) {
         mLauncher = launcher;
     }
 
diff --git a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
index 46c9006..4f8d53e 100644
--- a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
+++ b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
@@ -4,12 +4,12 @@
 import android.icu.text.AlphabeticIndex;
 import android.os.LocaleList;
 
+import androidx.annotation.NonNull;
+
 import com.android.launcher3.Utilities;
 
 import java.util.Locale;
 
-import androidx.annotation.NonNull;
-
 public class AlphabeticIndexCompat {
 
     private static final String MID_DOT = "\u2219";
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index c4421c3..ee71328 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -79,9 +79,6 @@
     public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(
             "KEYGUARD_ANIMATION", false, "Enable animation for keyguard going away on wallpaper");
 
-    public static final BooleanFlag ADAPTIVE_ICON_WINDOW_ANIM = getDebugFlag(
-            "ADAPTIVE_ICON_WINDOW_ANIM", true, "Use adaptive icons for window animations.");
-
     public static final BooleanFlag ENABLE_QUICKSTEP_LIVE_TILE = getDebugFlag(
             "ENABLE_QUICKSTEP_LIVE_TILE", true, "Enable live tile in Quickstep overview");
 
@@ -102,7 +99,7 @@
             "ENABLE_TWOLINE_ALLAPPS", false, "Enables two line label inside all apps.");
 
     public static final BooleanFlag ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING = new DeviceFlag(
-            "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", true,
+            "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", false,
             "Allows on device search in all apps logging");
 
     public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(
@@ -138,12 +135,12 @@
 
     public static final BooleanFlag ENABLE_BULK_WORKSPACE_ICON_LOADING = getDebugFlag(
             "ENABLE_BULK_WORKSPACE_ICON_LOADING",
-            false,
+            true,
             "Enable loading workspace icons in bulk.");
 
     public static final BooleanFlag ENABLE_BULK_ALL_APPS_ICON_LOADING = getDebugFlag(
             "ENABLE_BULK_ALL_APPS_ICON_LOADING",
-            false,
+            true,
             "Enable loading all apps icons in bulk.");
 
     // Keep as DeviceFlag for remote disable in emergency.
@@ -203,7 +200,7 @@
             "Enables showing taskbar education the first time an app is opened.");
 
     public static final BooleanFlag ENABLE_TASKBAR_POPUP_MENU = getDebugFlag(
-            "ENABLE_TASKBAR_POPUP_MENU", false, "Enables long pressing taskbar icons to show the"
+            "ENABLE_TASKBAR_POPUP_MENU", true, "Enables long pressing taskbar icons to show the"
                     + " popup menu.");
 
     public static final BooleanFlag ENABLE_OVERVIEW_GRID = getDebugFlag(
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index daef682..1e6342c 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -57,6 +57,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.widget.TextView;
 
+import androidx.annotation.IntDef;
 import androidx.annotation.Nullable;
 import androidx.core.content.res.ResourcesCompat;
 
@@ -101,6 +102,8 @@
 import com.android.launcher3.views.ClipPathView;
 import com.android.launcher3.widget.PendingAddShortcutInfo;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -130,10 +133,13 @@
      */
     private static final int MIN_CONTENT_DIMEN = 5;
 
-    static final int STATE_NONE = -1;
-    static final int STATE_SMALL = 0;
-    static final int STATE_ANIMATING = 1;
-    static final int STATE_OPEN = 2;
+    public static final int STATE_CLOSED = 0;
+    public static final int STATE_ANIMATING = 1;
+    public static final int STATE_OPEN = 2;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({STATE_CLOSED, STATE_ANIMATING, STATE_OPEN})
+    public @interface FolderState {}
 
     /**
      * Time for which the scroll hint is shown before automatically changing page.
@@ -198,13 +204,12 @@
 
     @ViewDebug.ExportedProperty(category = "launcher",
             mapping = {
-                    @ViewDebug.IntToString(from = STATE_NONE, to = "STATE_NONE"),
-                    @ViewDebug.IntToString(from = STATE_SMALL, to = "STATE_SMALL"),
+                    @ViewDebug.IntToString(from = STATE_CLOSED, to = "STATE_CLOSED"),
                     @ViewDebug.IntToString(from = STATE_ANIMATING, to = "STATE_ANIMATING"),
                     @ViewDebug.IntToString(from = STATE_OPEN, to = "STATE_OPEN"),
             })
-    @Thunk
-    int mState = STATE_NONE;
+    private int mState = STATE_CLOSED;
+    private OnFolderStateChangedListener mOnFolderStateChangedListener;
     @ViewDebug.ExportedProperty(category = "launcher")
     private boolean mRearrangeOnClose = false;
     boolean mItemsInvalidated = false;
@@ -277,19 +282,15 @@
         mPageIndicator = findViewById(R.id.folder_page_indicator);
         mFolderName = findViewById(R.id.folder_name);
         mFolderName.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.folderLabelTextSizePx);
-        if (mActivityContext.supportsIme()) {
-            mFolderName.setOnBackKeyListener(this);
-            mFolderName.setOnFocusChangeListener(this);
-            mFolderName.setOnEditorActionListener(this);
-            mFolderName.setSelectAllOnFocus(true);
-            mFolderName.setInputType(mFolderName.getInputType()
-                    & ~InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
-                    | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
-                    | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
-            mFolderName.forceDisableSuggestions(true);
-        } else {
-            mFolderName.setEnabled(false);
-        }
+        mFolderName.setOnBackKeyListener(this);
+        mFolderName.setOnFocusChangeListener(this);
+        mFolderName.setOnEditorActionListener(this);
+        mFolderName.setSelectAllOnFocus(true);
+        mFolderName.setInputType(mFolderName.getInputType()
+                & ~InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
+                | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
+                | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
+        mFolderName.forceDisableSuggestions(true);
 
         mFooter = findViewById(R.id.folder_footer);
         mFooterHeight = getResources().getDimensionPixelSize(R.dimen.folder_label_height);
@@ -561,7 +562,7 @@
         a.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
-                mState = STATE_ANIMATING;
+                setState(STATE_ANIMATING);
                 mCurrentAnimator = a;
             }
 
@@ -686,7 +687,7 @@
 
             @Override
             public void onAnimationEnd(Animator animation) {
-                mState = STATE_OPEN;
+                setState(STATE_OPEN);
                 announceAccessibilityChanges();
                 AccessibilityManagerCompat.sendFolderOpenedEventToTest(getContext());
 
@@ -862,7 +863,7 @@
         }
         mSuppressFolderDeletion = false;
         clearDragInfo();
-        mState = STATE_SMALL;
+        setState(STATE_CLOSED);
         mContent.setCurrentPage(0);
     }
 
@@ -1655,4 +1656,21 @@
 
         return windowBottomPx - folderBottomPx;
     }
+
+    private void setState(@FolderState int newState) {
+        mState = newState;
+        if (mOnFolderStateChangedListener != null) {
+            mOnFolderStateChangedListener.onFolderStateChanged(mState);
+        }
+    }
+
+    public void setOnFolderStateChangedListener(@Nullable OnFolderStateChangedListener listener) {
+        mOnFolderStateChangedListener = listener;
+    }
+
+    /** Listener that can be registered via {@link Folder#setOnFolderStateChangedListener} */
+    public interface OnFolderStateChangedListener {
+        /** See {@link Folder.FolderState} */
+        void onFolderStateChanged(@FolderState int newState);
+    }
 }
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 98be72a..7c665c6 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -55,7 +55,7 @@
 import com.android.launcher3.Reorderable;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dot.FolderDotInfo;
@@ -397,7 +397,7 @@
             float finalScale = scale * scaleRelativeToDragLayer;
 
             // Account for potentially different icon sizes with non-default grid settings
-            if (d.dragSource instanceof AllAppsContainerView) {
+            if (d.dragSource instanceof ActivityAllAppsContainerView) {
                 DeviceProfile grid = mActivity.getDeviceProfile();
                 float containerScale = (1f * grid.iconSizePx / grid.allAppsIconSizePx);
                 finalScale *= containerScale;
diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java
index 9c1b24d..3d3a96d 100644
--- a/src/com/android/launcher3/folder/FolderNameProvider.java
+++ b/src/com/android/launcher3/folder/FolderNameProvider.java
@@ -121,7 +121,8 @@
         if (packageNames.size() == 1) {
             Optional<AppInfo> info = getAppInfoByPackageName(packageNames.iterator().next());
             // Place it as first viable suggestion and shift everything else
-            info.ifPresent(i -> setAsFirstSuggestion(nameInfos, i.title.toString()));
+            info.ifPresent(i -> setAsFirstSuggestion(
+                    nameInfos, i.title == null ? "" : i.title.toString()));
         }
         if (DEBUG) {
             Log.d(TAG, "getSuggestedFolderName:" + nameInfos.toString());
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java
index dbed9a9..b8c9762 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -143,6 +143,8 @@
         if (loadIcon) {
             mIconCache.getTitleAndIcon(info, activityInfo, false /* useLowResIcon */);
             info.sectionName = mIndex.computeSectionName(info.title);
+        } else {
+            info.title = "";
         }
 
         data.add(info);
@@ -167,6 +169,8 @@
         if (loadIcon) {
             mIconCache.getTitleAndIcon(promiseAppInfo, promiseAppInfo.usingLowResIcon());
             promiseAppInfo.sectionName = mIndex.computeSectionName(promiseAppInfo.title);
+        } else {
+            promiseAppInfo.title = "";
         }
 
         data.add(promiseAppInfo);
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 83fb3d1..d47edff 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -112,7 +112,7 @@
                     activitiesLists.put(
                             packages[i], appsList.addPackage(context, packages[i], mUser));
                 }
-                flagOp = FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
+                flagOp = FlagOp.NO_OP.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
                 break;
             }
             case OP_UPDATE:
@@ -134,7 +134,7 @@
                     }
                 }
                 // Since package was just updated, the target must be available now.
-                flagOp = FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
+                flagOp = FlagOp.NO_OP.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
                 break;
             case OP_REMOVE: {
                 for (int i = 0; i < N; i++) {
@@ -148,13 +148,12 @@
                     if (DEBUG) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
                     appsList.removePackage(packages[i], mUser);
                 }
-                flagOp = FlagOp.addFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
+                flagOp = FlagOp.NO_OP.addFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
                 break;
             case OP_SUSPEND:
             case OP_UNSUSPEND:
-                flagOp = mOp == OP_SUSPEND ?
-                        FlagOp.addFlag(WorkspaceItemInfo.FLAG_DISABLED_SUSPENDED) :
-                        FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_SUSPENDED);
+                flagOp = FlagOp.NO_OP.setFlag(
+                        WorkspaceItemInfo.FLAG_DISABLED_SUSPENDED, mOp == OP_SUSPEND);
                 if (DEBUG) Log.d(TAG, "mAllAppsList.(un)suspend " + N);
                 appsList.updateDisabledFlags(matcher, flagOp);
                 break;
@@ -162,9 +161,8 @@
                 UserManagerState ums = new UserManagerState();
                 ums.init(UserCache.INSTANCE.get(context),
                         context.getSystemService(UserManager.class));
-                flagOp = ums.isUserQuiet(mUser)
-                        ? FlagOp.addFlag(WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER)
-                        : FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER);
+                flagOp = FlagOp.NO_OP.setFlag(
+                        WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER, ums.isUserQuiet(mUser));
                 appsList.updateDisabledFlags(matcher, flagOp);
 
                 // We are not synchronizing here, as int operations are atomic
diff --git a/src/com/android/launcher3/model/data/IconRequestInfo.java b/src/com/android/launcher3/model/data/IconRequestInfo.java
index 5dc6a3b..fbf01e5 100644
--- a/src/com/android/launcher3/model/data/IconRequestInfo.java
+++ b/src/com/android/launcher3/model/data/IconRequestInfo.java
@@ -75,7 +75,10 @@
         this.useLowResIcon = useLowResIcon;
     }
 
-    /** Loads  */
+    /**
+     * Loads this request's item info's title. This method should only be used on IconRequestInfos
+     * for WorkspaceItemInfos.
+     */
     public boolean loadWorkspaceIcon(Context context) {
         if (!(itemInfo instanceof WorkspaceItemInfo)) {
             throw new IllegalStateException(
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index b1a4109..f06e5ce 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -48,7 +48,7 @@
 import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
 
-import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.InsettableFrameLayout;
@@ -120,7 +120,7 @@
     private final GradientDrawable mRoundedTop;
     private final GradientDrawable mRoundedBottom;
 
-    private Runnable mOnCloseCallback = () -> { };
+    @Nullable private Runnable mOnCloseCallback = null;
 
     // The rect string of the view that the arrow is attached to, in screen reference frame.
     protected int mArrowColor;
@@ -766,7 +766,6 @@
         }
     }
 
-
     protected void animateClose() {
         if (!mIsOpen) {
             return;
@@ -816,7 +815,9 @@
         mDeferContainerRemoval = false;
         getPopupContainer().removeView(this);
         getPopupContainer().removeView(mArrow);
-        mOnCloseCallback.run();
+        if (mOnCloseCallback != null) {
+            mOnCloseCallback.run();
+        }
         if (mColorExtractors != null) {
             mColorExtractors.forEach(e -> e.setListener(null));
         }
@@ -825,7 +826,7 @@
     /**
      * Callback to be called when the popup is closed
      */
-    public void setOnCloseCallback(@NonNull Runnable callback) {
+    public void setOnCloseCallback(@Nullable Runnable callback) {
         mOnCloseCallback = callback;
     }
 
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 0097705..198397a 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -418,7 +418,7 @@
      * Current behavior:
      * - Start the drag if the touch passes a certain distance from the original touch down.
      */
-    public DragOptions.PreDragCondition createPreDragCondition() {
+    public DragOptions.PreDragCondition createPreDragCondition(boolean updateIconUi) {
         return new DragOptions.PreDragCondition() {
 
             @Override
@@ -428,6 +428,9 @@
 
             @Override
             public void onPreDragStart(DropTarget.DragObject dragObject) {
+                if (!updateIconUi) {
+                    return;
+                }
                 if (mIsAboveIcon) {
                     // Hide only the icon, keep the text visible.
                     mOriginalIcon.setIconVisible(false);
@@ -440,6 +443,9 @@
 
             @Override
             public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) {
+                if (!updateIconUi) {
+                    return;
+                }
                 mOriginalIcon.setIconVisible(true);
                 if (dragStarted) {
                     // Make sure we keep the original icon hidden while it is being dragged.
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
index 1a96c23..cba0655 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
@@ -30,7 +30,7 @@
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherModel;
 import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
 import com.android.launcher3.model.BgDataModel;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
@@ -52,7 +52,8 @@
     private LauncherModel mModel;
 
     private BaseDragLayer mDragLayer;
-    private AllAppsContainerView mAppsView;
+    // TODO(b/216191717): Verify all apps works on secondary display.
+    private ActivityAllAppsContainerView<SecondaryDisplayLauncher> mAppsView;
     private View mAppsButton;
 
     private PopupDataProvider mPopupDataProvider;
@@ -143,7 +144,8 @@
         return mAppDrawerShown;
     }
 
-    public AllAppsContainerView getAppsView() {
+    @Override
+    public ActivityAllAppsContainerView<SecondaryDisplayLauncher> getAppsView() {
         return mAppsView;
     }
 
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
index 0d8602f..967f2c8 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
@@ -30,7 +30,7 @@
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.popup.PopupContainerWithArrow;
 import com.android.launcher3.popup.PopupDataProvider;
@@ -47,7 +47,7 @@
 public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher> {
 
     private View mAllAppsButton;
-    private AllAppsContainerView mAppsView;
+    private ActivityAllAppsContainerView<SecondaryDisplayLauncher> mAppsView;
 
     private GridView mWorkspace;
     private PinnedAppsAdapter mPinnedAppsAdapter;
diff --git a/src/com/android/launcher3/statemanager/StatefulActivity.java b/src/com/android/launcher3/statemanager/StatefulActivity.java
index e036943..b45c97b 100644
--- a/src/com/android/launcher3/statemanager/StatefulActivity.java
+++ b/src/com/android/launcher3/statemanager/StatefulActivity.java
@@ -152,7 +152,7 @@
     /**
      * Called if the Activity UI changed while the activity was not visible
      */
-    protected void onUiChangedWhileSleeping() { }
+    public void onUiChangedWhileSleeping() { }
 
     private void handleDeferredResume() {
         if (hasBeenResumed() && !getStateManager().getState().hasFlag(FLAG_NON_INTERACTIVE)) {
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index a94ad7c..a6c9c4d 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -482,17 +482,14 @@
                 (FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
         FrameLayout.LayoutParams secondaryIconParams =
                 new FrameLayout.LayoutParams(primaryIconParams);
-        int dividerBar = (splitConfig.appsStackedVertically ?
-                splitConfig.visualDividerBounds.height() :
-                splitConfig.visualDividerBounds.width());
 
-        primaryIconParams.gravity = (isRtl ? START : END) | TOP;
-        primaryIconView.setTranslationY(primarySnapshotHeight - primaryIconView.getHeight() / 2f);
+        primaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? START : END);
         primaryIconView.setTranslationX(0);
-
-        secondaryIconParams.gravity = (isRtl ? START : END) | TOP;
-        secondaryIconView.setTranslationY(primarySnapshotHeight + taskIconHeight + dividerBar);
+        primaryIconView.setTranslationY(-(taskIconHeight / 2f));
+        secondaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? START : END);
         secondaryIconView.setTranslationX(0);
+        secondaryIconView.setTranslationY(taskIconHeight / 2f);
+
         primaryIconView.setLayoutParams(primaryIconParams);
         secondaryIconView.setLayoutParams(secondaryIconParams);
     }
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index ad9f95c..627aa11 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -581,26 +581,15 @@
                 (FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
         FrameLayout.LayoutParams secondaryIconParams =
                 new FrameLayout.LayoutParams(primaryIconParams);
-        int dividerBar = (splitConfig.appsStackedVertically ?
-                splitConfig.visualDividerBounds.height() :
-                splitConfig.visualDividerBounds.width());
 
-        if (deviceProfile.isLandscape) {
-            primaryIconParams.gravity = TOP | START;
-            primaryIconView.setTranslationX(
-                    primarySnapshotWidth - primaryIconView.getMeasuredWidth());
-            primaryIconView.setTranslationY(0);
-            secondaryIconParams.gravity = TOP | START;
-            secondaryIconView.setTranslationX(primarySnapshotWidth + dividerBar);
-        } else {
-            primaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
-            primaryIconView.setTranslationX(-(primaryIconView.getMeasuredWidth()) / 2f);
-            primaryIconView.setTranslationY(0);
-
-            secondaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
-            secondaryIconView.setTranslationX(secondaryIconView.getMeasuredWidth() / 2f);
-        }
+        primaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
+        // shifts icon half a width left (height is used conveniently here since icons are square)
+        primaryIconView.setTranslationX(-(taskIconHeight / 2f));
+        primaryIconView.setTranslationY(0);
+        secondaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
+        secondaryIconView.setTranslationX(taskIconHeight / 2f);
         secondaryIconView.setTranslationY(0);
+
         primaryIconView.setLayoutParams(primaryIconParams);
         secondaryIconView.setLayoutParams(secondaryIconParams);
     }
diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
index de5f99c..80a7229 100644
--- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
@@ -20,7 +20,6 @@
 import static android.view.Gravity.CENTER_VERTICAL;
 import static android.view.Gravity.END;
 import static android.view.Gravity.START;
-import static android.view.Gravity.TOP;
 
 import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
@@ -183,8 +182,8 @@
         FrameLayout.LayoutParams secondaryIconParams =
                 (FrameLayout.LayoutParams) secondaryIconView.getLayoutParams();
 
-        primaryIconParams.gravity = (isRtl ? END : START) | TOP;
-        secondaryIconParams.gravity = (isRtl ? END : START) | TOP;
+        primaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? END : START);
+        secondaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? END : START);
         primaryIconView.setLayoutParams(primaryIconParams);
         secondaryIconView.setLayoutParams(secondaryIconParams);
     }
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index c050c6c..ba925f5 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -67,12 +67,11 @@
 
     public static final int CHANGE_ACTIVE_SCREEN = 1 << 0;
     public static final int CHANGE_ROTATION = 1 << 1;
-    public static final int CHANGE_FRAME_DELAY = 1 << 2;
-    public static final int CHANGE_DENSITY = 1 << 3;
-    public static final int CHANGE_SUPPORTED_BOUNDS = 1 << 4;
+    public static final int CHANGE_DENSITY = 1 << 2;
+    public static final int CHANGE_SUPPORTED_BOUNDS = 1 << 3;
 
     public static final int CHANGE_ALL = CHANGE_ACTIVE_SCREEN | CHANGE_ROTATION
-            | CHANGE_FRAME_DELAY | CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS;
+            | CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS;
 
     private final Context mContext;
     private final DisplayManager mDM;
@@ -149,16 +148,15 @@
             return;
         }
         if (Utilities.ATLEAST_S) {
-            // Only check for refresh rate. Everything else comes from component callbacks
-            if (getSingleFrameMs(display) == mInfo.singleFrameMs) {
-                return;
-            }
+            // Only update refresh rate. Everything else comes from component callbacks
+            mInfo.mSingleFrameMs = getSingleFrameMs(display);
+            return;
         }
         handleInfoChange(display);
     }
 
     public static int getSingleFrameMs(Context context) {
-        return INSTANCE.get(context).getInfo().singleFrameMs;
+        return INSTANCE.get(context).getInfo().mSingleFrameMs;
     }
 
     /**
@@ -249,9 +247,6 @@
         if (newInfo.rotation != oldInfo.rotation) {
             change |= CHANGE_ROTATION;
         }
-        if (newInfo.singleFrameMs != oldInfo.singleFrameMs) {
-            change |= CHANGE_FRAME_DELAY;
-        }
         if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale) {
             change |= CHANGE_DENSITY;
         }
@@ -292,7 +287,7 @@
 
     public static class Info {
 
-        public final int singleFrameMs;
+        private int mSingleFrameMs;
 
         // Configuration properties
         public final int rotation;
@@ -323,7 +318,7 @@
             densityDpi = config.densityDpi;
             mScreenSizeDp = new PortraitSize(config.screenHeightDp, config.screenWidthDp);
 
-            singleFrameMs = getSingleFrameMs(display);
+            mSingleFrameMs = getSingleFrameMs(display);
             currentSize = new Point();
             display.getRealSize(currentSize);
 
@@ -353,6 +348,8 @@
                     mPerDisplayBounds.put(displayKey, displayBounds);
                 }
             }
+            Log.d("b/211775278", "displayId: " + displayId + ", currentSize: " + currentSize);
+            Log.d("b/211775278", "perDisplayBounds: " + mPerDisplayBounds);
         }
 
         private static Set<WindowBounds> getSupportedBoundsForDisplay(Display display, Point size) {
diff --git a/src/com/android/launcher3/util/FlagOp.java b/src/com/android/launcher3/util/FlagOp.java
deleted file mode 100644
index bd40eb9..0000000
--- a/src/com/android/launcher3/util/FlagOp.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.android.launcher3.util;
-
-public interface FlagOp {
-
-    FlagOp NO_OP = i -> i;
-
-    int apply(int flags);
-
-    static FlagOp addFlag(int flag) {
-        return i -> i | flag;
-    }
-
-    static FlagOp removeFlag(int flag) {
-        return i -> i & ~flag;
-    }
-}
diff --git a/src/com/android/launcher3/util/UiThreadHelper.java b/src/com/android/launcher3/util/UiThreadHelper.java
index ac5368c..a1f31fe 100644
--- a/src/com/android/launcher3/util/UiThreadHelper.java
+++ b/src/com/android/launcher3/util/UiThreadHelper.java
@@ -28,7 +28,6 @@
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 
-import com.android.launcher3.BaseActivity;
 import com.android.launcher3.views.ActivityContext;
 
 /**
@@ -56,7 +55,7 @@
                 STATS_LOGGER_KEY,
                 Message.obtain(
                         HANDLER.get(root.getContext()),
-                        () -> BaseActivity.fromContext(root.getContext())
+                        () -> ActivityContext.lookupContext(root.getContext())
                                 .getStatsLogManager()
                                 .logger()
                                 .log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED)
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index e09eff6..8b48bae 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -25,6 +25,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.allapps.BaseAllAppsContainerView;
 import com.android.launcher3.dot.DotInfo;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.folder.FolderIcon;
@@ -93,6 +94,13 @@
      */
     BaseDragLayer getDragLayer();
 
+    /**
+     * The all apps container, if it exists in this context.
+     */
+    default BaseAllAppsContainerView<?> getAppsView() {
+        return null;
+    }
+
     DeviceProfile getDeviceProfile();
 
     default ViewCache getViewCache() {
@@ -125,13 +133,6 @@
     }
 
     /**
-     * Returns whether we can show the IME for elements hosted by this ActivityContext.
-     */
-    default boolean supportsIme() {
-        return true;
-    }
-
-    /**
      * Called just before logging the given item.
      */
     default void applyOverwritesToLogItem(LauncherAtom.ItemInfo.Builder itemInfoBuilder) { }
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 06313e7..55524dd 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -17,7 +17,6 @@
 
 import static com.android.launcher3.Utilities.getBadge;
 import static com.android.launcher3.Utilities.getFullDrawable;
-import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 import static com.android.launcher3.views.IconLabelDotView.setIconAndDotVisible;
 
@@ -254,8 +253,7 @@
     private static void getIconResult(Launcher l, View originalView, ItemInfo info, RectF pos,
             Drawable btvIcon, IconLoadResult iconLoadResult) {
         Drawable drawable;
-        boolean supportsAdaptiveIcons = ADAPTIVE_ICON_WINDOW_ANIM.get()
-                && !info.isDisabled(); // Use original icon for disabled icons.
+        boolean supportsAdaptiveIcons = !info.isDisabled(); // Use original icon for disabled icons.
 
         Drawable badge = null;
         if (info instanceof SystemShortcut) {
diff --git a/src/com/android/launcher3/views/FloatingSurfaceView.java b/src/com/android/launcher3/views/FloatingSurfaceView.java
index f32f904..e7cb3b3 100644
--- a/src/com/android/launcher3/views/FloatingSurfaceView.java
+++ b/src/com/android/launcher3/views/FloatingSurfaceView.java
@@ -97,7 +97,7 @@
 
         // Remove after some time, to avoid flickering
         Executors.MAIN_EXECUTOR.getHandler().postDelayed(mRemoveViewRunnable,
-                DisplayController.INSTANCE.get(mLauncher).getInfo().singleFrameMs);
+                DisplayController.getSingleFrameMs(mLauncher));
     }
 
     private void removeViewFromParent() {
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
index 978c321..5543cc2 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -34,13 +34,6 @@
 
     private static final int STATE_FLAGS = FLAG_WORKSPACE_INACCESSIBLE;
 
-    private static final PageAlphaProvider PAGE_ALPHA_PROVIDER = new PageAlphaProvider(DEACCEL_2) {
-        @Override
-        public float getPageAlpha(int pageIndex) {
-            return 0;
-        }
-    };
-
     public AllAppsState(int id) {
         super(id, LAUNCHER_STATE_ALLAPPS, STATE_FLAGS);
     }
@@ -68,7 +61,15 @@
 
     @Override
     public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
-        return PAGE_ALPHA_PROVIDER;
+        PageAlphaProvider superPageAlphaProvider = super.getWorkspacePageAlphaProvider(launcher);
+        return new PageAlphaProvider(DEACCEL_2) {
+            @Override
+            public float getPageAlpha(int pageIndex) {
+                return launcher.getDeviceProfile().isTablet
+                        ? superPageAlphaProvider.getPageAlpha(pageIndex)
+                        : 0;
+            }
+        };
     }
 
     @Override
@@ -78,6 +79,8 @@
 
     @Override
     public int getWorkspaceScrimColor(Launcher launcher) {
-        return Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
+        return launcher.getDeviceProfile().isTablet
+                ? launcher.getResources().getColor(R.color.widgets_picker_scrim)
+                : Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
     }
 }
diff --git a/tests/Android.bp b/tests/Android.bp
index 8def20f..f3e0500 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -23,7 +23,10 @@
 // Source code used for test
 filegroup {
     name: "launcher-tests-src",
-    srcs: ["src/**/*.java"],
+    srcs: [
+      "src/**/*.java",
+      "src/**/*.kt"
+    ],
 }
 
 // Source code used for oop test helpers
diff --git a/tests/src/com/android/launcher3/DeviceProfileTest.kt b/tests/src/com/android/launcher3/DeviceProfileTest.kt
new file mode 100644
index 0000000..6c99a21
--- /dev/null
+++ b/tests/src/com/android/launcher3/DeviceProfileTest.kt
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3
+
+import android.content.Context
+import android.graphics.PointF
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.util.DisplayController.Info
+import com.android.launcher3.util.WindowBounds
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.*
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DeviceProfileTest {
+
+    private var context: Context? = null
+    private var inv: InvariantDeviceProfile? = null
+    private var info: Info = mock(Info::class.java)
+    private var windowBounds: WindowBounds? = null
+    private var isMultiWindowMode: Boolean = false
+    private var transposeLayoutWithOrientation: Boolean = false
+    private var useTwoPanels: Boolean = false
+
+    @Before
+    fun setUp() {
+        context = ApplicationProvider.getApplicationContext()
+        // make sure to reset values
+        useTwoPanels = false
+    }
+
+    @Test
+    fun qsbWidth_is_match_parent_for_phones() {
+        initializeVarsForPhone()
+
+        val dp = DeviceProfile(
+            context,
+            inv,
+            info,
+            windowBounds,
+            isMultiWindowMode,
+            transposeLayoutWithOrientation,
+            useTwoPanels
+        )
+
+        assertThat(dp.isQsbInline).isFalse()
+        assertThat(dp.qsbWidth).isEqualTo(0)
+    }
+
+    @Test
+    fun qsbWidth_is_match_parent_for_tablet_portrait() {
+        initializeVarsForTablet()
+
+        val dp = DeviceProfile(
+            context,
+            inv,
+            info,
+            windowBounds,
+            isMultiWindowMode,
+            transposeLayoutWithOrientation,
+            useTwoPanels
+        )
+
+        assertThat(dp.isQsbInline).isFalse()
+        assertThat(dp.qsbWidth).isEqualTo(0)
+    }
+
+    @Test
+    fun qsbWidth_has_size_for_tablet_landscape() {
+        initializeVarsForTablet(true)
+
+        val dp = DeviceProfile(
+            context,
+            inv,
+            info,
+            windowBounds,
+            isMultiWindowMode,
+            transposeLayoutWithOrientation,
+            useTwoPanels
+        )
+
+        if (dp.hotseatQsbHeight > 0) {
+            assertThat(dp.isQsbInline).isTrue()
+            assertThat(dp.qsbWidth).isGreaterThan(0)
+        } else {
+            assertThat(dp.isQsbInline).isFalse()
+            assertThat(dp.qsbWidth).isEqualTo(0)
+        }
+    }
+
+    /**
+     * This test is to make sure that two panels don't inline the QSB as tablets do
+     */
+    @Test
+    fun qsbWidth_is_match_parent_for_two_panel_landscape() {
+        initializeVarsForTablet(true)
+        useTwoPanels = true
+
+        val dp = DeviceProfile(
+            context,
+            inv,
+            info,
+            windowBounds,
+            isMultiWindowMode,
+            transposeLayoutWithOrientation,
+            useTwoPanels
+        )
+
+        assertThat(dp.isQsbInline).isFalse()
+        assertThat(dp.qsbWidth).isEqualTo(0)
+    }
+
+    private fun initializeVarsForPhone(isLandscape: Boolean = false) {
+        val (x, y) = if (isLandscape)
+            Pair(3120, 1440)
+        else
+            Pair(1440, 3120)
+
+        windowBounds = WindowBounds(x, y, x, y - 100)
+
+        `when`(info.isTablet(any())).thenReturn(false)
+
+        scalableInvariantDeviceProfile()
+    }
+
+    private fun initializeVarsForTablet(isLandscape: Boolean = false) {
+        val (x, y) = if (isLandscape)
+            Pair(2560, 1600)
+        else
+            Pair(1600, 2560)
+
+        windowBounds = WindowBounds(x, y, x, y - 100)
+
+        `when`(info.isTablet(any())).thenReturn(true)
+
+        scalableInvariantDeviceProfile()
+    }
+
+    /**
+     * A very generic grid, just to make qsb tests work. For real calculations, make sure to use
+     * values that better represent a real grid.
+     */
+    private fun scalableInvariantDeviceProfile() {
+        inv = InvariantDeviceProfile().apply {
+            isScalable = true
+            numColumns = 5
+            numRows = 5
+            horizontalMargin = FloatArray(4) { 22f }
+            borderSpaces = listOf(
+                PointF(16f, 16f),
+                PointF(16f, 16f),
+                PointF(16f, 16f),
+                PointF(16f, 16f)
+            ).toTypedArray()
+            allAppsBorderSpaces = listOf(
+                PointF(16f, 16f),
+                PointF(16f, 16f),
+                PointF(16f, 16f),
+                PointF(16f, 16f)
+            ).toTypedArray()
+            hotseatBorderSpaces = FloatArray(4) { 16f }
+            iconSize = FloatArray(4) { 56f }
+            allAppsIconSize = FloatArray(4) { 56f }
+            iconTextSize = FloatArray(4) { 14f }
+            allAppsIconTextSize = FloatArray(4) { 14f }
+            minCellSize = listOf(
+                PointF(64f, 83f),
+                PointF(64f, 83f),
+                PointF(64f, 83f),
+                PointF(64f, 83f)
+            ).toTypedArray()
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java b/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
index 032a7b4..f34a29e 100644
--- a/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
+++ b/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
@@ -27,6 +27,7 @@
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
 import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
+import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 
 import org.junit.After;
 import org.junit.Test;
@@ -73,6 +74,7 @@
     }
 
     @Test
+    @ScreenRecord // b/202985412
     public void testPromiseIcon_addedFromEligibleSession() throws Throwable {
         final String appLabel = "Test Promise App " + UUID.randomUUID().toString();
         final ItemOperator findPromiseApp = (info, view) ->
@@ -95,6 +97,7 @@
     }
 
     @Test
+    @ScreenRecord // b/202985412
     public void testPromiseIcon_notAddedFromIneligibleSession() throws Throwable {
         final String appLabel = "Test Promise App " + UUID.randomUUID().toString();
         final ItemOperator findPromiseApp = (info, view) ->
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 3e98983..5afbee2 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -134,8 +134,6 @@
 
         String result;
         if (sDumpWasGenerated) {
-            Log.d("b/195319692", "dump has already been generated by another test",
-                    new Exception());
             result = "dump has already been generated by another test";
         } else {
             try {
@@ -150,7 +148,6 @@
                             "am dumpheap " + device.getLauncherPackageName() + " " + fileName);
                 }
                 sDumpWasGenerated = true;
-                Log.d("b/195319692", "sDumpWasGenerated := true", new Exception());
                 result = "saved memory dump as an artifact";
             } catch (Throwable e) {
                 Log.e(TAG, "dumpHprofData failed", e);
diff --git a/tests/src/com/android/launcher3/ui/WorkProfileTest.java b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
index 939cfe1..f31e4f3 100644
--- a/tests/src/com/android/launcher3/ui/WorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
@@ -26,7 +26,7 @@
 import android.view.View;
 
 import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
 import com.android.launcher3.allapps.AllAppsPagedView;
 import com.android.launcher3.allapps.WorkAdapterProvider;
 import com.android.launcher3.allapps.WorkEduCard;
@@ -41,7 +41,7 @@
 
 public class WorkProfileTest extends AbstractLauncherUiTest {
 
-    private static final int WORK_PAGE = AllAppsContainerView.AdapterHolder.WORK;
+    private static final int WORK_PAGE = ActivityAllAppsContainerView.AdapterHolder.WORK;
 
     private int mProfileUserId;
 
@@ -132,7 +132,7 @@
 
         // start work profile toggle ON test
         executeOnLauncher(l -> {
-            AllAppsContainerView allApps = l.getAppsView();
+            ActivityAllAppsContainerView<?> allApps = l.getAppsView();
             assertEquals("Work tab is not focused", allApps.getCurrentPage(), WORK_PAGE);
             View workPausedCard = allApps.getActiveRecyclerView().findViewHolderForAdapterPosition(
                     0).itemView;
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index 2c9785c..4740097 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -33,6 +33,7 @@
 import com.android.launcher3.testcomponent.WidgetConfigActivity;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
 import com.android.launcher3.ui.TestViewHelpers;
+import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 import com.android.launcher3.util.rule.ShellCommandRule;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
 
@@ -72,6 +73,7 @@
 
     @Test
     @PortraitLandscape
+    @ScreenRecord // b/215672979
     public void testConfigCancelled() throws Throwable {
         runTest(false);
     }
diff --git a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
index ccbb662..0c1f0cd 100644
--- a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
@@ -42,6 +42,7 @@
 import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
 import com.android.launcher3.util.Wait;
 import com.android.launcher3.util.Wait.Condition;
+import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 import com.android.launcher3.util.rule.ShellCommandRule;
 
 import org.junit.Before;
@@ -77,6 +78,7 @@
     public void testEmpty() throws Throwable { /* needed while the broken tests are being fixed */ }
 
     @Test
+    @ScreenRecord // b/215673732
     public void testPinWidgetNoConfig() throws Throwable {
         runTest("pinWidgetNoConfig", true, (info, view) -> info instanceof LauncherAppWidgetInfo &&
                 ((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId &&
@@ -85,6 +87,7 @@
     }
 
     @Test
+    @ScreenRecord // b/215673732
     public void testPinWidgetNoConfig_customPreview() throws Throwable {
         // Command to set custom preview
         Intent command = RequestPinItemActivity.getCommandIntent(
@@ -98,6 +101,7 @@
     }
 
     @Test
+    @ScreenRecord // b/215673732
     public void testPinWidgetWithConfig() throws Throwable {
         runTest("pinWidgetWithConfig", true,
                 (info, view) -> info instanceof LauncherAppWidgetInfo &&
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 4eaecca..d84d723 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -134,31 +134,6 @@
                 break;
             }
 
-            case TWO_BUTTON: {
-                final int startX;
-                final int startY;
-                final int endX;
-                final int endY;
-                final int swipeLength = mLauncher.getTestInfo(getSwipeHeightRequestName()).
-                        getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD) + mLauncher.getTouchSlop();
-
-                if (mLauncher.getDevice().isNaturalOrientation()) {
-                    startX = endX = mLauncher.getDevice().getDisplayWidth() / 2;
-                    startY = getSwipeStartY();
-                    endY = startY - swipeLength;
-                } else {
-                    startX = getSwipeStartX();
-                    // TODO(b/184059820) make horizontal swipe use swipe width not height, for the
-                    // moment just double the swipe length.
-                    endX = startX - swipeLength * 2;
-                    startY = endY = mLauncher.getDevice().getDisplayHeight() / 2;
-                }
-
-                mLauncher.swipeToState(startX, startY, endX, endY, 10, OVERVIEW_STATE_ORDINAL,
-                        LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
-                break;
-            }
-
             case THREE_BUTTON:
                 if (mLauncher.isTablet()) {
                     mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
@@ -253,11 +228,7 @@
                      "want to quick switch to the previous app")) {
             verifyActiveContainer();
             final boolean launcherWasVisible = mLauncher.isLauncherVisible();
-            boolean transposeInLandscape = false;
             switch (mLauncher.getNavigationModel()) {
-                case TWO_BUTTON:
-                    transposeInLandscape = true;
-                    // Fall through, zero button and two button modes behave the same.
                 case ZERO_BUTTON: {
                     final int startX;
                     final int startY;
@@ -265,33 +236,17 @@
                     final int endY;
                     final int cornerRadius = (int) Math.ceil(mLauncher.getWindowCornerRadius());
                     if (toRight) {
-                        if (mLauncher.getDevice().isNaturalOrientation() || !transposeInLandscape) {
-                            // Swipe from the bottom left to the bottom right of the screen.
-                            startX = cornerRadius;
-                            startY = getSwipeStartY();
-                            endX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
-                            endY = startY;
-                        } else {
-                            // Swipe from the bottom right to the top right of the screen.
-                            startX = getSwipeStartX();
-                            startY = mLauncher.getRealDisplaySize().y - 1 - cornerRadius;
-                            endX = startX;
-                            endY = cornerRadius;
-                        }
+                        // Swipe from the bottom left to the bottom right of the screen.
+                        startX = cornerRadius;
+                        startY = getSwipeStartY();
+                        endX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
+                        endY = startY;
                     } else {
-                        if (mLauncher.getDevice().isNaturalOrientation() || !transposeInLandscape) {
-                            // Swipe from the bottom right to the bottom left of the screen.
-                            startX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
-                            startY = getSwipeStartY();
-                            endX = cornerRadius;
-                            endY = startY;
-                        } else {
-                            // Swipe from the bottom left to the top left of the screen.
-                            startX = getSwipeStartX();
-                            startY = cornerRadius;
-                            endX = startX;
-                            endY = mLauncher.getRealDisplaySize().y - 1 - cornerRadius;
-                        }
+                        // Swipe from the bottom right to the bottom left of the screen.
+                        startX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
+                        startY = getSwipeStartY();
+                        endX = cornerRadius;
+                        endY = startY;
                     }
 
                     final boolean isZeroButton = mLauncher.getNavigationModel()
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index bc2afaf..5511770 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -124,7 +124,7 @@
         WORKSPACE, ALL_APPS, OVERVIEW, WIDGETS, BACKGROUND, FALLBACK_OVERVIEW
     }
 
-    public enum NavigationModel {ZERO_BUTTON, TWO_BUTTON, THREE_BUTTON}
+    public enum NavigationModel {ZERO_BUTTON, THREE_BUTTON}
 
     // Where the gesture happens: outside of Launcher, inside or from inside to outside and
     // whether the gesture recognition triggers pilfer.
@@ -391,8 +391,6 @@
     public static NavigationModel getNavigationModel(int currentInteractionMode) {
         if (QuickStepContract.isGesturalMode(currentInteractionMode)) {
             return NavigationModel.ZERO_BUTTON;
-        } else if (QuickStepContract.isSwipeUpMode(currentInteractionMode)) {
-            return NavigationModel.TWO_BUTTON;
         } else if (QuickStepContract.isLegacyMode(currentInteractionMode)) {
             return NavigationModel.THREE_BUTTON;
         }
@@ -432,12 +430,13 @@
             {
                 final StringBuilder sb = new StringBuilder();
 
-                UiObject2 object = mDevice.findObject(By.res("android", "alertTitle"));
+                UiObject2 object =
+                        mDevice.findObject(By.res("android", "alertTitle").pkg("android"));
                 if (object != null) {
                     sb.append("TITLE: ").append(object.getText());
                 }
 
-                object = mDevice.findObject(By.res("android", "message"));
+                object = mDevice.findObject(By.res("android", "message").pkg("android"));
                 if (object != null) {
                     sb.append(" PACKAGE: ").append(object.getApplicationPackage())
                             .append(" MESSAGE: ").append(object.getText());
@@ -864,7 +863,7 @@
 
                     swipeToState(
                             displaySize.x / 2, displaySize.y - 1,
-                            displaySize.x / 2, 0,
+                            displaySize.x / 2, displaySize.y / 2,
                             ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME, NORMAL_STATE_ORDINAL,
                             gestureStartFromLauncher ? GestureScope.INSIDE_TO_OUTSIDE
                                     : GestureScope.OUTSIDE_WITH_PILFER);
@@ -873,10 +872,6 @@
                 log("Hierarchy before clicking home:");
                 dumpViewHierarchy();
                 action = "clicking home button";
-                if (!isLauncher3() && getNavigationModel() == NavigationModel.TWO_BUTTON) {
-                    expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
-                    expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
-                }
                 if (isTablet()) {
                     expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
                     expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_UP);
@@ -917,9 +912,6 @@
                 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) {
diff --git a/tests/tapl/com/android/launcher3/tapl/Widgets.java b/tests/tapl/com/android/launcher3/tapl/Widgets.java
index 0bac2ca..7fd68c0 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widgets.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widgets.java
@@ -115,6 +115,7 @@
             final BySelector labelSelector = By.clazz("android.widget.TextView").text(labelText);
             final BySelector previewSelector = By.res(mLauncher.getLauncherPackageName(),
                     "widget_preview");
+            final int bottomGestureStartOnScreen = mLauncher.getBottomGestureStartOnScreen();
             int i = 0;
             for (; ; ) {
                 final Collection<UiObject2> tableRows = mLauncher.getChildren(widgetsContainer);
@@ -126,6 +127,9 @@
                         if (label == null) {
                             continue;
                         }
+                        if (widget.getVisibleCenter().y >= bottomGestureStartOnScreen) {
+                            continue;
+                        }
                         mLauncher.assertEquals(
                                 "View is not WidgetCell",
                                 "com.android.launcher3.widget.WidgetCell",