Merge "Log the input type for gesture nav gestures" into udc-dev
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index b1064f7..bf84820 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -177,7 +177,7 @@
   ALL_APPS_SEARCH_RESULT_SUGGEST = 22 [deprecated = true];
   ALL_APPS_SEARCH_RESULT_ASSISTANT = 23;
   ALL_APPS_SEARCH_RESULT_CHROMETAB = 24;
-  ALL_APPS_SEARCH_RESULT_NAVVYSITE = 25;
+  ALL_APPS_SEARCH_RESULT_NAVVYSITE = 25 [deprecated = true];
   ALL_APPS_SEARCH_RESULT_TIPS = 26;
   ALL_APPS_SEARCH_RESULT_PEOPLE_TILE = 27;
   ALL_APPS_SEARCH_RESULT_LEGACY_SHORTCUT = 30;
diff --git a/quickstep/res/drawable/ic_save_app_pair.xml b/quickstep/res/drawable/ic_save_app_pair.xml
new file mode 100644
index 0000000..4a7ee1a
--- /dev/null
+++ b/quickstep/res/drawable/ic_save_app_pair.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+     Copyright (C) 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M13.329,2.305H4.242C2.751,2.305 1.542,3.514 1.542,5.005V13.005C1.542,14.496 2.751,15.705 4.242,15.705H7.875V19.011C7.875,20.502 9.084,21.711 10.575,21.711H19.662C21.153,21.711 22.362,20.502 22.362,19.011V10.011C22.362,8.52 21.153,7.311 19.662,7.311H16.029V5.005C16.029,3.514 14.821,2.305 13.329,2.305ZM14.329,7.311V5.005C14.329,4.452 13.882,4.005 13.329,4.005H4.242C3.69,4.005 3.242,4.452 3.242,5.005V13.005C3.242,13.557 3.69,14.005 4.242,14.005H7.875V10.011C7.875,8.52 9.084,7.311 10.575,7.311H14.329ZM9.575,14.005V10.011C9.575,9.611 9.81,9.266 10.15,9.106C10.285,9.037 10.438,8.999 10.6,8.999H19.687C20.239,8.999 20.687,9.447 20.687,9.999V18.999C20.687,19.399 20.452,19.744 20.113,19.904C19.977,19.972 19.824,20.011 19.662,20.011H10.575C10.023,20.011 9.575,19.563 9.575,19.011V15.705H9.6V14.005H9.575ZM15.542,11.996V14H17.588V15H15.542V16.996H14.542V15H12.464V14H14.542V11.996H15.542Z"
+      android:fillColor="#000000"
+      android:fillType="evenOdd"/>
+</vector>
diff --git a/quickstep/res/layout/keyboard_quick_switch_view.xml b/quickstep/res/layout/keyboard_quick_switch_view.xml
index 5c20a2d..64d3f67 100644
--- a/quickstep/res/layout/keyboard_quick_switch_view.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_view.xml
@@ -25,7 +25,8 @@
     android:clipToOutline="true"
     android:alpha="0"
     android:visibility="invisible"
-    android:focusableInTouchMode="true">
+    android:focusableInTouchMode="true"
+    app:layout_ignoreInsets="true">
 
     <HorizontalScrollView
         android:id="@+id/scroll_view"
diff --git a/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml b/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
index 43439c6..2887518 100644
--- a/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
@@ -205,15 +205,16 @@
             android:id="@+id/checkmark_animation"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_marginBottom="44dp"
             android:gravity="center"
             android:scaleType="centerCrop"
             app:lottie_loop="false"
             android:visibility="gone"
 
-            app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_fragment_feedback_subtitle" />
+            app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_fragment_feedback_subtitle"
+            app:layout_constraintBottom_toBottomOf="parent" />
 
         <Button
             android:id="@+id/gesture_tutorial_fragment_action_button"
@@ -224,6 +225,7 @@
             android:stateListAnimator="@null"
             android:text="@string/gesture_tutorial_action_button_label"
             android:visibility="invisible"
+            android:layout_marginBottom="60dp"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
diff --git a/quickstep/res/layout/taskbar_edu.xml b/quickstep/res/layout/taskbar_edu.xml
index d7daea3..f3856ba 100644
--- a/quickstep/res/layout/taskbar_edu.xml
+++ b/quickstep/res/layout/taskbar_edu.xml
@@ -55,7 +55,7 @@
             style="@style/TaskbarEdu.Button.Close"
             android:textColor="?android:attr/textColorPrimary"/>
 
-        <com.android.launcher3.pageindicators.PageIndicatorDots
+        <com.android.launcher3.pageindicators.LauncherDotsPageIndicator
             android:id="@+id/content_page_indicator"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
@@ -63,6 +63,7 @@
             app:layout_constraintBottom_toBottomOf="@id/edu_start_button"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
+            app:indicatorDotColor="@color/folder_pagination_color"
             android:elevation="1dp" />
 
         <Button
diff --git a/quickstep/res/layout/taskbar_edu_tooltip.xml b/quickstep/res/layout/taskbar_edu_tooltip.xml
index 3fcd713..657066c 100644
--- a/quickstep/res/layout/taskbar_edu_tooltip.xml
+++ b/quickstep/res/layout/taskbar_edu_tooltip.xml
@@ -20,7 +20,6 @@
     android:layout_marginBottom="16dp"
     android:clipChildren="false"
     android:clipToPadding="false"
-    android:fitsSystemWindows="true"
     android:focusable="true"
     android:importantForAccessibility="yes"
     android:gravity="center"
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 72e7a42..3df50c9 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -53,8 +53,7 @@
     <string name="back_gesture_intro_title" msgid="19551256430224428">"Zum Zurückgehen wischen"</string>
     <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Wenn du zum letzten Bildschirm zurückgehen möchtest, wische vom linken oder rechten Rand zur Mitte."</string>
     <string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Wenn du zum letzten Bildschirm zurückgehen möchtest, wische mit zwei Fingern vom linken oder rechten Displayrand zur Mitte."</string>
-    <!-- no translation found for back_gesture_tutorial_title (1944737946101059789) -->
-    <skip />
+    <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Zurück"</string>
     <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Wische vom unteren Displayrand nach oben."</string>
     <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Achte darauf, nicht innezuhalten, bevor du loslässt."</string>
     <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Wische gerade nach oben."</string>
@@ -73,12 +72,11 @@
     <string name="overview_gesture_intro_title" msgid="2902054412868489378">"Zwischen Apps wechseln"</string>
     <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Wische auf dem Display von unten nach oben, halte den Finger gedrückt und lass dann los, um zwischen Apps zu wechseln."</string>
     <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Wische zum App-Wechseln mit zwei Fingern vom unteren Displayrand nach oben, halte und lass dann los."</string>
-    <!-- no translation found for overview_gesture_tutorial_title (4125835002668708720) -->
-    <skip />
+    <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Apps wechseln"</string>
     <string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Fertig"</string>
     <string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Fertig"</string>
     <string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Einstellungen"</string>
-    <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Wiederholen"</string>
+    <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Noch einmal versuchen"</string>
     <string name="gesture_tutorial_nice" msgid="2936275692616928280">"Sehr gut!"</string>
     <string name="gesture_tutorial_step" msgid="1279786122817620968">"Anleitung <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="allset_title" msgid="5021126669778966707">"Fertig!"</string>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index a0f23cb..4badb49 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -53,8 +53,7 @@
     <string name="back_gesture_intro_title" msgid="19551256430224428">"पिछली स्क्रीन पर वापस जाने के लिए स्वाइप करें"</string>
     <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"पिछली स्क्रीन पर वापस जाने के लिए, स्क्रीन के बाएं या दाएं किनारे से बीचों-बीच तक स्वाइप करें."</string>
     <string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"पिछली स्क्रीन पर वापस जाने के लिए, स्क्रीन के बाएं या दाएं किनारे से स्क्रीन के बीच तक दो उंगलियों से स्वाइप करें."</string>
-    <!-- no translation found for back_gesture_tutorial_title (1944737946101059789) -->
-    <skip />
+    <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"वापस जाएं"</string>
     <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"देख लें कि आप स्क्रीन के निचले किनारे से ऊपर की ओर स्वाइप कर रहे हों."</string>
     <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"देख लें कि आप स्क्रीन से अपनी उंगली उठाने से पहले, इसे कहीं न रोक रहे हों."</string>
     <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"देख लें कि आपने ऊपर की ओर बिलकुल सीधे स्वाइप किया हो."</string>
@@ -73,8 +72,7 @@
     <string name="overview_gesture_intro_title" msgid="2902054412868489378">"एक ऐप्लिकेशन से दूसरे पर जाने के लिए स्वाइप करें"</string>
     <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"एक ऐप से दूसरे पर जाने के लिए, स्क्रीन पर नीचे से ऊपर की ओर स्वाइप करें, दबाकर रखें, और फिर छोड़ दें."</string>
     <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"इन ऐप के बीच स्विच करने के लिए, दो उंगलियों से नीचे से ऊपर स्वाइप करें, होल्ड करें, और फिर छोड़ें."</string>
-    <!-- no translation found for overview_gesture_tutorial_title (4125835002668708720) -->
-    <skip />
+    <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"ऐप्लिकेशन के बीच स्विच करें"</string>
     <string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"आप पूरी तरह तैयार हैं"</string>
     <string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"हो गया"</string>
     <string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"सेटिंग"</string>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 2134d14..5ac931d 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -24,7 +24,7 @@
     <string name="recents_empty_message" msgid="7040467240571714191">"Վերջին տարրեր չկան"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Հավելվածի օգտագործման կարգավորումներ"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Փակել բոլորը"</string>
-    <string name="accessibility_recent_apps" msgid="4058661986695117371">"Վերջին օգտագործած հավելվածները"</string>
+    <string name="accessibility_recent_apps" msgid="4058661986695117371">"Վերջին հավելվածներ"</string>
     <string name="task_view_closed" msgid="9170038230110856166">"Առաջադրանքը փակված է"</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 ր"</string>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 6782013..6f30fe6 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -100,7 +100,7 @@
     <string name="taskbar_edu_opened" msgid="3950252793551919129">"タスクバーの説明を開きました"</string>
     <string name="taskbar_edu_closed" msgid="126643734478892862">"タスクバーの説明を閉じました"</string>
     <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"アプリを横にドラッグして 2 個のアプリを同時に使用できます"</string>
-    <string name="taskbar_edu_stashing" msgid="5645461372669217294">"タスクバーを表示するには、ゆっくりと上にスワイプします"</string>
+    <string name="taskbar_edu_stashing" msgid="5645461372669217294">"タスクバーを表示するには、上にゆっくりとスワイプします"</string>
     <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"毎日の使用状況に基づいてアプリの候補が表示されます"</string>
     <string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"[設定] でジェスチャー ナビゲーションを ON にすると、タスクバーを自動的に非表示にできます"</string>
     <string name="taskbar_edu_features" msgid="3320337287472848162">"タスクバーの各種機能"</string>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index 66ffae5..a88d5e1 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -24,7 +24,7 @@
     <string name="recents_empty_message" msgid="7040467240571714191">"Соңғы элементтер жоқ"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Қолданбаны пайдалану параметрлері"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Барлығын өшіру"</string>
-    <string name="accessibility_recent_apps" msgid="4058661986695117371">"Соңғы пайдаланылған қолданбалар"</string>
+    <string name="accessibility_recent_apps" msgid="4058661986695117371">"Соңғы қолданбалар"</string>
     <string name="task_view_closed" msgid="9170038230110856166">"Тапсырма жабылды."</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 мин"</string>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index de3b511..fa6e5d2 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -109,7 +109,7 @@
     <string name="taskbar_edu_close" msgid="887022990168191073">"ಮುಚ್ಚಿರಿ"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ಮುಗಿದಿದೆ"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ಮುಖಪುಟ"</string>
-    <string name="taskbar_button_a11y" msgid="5241161324875094465">"ಪ್ರವೇಶಿಸುವಿಕೆ"</string>
+    <string name="taskbar_button_a11y" msgid="5241161324875094465">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ"</string>
     <string name="taskbar_button_back" msgid="8558862226461164514">"ಹಿಂದೆ"</string>
     <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME ಪರಿವರ್ತಕ"</string>
     <string name="taskbar_button_recents" msgid="7273376136216613134">"ಇತ್ತೀಚಿನವು"</string>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 79aba94..34285b7 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -114,7 +114,7 @@
     <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME которгучу"</string>
     <string name="taskbar_button_recents" msgid="7273376136216613134">"Акыркылар"</string>
     <string name="taskbar_button_notifications" msgid="7471740351507357318">"Билдирмелер"</string>
-    <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Ыкчам жөндөөлөр"</string>
+    <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Ыкчам параметрлер"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Тапшырмалар тактасы"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Тапшырмалар панели көрсөтүлдү"</string>
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Тапшырмалар панели жашырылды"</string>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index fe0aff2..fe4e954 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -109,7 +109,7 @@
     <string name="taskbar_edu_close" msgid="887022990168191073">"ပိတ်ရန်"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ပြီးပြီ"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ပင်မစာမျက်နှာ"</string>
-    <string name="taskbar_button_a11y" msgid="5241161324875094465">"အများသုံးစွဲနိုင်မှု"</string>
+    <string name="taskbar_button_a11y" msgid="5241161324875094465">"အများသုံးနိုင်မှု"</string>
     <string name="taskbar_button_back" msgid="8558862226461164514">"နောက်သို့"</string>
     <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME ပြောင်းစနစ်"</string>
     <string name="taskbar_button_recents" msgid="7273376136216613134">"လတ်တလောများ"</string>
diff --git a/quickstep/res/values-sw600dp/config.xml b/quickstep/res/values-sw600dp/config.xml
deleted file mode 100644
index e1e442f..0000000
--- a/quickstep/res/values-sw600dp/config.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<!-- Applies to large tablet screens portrait -->
-<resources>
-    <!-- Taskbar -->
-    <!-- Align the Taskbar to the start (Left/Right) of the device when 3 button nav is enabled. -->
-    <bool name="start_align_taskbar">true</bool>
-</resources>
\ No newline at end of file
diff --git a/quickstep/res/values-sw720dp-land/config.xml b/quickstep/res/values-sw720dp-land/config.xml
deleted file mode 100644
index bf0f9ad..0000000
--- a/quickstep/res/values-sw720dp-land/config.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<!-- Applies to large tablet screens landscape -->
-<resources>
-    <!-- Taskbar -->
-    <!-- Align the Taskbar to the start (Left/Right) of the device when 3 button nav is enabled. -->
-    <bool name="start_align_taskbar">false</bool>
-</resources>
\ No newline at end of file
diff --git a/quickstep/res/values-sw720dp/config.xml b/quickstep/res/values-sw720dp/config.xml
deleted file mode 100644
index e1e442f..0000000
--- a/quickstep/res/values-sw720dp/config.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<!-- Applies to large tablet screens portrait -->
-<resources>
-    <!-- Taskbar -->
-    <!-- Align the Taskbar to the start (Left/Right) of the device when 3 button nav is enabled. -->
-    <bool name="start_align_taskbar">true</bool>
-</resources>
\ No newline at end of file
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 4c69b2b..d12513d 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -109,7 +109,7 @@
     <string name="taskbar_edu_close" msgid="887022990168191073">"Закрити"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Головний екран"</string>
-    <string name="taskbar_button_a11y" msgid="5241161324875094465">"Спеціальні можливості"</string>
+    <string name="taskbar_button_a11y" msgid="5241161324875094465">"Доступність"</string>
     <string name="taskbar_button_back" msgid="8558862226461164514">"Назад"</string>
     <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Перемикач IME"</string>
     <string name="taskbar_button_recents" msgid="7273376136216613134">"Нещодавні"</string>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index ae3c445..0433177 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -24,7 +24,7 @@
     <string name="recents_empty_message" msgid="7040467240571714191">"Yaqinda ishlatilgan ilovalar yo‘q"</string>
     <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>
+    <string name="accessibility_recent_apps" msgid="4058661986695117371">"Oxirgi ilovalar"</string>
     <string name="task_view_closed" msgid="9170038230110856166">"Vazifalar yopildi"</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 daqiqa"</string>
@@ -109,7 +109,7 @@
     <string name="taskbar_edu_close" msgid="887022990168191073">"Yopish"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Tayyor"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Bosh ekran"</string>
-    <string name="taskbar_button_a11y" msgid="5241161324875094465">"Maxsus imkoniyatlar"</string>
+    <string name="taskbar_button_a11y" msgid="5241161324875094465">"Qulayliklar"</string>
     <string name="taskbar_button_back" msgid="8558862226461164514">"Orqaga"</string>
     <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME tugmasi"</string>
     <string name="taskbar_button_recents" msgid="7273376136216613134">"Oxirgilar"</string>
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 0d3aeb3..e45d9fd 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -52,10 +52,6 @@
 
     <string name="setup_wizard_pkg" translatable="false" />
 
-    <!-- Taskbar -->
-    <!-- Align the Taskbar to the start (Left/Right) of the device when 3 button nav is enabled. -->
-    <bool name="start_align_taskbar">false</bool>
-
     <!-- This is a float because it is converted to dp later in DeviceProfile -->
     <item name="taskbar_icon_size" type="dimen" format="float">44</item>
 </resources>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 8796d6c..7eecb29 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -321,7 +321,7 @@
         ActivityOptions options = ActivityOptions.makeRemoteAnimation(
                 new RemoteAnimationAdapter(runner, duration, statusBarTransitionDelay),
                 new RemoteTransition(runner.toRemoteTransition(),
-                        mLauncher.getIApplicationThread()));
+                        mLauncher.getIApplicationThread(), "QuickstepLaunch"));
         return new ActivityOptionsWrapper(options, onEndCallback);
     }
 
@@ -1122,7 +1122,7 @@
             mLauncherOpenTransition = new RemoteTransition(
                     new LauncherAnimationRunner(mHandler, mWallpaperOpenTransitionRunner,
                             false /* startAtFrontOfQueue */).toRemoteTransition(),
-                    mLauncher.getIApplicationThread());
+                    mLauncher.getIApplicationThread(), "QuickstepLaunchHome");
 
             TransitionFilter homeCheck = new TransitionFilter();
             // No need to handle the transition that also dismisses keyguard.
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index e8f2496..3510fbe 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -76,7 +76,6 @@
 
         mFocusHelper = new SimpleFocusIndicatorHelper(this);
         mActivityContext = ActivityContext.lookupContext(context);
-        mActivityContext.addOnDeviceProfileChangeListener(this);
         mNumPredictedAppsPerRow = mActivityContext.getDeviceProfile().numShownAllAppsColumns;
         updateVisibility();
     }
@@ -84,6 +83,13 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
+        mActivityContext.addOnDeviceProfileChangeListener(this);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mActivityContext.removeOnDeviceProfileChangeListener(this);
     }
 
     public void setup(FloatingHeaderView parent, FloatingHeaderRow[] rows, boolean tabsHidden) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
index c165750..ed4a212 100644
--- a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.taskbar;
 
+import static com.android.launcher3.Utilities.isRunningInTestHarness;
 import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
 import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
 
@@ -80,10 +81,13 @@
      * Currently this animation just force stashes the taskbar in Overview.
      */
     public Animator createAnimToRecentsState(RecentsState toState, long duration) {
-        boolean useStashedLauncherState = toState.hasOverviewActions();
-        boolean stashedLauncherState =
-                useStashedLauncherState && FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get()
-                        && toState == RecentsState.MODAL_TASK;
+        // Force stash the taskbar in overview modal state or when going home. We do not force
+        // stash on home when running in a test as 3p launchers rely on taskbar instead of hotseat.
+        boolean isGoingHome = toState == RecentsState.HOME && !isRunningInTestHarness();
+        boolean useStashedLauncherState = toState.hasOverviewActions() || isGoingHome;
+        boolean stashedLauncherState = useStashedLauncherState && (
+                (FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get() && toState == RecentsState.MODAL_TASK)
+                        || isGoingHome);
         TaskbarStashController stashController = mControllers.taskbarStashController;
         // Set both FLAG_IN_STASHED_LAUNCHER_STATE and FLAG_IN_APP to ensure the state is respected.
         // For all other states, just use the current stashed-in-app setting (e.g. if long clicked).
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index 941b4b0..c4255bf 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -49,7 +49,8 @@
     public static final int ALPHA_INDEX_STASHED = 0;
     public static final int ALPHA_INDEX_HOME_DISABLED = 1;
     public static final int ALPHA_INDEX_ASSISTANT_INVOKED = 2;
-    private static final int NUM_ALPHA_CHANNELS = 3;
+    public static final int ALPHA_INDEX_HIDDEN_WHILE_DREAMING = 3;
+    private static final int NUM_ALPHA_CHANNELS = 4;
 
     /**
      * The SharedPreferences key for whether the stashed handle region is dark.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 66a903b..41093bd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -55,7 +55,6 @@
 import com.android.launcher3.R;
 import com.android.launcher3.accessibility.DragViewStateAnnouncer;
 import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragDriver;
 import com.android.launcher3.dragndrop.DragOptions;
@@ -188,12 +187,10 @@
 
         DragOptions dragOptions = new DragOptions();
         dragOptions.preDragCondition = null;
-        if (FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()) {
-            PopupContainerWithArrow<BaseTaskbarContext> popupContainer =
-                    mControllers.taskbarPopupController.showForIcon(btv);
-            if (popupContainer != null) {
-                dragOptions.preDragCondition = popupContainer.createPreDragCondition(false);
-            }
+        PopupContainerWithArrow<BaseTaskbarContext> popupContainer =
+                mControllers.taskbarPopupController.showForIcon(btv);
+        if (popupContainer != null) {
+            dragOptions.preDragCondition = popupContainer.createPreDragCondition(false);
         }
         if (dragOptions.preDragCondition == null) {
             dragOptions.preDragCondition = new DragOptions.PreDragCondition() {
@@ -208,8 +205,7 @@
                 public void onPreDragStart(DropTarget.DragObject dragObject) {
                     mDragView = dragObject.dragView;
 
-                    if (FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()
-                            && !shouldStartDrag(0)) {
+                    if (!shouldStartDrag(0)) {
                         mDragView.setOnAnimationEndCallback(() -> {
                             // Drag might be cancelled during the DragView animation, so check
                             // mIsPreDrag again.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index 60b5c0d..77f681e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -53,6 +53,10 @@
     // Translation property for taskbar background.
     private final AnimatedFloat mBgOffset = new AnimatedFloat(this::updateBackgroundOffset);
 
+    // Used to fade in/out the entirety of the taskbar, for a smooth transition before/after sysui
+    // changes the inset visibility.
+    private final AnimatedFloat mTaskbarAlpha = new AnimatedFloat(this::updateTaskbarAlpha);
+
     // Initialized in init.
     private TaskbarControllers mControllers;
     private TaskbarStashViaTouchController mTaskbarStashViaTouchController;
@@ -83,6 +87,9 @@
         mAssistantBgTaskbar.value = 1;
         mBgOverride.value = 1;
         updateBackgroundAlpha();
+
+        mTaskbarAlpha.value = 1;
+        updateTaskbarAlpha();
     }
 
     public void onDestroy() {
@@ -127,6 +134,10 @@
         return mBgOffset;
     }
 
+    public AnimatedFloat getTaskbarAlpha() {
+        return mTaskbarAlpha;
+    }
+
     /**
      * Make updates when configuration changes.
      */
@@ -165,6 +176,10 @@
         updateOnBackgroundNavButtonColorIntensity();
     }
 
+    private void updateTaskbarAlpha() {
+        mTaskbarDragLayer.setAlpha(mTaskbarAlpha.value);
+    }
+
     @Override
     public void setCornerRoundness(float cornerRoundness) {
         mTaskbarDragLayer.setCornerRoundness(cornerRoundness);
@@ -197,6 +212,7 @@
         pw.println(prefix + "TaskbarDragLayerController:");
 
         pw.println(prefix + "\tmBgOffset=" + mBgOffset.value);
+        pw.println(prefix + "\tmTaskbarAlpha=" + mTaskbarAlpha.value);
         pw.println(prefix + "\tmFolderMargin=" + mFolderMargin);
         pw.println(prefix + "\tmLastSetBackgroundAlpha=" + mLastSetBackgroundAlpha);
         pw.println(prefix + "\t\tmBgOverride=" + mBgOverride.value);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
index 6cd6512..d0e6386 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
@@ -25,12 +25,12 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.PagedView;
 import com.android.launcher3.R;
-import com.android.launcher3.pageindicators.PageIndicatorDots;
+import com.android.launcher3.pageindicators.LauncherDotsPageIndicator;
 import com.android.launcher3.taskbar.TaskbarEduController.TaskbarEduCallbacks;
 import com.android.launcher3.views.ActivityContext;
 
 /** Horizontal carousel of tutorial screens for Taskbar Edu. */
-public class TaskbarEduPagedView extends PagedView<PageIndicatorDots> {
+public class TaskbarEduPagedView extends PagedView<LauncherDotsPageIndicator> {
 
     private TaskbarEduView mTaskbarEduView;
     private TaskbarEduCallbacks mControllerCallbacks;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 1adbf39..fcb2042 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -70,20 +70,9 @@
     fun init(controllers: TaskbarControllers) {
         this.controllers = controllers
         windowLayoutParams = context.windowLayoutParams
-        windowLayoutParams.providedInsets =
-            arrayOf(
-                InsetsFrameProvider(insetsOwner, 0, navigationBars()),
-                InsetsFrameProvider(insetsOwner, 0, tappableElement()),
-                InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures()),
-                InsetsFrameProvider(insetsOwner, INDEX_LEFT, systemGestures())
-                    .setSource(SOURCE_DISPLAY),
-                InsetsFrameProvider(insetsOwner, INDEX_RIGHT, systemGestures())
-                    .setSource(SOURCE_DISPLAY)
-            )
-
+        windowLayoutParams.insetsRoundedCornerFrame = true
         onTaskbarWindowHeightOrInsetsChanged()
 
-        windowLayoutParams.insetsRoundedCornerFrame = true
         context.addOnDeviceProfileChangeListener(deviceProfileChangeListener)
         gestureNavSettingsObserver.registerForCallingUser()
     }
@@ -94,6 +83,26 @@
     }
 
     fun onTaskbarWindowHeightOrInsetsChanged() {
+        if (context.isGestureNav) {
+            windowLayoutParams.providedInsets =
+                    arrayOf(
+                            InsetsFrameProvider(insetsOwner, 0, navigationBars()),
+                            InsetsFrameProvider(insetsOwner, 0, tappableElement()),
+                            InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures()),
+                            InsetsFrameProvider(insetsOwner, INDEX_LEFT, systemGestures())
+                                    .setSource(SOURCE_DISPLAY),
+                            InsetsFrameProvider(insetsOwner, INDEX_RIGHT, systemGestures())
+                                    .setSource(SOURCE_DISPLAY)
+                    )
+        } else {
+            windowLayoutParams.providedInsets =
+                    arrayOf(
+                            InsetsFrameProvider(insetsOwner, 0, navigationBars()),
+                            InsetsFrameProvider(insetsOwner, 0, tappableElement()),
+                            InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures())
+                    )
+        }
+
         val touchableHeight = controllers.taskbarStashController.touchableHeight
         touchableRegion.set(
             0,
@@ -146,7 +155,8 @@
         for (provider in windowLayoutParams.providedInsets) {
             if (context.isGestureNav && provider.type == tappableElement()) {
                 provider.insetsSizeOverrides = insetsSizeOverrideForGestureNavTappableElement
-            } else {
+            } else if (provider.type != systemGestures()) {
+                // We only override insets at the bottom of the screen
                 provider.insetsSizeOverrides = insetsSizeOverride
             }
         }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
index edcd4c8..03d08eb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
@@ -1,17 +1,17 @@
 package com.android.launcher3.taskbar;
 
 import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
-import static com.android.systemui.shared.system.QuickStepContract.SCREEN_STATE_OFF;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_AWAKE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DOZING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_ON;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_STATE_MASK;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_WAKEFULNESS_MASK;
+import static com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_ASLEEP;
 
 import android.app.KeyguardManager;
 
@@ -29,7 +29,7 @@
             | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING | SYSUI_STATE_DEVICE_DOZING
             | SYSUI_STATE_OVERVIEW_DISABLED | SYSUI_STATE_HOME_DISABLED
             | SYSUI_STATE_BACK_DISABLED | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
-            | SYSUI_STATE_SCREEN_STATE_MASK;
+            | SYSUI_STATE_WAKEFULNESS_MASK;
 
     // If any of these SysUi flags (via QuickstepContract) is set, the device to be considered
     // locked.
@@ -75,13 +75,13 @@
                 keyguardOccluded);
         updateIconsForBouncer();
 
-        boolean screenOffOrTransitioningOff = (systemUiStateFlags & SYSUI_STATE_SCREEN_ON) == 0;
-        boolean closeFloatingViews = keyguardShowing || screenOffOrTransitioningOff;
+        boolean asleepOrGoingToSleep = (systemUiStateFlags & SYSUI_STATE_AWAKE) == 0;
+        boolean closeFloatingViews = keyguardShowing || asleepOrGoingToSleep;
 
         if (closeFloatingViews) {
-            // animate the closing of the views, unless the screen is already fully turned off.
+            // animate the closing of the views, unless the screen is already asleep.
             boolean animateViewClosing =
-                    (systemUiStateFlags & SYSUI_STATE_SCREEN_STATE_MASK) != SCREEN_STATE_OFF;
+                    (systemUiStateFlags & SYSUI_STATE_WAKEFULNESS_MASK) != WAKEFULNESS_ASLEEP;
             AbstractFloatingView.closeOpenViews(mContext, animateViewClosing, TYPE_ALL);
         }
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index cf8148e..58cb558 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -22,12 +22,16 @@
 import static com.android.launcher3.util.FlagDebugUtils.appendFlag;
 import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
 import static com.android.systemui.animation.Interpolators.EMPHASIZED;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_ON;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_AWAKE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_WAKEFULNESS_MASK;
+import static com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_AWAKE;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
+import android.os.SystemClock;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
@@ -81,21 +85,37 @@
      *
      * This is cleared as soon as the screen begins to transition off.
      */
-    private static final int FLAG_SCREEN_ON = 1 << 3;
+    private static final int FLAG_AWAKE = 1 << 3;
 
     /**
-     * Captures whether the launcher was active at the time the FLAG_SCREEN_ON was cleared.
-     * Always cleared when FLAG_SCREEN_ON is set.
+     * Captures whether the launcher was active at the time the FLAG_AWAKE was cleared.
+     * Always cleared when FLAG_AWAKE is set.
      * <p>
-     * FLAG_RESUMED will be cleared when the screen is off, since all apps get paused at this point.
-     * Thus, this flag indicates whether the launcher will be shown when the screen gets turned on
+     * FLAG_RESUMED will be cleared when the device is asleep, since all apps get paused at this
+     * point. Thus, this flag indicates whether the launcher will be shown when the device wakes up
      * again.
      */
-    private static final int FLAG_LAUNCHER_ACTIVE_AT_SCREEN_OFF = 1 << 4;
+    private static final int FLAG_LAUNCHER_WAS_ACTIVE_WHILE_AWAKE = 1 << 4;
 
-    /** Whether the device is currently locked. */
+    /**
+     * Whether the device is currently locked.
+     * <ul>
+     *  <li>While locked, the taskbar is always stashed.<li/>
+     *  <li>Navbar animations on FLAG_DEVICE_LOCKED transitions will get special treatment.</li>
+     * </ul>
+     */
     private static final int FLAG_DEVICE_LOCKED = 1 << 5;
 
+    /**
+     * Whether the complete taskbar is completely hidden (neither visible stashed or unstashed).
+     * This is tracked to allow a nice transition of the taskbar before SysUI forces it away by
+     * hiding the inset.
+     *
+     * This flag is predominanlty set while FLAG_DEVICE_LOCKED is set, thus the taskbar's invisible
+     * resting state while hidden is stashed.
+     */
+    private static final int FLAG_TASKBAR_HIDDEN = 1 << 6;
+
     private static final int FLAGS_LAUNCHER_ACTIVE = FLAG_RESUMED | FLAG_TRANSITION_TO_RESUMED;
     /** Equivalent to an int with all 1s for binary operation purposes */
     private static final int FLAGS_ALL = ~0;
@@ -104,11 +124,21 @@
     private static final float TASKBAR_BG_ALPHA_NOT_LAUNCHER_NOT_ALIGNED_DELAY_MULT = 0.33f;
     private static final float TASKBAR_BG_ALPHA_LAUNCHER_IS_ALIGNED_DURATION_MULT = 0.25f;
 
+    /**
+     * Delay for the taskbar fade-in.
+     *
+     * Helps to avoid visual noise when unlocking successfully via SFPS, and the device transitions
+     * to launcher directly. The delay avoids the navbar to become briefly visible. The duration
+     * is the same as in SysUI, see http://shortn/_uNSbDoRUSr.
+     */
+    private static final long TASKBAR_SHOW_DELAY_MS = 250;
+
     private final AnimatedFloat mIconAlignment =
             new AnimatedFloat(this::onIconAlignmentRatioChanged);
 
     private TaskbarControllers mControllers;
     private AnimatedFloat mTaskbarBackgroundAlpha;
+    private AnimatedFloat mTaskbarAlpha;
     private AnimatedFloat mTaskbarCornerRoundness;
     private MultiProperty mIconAlphaForHome;
     private QuickstepLauncher mLauncher;
@@ -117,6 +147,9 @@
     private int mState;
     private LauncherState mLauncherState = LauncherState.NORMAL;
 
+    // Time when FLAG_TASKBAR_HIDDEN was last cleared, SystemClock.elapsedRealtime (milliseconds).
+    private long mLastUnlockTimeMs = 0;
+
     private @Nullable TaskBarRecentsAnimationListener mTaskBarRecentsAnimationListener;
 
     private boolean mIsAnimatingToLauncher;
@@ -187,6 +220,7 @@
 
         mTaskbarBackgroundAlpha = mControllers.taskbarDragLayerController
                 .getTaskbarBackgroundAlpha();
+        mTaskbarAlpha = mControllers.taskbarDragLayerController.getTaskbarAlpha();
         mTaskbarCornerRoundness = mControllers.getTaskbarCornerRoundness();
         mIconAlphaForHome = mControllers.taskbarViewController
                 .getTaskbarIconAlpha().get(ALPHA_INDEX_HOME);
@@ -265,20 +299,29 @@
 
     /** SysUI flags updated, see QuickStepContract.SYSUI_STATE_* values. */
     public void updateStateForSysuiFlags(int systemUiStateFlags, boolean skipAnim) {
-        final boolean prevScreenIsOn = hasAnyFlag(FLAG_SCREEN_ON);
-        final boolean currScreenIsOn = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_SCREEN_ON);
+        final boolean prevIsAwake = hasAnyFlag(FLAG_AWAKE);
+        final boolean currIsAwake = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_AWAKE);
 
-        updateStateForFlag(FLAG_SCREEN_ON, currScreenIsOn);
-        if (prevScreenIsOn != currScreenIsOn) {
+        updateStateForFlag(FLAG_AWAKE, currIsAwake);
+        if (prevIsAwake != currIsAwake) {
             // The screen is switching between on/off. When turning off, capture whether the
             // launcher is active and memoize this state.
-            updateStateForFlag(FLAG_LAUNCHER_ACTIVE_AT_SCREEN_OFF,
-                    prevScreenIsOn && hasAnyFlag(FLAGS_LAUNCHER_ACTIVE));
+            updateStateForFlag(FLAG_LAUNCHER_WAS_ACTIVE_WHILE_AWAKE,
+                    prevIsAwake && hasAnyFlag(FLAGS_LAUNCHER_ACTIVE));
         }
 
         boolean isDeviceLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED);
         updateStateForFlag(FLAG_DEVICE_LOCKED, isDeviceLocked);
 
+        // Taskbar is hidden whenever the device is dreaming. The dreaming state includes the
+        // interactive dreams, AoD, screen off. Since the SYSUI_STATE_DEVICE_DREAMING only kicks in
+        // when the device is asleep, the second condition extends ensures that the transition from
+        // and to the WAKEFULNESS_ASLEEP state also hide the taskbar, and improves the taskbar
+        // hide/reveal animation timings.
+        boolean isTaskbarHidden = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_DEVICE_DREAMING)
+                || (systemUiStateFlags & SYSUI_STATE_WAKEFULNESS_MASK) != WAKEFULNESS_AWAKE;
+        updateStateForFlag(FLAG_TASKBAR_HIDDEN, isTaskbarHidden);
+
         if (skipAnim) {
             applyState(0);
         } else {
@@ -377,7 +420,7 @@
             }
         }
 
-        if (hasAnyFlag(changedFlags, FLAGS_LAUNCHER_ACTIVE | FLAG_SCREEN_ON)) {
+        if (hasAnyFlag(changedFlags, FLAGS_LAUNCHER_ACTIVE | FLAG_AWAKE)) {
             animatorSet.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationStart(Animator animation) {
@@ -406,6 +449,41 @@
             AbstractFloatingView.closeAllOpenViews(mControllers.taskbarActivityContext);
         }
 
+        if (hasAnyFlag(changedFlags, FLAG_TASKBAR_HIDDEN) && !hasAnyFlag(FLAG_TASKBAR_HIDDEN)) {
+            // Take note of the current time, as the taskbar is made visible again.
+            mLastUnlockTimeMs = SystemClock.elapsedRealtime();
+        }
+
+        boolean isHidden = hasAnyFlag(FLAG_TASKBAR_HIDDEN);
+        float taskbarAlpha = isHidden ? 0 : 1;
+        if (mTaskbarAlpha.isAnimating() || mTaskbarAlpha.value != taskbarAlpha) {
+            Animator taskbarVisibility = mTaskbarAlpha.animateToValue(taskbarAlpha);
+
+            taskbarVisibility.setDuration(duration);
+            if (isHidden) {
+                // Stash the transient taskbar once the taskbar is not visible. This reduces
+                // visual noise when unlocking the device afterwards.
+                animatorSet.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        TaskbarStashController stashController =
+                                mControllers.taskbarStashController;
+                        stashController.updateAndAnimateTransientTaskbar(
+                                /* stash */ true, /* duration */ 0);
+                    }
+                });
+            } else {
+                // delay the fade in animation a bit to reduce visual noise when waking up a device
+                // with a fingerprint reader. This should only be done when the device was woken
+                // up via fingerprint reader, however since this information is currently not
+                // available, opting to always delay the fade-in a bit.
+                long durationSinceLastUnlockMs = SystemClock.elapsedRealtime() - mLastUnlockTimeMs;
+                taskbarVisibility.setStartDelay(
+                        Math.max(0, TASKBAR_SHOW_DELAY_MS - durationSinceLastUnlockMs));
+            }
+            animatorSet.play(taskbarVisibility);
+        }
+
         float backgroundAlpha = isInLauncher && isTaskbarAlignedWithHotseat() ? 0 : 1;
 
         // Don't animate if background has reached desired value.
@@ -564,7 +642,7 @@
         long resetDuration = mControllers.taskbarStashController.isInApp()
                 ? duration
                 : duration / 2;
-        if (!mControllers.taskbarTranslationController.willAnimateToZeroBefore(resetDuration)
+        if (mControllers.taskbarTranslationController.shouldResetBackToZero(resetDuration)
                 && (isAnimatingToLauncher() || mLauncherState == LauncherState.NORMAL)) {
             animatorSet.play(mControllers.taskbarTranslationController
                     .createAnimToResetTranslation(resetDuration));
@@ -573,10 +651,10 @@
 
     /** Whether the launcher is considered active. */
     private boolean isInLauncher() {
-        if (hasAnyFlag(FLAG_SCREEN_ON)) {
+        if (hasAnyFlag(FLAG_AWAKE)) {
             return hasAnyFlag(FLAGS_LAUNCHER_ACTIVE);
         } else {
-            return hasAnyFlag(FLAG_LAUNCHER_ACTIVE_AT_SCREEN_OFF);
+            return hasAnyFlag(FLAG_LAUNCHER_WAS_ACTIVE_WHILE_AWAKE);
         }
     }
 
@@ -677,9 +755,9 @@
         appendFlag(result, flags, FLAG_TRANSITION_TO_RESUMED, "transition_to_resumed");
         appendFlag(result, flags, FLAG_LAUNCHER_IN_STATE_TRANSITION,
                 "launcher_in_state_transition");
-        appendFlag(result, flags, FLAG_SCREEN_ON, "screen_on");
-        appendFlag(result, flags, FLAG_LAUNCHER_ACTIVE_AT_SCREEN_OFF,
-                "launcher_active_at_screen_off");
+        appendFlag(result, flags, FLAG_AWAKE, "awake");
+        appendFlag(result, flags, FLAG_LAUNCHER_WAS_ACTIVE_WHILE_AWAKE,
+                "was_active_while_awake");
         appendFlag(result, flags, FLAG_DEVICE_LOCKED, "device_locked");
         return result.toString();
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index c537106..3d8bf9e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -22,6 +22,7 @@
 
 import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
 import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
+import static com.android.launcher3.util.DisplayController.TASKBAR_NOT_DESTROYED_TAG;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
 
@@ -63,6 +64,7 @@
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
 
 import java.io.PrintWriter;
+import java.util.StringJoiner;
 
 /**
  * Class to manage taskbar lifecycle
@@ -147,6 +149,8 @@
 
             @Override
             public void onConfigurationChanged(Configuration newConfig) {
+                debugWhyTaskbarNotDestroyed(
+                        "TaskbarManager#mComponentCallbacks.onConfigurationChanged: " + newConfig);
                 DeviceProfile dp = mUserUnlocked
                         ? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext)
                         : null;
@@ -179,6 +183,9 @@
                     }
                 }
 
+                debugWhyTaskbarNotDestroyed("ComponentCallbacks#onConfigurationChanged() "
+                        + "configDiffForRecreate="
+                        + Configuration.configurationDiffToString(configDiffForRecreate));
                 if ((configDiffForRecreate & configsRequiringRecreate) != 0) {
                     recreateTaskbar();
                 } else {
@@ -207,6 +214,8 @@
                 mNavMode = info.navigationMode;
                 recreateTaskbar();
             }
+            debugWhyTaskbarNotDestroyed("DisplayInfoChangeListener#"
+                    + mDisplayController.getChangeFlagsString(flags));
         };
         mNavMode = mDisplayController.getInfo().navigationMode;
         mDisplayController.addChangeListener(mDispInfoChangeListener);
@@ -227,10 +236,13 @@
                     new IntentFilter(ACTION_SHOW_TASKBAR),
                     RECEIVER_NOT_EXPORTED);
         });
+
+        debugWhyTaskbarNotDestroyed("TaskbarManager created");
         recreateTaskbar();
     }
 
     private void destroyExistingTaskbar() {
+        debugWhyTaskbarNotDestroyed("destroyExistingTaskbar: " + mTaskbarActivityContext);
         if (mTaskbarActivityContext != null) {
             mTaskbarActivityContext.onDestroy();
             if (!FLAG_HIDE_NAVBAR_WINDOW) {
@@ -274,7 +286,12 @@
         if (mActivity == activity) {
             return;
         }
+        if (mActivity != null) {
+            mActivity.removeOnDeviceProfileChangeListener(mDebugActivityDeviceProfileChanged);
+        }
         mActivity = activity;
+        debugWhyTaskbarNotDestroyed("Set mActivity=" + mActivity);
+        mActivity.addOnDeviceProfileChangeListener(mDebugActivityDeviceProfileChanged);
         UnfoldTransitionProgressProvider unfoldTransitionProgressProvider =
                 getUnfoldTransitionProgressProviderForActivity(activity);
         mUnfoldProgressProvider.setSourceProvider(unfoldTransitionProgressProvider);
@@ -318,7 +335,9 @@
      */
     public void clearActivity(@NonNull StatefulActivity activity) {
         if (mActivity == activity) {
+            mActivity.removeOnDeviceProfileChangeListener(mDebugActivityDeviceProfileChanged);
             mActivity = null;
+            debugWhyTaskbarNotDestroyed("clearActivity");
             if (mTaskbarActivityContext != null) {
                 mTaskbarActivityContext.setUIController(TaskbarUIController.DEFAULT);
             }
@@ -338,8 +357,12 @@
 
         destroyExistingTaskbar();
 
-        boolean isTaskBarEnabled = dp != null && isTaskbarPresent(dp);
-        if (!isTaskBarEnabled) {
+        boolean isTaskbarEnabled = dp != null && isTaskbarPresent(dp);
+        debugWhyTaskbarNotDestroyed("recreateTaskbar: isTaskbarEnabled=" + isTaskbarEnabled
+                + " [dp != null (i.e. mUserUnlocked)]=" + (dp != null)
+                + " FLAG_HIDE_NAVBAR_WINDOW=" + FLAG_HIDE_NAVBAR_WINDOW
+                + " dp.isTaskbarPresent=" + (dp == null ? "null" : dp.isTaskbarPresent));
+        if (!isTaskbarEnabled) {
             SystemUiProxy.INSTANCE.get(mContext)
                     .notifyTaskbarStatus(/* visible */ false, /* stashed */ false);
             return;
@@ -440,6 +463,11 @@
      * Called when the manager is no longer needed
      */
     public void destroy() {
+        debugWhyTaskbarNotDestroyed("TaskbarManager#destroy()");
+        if (mActivity != null) {
+            mActivity.removeOnDeviceProfileChangeListener(mDebugActivityDeviceProfileChanged);
+        }
+
         UI_HELPER_EXECUTOR.execute(
                 () -> mTaskbarBroadcastReceiver.unregisterReceiverSafely(mContext));
         destroyExistingTaskbar();
@@ -464,4 +492,46 @@
             mTaskbarActivityContext.dumpLogs(prefix + "\t", pw);
         }
     }
+
+    /** Temp logs for b/254119092. */
+    public void debugWhyTaskbarNotDestroyed(String debugReason) {
+        StringJoiner log = new StringJoiner("\n");
+        log.add(debugReason);
+
+        boolean activityTaskbarPresent = mActivity != null
+                && mActivity.getDeviceProfile().isTaskbarPresent;
+        boolean contextTaskbarPresent = mUserUnlocked
+                && LauncherAppState.getIDP(mContext).getDeviceProfile(mContext).isTaskbarPresent;
+        if (activityTaskbarPresent == contextTaskbarPresent) {
+            log.add("mActivity and mContext agree taskbarIsPresent=" + contextTaskbarPresent);
+            Log.d(TASKBAR_NOT_DESTROYED_TAG, log.toString());
+            return;
+        }
+
+        log.add("mActivity and mContext device profiles have different values, add more logs.");
+
+        log.add("\tmActivity logs:");
+        log.add("\t\tmActivity=" + mActivity);
+        if (mActivity != null) {
+            log.add("\t\tmActivity.getResources().getConfiguration()="
+                    + mActivity.getResources().getConfiguration());
+            log.add("\t\tmActivity.getDeviceProfile().isTaskbarPresent="
+                    + activityTaskbarPresent);
+        }
+        log.add("\tmContext logs:");
+        log.add("\t\tmContext=" + mContext);
+        log.add("\t\tmContext.getResources().getConfiguration()="
+                + mContext.getResources().getConfiguration());
+        if (mUserUnlocked) {
+            log.add("\t\tLauncherAppState.getIDP().getDeviceProfile(mContext).isTaskbarPresent="
+                    + contextTaskbarPresent);
+        } else {
+            log.add("\t\tCouldn't get DeviceProfile because !mUserUnlocked");
+        }
+
+        Log.d(TASKBAR_NOT_DESTROYED_TAG, log.toString());
+    }
+
+    private final DeviceProfile.OnDeviceProfileChangeListener mDebugActivityDeviceProfileChanged =
+            dp -> debugWhyTaskbarNotDestroyed("mActivity onDeviceProfileChanged");
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index 5bb958a..610efeb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -27,6 +27,7 @@
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_IME_SWITCHER_BUTTON_TAP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_OVERVIEW_BUTTON_LONGPRESS;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_OVERVIEW_BUTTON_TAP;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
 
@@ -265,6 +266,7 @@
     }
 
     private void navigateHome() {
+        TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY);
         mService.getOverviewCommandHelper().addCommand(OverviewCommandHelper.TYPE_HOME);
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java
index c10b57a..054689b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java
@@ -32,7 +32,6 @@
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.R;
 import com.android.launcher3.accessibility.BaseAccessibilityDelegate;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -75,7 +74,7 @@
 
     @Override
     protected void getSupportedActions(View host, ItemInfo item, List<LauncherAction> out) {
-        if (ShortcutUtil.supportsShortcuts(item) && FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()) {
+        if (ShortcutUtil.supportsShortcuts(item)) {
             out.add(mActions.get(NotificationListener.getInstanceIfConnected() != null
                     ? SHORTCUTS_AND_NOTIFICATIONS : DEEP_SHORTCUTS));
         }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index c43b621..69ea9fd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -36,6 +36,7 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -43,6 +44,7 @@
 import android.app.RemoteAction;
 import android.content.SharedPreferences;
 import android.graphics.drawable.Icon;
+import android.os.SystemClock;
 import android.util.Log;
 import android.view.InsetsController;
 import android.view.View;
@@ -50,6 +52,7 @@
 import android.view.accessibility.AccessibilityManager;
 import android.view.animation.Interpolator;
 
+import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
@@ -68,6 +71,8 @@
 import com.android.quickstep.SystemUiProxy;
 
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.StringJoiner;
 import java.util.function.IntPredicate;
 
@@ -184,6 +189,40 @@
     // Auto stashes when user has not interacted with the Taskbar after X ms.
     private static final long NO_TOUCH_TIMEOUT_TO_STASH_MS = 5000;
 
+    // Duration for which an unlock event is considered "current", as other events are received
+    // asynchronously.
+    private static final long UNLOCK_TRANSITION_MEMOIZATION_MS = 200;
+
+    /**
+     * The default stash animation, morphing the taskbar into the navbar.
+     */
+    private static final int TRANSITION_DEFAULT = 0;
+    /**
+     * Transitioning from launcher to app. Same as TRANSITION_DEFAULT, differs in internal
+     * animation timings.
+     */
+    private static final int TRANSITION_HOME_TO_APP = 1;
+    /**
+     * Fading the navbar in and out, where the taskbar jumpcuts in and out at the very begin/end of
+     * the transition. Used to transition between the hotseat and navbar` without the stash/unstash
+     * transition.
+     */
+    private static final int TRANSITION_HANDLE_FADE = 2;
+    /**
+     * Same as TRANSITION_DEFAULT, but exclusively used during an "navbar unstash to hotseat
+     * animation" bound to the progress of a swipe gesture. It differs from TRANSITION_DEFAULT
+     * by not scaling the height of the taskbar background.
+     */
+    private static final int TRANSITION_UNSTASH_SUW_MANUAL = 3;
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+            TRANSITION_DEFAULT,
+            TRANSITION_HOME_TO_APP,
+            TRANSITION_HANDLE_FADE,
+            TRANSITION_UNSTASH_SUW_MANUAL,
+    })
+    private @interface StashAnimation {}
+
     private final TaskbarActivityContext mActivity;
     private final SharedPreferences mPrefs;
     private final int mStashedHeight;
@@ -472,9 +511,16 @@
     }
 
     /**
-     * Stash or unstashes the transient taskbar.
+     * Stash or unstashes the transient taskbar, using the default TASKBAR_STASH_DURATION.
      */
     public void updateAndAnimateTransientTaskbar(boolean stash) {
+        updateAndAnimateTransientTaskbar(stash, TASKBAR_STASH_DURATION);
+    }
+
+    /**
+     * Stash or unstashes the transient taskbar.
+     */
+    public void updateAndAnimateTransientTaskbar(boolean stash, long duration) {
         if (!DisplayController.isTransientTaskbar(mActivity)) {
             return;
         }
@@ -553,8 +599,7 @@
         createAnimToIsStashed(
                 /* isStashed= */ false,
                 placeholderDuration,
-                /* animateBg= */ false,
-                /* changedFlags=*/ 0);
+                TRANSITION_UNSTASH_SUW_MANUAL);
         animation.play(mAnimator);
     }
 
@@ -562,10 +607,15 @@
      * Create a stash animation and save to {@link #mAnimator}.
      * @param isStashed whether it's a stash animation or an unstash animation
      * @param duration duration of the animation
-     * @param animateBg whether the taskbar's background should be animated
+     * @param animationType what transition type to play.
      */
-    private void createAnimToIsStashed(boolean isStashed, long duration, boolean animateBg,
-            int changedFlags) {
+    private void createAnimToIsStashed(boolean isStashed, long duration,
+            @StashAnimation int animationType) {
+        if (animationType == TRANSITION_UNSTASH_SUW_MANUAL && isStashed) {
+            // The STASH_ANIMATION_SUW_MANUAL must only be used during an unstash animation.
+            Log.e(TAG, "Illegal arguments:Using TRANSITION_UNSTASH_SUW_MANUAL to stash taskbar");
+        }
+
         if (mAnimator != null) {
             mAnimator.cancel();
         }
@@ -591,23 +641,10 @@
             return;
         }
 
-        // If Hotseat is not the top element during animation to/from Launcher, fade in/out a
-        // already stashed Taskbar.
-        boolean hotseatTopElement = mControllers.uiController.isHotseatIconOnTopWhenAligned()
-                || !hasAnyFlag(changedFlags, FLAG_IN_APP);
-        // If transitioning to unlocked device, do not play a stash animation.
-        // Keep isUnlockTransition in sync with its counterpart in
-        // TaskbarLauncherStateController#onStateChangeApplied.
-        boolean isUnlockTransition = hasAnyFlag(changedFlags, FLAG_STASHED_DEVICE_LOCKED)
-                && !hasAnyFlag(FLAG_STASHED_DEVICE_LOCKED);
-        boolean skipStashAnimation = !hotseatTopElement || isUnlockTransition;
-
         if (isTransientTaskbar) {
-            createTransientAnimToIsStashed(mAnimator, isStashed, duration, animateBg, changedFlags,
-                    skipStashAnimation);
+            createTransientAnimToIsStashed(mAnimator, isStashed, duration, animationType);
         } else {
-            createAnimToIsStashed(mAnimator, isStashed, duration, animateBg, skipStashAnimation,
-                    stashTranslation);
+            createAnimToIsStashed(mAnimator, isStashed, duration, stashTranslation, animationType);
         }
 
         mAnimator.addListener(new AnimatorListenerAdapter() {
@@ -636,7 +673,7 @@
     }
 
     private void createAnimToIsStashed(AnimatorSet as, boolean isStashed, long duration,
-            boolean animateBg, boolean skipStashAnimation, float stashTranslation) {
+            float stashTranslation, @StashAnimation int animationType) {
         AnimatorSet fullLengthAnimatorSet = new AnimatorSet();
         // Not exactly half and may overlap. See [first|second]HalfDurationScale below.
         AnimatorSet firstHalfAnimatorSet = new AnimatorSet();
@@ -650,12 +687,7 @@
             secondHalfDurationScale = 0.5f;
 
             fullLengthAnimatorSet.play(mIconTranslationYForStash.animateToValue(stashTranslation));
-            if (animateBg) {
-                fullLengthAnimatorSet.play(mTaskbarBackgroundOffset.animateToValue(1));
-            } else {
-                fullLengthAnimatorSet.addListener(AnimatorListeners.forEndCallback(
-                        () -> mTaskbarBackgroundOffset.updateValue(1)));
-            }
+            fullLengthAnimatorSet.play(mTaskbarBackgroundOffset.animateToValue(1));
 
             firstHalfAnimatorSet.playTogether(
                     mIconAlphaForStash.animateToValue(0),
@@ -666,7 +698,7 @@
                     mTaskbarStashedHandleAlpha.animateToValue(1)
             );
 
-            if (skipStashAnimation) {
+            if (animationType == TRANSITION_HANDLE_FADE) {
                 fullLengthAnimatorSet.setInterpolator(INSTANT);
                 firstHalfAnimatorSet.setInterpolator(INSTANT);
             }
@@ -677,6 +709,8 @@
             fullLengthAnimatorSet.playTogether(
                     mIconScaleForStash.animateToValue(1),
                     mIconTranslationYForStash.animateToValue(0));
+
+            final boolean animateBg = animationType != TRANSITION_UNSTASH_SUW_MANUAL;
             if (animateBg) {
                 fullLengthAnimatorSet.play(mTaskbarBackgroundOffset.animateToValue(0));
             } else {
@@ -691,7 +725,7 @@
                     mIconAlphaForStash.animateToValue(1)
             );
 
-            if (skipStashAnimation) {
+            if (animationType == TRANSITION_HANDLE_FADE) {
                 fullLengthAnimatorSet.setInterpolator(FINAL_FRAME);
                 secondHalfAnimatorSet.setInterpolator(FINAL_FRAME);
             }
@@ -714,61 +748,78 @@
     }
 
     private void createTransientAnimToIsStashed(AnimatorSet as, boolean isStashed, long duration,
-            boolean animateBg, int changedFlags, boolean skipStashAnimation) {
-        Interpolator skipInterpolator = null;
+            @StashAnimation int animationType) {
+        // Target values of the properties this is going to set
+        final float backgroundOffsetTarget = isStashed ? 1 : 0;
+        final float iconAlphaTarget = isStashed ? 0 : 1;
+        final float stashedHandleAlphaTarget = isStashed ? 1 : 0;
+
+        // Timing for the alpha values depend on the animation played
+        long iconAlphaStartDelay = 0, iconAlphaDuration = 0, stashedHandleAlphaDelay = 0,
+                stashedHandleAlphaDuration = 0;
+        if (duration > 0) {
+            if (animationType == TRANSITION_HANDLE_FADE) {
+                // When fading, the handle fades in/out at the beginning of the transition with
+                // TASKBAR_STASH_ALPHA_DURATION.
+                stashedHandleAlphaDuration = TASKBAR_STASH_ALPHA_DURATION;
+                // The iconAlphaDuration must be set to duration for the skippable interpolators
+                // below to work.
+                iconAlphaDuration = duration;
+            } else {
+                iconAlphaStartDelay = TASKBAR_STASH_ALPHA_START_DELAY;
+                iconAlphaDuration = TASKBAR_STASH_ALPHA_DURATION;
+                stashedHandleAlphaDuration = TASKBAR_STASH_ALPHA_DURATION;
+
+                if (isStashed) {
+                    if (animationType == TRANSITION_HOME_TO_APP) {
+                        iconAlphaStartDelay = TASKBAR_STASH_ICON_ALPHA_HOME_TO_APP_START_DELAY;
+                    }
+                    stashedHandleAlphaDelay = iconAlphaStartDelay;
+                    stashedHandleAlphaDuration = Math.max(0, duration - iconAlphaStartDelay);
+                }
+
+            }
+        }
+
+        play(as, mTaskbarStashedHandleAlpha.animateToValue(stashedHandleAlphaTarget),
+                stashedHandleAlphaDelay,
+                stashedHandleAlphaDuration, LINEAR);
+
+        // The rest of the animations might be "skipped" in TRANSITION_HANDLE_FADE transitions.
+        AnimatorSet skippable = as;
+        if (animationType == TRANSITION_HANDLE_FADE) {
+            skippable = new AnimatorSet();
+            as.play(skippable);
+            skippable.setInterpolator(isStashed ? INSTANT : FINAL_FRAME);
+        }
+
+        final boolean animateBg = animationType != TRANSITION_UNSTASH_SUW_MANUAL;
+        if (animateBg) {
+            play(skippable, mTaskbarBackgroundOffset.animateToValue(backgroundOffsetTarget), 0,
+                    duration, EMPHASIZED);
+        } else {
+            skippable.addListener(AnimatorListeners.forEndCallback(
+                    () -> mTaskbarBackgroundOffset.updateValue(backgroundOffsetTarget)));
+        }
+
+        play(skippable, mIconAlphaForStash.animateToValue(iconAlphaTarget), iconAlphaStartDelay,
+                iconAlphaDuration,
+                LINEAR);
 
         if (isStashed) {
-            if (animateBg) {
-                play(as, mTaskbarBackgroundOffset.animateToValue(1), 0, duration, EMPHASIZED);
-            } else {
-                as.addListener(AnimatorListeners.forEndCallback(
-                        () -> mTaskbarBackgroundOffset.updateValue(1)));
-            }
-
-            long alphaStartDelay = duration == 0 ? 0 : (changedFlags == FLAG_IN_APP)
-                    ? TASKBAR_STASH_ICON_ALPHA_HOME_TO_APP_START_DELAY
-                    : TASKBAR_STASH_ALPHA_START_DELAY;
-            long alphaDuration = duration == 0 ? 0 : TASKBAR_STASH_ALPHA_DURATION;
-            play(as, mIconAlphaForStash.animateToValue(0), alphaStartDelay, alphaDuration, LINEAR);
-            play(as, mTaskbarStashedHandleAlpha.animateToValue(1), alphaStartDelay,
-                    Math.max(0, duration - alphaStartDelay), LINEAR);
-
-            play(as, mControllers.taskbarSpringOnStashController.createSpringToStash(), 0, duration,
-                    LINEAR);
-
-            if (skipStashAnimation) {
-                skipInterpolator = INSTANT;
-            }
-        } else  {
-            if (animateBg) {
-                play(as, mTaskbarBackgroundOffset.animateToValue(0), 0, duration, EMPHASIZED);
-            } else {
-                as.addListener(AnimatorListeners.forEndCallback(
-                        () -> mTaskbarBackgroundOffset.updateValue(0)));
-            }
-
-            long alphaStartDelay = duration == 0 ? 0 : TASKBAR_STASH_ALPHA_START_DELAY;
-            long alphaDuration = duration == 0 ? 0 : TASKBAR_STASH_ALPHA_DURATION;
-            play(as, mIconAlphaForStash.animateToValue(1), alphaStartDelay, alphaDuration, LINEAR);
-            play(as, mTaskbarStashedHandleAlpha.animateToValue(0), 0, alphaDuration, LINEAR);
-
-            if (skipStashAnimation) {
-                skipInterpolator = FINAL_FRAME;
-            }
+            play(skippable, mControllers.taskbarSpringOnStashController.createSpringToStash(),
+                    0, duration, LINEAR);
         }
-        mControllers.taskbarViewController.addRevealAnimToIsStashed(as, isStashed, duration,
+
+        mControllers.taskbarViewController.addRevealAnimToIsStashed(skippable, isStashed, duration,
                 EMPHASIZED);
 
-        if (skipInterpolator != null) {
-            as.setInterpolator(skipInterpolator);
-        }
-
-        play(as, mControllers.stashedHandleViewController
+        play(skippable, mControllers.stashedHandleViewController
                 .createRevealAnimToIsStashed(isStashed), 0, duration, EMPHASIZED);
 
         // Return the stashed handle to its default scale in case it was changed as part of the
         // feedforward hint. Note that the reveal animation above also visually scales it.
-        as.play(mTaskbarStashedHandleHintScale.animateToValue(1f)
+        skippable.play(mTaskbarStashedHandleHintScale.animateToValue(1f)
                 .setDuration(isStashed ? duration / 2 : duration));
     }
 
@@ -927,17 +978,10 @@
         updateStateForFlag(FLAG_STASHED_SYSUI,
                 hasAnyFlag(systemUiStateFlags, SYSUI_STATE_SCREEN_PINNING));
 
-        boolean isLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED);
-        boolean wasLocked = hasAnyFlag(FLAG_STASHED_DEVICE_LOCKED);
+        boolean isLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED)
+                && !hasAnyFlag(systemUiStateFlags, SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY);
         updateStateForFlag(FLAG_STASHED_DEVICE_LOCKED, isLocked);
 
-        if (isLocked && !wasLocked && DisplayController.isTransientTaskbar(mActivity)) {
-            // Stash the transient taskbar when locking the device. This improves the transition
-            // to AoD (otherwise the taskbar stays a bit too long above the collapsing AoD scrim),
-            // and ensures the taskar state is reset when unlocking the device afterwards.
-            updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, true);
-        }
-
         // Only update FLAG_STASHED_IN_APP_IME when system gesture is not in progress.
         mIsImeShowing = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_SHOWING);
         mIsImeSwitcherShowing = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_SWITCHER_SHOWING);
@@ -1150,9 +1194,11 @@
         private final IntPredicate mStashCondition;
 
         private boolean mIsStashed;
-        private boolean mIsHotseatIconOnTopWhenAligned;
+        private @StashAnimation int mLastStartedTransitionType = TRANSITION_DEFAULT;
         private int mPrevFlags;
 
+        private long mLastUnlockTransitionTimeout = 0;
+
         StatePropertyHolder(IntPredicate stashCondition) {
             mStashCondition = stashCondition;
         }
@@ -1170,7 +1216,7 @@
 
             if (DEBUG) {
                 String stateString = formatFlagChange(flags, mPrevFlags,
-                            TaskbarStashController::getStateString);
+                        TaskbarStashController::getStateString);
                 Log.d(TAG, "createSetStateAnimator: flags: " + stateString
                         + ", duration: " + duration
                         + ", isStashed: " + isStashed
@@ -1182,28 +1228,76 @@
                 onStateChangeApplied(changedFlags);
                 mPrevFlags = flags;
             }
-            boolean isHotseatIconOnTopWhenAligned =
-                    mControllers.uiController.isHotseatIconOnTopWhenAligned();
-            // If an animation has started and mIsHotseatIconOnTopWhenAligned is changed, we need
-            // to restart the animation with new parameters.
-            if (mIsStashed != isStashed
-                    || (mIsHotseatIconOnTopWhenAligned != isHotseatIconOnTopWhenAligned
-                    && mAnimator != null && mAnimator.isStarted())) {
+
+            boolean isUnlockTransition = hasAnyFlag(changedFlags, FLAG_STASHED_DEVICE_LOCKED)
+                    && !hasAnyFlag(FLAG_STASHED_DEVICE_LOCKED);
+            if (isUnlockTransition) {
+                // the launcher might not be resumed at the time the device is considered
+                // unlocked (when the keyguard goes away), but possibly shortly afterwards.
+                // To play the unlock transition at the time the unstash animation actually happens,
+                // this memoizes the state transition for UNLOCK_TRANSITION_MEMOIZATION_MS.
+                mLastUnlockTransitionTimeout =
+                        SystemClock.elapsedRealtime() + UNLOCK_TRANSITION_MEMOIZATION_MS;
+            }
+
+            @StashAnimation int animationType = computeTransitionType(changedFlags);
+
+            // Allow re-starting animation if upgrading from default animation type, otherwise
+            // stick with the already started transition.
+            boolean transitionTypeChanged = mAnimator != null && mAnimator.isStarted()
+                    && mLastStartedTransitionType == TRANSITION_DEFAULT
+                    && animationType != TRANSITION_DEFAULT;
+
+            if (mIsStashed != isStashed || transitionTypeChanged) {
                 if (TestProtocol.sDebugTracing) {
                     Log.d(TestProtocol.TASKBAR_IN_APP_STATE, String.format(
-                            "setState: mIsStashed=%b, isStashed=%b, duration=%d",
+                            "setState: mIsStashed=%b, isStashed=%b, "
+                                    + "mAnimationType=%d, animationType=%d, duration=%d",
                             mIsStashed,
                             isStashed,
+                            mLastStartedTransitionType,
+                            animationType,
                             duration));
                 }
                 mIsStashed = isStashed;
-                mIsHotseatIconOnTopWhenAligned = isHotseatIconOnTopWhenAligned;
+                mLastStartedTransitionType = animationType;
 
                 // This sets mAnimator.
-                createAnimToIsStashed(mIsStashed, duration, /* animateBg= */ true, changedFlags);
+                createAnimToIsStashed(mIsStashed, duration, animationType);
                 return mAnimator;
             }
             return null;
         }
+
+        private @StashAnimation int computeTransitionType(int changedFlags) {
+
+            boolean hotseatHiddenDuringAppLaunch =
+                    !mControllers.uiController.isHotseatIconOnTopWhenAligned()
+                            && hasAnyFlag(changedFlags, FLAG_IN_APP);
+            if (hotseatHiddenDuringAppLaunch) {
+                // When launching an app from the all-apps drawer, the hotseat is hidden behind the
+                // drawer. In this case, the navbar must just fade in, without a stash transition,
+                // as the taskbar stash animation would otherwise be visible above the all-apps
+                // drawer once the hotseat is detached.
+                return TRANSITION_HANDLE_FADE;
+            }
+
+            boolean isUnlockTransition =
+                    SystemClock.elapsedRealtime() < mLastUnlockTransitionTimeout;
+            if (isUnlockTransition) {
+                // When transitioning to unlocked device, the  hotseat will already be visible on
+                // the homescreen, thus do not play an un-stash animation.
+                // Keep isUnlockTransition in sync with its counterpart in
+                // TaskbarLauncherStateController#onStateChangeApplied.
+                return TRANSITION_HANDLE_FADE;
+            }
+
+            boolean homeToApp = hasAnyFlag(changedFlags, FLAG_IN_APP) && hasAnyFlag(FLAG_IN_APP);
+            if (homeToApp) {
+                return TRANSITION_HOME_TO_APP;
+            }
+
+            return TRANSITION_DEFAULT;
+        }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
index 065d111..4b18bb6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
@@ -54,6 +54,7 @@
     private boolean mHasSprungOnceThisGesture;
     private @Nullable ValueAnimator mSpringBounce;
     private boolean mGestureEnded;
+    private boolean mGestureInProgress;
     private boolean mAnimationToHomeRunning;
 
     private final boolean mIsTransientTaskbar;
@@ -123,6 +124,7 @@
 
     private void reset() {
         mGestureEnded = false;
+        mGestureInProgress = false;
         mHasSprungOnceThisGesture = false;
     }
 
@@ -134,18 +136,24 @@
     }
 
     /**
-     * Returns true if we will animate to zero before the input duration.
+     * Returns {@code true} if we should reset the animation back to zero.
+     *
+     * Returns {@code false} if there is a gesture in progress, or if we are already animating
+     * to 0 within the specified duration.
      */
-    public boolean willAnimateToZeroBefore(long duration) {
+    public boolean shouldResetBackToZero(long duration) {
+        if (mGestureInProgress) {
+            return false;
+        }
         if (mSpringBounce != null && mSpringBounce.isRunning()) {
             long springDuration = mSpringBounce.getDuration();
             long current = mSpringBounce.getCurrentPlayTime();
-            return (springDuration - current < duration);
+            return (springDuration - current >= duration);
         }
         if (mTranslationYForSwipe.isAnimatingToValue(0)) {
-            return mTranslationYForSwipe.getRemainingTime() < duration;
+            return mTranslationYForSwipe.getRemainingTime() >= duration;
         }
-        return false;
+        return true;
     }
 
     /**
@@ -188,6 +196,7 @@
             mAnimationToHomeRunning = false;
             cancelSpringIfExists();
             reset();
+            mGestureInProgress = true;
         }
         /**
          * Called when there is movement to move the taskbar.
@@ -211,6 +220,7 @@
                 mGestureEnded = true;
                 startSpring();
             }
+            mGestureInProgress = false;
         }
     }
 
@@ -222,6 +232,7 @@
         pw.println(prefix + "\tmHasSprungOnceThisGesture=" + mHasSprungOnceThisGesture);
         pw.println(prefix + "\tmAnimationToHomeRunning=" + mAnimationToHomeRunning);
         pw.println(prefix + "\tmGestureEnded=" + mGestureEnded);
+        pw.println(prefix + "\tmGestureInProgress=" + mGestureInProgress);
         pw.println(prefix + "\tmSpringBounce is running=" + (mSpringBounce != null
                 && mSpringBounce.isRunning()));
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index b9242b2..1435cb0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -244,7 +244,8 @@
                                     taskAttributes.getIconView().getDrawable(),
                                     taskAttributes.getThumbnailView(),
                                     taskAttributes.getThumbnailView().getThumbnail(),
-                                    null /* intent */);
+                                    null /* intent */,
+                                    null /* user */);
                             return;
                         }
                     }
@@ -256,7 +257,8 @@
                             new BitmapDrawable(info.bitmap.icon),
                             startingView,
                             null /* thumbnail */,
-                            intent);
+                            intent,
+                            info.user);
                 }
         );
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 87df5b0..a3e6814 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -57,7 +57,8 @@
 /**
  * Hosts the Taskbar content such as Hotseat and Recent Apps. Drawn on top of other apps.
  */
-public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconParent, Insettable {
+public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconParent, Insettable,
+        DeviceProfile.OnDeviceProfileChangeListener {
     private static final String TAG = TaskbarView.class.getSimpleName();
 
     private static final Rect sTmpRect = new Rect();
@@ -92,7 +93,7 @@
 
     private float mTransientTaskbarAllAppsButtonTranslationXOffset;
 
-    private final boolean mShouldTryStartAlign;
+    private boolean mShouldTryStartAlign;
 
     public TaskbarView(@NonNull Context context) {
         this(context, null);
@@ -121,8 +122,8 @@
                 resources.getDimension(isTransientTaskbar
                         ? R.dimen.transient_taskbar_all_apps_button_translation_x_offset
                         : R.dimen.taskbar_all_apps_button_translation_x_offset);
-        mShouldTryStartAlign = mActivityContext.isThreeButtonNav()
-                && resources.getBoolean(R.bool.start_align_taskbar);
+
+        onDeviceProfileChanged(mActivityContext.getDeviceProfile());
 
         int actualMargin = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
         int actualIconSize = mActivityContext.getDeviceProfile().taskbarIconSize;
@@ -162,6 +163,23 @@
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mActivityContext.addOnDeviceProfileChangeListener(this);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mActivityContext.removeOnDeviceProfileChangeListener(this);
+    }
+
+    @Override
+    public void onDeviceProfileChanged(DeviceProfile dp) {
+        mShouldTryStartAlign = mActivityContext.isThreeButtonNav() && dp.startAlignTaskbar;
+    }
+
+    @Override
     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
         if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) {
             announceForAccessibility(mContext.getString(R.string.taskbar_a11y_shown_title));
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 4ab093f..6eb409e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -286,7 +286,7 @@
     }
 
     private ValueAnimator createRevealAnimForView(View view, boolean isStashed, float newWidth,
-            boolean shouldStartAlign) {
+            boolean isQsb) {
         Rect viewBounds = new Rect(0, 0, view.getWidth(), view.getHeight());
         int centerY = viewBounds.centerY();
         int halfHandleHeight = mStashedHandleHeight / 2;
@@ -295,7 +295,8 @@
 
         final int left;
         final int right;
-        if (shouldStartAlign) {
+        // QSB will crop from the 'start' whereas all other icons will crop from the center.
+        if (isQsb) {
             if (mIsRtl) {
                 right = viewBounds.right;
                 left = (int) (right - newWidth);
@@ -311,7 +312,10 @@
         }
 
         Rect stashedRect = new Rect(left, top, right, bottom);
-        float radius = viewBounds.height() / 2f;
+        // QSB radius can be > 0 since it does not have any UI elements outside of it bounds.
+        float radius = isQsb
+                ? viewBounds.height() / 2f
+                : 0f;
         float stashedRadius = stashedRect.height() / 2f;
 
         return new RoundedRectRevealOutlineProvider(radius, stashedRadius, viewBounds, stashedRect)
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
index 7f6d78a..623e234 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
@@ -18,10 +18,10 @@
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.WindowInsets;
 
 import com.android.launcher3.R;
 import com.android.launcher3.allapps.ActivityAllAppsContainerView;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
 
 /** All apps container accessible from taskbar. */
@@ -37,13 +37,11 @@
     }
 
     @Override
-    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        setInsets(insets.getInsets(WindowInsets.Type.systemBars()).toRect());
-        return super.onApplyWindowInsets(insets);
-    }
-
-    @Override
     protected View inflateSearchBox() {
+        if (isSearchSupported()) {
+            return super.inflateSearchBox();
+        }
+
         // Remove top padding of header, since we do not have any search
         mHeader.setPadding(mHeader.getPaddingLeft(), 0,
                 mHeader.getPaddingRight(), mHeader.getPaddingBottom());
@@ -57,7 +55,7 @@
 
     @Override
     protected boolean isSearchSupported() {
-        return false;
+        return FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get();
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index 9db4ddd..d69769a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -112,13 +112,24 @@
         DeviceProfile dp = mActivityContext.getDeviceProfile();
         setShiftRange(dp.allAppsShiftRange);
 
-        mActivityContext.addOnDeviceProfileChangeListener(this);
         setContentBackgroundWithParent(
                 getContext().getDrawable(R.drawable.bg_rounded_corner_bottom_sheet),
                 mAppsView.getBottomSheetBackground());
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mActivityContext.addOnDeviceProfileChangeListener(this);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mActivityContext.removeOnDeviceProfileChangeListener(this);
+    }
+
+    @Override
     protected void onScaleProgressChanged() {
         super.onScaleProgressChanged();
         mAppsView.setClipChildren(!mIsBackProgressing);
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
index ec64128..2c3e1ac 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
@@ -120,7 +120,9 @@
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        return updateInsetsDueToStashing(insets);
+        insets = updateInsetsDueToStashing(insets);
+        setInsets(insets.getInsets(WindowInsets.Type.systemBars()).toRect());
+        return insets;
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 6475b74..b2b0623 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -641,7 +641,7 @@
         PendingAnimation anim = new PendingAnimation(TABLET_HOME_TO_SPLIT.getDuration());
         RectF startingTaskRect = new RectF();
         final FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(this,
-                source.view, null /* thumbnail */, source.drawable, startingTaskRect);
+                source.getView(), null /* thumbnail */, source.getDrawable(), startingTaskRect);
         floatingTaskView.setAlpha(1);
         floatingTaskView.addStagingAnimation(anim, startingTaskRect, tempRect,
                 false /* fadeWithThumbnail */, true /* isStagedTask */);
@@ -745,6 +745,10 @@
 
     @Override
     protected void registerBackDispatcher() {
+        if (!FeatureFlags.ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION.get()) {
+            super.registerBackDispatcher();
+            return;
+        }
         getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
                 OnBackInvokedDispatcher.PRIORITY_DEFAULT,
                 new OnBackAnimationCallback() {
@@ -1241,6 +1245,9 @@
         Trace.instantForTrack(TRACE_TAG_APP, "QuickstepLauncher#DeviceProfileChanged",
                 getDeviceProfile().toSmallString());
         SystemUiProxy.INSTANCE.get(this).setLauncherAppIconSize(mDeviceProfile.iconSizePx);
+        if (mTaskbarManager != null) {
+            mTaskbarManager.debugWhyTaskbarNotDestroyed("QuickstepLauncher#onDeviceProfileChanged");
+        }
     }
 
     /**
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java
index d4944d0..481e200 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java
@@ -15,16 +15,20 @@
  */
 package com.android.launcher3.uioverrides.flags;
 
+import androidx.annotation.NonNull;
+
 import com.android.launcher3.config.FeatureFlags.BooleanFlag;
+import com.android.launcher3.config.FeatureFlags.FlagState;
 
 class DebugFlag extends BooleanFlag {
 
     public final String key;
     public final String description;
 
-    public final boolean defaultValue;
+    @NonNull
+    public final FlagState defaultValue;
 
-    public DebugFlag(String key, String description, boolean defaultValue, boolean currentValue) {
+    DebugFlag(String key, String description, FlagState defaultValue, boolean currentValue) {
         super(currentValue);
         this.key = key;
         this.defaultValue = defaultValue;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
index 67ea1af..89aba90 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
@@ -39,6 +39,7 @@
 import android.os.Bundle;
 import android.provider.Settings;
 import android.text.Editable;
+import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.ArrayMap;
 import android.util.Pair;
@@ -182,9 +183,16 @@
     }
 
     private PreferenceCategory newCategory(String title) {
+        return newCategory(title, null);
+    }
+
+    private PreferenceCategory newCategory(String title, @Nullable String summary) {
         PreferenceCategory category = new PreferenceCategory(getContext());
         category.setOrder(Preference.DEFAULT_ORDER);
         category.setTitle(title);
+        if (!TextUtils.isEmpty(summary)) {
+            category.setSummary(summary);
+        }
         mPreferenceScreen.addPreference(category);
         return category;
     }
@@ -195,7 +203,7 @@
         }
 
         mFlagTogglerPrefUi = new FlagTogglerPrefUi(this);
-        mFlagTogglerPrefUi.applyTo(newCategory("Feature flags"));
+        mFlagTogglerPrefUi.applyTo(newCategory("Feature flags", "Long press to reset"));
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java
index 3900ebb..035beb4 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java
@@ -16,11 +16,13 @@
 
 package com.android.launcher3.uioverrides.flags;
 
+import com.android.launcher3.config.FeatureFlags.FlagState;
+
 class DeviceFlag extends DebugFlag {
 
     private final boolean mDefaultValueInCode;
 
-    public DeviceFlag(String key, String description, boolean defaultValue,
+    DeviceFlag(String key, String description, FlagState defaultValue,
             boolean currentValue, boolean defaultValueInCode) {
         super(key, description, defaultValue, currentValue);
         mDefaultValueInCode = defaultValueInCode;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java
index b7fb2ed..9c59361 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java
@@ -17,11 +17,15 @@
 package com.android.launcher3.uioverrides.flags;
 
 import static com.android.launcher3.config.FeatureFlags.FLAGS_PREF_NAME;
+import static com.android.launcher3.config.FeatureFlags.FlagState.TEAMFOOD;
+import static com.android.launcher3.uioverrides.flags.FlagsFactory.TEAMFOOD_FLAG;
 
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.os.Handler;
 import android.os.Process;
 import android.text.Html;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -30,6 +34,7 @@
 import androidx.preference.PreferenceDataStore;
 import androidx.preference.PreferenceFragmentCompat;
 import androidx.preference.PreferenceGroup;
+import androidx.preference.PreferenceViewHolder;
 import androidx.preference.SwitchPreference;
 
 import com.android.launcher3.R;
@@ -59,12 +64,7 @@
 
         @Override
         public boolean getBoolean(String key, boolean defaultValue) {
-            for (DebugFlag flag : FlagsFactory.getDebugFlags()) {
-                if (flag.key.equals(key)) {
-                    return mSharedPreferences.getBoolean(key, flag.defaultValue);
-                }
-            }
-            return defaultValue;
+            return mSharedPreferences.getBoolean(key, defaultValue);
         }
     };
 
@@ -87,18 +87,41 @@
                     : f1.key.compareToIgnoreCase(f2.key);
         });
 
+        // Ensure that teamfood flag comes on the top
+        if (flags.remove(TEAMFOOD_FLAG)) {
+            flags.add(0, (DebugFlag) TEAMFOOD_FLAG);
+        }
+
         // For flag overrides we only want to store when the engineer chose to override the
         // flag with a different value than the default. That way, when we flip flags in
         // future, engineers will pick up the new value immediately. To accomplish this, we use a
         // custom preference data store.
         for (DebugFlag flag : flags) {
-            SwitchPreference switchPreference = new SwitchPreference(mContext);
+            SwitchPreference switchPreference = new SwitchPreference(mContext) {
+                @Override
+                public void onBindViewHolder(PreferenceViewHolder holder) {
+                    super.onBindViewHolder(holder);
+                    holder.itemView.setOnLongClickListener(v -> {
+                        mSharedPreferences.edit().remove(flag.key).apply();
+                        setChecked(getFlagStateFromSharedPrefs(flag));
+                        updateSummary(this, flag);
+                        updateMenu();
+                        return true;
+                    });
+                }
+            };
             switchPreference.setKey(flag.key);
-            switchPreference.setDefaultValue(flag.defaultValue);
+            switchPreference.setDefaultValue(FlagsFactory.getEnabledValue(flag.defaultValue));
             switchPreference.setChecked(getFlagStateFromSharedPrefs(flag));
             switchPreference.setTitle(flag.key);
             updateSummary(switchPreference, flag);
             switchPreference.setPreferenceDataStore(mDataStore);
+            switchPreference.setOnPreferenceChangeListener((p, v) -> {
+                new Handler().post(() -> updateSummary(switchPreference, flag));
+                return true;
+            });
+
+
             parent.addPreference(switchPreference);
         }
         updateMenu();
@@ -108,10 +131,15 @@
      * Updates the summary to show the description and whether the flag overrides the default value.
      */
     private void updateSummary(SwitchPreference switchPreference, DebugFlag flag) {
-        String onWarning = flag.defaultValue ? "" : "<b>OVERRIDDEN</b><br>";
-        String offWarning = flag.defaultValue ? "<b>OVERRIDDEN</b><br>" : "";
-        switchPreference.setSummaryOn(Html.fromHtml(onWarning + flag.description));
-        switchPreference.setSummaryOff(Html.fromHtml(offWarning + flag.description));
+        String summary = flag.defaultValue == TEAMFOOD
+                ? "<font color='blue'><b>[TEAMFOOD]</b> </font>" : "";
+        if (mSharedPreferences.contains(flag.key)) {
+            summary += "<font color='red'><b>[OVERRIDDEN]</b> </font>";
+        }
+        if (!TextUtils.isEmpty(summary)) {
+            summary += "<br>";
+        }
+        switchPreference.setSummary(Html.fromHtml(summary + flag.description));
     }
 
     private void updateMenu() {
@@ -143,7 +171,8 @@
     }
 
     private boolean getFlagStateFromSharedPrefs(DebugFlag flag) {
-        return mDataStore.getBoolean(flag.key, flag.defaultValue);
+        boolean defaultValue = FlagsFactory.getEnabledValue(flag.defaultValue);
+        return mDataStore.getBoolean(flag.key, defaultValue);
     }
 
     private boolean anyChanged() {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
index f748e8a..d066abe 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
@@ -18,6 +18,10 @@
 
 import static android.app.ActivityThread.currentApplication;
 
+import static com.android.launcher3.BuildConfig.IS_DEBUG_DEVICE;
+import static com.android.launcher3.config.FeatureFlags.FlagState.DISABLED;
+import static com.android.launcher3.config.FeatureFlags.FlagState.ENABLED;
+import static com.android.launcher3.config.FeatureFlags.FlagState.TEAMFOOD;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 
 import android.content.Context;
@@ -26,8 +30,8 @@
 import android.provider.DeviceConfig.Properties;
 import android.util.Log;
 
-import com.android.launcher3.Utilities;
 import com.android.launcher3.config.FeatureFlags.BooleanFlag;
+import com.android.launcher3.config.FeatureFlags.FlagState;
 import com.android.launcher3.config.FeatureFlags.IntFlag;
 import com.android.launcher3.util.ScreenOnTracker;
 
@@ -53,6 +57,9 @@
 
     private static final List<DebugFlag> sDebugFlags = new ArrayList<>();
 
+    static final BooleanFlag TEAMFOOD_FLAG = getReleaseFlag(
+            0, "LAUNCHER_TEAMFOOD", DISABLED, "Enable this flag to opt-in all team food flags");
+
     private final Set<String> mKeySet = new HashSet<>();
     private boolean mRestartRequested = false;
 
@@ -64,35 +71,54 @@
                 NAMESPACE_LAUNCHER, UI_HELPER_EXECUTOR, this::onPropertiesChanged);
     }
 
-    /**
-     * Creates a new debug flag
-     */
-    public static BooleanFlag getDebugFlag(
-            int bugId, String key, boolean defaultValue, String description) {
-        if (Utilities.IS_DEBUG_DEVICE) {
-            SharedPreferences prefs = currentApplication()
-                    .getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
-            boolean currentValue = prefs.getBoolean(key, defaultValue);
-            DebugFlag flag = new DebugFlag(key, description, defaultValue, currentValue);
-            sDebugFlags.add(flag);
-            return flag;
+    static boolean getEnabledValue(FlagState flagState) {
+        if (IS_DEBUG_DEVICE) {
+            switch (flagState) {
+                case ENABLED:
+                    return true;
+                case TEAMFOOD:
+                    return TEAMFOOD_FLAG.get();
+                default:
+                    return false;
+            }
         } else {
-            return new BooleanFlag(defaultValue);
+            return flagState == ENABLED;
         }
     }
 
     /**
-     * Creates a new release flag
+     * Creates a new debug flag. Debug flags always take their default value in release builds. On
+     * dogfood builds, they can be manually turned on using the flag toggle UI.
+     */
+    public static BooleanFlag getDebugFlag(
+            int bugId, String key, FlagState flagState, String description) {
+        if (IS_DEBUG_DEVICE) {
+            SharedPreferences prefs = currentApplication()
+                    .getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
+            boolean defaultValue = getEnabledValue(flagState);
+            boolean currentValue = prefs.getBoolean(key, defaultValue);
+            DebugFlag flag = new DebugFlag(key, description, flagState, currentValue);
+            sDebugFlags.add(flag);
+            return flag;
+        } else {
+            return new BooleanFlag(getEnabledValue(flagState));
+        }
+    }
+
+    /**
+     * Creates a new release flag. Release flags can be rolled out using server configurations and
+     * also allow manual overrides on debug builds.
      */
     public static BooleanFlag getReleaseFlag(
-            int bugId, String key, boolean defaultValueInCode, String description) {
+            int bugId, String key, FlagState flagState, String description) {
         INSTANCE.mKeySet.add(key);
+        boolean defaultValueInCode = getEnabledValue(flagState);
         boolean defaultValue = DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, key, defaultValueInCode);
-        if (Utilities.IS_DEBUG_DEVICE) {
+        if (IS_DEBUG_DEVICE) {
             SharedPreferences prefs = currentApplication()
                     .getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
             boolean currentValue = prefs.getBoolean(key, defaultValue);
-            DebugFlag flag = new DeviceFlag(key, description, defaultValue, currentValue,
+            DebugFlag flag = new DeviceFlag(key, description, flagState, currentValue,
                     defaultValueInCode);
             sDebugFlags.add(flag);
             return flag;
@@ -111,7 +137,7 @@
     }
 
     static List<DebugFlag> getDebugFlags() {
-        if (!Utilities.IS_DEBUG_DEVICE) {
+        if (!IS_DEBUG_DEVICE) {
             return Collections.emptyList();
         }
         synchronized (sDebugFlags) {
@@ -123,7 +149,7 @@
      * Dumps the current flags state to the print writer
      */
     public static void dump(PrintWriter pw) {
-        if (!Utilities.IS_DEBUG_DEVICE) {
+        if (!IS_DEBUG_DEVICE) {
             return;
         }
         pw.println("DeviceFlags:");
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 3f8da56..253341d 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -267,7 +267,8 @@
                 new RemoteAnimationAdapter(wrapper, RECENTS_LAUNCH_DURATION,
                         RECENTS_LAUNCH_DURATION - STATUS_BAR_TRANSITION_DURATION
                                 - STATUS_BAR_TRANSITION_PRE_DELAY),
-                new RemoteTransition(wrapper.toRemoteTransition(), getIApplicationThread()));
+                new RemoteTransition(wrapper.toRemoteTransition(), getIApplicationThread(),
+                        "LaunchFromRecents"));
         final ActivityOptionsWrapper activityOptions = new ActivityOptionsWrapper(options,
                 onEndCallback);
         activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
@@ -405,7 +406,8 @@
                 getMainThreadHandler(), mAnimationToHomeFactory, true);
         ActivityOptions options = ActivityOptions.makeRemoteAnimation(
                 new RemoteAnimationAdapter(runner, HOME_APPEAR_DURATION, 0),
-                new RemoteTransition(runner.toRemoteTransition(), getIApplicationThread()));
+                new RemoteTransition(runner.toRemoteTransition(), getIApplicationThread(),
+                        "StartHomeFromRecents"));
         startHomeIntentSafely(this, options.toBundle());
     }
 
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 1f99d6e..73f05c2 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -218,29 +218,15 @@
         mUnfoldAnimation = unfoldAnimation;
         linkToDeath();
         // re-attach the listeners once missing due to setProxy has not been initialized yet.
-        if (mPipAnimationListener != null && mPip != null) {
-            setPipAnimationListener(mPipAnimationListener);
-        }
-        if (mSplitScreenListener != null && mSplitScreen != null) {
-            registerSplitScreenListener(mSplitScreenListener);
-        }
-        if (mStartingWindowListener != null && mStartingWindow != null) {
-            setStartingWindowListener(mStartingWindowListener);
-        }
-        if (mSysuiUnlockAnimationController != null && mLauncherUnlockAnimationController != null) {
-            setLauncherUnlockAnimationController(mLauncherUnlockAnimationController);
-        }
+        setPipAnimationListener(mPipAnimationListener);
+        registerSplitScreenListener(mSplitScreenListener);
+        setStartingWindowListener(mStartingWindowListener);
+        setLauncherUnlockAnimationController(mLauncherUnlockAnimationController);
         new LinkedHashMap<>(mRemoteTransitions).forEach(this::registerRemoteTransition);
         setupTransactionQueue();
-        if (mRecentTasksListener != null && mRecentTasks != null) {
-            registerRecentTasksListener(mRecentTasksListener);
-        }
-        if (mBackAnimation != null && mBackToLauncherCallback != null) {
-            setBackToLauncherCallback(mBackToLauncherCallback, mBackToLauncherRunner);
-        }
-        if (unfoldAnimation != null && mUnfoldAnimationListener != null) {
-            setUnfoldAnimationListener(mUnfoldAnimationListener);
-        }
+        registerRecentTasksListener(mRecentTasksListener);
+        setBackToLauncherCallback(mBackToLauncherCallback, mBackToLauncherRunner);
+        setUnfoldAnimationListener(mUnfoldAnimationListener);
     }
 
     public void clearProxy() {
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 6e47ff4..2aa0be6 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -129,7 +129,8 @@
             TaskShortcutFactory.PIN,
             TaskShortcutFactory.INSTALL,
             TaskShortcutFactory.FREE_FORM,
-            TaskShortcutFactory.WELLBEING
+            TaskShortcutFactory.WELLBEING,
+            TaskShortcutFactory.SAVE_APP_PAIR
     };
 
     /**
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index 255b910..fd7b343 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -40,6 +40,7 @@
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
 import com.android.launcher3.model.WellbeingModel;
 import com.android.launcher3.popup.SystemShortcut;
@@ -63,7 +64,8 @@
 import java.util.stream.Collectors;
 
 /**
- * Represents a system shortcut that can be shown for a recent task.
+ * Represents a system shortcut that can be shown for a recent task. Appears as a single entry in
+ * the dropdown menu that shows up when you tap an app icon in Overview.
  */
 public interface TaskShortcutFactory {
     @Nullable
@@ -122,6 +124,26 @@
         }
     }
 
+    /**
+     * A menu item, "Save app pair", that allows the user to preserve the current app combination as
+     * a single persistent icon on the Home screen, allowing for quick split screen initialization.
+     */
+    class SaveAppPairSystemShortcut extends SystemShortcut {
+
+        private final TaskView mTaskView;
+
+        public SaveAppPairSystemShortcut(BaseDraggingActivity target, TaskView taskView) {
+            super(R.drawable.ic_save_app_pair, R.string.save_app_pair, target,
+                    taskView.getItemInfo(), taskView);
+            mTaskView = taskView;
+        }
+
+        @Override
+        public void onClick(View view) {
+            // TODO (b/274189428): Call "saveAppPair" function in new AppPairController class
+        }
+    }
+
     class FreeformSystemShortcut extends SystemShortcut<BaseDraggingActivity> {
         private static final String TAG = "FreeformSystemShortcut";
 
@@ -257,9 +279,6 @@
             final PagedOrientationHandler orientationHandler =
                     recentsView.getPagedOrientationHandler();
 
-            int[] taskViewTaskIds = taskView.getTaskIds();
-            boolean taskViewHasMultipleTasks = taskViewTaskIds[0] != -1 &&
-                    taskViewTaskIds[1] != -1;
             boolean notEnoughTasksToSplit = recentsView.getTaskViewCount() < 2;
             boolean isFocusedTask = deviceProfile.isTablet && taskView.isFocusedTask();
             boolean isTaskInExpectedScrollPosition =
@@ -267,11 +286,11 @@
             boolean isTaskSplitNotSupported = !task.isDockable;
             boolean hideForExistingMultiWindow = activity.getDeviceProfile().isMultiWindowMode;
 
-            if (taskViewHasMultipleTasks ||
-                    notEnoughTasksToSplit ||
-                    isTaskSplitNotSupported ||
-                    hideForExistingMultiWindow ||
-                    (isFocusedTask && isTaskInExpectedScrollPosition)) {
+            if (taskView.containsMultipleTasks()
+                    || notEnoughTasksToSplit
+                    || isTaskSplitNotSupported
+                    || hideForExistingMultiWindow
+                    || (isFocusedTask && isTaskInExpectedScrollPosition)) {
                 return null;
             }
 
@@ -283,6 +302,26 @@
         }
     };
 
+    TaskShortcutFactory SAVE_APP_PAIR = new TaskShortcutFactory() {
+        @Nullable
+        @Override
+        public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
+                TaskIdAttributeContainer taskContainer) {
+            final TaskView taskView = taskContainer.getTaskView();
+
+            if (!FeatureFlags.ENABLE_APP_PAIRS.get() || !taskView.containsMultipleTasks()) {
+                return null;
+            }
+
+            return Collections.singletonList(new SaveAppPairSystemShortcut(activity, taskView));
+        }
+
+        @Override
+        public boolean showForSplitscreen() {
+            return true;
+        }
+    };
+
     TaskShortcutFactory FREE_FORM = new TaskShortcutFactory() {
         @Override
         public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 5e14d19..9ca8928 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -22,6 +22,7 @@
 import static android.view.MotionEvent.ACTION_POINTER_UP;
 import static android.view.MotionEvent.ACTION_UP;
 
+import static com.android.launcher3.Launcher.INTENT_ACTION_ALL_APPS_TOGGLE;
 import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
 import static com.android.launcher3.config.FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -72,7 +73,6 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
 
-import com.android.app.viewcapture.SettingsAwareViewCapture;
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.R;
@@ -514,7 +514,7 @@
 
         if (isHomeAndOverviewSame) {
             Intent intent = new Intent(mOverviewComponentObserver.getHomeIntent())
-                    .setAction(Intent.ACTION_ALL_APPS);
+                    .setAction(INTENT_ACTION_ALL_APPS_TOGGLE);
             RemoteAction allAppsAction = new RemoteAction(
                     Icon.createWithResource(this, R.drawable.ic_apps),
                     getString(R.string.all_apps_label),
@@ -910,10 +910,6 @@
 
     private void logInputConsumerSelectionReason(
             InputConsumer consumer, CompoundString reasonString) {
-        if (!FeatureFlags.ENABLE_INPUT_CONSUMER_REASON_LOGGING.get()) {
-            ActiveGestureLog.INSTANCE.addLog("setInputConsumer: " + consumer.getName());
-            return;
-        }
         ActiveGestureLog.INSTANCE.addLog(new CompoundString("setInputConsumer: ")
                 .append(consumer.getName())
                 .append(". reason(s):")
@@ -1235,10 +1231,6 @@
                 createdOverviewActivity.getDeviceProfile().dump(this, "", pw);
             }
             mTaskbarManager.dumpLogs("", pw);
-
-            if (FeatureFlags.CONTINUOUS_VIEW_TREE_CAPTURE.get()) {
-                SettingsAwareViewCapture.getInstance(this).dump(pw, fd, this);
-            }
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
index 6dd67de..b76fe5c 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
@@ -24,6 +24,7 @@
 import com.android.launcher3.DeviceProfile
 import com.android.launcher3.anim.PendingAnimation
 import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource
+import com.android.quickstep.views.IconView
 import com.android.quickstep.views.TaskThumbnailView
 import com.android.quickstep.views.TaskView
 import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
@@ -52,21 +53,22 @@
      * depending on the state of the surface from which the split was initiated
      */
     fun getFirstAnimInitViews(taskViewSupplier: Supplier<TaskView>,
-                              splitSelectSourceSupplier: Supplier<SplitSelectSource>)
+                              splitSelectSourceSupplier: Supplier<SplitSelectSource?>)
             : SplitAnimInitProps {
+        val splitSelectSource = splitSelectSourceSupplier.get()
         if (!splitSelectStateController.isAnimateCurrentTaskDismissal) {
             // Initiating from home
-            val splitSelectSource = splitSelectSourceSupplier.get()
-            return SplitAnimInitProps(splitSelectSource.view, originalBitmap = null,
+            return SplitAnimInitProps(splitSelectSource!!.view, originalBitmap = null,
                     splitSelectSource.drawable, fadeWithThumbnail = false, isStagedTask = true,
                     iconView = null)
         } else if (splitSelectStateController.isDismissingFromSplitPair) {
             // Initiating split from overview, but on a split pair
             val taskView = taskViewSupplier.get()
             for (container : TaskIdAttributeContainer in taskView.taskIdAttributeContainers) {
-                if (container.task.key.id == splitSelectStateController.initialTaskId) {
+                if (container.task.getKey().getId() == splitSelectStateController.initialTaskId) {
+                    val drawable = getDrawable(container.iconView, splitSelectSource)
                     return SplitAnimInitProps(container.thumbnailView,
-                            container.thumbnailView.thumbnail, container.iconView.drawable!!,
+                            container.thumbnailView.thumbnail, drawable!!,
                             fadeWithThumbnail = true, isStagedTask = true,
                             iconView = container.iconView
                     )
@@ -77,14 +79,28 @@
         } else {
             // Initiating split from overview on fullscreen task TaskView
             val taskView = taskViewSupplier.get()
+            val drawable = getDrawable(taskView.iconView, splitSelectSource)
             return SplitAnimInitProps(taskView.thumbnail, taskView.thumbnail.thumbnail,
-                    taskView.iconView.drawable!!, fadeWithThumbnail = true, isStagedTask = true,
+                    drawable!!, fadeWithThumbnail = true, isStagedTask = true,
                     taskView.iconView
             )
         }
     }
 
     /**
+     * Returns the drawable that's provided in iconView, however if that
+     * is null it falls back to the drawable that's in splitSelectSource.
+     * TaskView's icon drawable can be null if the TaskView is scrolled far enough off screen
+     * @return [Drawable]
+     */
+    fun getDrawable(iconView: IconView, splitSelectSource: SplitSelectSource?) : Drawable? {
+        if (iconView.drawable == null && splitSelectSource != null) {
+            return splitSelectSource.drawable
+        }
+        return iconView.drawable
+    }
+
+    /**
      * When selecting first app from split pair, second app's thumbnail remains. This animates
      * the second thumbnail by expanding it to take up the full taskViewWidth/Height and overlaying
      * it with [TaskThumbnailView]'s splashView. Adds animations to the provided builder.
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 00d6571..11e1fbd 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -89,11 +89,17 @@
     private final StateManager mStateManager;
     @Nullable
     private DepthController mDepthController;
-    private @StagePosition int mStagePosition;
+    private @StagePosition int mInitialStagePosition;
     private ItemInfo mItemInfo;
+    /** {@link #mInitialTaskIntent} and {@link #mInitialUser} (the user of the Intent) are set
+     * together when split is initiated from an Intent. */
     private Intent mInitialTaskIntent;
+    private UserHandle mInitialUser;
     private int mInitialTaskId = INVALID_TASK_ID;
+    /** {@link #mSecondTaskIntent} and {@link #mSecondUser} (the user of the Intent) are set
+     * together when split is confirmed with an Intent. */
     private Intent mSecondTaskIntent;
+    private UserHandle mSecondUser;
     private int mSecondTaskId = INVALID_TASK_ID;
     private boolean mRecentsAnimationRunning;
     /** If {@code true}, animates the existing task view split placeholder view */
@@ -103,8 +109,6 @@
      * split pair task view without wanting to animate current task dismissal overall
      */
     private boolean mDismissingFromSplitPair;
-    @Nullable
-    private UserHandle mUser;
     /** If not null, this is the TaskView we want to launch from */
     @Nullable
     private GroupedTaskView mLaunchingTaskView;
@@ -138,7 +142,7 @@
             mInitialTaskId = alreadyRunningTask;
         } else {
             mInitialTaskIntent = intent;
-            mUser = itemInfo.user;
+            mInitialUser = itemInfo.user;
         }
 
         setInitialData(stagePosition, splitEvent, itemInfo);
@@ -158,7 +162,7 @@
     private void setInitialData(@StagePosition int stagePosition,
             StatsLogManager.EventEnum splitEvent, ItemInfo itemInfo) {
         mItemInfo = itemInfo;
-        mStagePosition = stagePosition;
+        mInitialStagePosition = stagePosition;
         mSplitEvent = splitEvent;
     }
 
@@ -215,7 +219,7 @@
         Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
                 LogUtils.getShellShareableInstanceId();
         launchTasks(mInitialTaskId, mInitialTaskIntent, mSecondTaskId, mSecondTaskIntent,
-                mStagePosition, callback, false /* freezeTaskList */, DEFAULT_SPLIT_RATIO,
+                mInitialStagePosition, callback, false /* freezeTaskList */, DEFAULT_SPLIT_RATIO,
                 instanceIds.first);
 
         mStatsLogManager.logger()
@@ -232,8 +236,14 @@
         mSecondTaskId = task.key.id;
     }
 
-    public void setSecondTask(Intent intent) {
+    /**
+     * To be called as soon as user selects the second app (even if animations aren't complete)
+     * @param intent The second intent that will be launched.
+     * @param user The user of that intent.
+     */
+    public void setSecondTask(Intent intent, UserHandle user) {
         mSecondTaskIntent = intent;
+        mSecondUser = user;
     }
 
     /**
@@ -284,22 +294,24 @@
             final RemoteSplitLaunchTransitionRunner animationRunner =
                     new RemoteSplitLaunchTransitionRunner(taskId1, taskId2, callback);
             final RemoteTransition remoteTransition = new RemoteTransition(animationRunner,
-                    ActivityThread.currentActivityThread().getApplicationThread());
+                    ActivityThread.currentActivityThread().getApplicationThread(),
+                    "LaunchSplitPair");
             if (intent1 == null && intent2 == null) {
                 mSystemUiProxy.startTasks(taskId1, options1.toBundle(), taskId2,
                         null /* options2 */, stagePosition, splitRatio, remoteTransition,
                         shellInstanceId);
             } else if (intent2 == null) {
-                launchIntentOrShortcut(intent1, options1, taskId2, stagePosition, splitRatio,
-                        remoteTransition, shellInstanceId);
+                launchIntentOrShortcut(intent1, mInitialUser, options1, taskId2, stagePosition,
+                        splitRatio, remoteTransition, shellInstanceId);
             } else if (intent1 == null) {
-                launchIntentOrShortcut(intent2, options1, taskId1,
+                launchIntentOrShortcut(intent2, mSecondUser, options1, taskId1,
                         getOppositeStagePosition(stagePosition), splitRatio, remoteTransition,
                         shellInstanceId);
             } else {
-                mSystemUiProxy.startIntents(getPendingIntent(intent1), options1.toBundle(),
-                        getPendingIntent(intent2), null /* options2 */, stagePosition,
-                        splitRatio, remoteTransition, shellInstanceId);
+                mSystemUiProxy.startIntents(getPendingIntent(intent1, mInitialUser),
+                        options1.toBundle(), getPendingIntent(intent2, mSecondUser),
+                        null /* options2 */, stagePosition, splitRatio, remoteTransition,
+                        shellInstanceId);
             }
         } else {
             final RemoteSplitLaunchAnimationRunner animationRunner =
@@ -313,61 +325,64 @@
                         taskId2, null /* options2 */, stagePosition, splitRatio, adapter,
                         shellInstanceId);
             } else if (intent2 == null) {
-                launchIntentOrShortcutLegacy(intent1, options1, taskId2, stagePosition, splitRatio,
-                        adapter, shellInstanceId);
+                launchIntentOrShortcutLegacy(intent1, mInitialUser, options1, taskId2,
+                        stagePosition, splitRatio, adapter, shellInstanceId);
             } else if (intent1 == null) {
-                launchIntentOrShortcutLegacy(intent2, options1, taskId1,
+                launchIntentOrShortcutLegacy(intent2, mSecondUser, options1, taskId1,
                         getOppositeStagePosition(stagePosition), splitRatio, adapter,
                         shellInstanceId);
             } else {
                 mSystemUiProxy.startIntentsWithLegacyTransition(
-                        getPendingIntent(intent1), getShortcutInfo(intent1), options1.toBundle(),
-                        getPendingIntent(intent2), getShortcutInfo(intent2), null /* options2 */,
-                        stagePosition, splitRatio, adapter, shellInstanceId);
+                        getPendingIntent(intent1, mInitialUser),
+                        getShortcutInfo(intent1, mInitialUser), options1.toBundle(),
+                        getPendingIntent(intent2, mSecondUser),
+                        getShortcutInfo(intent2, mSecondUser), null /* options2 */, stagePosition,
+                        splitRatio, adapter, shellInstanceId);
             }
         }
     }
 
-    private void launchIntentOrShortcut(Intent intent, ActivityOptions options1, int taskId,
-            @StagePosition int stagePosition, float splitRatio, RemoteTransition remoteTransition,
-            @Nullable InstanceId shellInstanceId) {
-        final ShortcutInfo shortcutInfo = getShortcutInfo(intent);
+    private void launchIntentOrShortcut(Intent intent, UserHandle user, ActivityOptions options1,
+            int taskId, @StagePosition int stagePosition, float splitRatio,
+            RemoteTransition remoteTransition, @Nullable InstanceId shellInstanceId) {
+        final ShortcutInfo shortcutInfo = getShortcutInfo(intent, user);
         if (shortcutInfo != null) {
             mSystemUiProxy.startShortcutAndTask(shortcutInfo,
                     options1.toBundle(), taskId, null /* options2 */, stagePosition,
                     splitRatio, remoteTransition, shellInstanceId);
         } else {
-            mSystemUiProxy.startIntentAndTask(getPendingIntent(intent), options1.toBundle(), taskId,
-                    null /* options2 */, stagePosition, splitRatio, remoteTransition,
-                    shellInstanceId);
+            mSystemUiProxy.startIntentAndTask(getPendingIntent(intent, user),
+                    options1.toBundle(), taskId, null /* options2 */, stagePosition, splitRatio,
+                    remoteTransition, shellInstanceId);
         }
     }
 
-    private void launchIntentOrShortcutLegacy(Intent intent, ActivityOptions options1, int taskId,
-            @StagePosition int stagePosition, float splitRatio, RemoteAnimationAdapter adapter,
+    private void launchIntentOrShortcutLegacy(Intent intent, UserHandle user,
+            ActivityOptions options1, int taskId, @StagePosition int stagePosition,
+            float splitRatio, RemoteAnimationAdapter adapter,
             @Nullable InstanceId shellInstanceId) {
-        final ShortcutInfo shortcutInfo = getShortcutInfo(intent);
+        final ShortcutInfo shortcutInfo = getShortcutInfo(intent, user);
         if (shortcutInfo != null) {
             mSystemUiProxy.startShortcutAndTaskWithLegacyTransition(shortcutInfo,
                     options1.toBundle(), taskId, null /* options2 */, stagePosition,
                     splitRatio, adapter, shellInstanceId);
         } else {
-            mSystemUiProxy.startIntentAndTaskWithLegacyTransition(getPendingIntent(intent),
-                    options1.toBundle(), taskId, null /* options2 */, stagePosition, splitRatio,
-                    adapter, shellInstanceId);
+            mSystemUiProxy.startIntentAndTaskWithLegacyTransition(
+                    getPendingIntent(intent, user), options1.toBundle(), taskId,
+                    null /* options2 */, stagePosition, splitRatio, adapter, shellInstanceId);
         }
     }
 
-    private PendingIntent getPendingIntent(Intent intent) {
-        return intent == null ? null : (mUser != null
+    private PendingIntent getPendingIntent(Intent intent, UserHandle user) {
+        return intent == null ? null : (user != null
                 ? PendingIntent.getActivityAsUser(mContext, 0, intent,
-                FLAG_MUTABLE | FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT, null /* options */, mUser)
+                FLAG_MUTABLE | FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT, null /* options */, user)
                 : PendingIntent.getActivity(mContext, 0, intent,
                         FLAG_MUTABLE | FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT));
     }
 
     public @StagePosition int getActiveSplitStagePosition() {
-        return mStagePosition;
+        return mInitialStagePosition;
     }
 
     public StatsLogManager.EventEnum getSplitEvent() {
@@ -379,7 +394,7 @@
     }
 
     @Nullable
-    private ShortcutInfo getShortcutInfo(Intent intent) {
+    private ShortcutInfo getShortcutInfo(Intent intent, UserHandle user) {
         if (intent == null || intent.getPackage() == null) {
             return null;
         }
@@ -391,7 +406,7 @@
 
         try {
             final Context context = mContext.createPackageContextAsUser(
-                    intent.getPackage(), 0 /* flags */, mUser);
+                    intent.getPackage(), 0 /* flags */, user);
             return new ShortcutInfo.Builder(context, shortcutId).build();
         } catch (PackageManager.NameNotFoundException e) {
             Log.w(TAG, "Failed to create a ShortcutInfo for " + intent.getPackage());
@@ -521,7 +536,9 @@
         mInitialTaskIntent = null;
         mSecondTaskId = INVALID_TASK_ID;
         mSecondTaskIntent = null;
-        mStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
+        mInitialUser = null;
+        mSecondUser = null;
+        mInitialStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
         mRecentsAnimationRunning = false;
         mLaunchingTaskView = null;
         mItemInfo = null;
diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
index e5c74dc..dd10c2d 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.os.UserHandle;
 import android.view.View;
 
 import com.android.launcher3.DeviceProfile;
@@ -66,21 +67,24 @@
         }
         Object tag = view.getTag();
         Intent intent;
+        UserHandle user;
         BitmapInfo bitmapInfo;
         if (tag instanceof WorkspaceItemInfo) {
             final WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) tag;
             intent = workspaceItemInfo.intent;
+            user = workspaceItemInfo.user;
             bitmapInfo = workspaceItemInfo.bitmap;
         } else if (tag instanceof com.android.launcher3.model.data.AppInfo) {
             final com.android.launcher3.model.data.AppInfo appInfo =
                     (com.android.launcher3.model.data.AppInfo) tag;
             intent = appInfo.intent;
+            user = appInfo.user;
             bitmapInfo = appInfo.bitmap;
         } else {
             return false;
         }
 
-        mController.setSecondTask(intent);
+        mController.setSecondTask(intent, user);
 
         boolean isTablet = mLauncher.getDeviceProfile().isTablet;
         SplitAnimationTimings timings = AnimUtils.getDeviceSplitToConfirmTimings(isTablet);
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 9a25e9c..cf6ee2d 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -185,6 +185,7 @@
 import com.android.quickstep.util.DesktopTask;
 import com.android.quickstep.util.GroupTask;
 import com.android.quickstep.util.LayoutUtils;
+import com.android.quickstep.util.RecentsAtomicAnimationFactory;
 import com.android.quickstep.util.RecentsOrientedState;
 import com.android.quickstep.util.SplitAnimationController.Companion.SplitAnimInitProps;
 import com.android.quickstep.util.SplitAnimationTimings;
@@ -801,8 +802,29 @@
 
         // if multi-instance feature is enabled
         if (FeatureFlags.ENABLE_MULTI_INSTANCE.get()) {
-            // invalidate the current list of tasks if filter changes
-            mFilterState.setOnFilterUpdatedListener(this::invalidateTaskList);
+            // invalidate the current list of tasks if filter changes with a fading in/out animation
+            mFilterState.setOnFilterUpdatedListener(() -> {
+                Animator animatorFade = mActivity.getStateManager().createStateElementAnimation(
+                        RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM, 1f, 0f);
+                Animator animatorAppear = mActivity.getStateManager().createStateElementAnimation(
+                        RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM, 0f, 1f);
+                animatorFade.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(@NonNull Animator animation) {
+                        RecentsView.this.invalidateTaskList();
+                        updateClearAllFunction();
+                        reloadIfNeeded();
+                        if (mPendingAnimation != null) {
+                            mPendingAnimation.addEndListener(success -> {
+                                animatorAppear.start();
+                            });
+                        } else {
+                            animatorAppear.start();
+                        }
+                    }
+                });
+                animatorFade.start();
+            });
         }
         // make sure filter is turned off by default
         mFilterState.setFilterBy(null);
@@ -821,8 +843,6 @@
      */
     public void setAndApplyFilter(@Nullable String packageName) {
         mFilterState.setFilterBy(packageName);
-        updateClearAllFunction();
-        reloadIfNeeded();
     }
 
     /**
@@ -4569,11 +4589,13 @@
      *                   is (either the ThumbnailView or the tapped icon).
      * @param intent If we are launching a fresh instance of the app, this is the Intent for it. If
      *               the second app is already running in Recents, this will be null.
+     * @param user If we are launching a fresh instance of the app, this is the UserHandle for it.
+     *             If the second app is already running in Recents, this will be null.
      * @return true if waiting for confirmation of second app or if split animations are running,
      *          false otherwise
      */
     public boolean confirmSplitSelect(TaskView containerTaskView, Task task, Drawable drawable,
-            View secondView, @Nullable Bitmap thumbnail, Intent intent) {
+            View secondView, @Nullable Bitmap thumbnail, Intent intent, UserHandle user) {
         if (canLaunchFullscreenTask()) {
             return false;
         }
@@ -4589,7 +4611,7 @@
             }
             mSplitSelectStateController.setSecondTask(task);
         } else {
-            mSplitSelectStateController.setSecondTask(intent);
+            mSplitSelectStateController.setSecondTask(intent, user);
         }
 
         RectF secondTaskStartingBounds = new RectF();
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index df90583..42589ce 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -761,7 +761,8 @@
         if (container != null) {
             return getRecentsView().confirmSplitSelect(this, container.getTask(),
                     container.getIconView().getDrawable(), container.getThumbnailView(),
-                    container.getThumbnailView().getThumbnail(), /* intent */ null);
+                    container.getThumbnailView().getThumbnail(), /* intent */ null,
+                    /* user */ null);
         }
         return false;
     }
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 9a65b4f..c39d095 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -186,35 +186,6 @@
         actionsView.clickAndDismissScreenshot();
     }
 
-    @Test
-    @PortraitLandscape
-    public void testSplitFromOverview() {
-        assumeTrue(!mLauncher.isTablet());
-
-        startTestActivity(2);
-        startTestActivity(3);
-
-        mLauncher.goHome().switchToOverview().getCurrentTask()
-                .tapMenu()
-                .tapSplitMenuItem()
-                .getCurrentTask()
-                .open();
-    }
-
-    @Test
-    @PortraitLandscape
-    public void testSplitFromOverviewForTablet() {
-        assumeTrue(mLauncher.isTablet());
-
-        startTestActivity(2);
-        startTestActivity(3);
-
-        mLauncher.goHome().switchToOverview().getOverviewActions()
-                .clickSplit()
-                .getTestActivityTask(2)
-                .open();
-    }
-
     private int getCurrentOverviewPage(Launcher launcher) {
         return launcher.<RecentsView>getOverviewPanel().getCurrentPage();
     }
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
index d3fbe93..2ae512a 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
@@ -15,14 +15,18 @@
  */
 package com.android.quickstep;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
 import android.content.Intent;
 
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.ui.TaplTestsLauncher3;
 import com.android.launcher3.util.rule.TestStabilityRule;
 import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
 
 import org.junit.After;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -37,13 +41,6 @@
         super.setUp();
         TaplTestsLauncher3.initialize(this);
 
-        mLauncher.getWorkspace()
-                .deleteAppIcon(mLauncher.getWorkspace().getHotseatAppIcon(0))
-                .switchToAllApps()
-                .getAppIcon(CALCULATOR_APP_NAME)
-                .dragToHotseat(0);
-
-        startAppFast(CALCULATOR_APP_PACKAGE);
         if (mLauncher.isTablet()) {
             mLauncher.enableBlockTimeout(true);
             mLauncher.showTaskbarIfHidden();
@@ -58,14 +55,29 @@
     }
 
     @Test
+    @PortraitLandscape
+    public void testSplitFromOverview() {
+        createAndLaunchASplitPair();
+    }
+
+    @Test
     // TODO (b/270201357): When this test is proven stable, remove this TestStabilityRule and
-    // introduce into presubmit as well.
+    //  introduce into presubmit as well.
     @TestStabilityRule.Stability(
             flavors = TestStabilityRule.LOCAL | TestStabilityRule.PLATFORM_POSTSUBMIT)
     @PortraitLandscape
     @TaskbarModeSwitch
     public void testSplitAppFromHomeWithItself() throws Exception {
-        Assume.assumeTrue(mLauncher.isTablet());
+        // Currently only tablets have Taskbar in Overview, so test is only active on tablets
+        assumeTrue(mLauncher.isTablet());
+
+        mLauncher.getWorkspace()
+                .deleteAppIcon(mLauncher.getWorkspace().getHotseatAppIcon(0))
+                .switchToAllApps()
+                .getAppIcon(CALCULATOR_APP_NAME)
+                .dragToHotseat(0);
+
+        startAppFast(CALCULATOR_APP_PACKAGE);
 
         mLauncher.goHome()
                 .switchToAllApps()
@@ -79,4 +91,50 @@
                 .getAppIcon(CALCULATOR_APP_NAME)
                 .launchIntoSplitScreen();
     }
+
+    @Test
+    public void testSaveAppPairMenuItemExistsOnSplitPair() throws Exception {
+        assumeTrue(FeatureFlags.ENABLE_APP_PAIRS.get());
+
+        createAndLaunchASplitPair();
+
+        assertTrue("Save app pair menu item is missing",
+                mLauncher.goHome()
+                        .switchToOverview()
+                        .getCurrentTask()
+                        .tapMenu()
+                        .hasMenuItem("Save app pair"));
+    }
+
+    @Test
+    public void testSaveAppPairMenuItemDoesNotExistOnSingleTask() throws Exception {
+        assumeTrue(FeatureFlags.ENABLE_APP_PAIRS.get());
+
+        startAppFast(CALCULATOR_APP_PACKAGE);
+
+        assertFalse("Save app pair menu item is erroneously appearing on single task",
+                mLauncher.goHome()
+                        .switchToOverview()
+                        .getCurrentTask()
+                        .tapMenu()
+                        .hasMenuItem("Save app pair"));
+    }
+
+    private void createAndLaunchASplitPair() {
+        startTestActivity(2);
+        startTestActivity(3);
+
+        if (mLauncher.isTablet()) {
+            mLauncher.goHome().switchToOverview().getOverviewActions()
+                    .clickSplit()
+                    .getTestActivityTask(2)
+                    .open();
+        } else {
+            mLauncher.goHome().switchToOverview().getCurrentTask()
+                    .tapMenu()
+                    .tapSplitMenuItem()
+                    .getCurrentTask()
+                    .open();
+        }
+    }
 }
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt b/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
new file mode 100644
index 0000000..7e07b81
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
@@ -0,0 +1,165 @@
+/*
+ *  Copyright (C) 2023 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package com.android.quickstep.util
+
+import android.graphics.Bitmap
+import android.graphics.drawable.Drawable
+import android.view.View
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.launcher3.util.SplitConfigurationOptions
+import com.android.quickstep.views.GroupedTaskView
+import com.android.quickstep.views.IconView
+import com.android.quickstep.views.TaskThumbnailView
+import com.android.quickstep.views.TaskView
+import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
+import com.android.systemui.shared.recents.model.Task
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.`when` as whenever
+
+@RunWith(AndroidJUnit4::class)
+class SplitAnimationControllerTest {
+
+    private val taskId = 9
+
+    @Mock lateinit var mockSplitSelectStateController: SplitSelectStateController
+    // TaskView
+    @Mock lateinit var mockTaskView: TaskView
+    @Mock lateinit var mockThumbnailView: TaskThumbnailView
+    @Mock lateinit var mockBitmap: Bitmap
+    @Mock lateinit var mockIconView: IconView
+    @Mock lateinit var mockTaskViewDrawable: Drawable
+    // GroupedTaskView
+    @Mock lateinit var mockGroupedTaskView: GroupedTaskView
+    @Mock lateinit var mockTask: Task
+    @Mock lateinit var mockTaskKey: Task.TaskKey
+    @Mock lateinit var mockTaskIdAttributeContainer: TaskIdAttributeContainer
+
+    // SplitSelectSource
+    @Mock lateinit var splitSelectSource: SplitConfigurationOptions.SplitSelectSource
+    @Mock lateinit var mockSplitSourceDrawable: Drawable
+    @Mock lateinit var mockSplitSourceView: View
+
+    lateinit var splitAnimationController: SplitAnimationController
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+
+        whenever(mockTaskView.thumbnail).thenReturn(mockThumbnailView)
+        whenever(mockThumbnailView.thumbnail).thenReturn(mockBitmap)
+        whenever(mockTaskView.iconView).thenReturn(mockIconView)
+        whenever(mockIconView.drawable).thenReturn(mockTaskViewDrawable)
+
+        whenever(splitSelectSource.drawable).thenReturn(mockSplitSourceDrawable)
+        whenever(splitSelectSource.view).thenReturn(mockSplitSourceView)
+
+        splitAnimationController = SplitAnimationController(mockSplitSelectStateController)
+    }
+
+    @Test
+    fun getFirstAnimInitViews_nullTaskViewIcon_useSplitSourceIcon() {
+        // Hit fullscreen task dismissal state
+        whenever(mockSplitSelectStateController.isAnimateCurrentTaskDismissal).thenReturn(true)
+        whenever(mockSplitSelectStateController.isDismissingFromSplitPair).thenReturn(false)
+
+        // Missing taskView icon
+        whenever(mockIconView.drawable).thenReturn(null)
+
+        val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
+                splitAnimationController.getFirstAnimInitViews(
+                        { mockTaskView }, { splitSelectSource })
+
+        assertEquals("Did not fallback to use splitSource icon drawable",
+                mockSplitSourceDrawable, splitAnimInitProps.iconDrawable)
+    }
+
+    @Test
+    fun getFirstAnimInitViews_validTaskViewIcon_useTaskViewIcon() {
+        // Hit fullscreen task dismissal state
+        whenever(mockSplitSelectStateController.isAnimateCurrentTaskDismissal).thenReturn(true)
+        whenever(mockSplitSelectStateController.isDismissingFromSplitPair).thenReturn(false)
+
+        val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
+                splitAnimationController.getFirstAnimInitViews(
+                        { mockTaskView }, { splitSelectSource })
+
+        assertEquals("Did not use taskView icon drawable", mockTaskViewDrawable,
+                splitAnimInitProps.iconDrawable)
+    }
+
+    @Test
+    fun getFirstAnimInitViews_validTaskViewNullSplitSource_useTaskViewIcon() {
+        // Hit fullscreen task dismissal state
+        whenever(mockSplitSelectStateController.isAnimateCurrentTaskDismissal).thenReturn(true)
+        whenever(mockSplitSelectStateController.isDismissingFromSplitPair).thenReturn(false)
+
+        // Set split source to null
+        whenever(splitSelectSource.drawable).thenReturn(null)
+
+        val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
+                splitAnimationController.getFirstAnimInitViews(
+                        { mockTaskView }, { splitSelectSource })
+
+        assertEquals("Did not use taskView icon drawable", mockTaskViewDrawable,
+                splitAnimInitProps.iconDrawable)
+    }
+
+    @Test
+    fun getFirstAnimInitViews_nullTaskViewValidSplitSource_noTaskDismissal() {
+        // Hit initiating split from home
+        whenever(mockSplitSelectStateController.isAnimateCurrentTaskDismissal).thenReturn(false)
+        whenever(mockSplitSelectStateController.isDismissingFromSplitPair).thenReturn(false)
+
+        val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
+                splitAnimationController.getFirstAnimInitViews(
+                        { mockTaskView }, { splitSelectSource })
+
+        assertEquals("Did not use splitSource icon drawable", mockSplitSourceDrawable,
+                splitAnimInitProps.iconDrawable)
+    }
+
+    @Test
+    fun getFirstAnimInitViews_nullTaskViewValidSplitSource_groupedTaskView() {
+        // Hit groupedTaskView dismissal
+        whenever(mockSplitSelectStateController.isAnimateCurrentTaskDismissal).thenReturn(true)
+        whenever(mockSplitSelectStateController.isDismissingFromSplitPair).thenReturn(true)
+
+        // Remove icon view from GroupedTaskView
+        whenever(mockIconView.drawable).thenReturn(null)
+
+        whenever(mockTaskIdAttributeContainer.task).thenReturn(mockTask)
+        whenever(mockTaskIdAttributeContainer.iconView).thenReturn(mockIconView)
+        whenever(mockTaskIdAttributeContainer.thumbnailView).thenReturn(mockThumbnailView)
+        whenever(mockTask.getKey()).thenReturn(mockTaskKey)
+        whenever(mockTaskKey.getId()).thenReturn(taskId)
+        whenever(mockSplitSelectStateController.initialTaskId).thenReturn(taskId)
+        whenever(mockGroupedTaskView.taskIdAttributeContainers)
+                .thenReturn(Array(1) { mockTaskIdAttributeContainer })
+        val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
+                splitAnimationController.getFirstAnimInitViews(
+                        { mockGroupedTaskView }, { splitSelectSource })
+
+        assertEquals("Did not use splitSource icon drawable", mockSplitSourceDrawable,
+                splitAnimInitProps.iconDrawable)
+    }
+}
\ No newline at end of file
diff --git a/res/drawable/bg_widgets_header_large_screen.xml b/res/drawable/bg_widgets_header_two_pane.xml
similarity index 100%
rename from res/drawable/bg_widgets_header_large_screen.xml
rename to res/drawable/bg_widgets_header_two_pane.xml
diff --git a/res/drawable/page_indicator.xml b/res/drawable/page_indicator.xml
deleted file mode 100644
index c0ccc49..0000000
--- a/res/drawable/page_indicator.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <solid android:color="?attr/folderPaginationColor"/>
-    <size android:width="@dimen/page_indicator_size" android:height="@dimen/page_indicator_size"/>
-</shape>
\ No newline at end of file
diff --git a/res/layout/page_indicator_dots.xml b/res/layout/page_indicator_dots.xml
index d5fe51e..41844b7 100644
--- a/res/layout/page_indicator_dots.xml
+++ b/res/layout/page_indicator_dots.xml
@@ -14,9 +14,13 @@
      limitations under the License.
 -->
 
-<com.android.launcher3.pageindicators.PageIndicatorDots xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.launcher3.pageindicators.LauncherDotsPageIndicator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res-auto"
     android:id="@+id/page_indicator"
     android:layout_width="match_parent"
     android:layout_height="@dimen/workspace_page_indicator_height"
     android:layout_gravity="bottom | center_horizontal"
-    android:theme="@style/HomeScreenElementTheme" />
\ No newline at end of file
+    android:theme="@style/HomeScreenElementTheme"
+    launcher:indicatorDotColor="?attr/workspaceTextColor"
+    />
\ No newline at end of file
diff --git a/res/layout/system_shortcut_content.xml b/res/layout/system_shortcut_content.xml
index ddcef09..3008339 100644
--- a/res/layout/system_shortcut_content.xml
+++ b/res/layout/system_shortcut_content.xml
@@ -22,15 +22,12 @@
         android:id="@+id/bubble_text"
         android:background="?android:attr/selectableItemBackground"
         android:gravity="start|center_vertical"
-        android:paddingTop="@dimen/bg_popup_item_vertical_padding"
-        android:paddingBottom="@dimen/bg_popup_item_vertical_padding"
         android:minHeight="@dimen/bg_popup_item_height"
         android:textAlignment="viewStart"
         android:paddingStart="@dimen/deep_shortcuts_text_padding_start"
         android:paddingEnd="@dimen/popup_padding_end"
         android:textSize="14sp"
-        android:minLines="1"
-        android:maxLines="2"
+        android:lines="1"
         android:ellipsize="end"
         android:hyphenationFrequency="full"
         android:textColor="@color/system_shortcut_text"
diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml
index 5518dc8..35ccc5a 100644
--- a/res/layout/user_folder_icon_normalized.xml
+++ b/res/layout/user_folder_icon_normalized.xml
@@ -53,12 +53,13 @@
             android:textColorHighlight="?android:attr/colorControlHighlight"
             android:textColorHint="?attr/folderHintColor"/>
 
-        <com.android.launcher3.pageindicators.PageIndicatorDots
+        <com.android.launcher3.pageindicators.LauncherDotsPageIndicator
             android:id="@+id/folder_page_indicator"
             android:layout_gravity="center_vertical"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:elevation="1dp"
+            launcher:indicatorDotColor="@color/folder_pagination_color"
             />
 
     </LinearLayout>
diff --git a/res/layout/widgets_list_row_header_two_pane.xml b/res/layout/widgets_list_row_header_two_pane.xml
index 6465db5..c0a6ea8 100644
--- a/res/layout/widgets_list_row_header_two_pane.xml
+++ b/res/layout/widgets_list_row_header_two_pane.xml
@@ -24,7 +24,7 @@
     android:focusable="true"
     launcher:appIconSize="48dp"
     android:descendantFocusability="afterDescendants"
-    android:background="@drawable/bg_widgets_header_large_screen" >
+    android:background="@drawable/bg_widgets_header_two_pane" >
 
     <ImageView
         android:id="@+id/app_icon"
diff --git a/res/layout/widgets_full_sheet_large_screen.xml b/res/layout/widgets_two_pane_sheet.xml
similarity index 97%
rename from res/layout/widgets_full_sheet_large_screen.xml
rename to res/layout/widgets_two_pane_sheet.xml
index f563baa..4333a80 100644
--- a/res/layout/widgets_full_sheet_large_screen.xml
+++ b/res/layout/widgets_two_pane_sheet.xml
@@ -42,7 +42,7 @@
             android:layout_marginTop="24dp"
             android:gravity="center_horizontal"
             android:layout_below="@id/collapse_handle"
-            android:paddingHorizontal="@dimen/widget_list_horizontal_margin_large_screen"
+            android:paddingHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
             android:text="@string/widget_button_text"
             android:textColor="?android:attr/textColorSecondary"
             android:textSize="24sp" />
@@ -76,7 +76,7 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:clipToPadding="false"
-                    android:paddingHorizontal="@dimen/widget_list_horizontal_margin_large_screen"
+                    android:paddingHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
                     android:visibility="gone" />
             </FrameLayout>
 
@@ -85,8 +85,8 @@
                 android:layout_width="0dp"
                 android:layout_height="match_parent"
                 android:layout_weight="0.67"
-                android:layout_marginEnd="@dimen/widget_list_horizontal_margin_large_screen"
-                android:paddingTop="@dimen/widget_list_horizontal_margin_large_screen"
+                android:layout_marginEnd="@dimen/widget_list_horizontal_margin_two_pane"
+                android:paddingTop="@dimen/widget_list_horizontal_margin_two_pane"
                 android:gravity="end"
                 android:layout_gravity="end"
                 android:orientation="horizontal">
@@ -118,7 +118,7 @@
                             android:layout_width="match_parent"
                             android:layout_height="wrap_content"
                             android:paddingHorizontal=
-                                "@dimen/widget_list_horizontal_margin_large_screen"
+                                "@dimen/widget_list_horizontal_margin_two_pane"
                             android:visibility="gone" />
                     </LinearLayout>
                 </ScrollView>
diff --git a/res/layout/widgets_full_sheet_paged_view_large_screen.xml b/res/layout/widgets_two_pane_sheet_paged_view.xml
similarity index 93%
rename from res/layout/widgets_full_sheet_paged_view_large_screen.xml
rename to res/layout/widgets_two_pane_sheet_paged_view.xml
index f729981..d3a8584 100644
--- a/res/layout/widgets_full_sheet_paged_view_large_screen.xml
+++ b/res/layout/widgets_two_pane_sheet_paged_view.xml
@@ -17,7 +17,7 @@
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <FrameLayout
-        android:id="@+id/widgets_full_sheet_paged_view_large_screen"
+        android:id="@+id/widgets_two_pane_sheet_paged_view"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:gravity="start"
@@ -29,7 +29,7 @@
             android:layout_height="match_parent"
             android:clipToPadding="false"
             android:descendantFocusability="afterDescendants"
-            android:paddingHorizontal="@dimen/widget_list_horizontal_margin_large_screen"
+            android:paddingHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
             launcher:pageIndicator="@+id/tabs" >
 
             <com.android.launcher3.widget.picker.WidgetsRecyclerView
@@ -62,7 +62,7 @@
                 android:clipToPadding="false"
                 android:elevation="0.1dp"
                 android:paddingBottom="8dp"
-                android:paddingHorizontal="@dimen/widget_list_horizontal_margin_large_screen"
+                android:paddingHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
                 launcher:layout_sticky="true">
 
                 <include layout="@layout/widgets_search_bar" />
@@ -73,8 +73,10 @@
                 android:layout_height="match_parent"
                 android:id="@+id/suggestions_header"
                 android:layout_marginTop="8dp"
-                android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_large_screen"
-                android:orientation="horizontal">
+                android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
+                android:orientation="horizontal"
+                android:background="?android:attr/colorBackground"
+                launcher:layout_sticky="true">
             </LinearLayout>
 
             <com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip
@@ -84,7 +86,7 @@
                 android:gravity="center_horizontal"
                 android:orientation="horizontal"
                 android:paddingVertical="8dp"
-                android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_large_screen"
+                android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
                 android:background="?android:attr/colorBackground"
                 style="@style/TextHeadline"
                 launcher:layout_sticky="true">
diff --git a/res/layout/widgets_full_sheet_recyclerview_large_screen.xml b/res/layout/widgets_two_pane_sheet_recyclerview.xml
similarity index 88%
rename from res/layout/widgets_full_sheet_recyclerview_large_screen.xml
rename to res/layout/widgets_two_pane_sheet_recyclerview.xml
index 8fef303..8f2a25e 100644
--- a/res/layout/widgets_full_sheet_recyclerview_large_screen.xml
+++ b/res/layout/widgets_two_pane_sheet_recyclerview.xml
@@ -17,7 +17,7 @@
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <FrameLayout
-        android:id="@+id/widgets_full_sheet_recyclerview_large_screen"
+        android:id="@+id/widgets_two_pane_sheet_recyclerview"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:gravity="start"
@@ -28,7 +28,7 @@
             android:id="@+id/primary_widgets_list_view"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_large_screen"
+            android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
             android:clipToPadding="false" />
 
         <!-- SearchAndRecommendationsView without the tab layout as well -->
@@ -47,7 +47,7 @@
                 android:clipToPadding="false"
                 android:elevation="0.1dp"
                 android:paddingBottom="8dp"
-                android:paddingHorizontal="@dimen/widget_list_horizontal_margin_large_screen"
+                android:paddingHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
                 launcher:layout_sticky="true">
 
                 <include layout="@layout/widgets_search_bar" />
@@ -58,8 +58,11 @@
                 android:layout_height="match_parent"
                 android:id="@+id/suggestions_header"
                 android:layout_marginTop="8dp"
-                android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_large_screen"
-                android:orientation="horizontal">
+                android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
+                android:paddingBottom="16dp"
+                android:orientation="horizontal"
+                android:background="?android:attr/colorBackground"
+                launcher:layout_sticky="true">
             </LinearLayout>
         </com.android.launcher3.views.StickyHeaderLayout>
     </FrameLayout>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 5c4313a..99cbd53 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Tuis"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Verdeelde skerm"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Programinligting vir %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Raak en hou om \'n legstuk te skuif."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dubbeltik en hou om \'n legstuk te skuif of gebruik gepasmaakte handelinge."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index df4525e..5b10654 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"መነሻ"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"የተከፈለ ማያ ገጽ"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"የመተግበሪያ መረጃ ለ%1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ምግብርን ለማንቀሳቀስ ይንኩ እና ይያዙ።"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ምግብርን ለማንቀሳቀስ ወይም ብጁ እርምጃዎችን ለመጠቀም ሁለቴ መታ ያድርጉ እና ይያዙ።"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 9155e7b..8f55646 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"الشاشة الرئيسية"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"تقسيم الشاشة"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"‏معلومات تطبيق %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"انقر مع الاستمرار لنقل أداة."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"انقر مرتين مع تثبيت إصبعك لنقل أداة أو استخدام الإجراءات المخصّصة."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index dc7ed51..2378f23 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"গৃহ স্ক্ৰীন"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"বিভাজিত স্ক্ৰীন"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$sৰ বাবে এপৰ তথ্য"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ৱিজেট স্থানান্তৰ কৰিবলৈ টিপি ধৰি ৰাখক।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"কোনো ৱিজেট স্থানান্তৰ কৰিবলৈ দুবাৰ টিপি ধৰি ৰাখক অথবা কাষ্টম কাৰ্য ব্যৱহাৰ কৰক।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 6b1d484..c24b9a5 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Əsas səhifə"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ekran bölünməsi"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ilə bağlı tətbiq məlumatı"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Vidceti daşımaq üçün toxunub saxlayın."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Vidceti daşımaq üçün iki dəfə toxunub saxlayın və ya fərdi əməliyyatlardan istifadə edin."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 4e3ec96..197b3b0 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Početni ekran"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podeljeni ekran"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacije o aplikaciji za: %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Dodirnite i zadržite radi pomeranja vidžeta."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvaput dodirnite i zadržite da biste pomerali vidžet ili koristite prilagođene radnje."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 05d58f7..cff40b6 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Галоўны экран"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Падзелены экран"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Інфармацыя пра праграму для: %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Націсніце і ўтрымлівайце віджэт для перамяшчэння."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Дакраніцеся двойчы і ўтрымлівайце, каб перамясціць віджэт або выкарыстоўваць спецыяльныя дзеянні."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index b847083..4d94341 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Начален екран"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Разделен екран"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Информация за приложението за %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Докоснете и задръжте за преместване на приспособление"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Докоснете двукратно и задръжте за преместване на приспособление или използвайте персонал. действия."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 9351f9b..d277a3a 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"হোম"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"স্প্লিট স্ক্রিন"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s-এর জন্য অ্যাপ সম্পর্কিত তথ্য"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"কোনও উইজেট সরাতে সেটি টাচ করে ধরে রাখুন।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"একটি উইজেট সরাতে বা কাস্টম অ্যাকশন ব্যবহার করতে ডবল ট্যাপ করে ধরে রাখুন।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 6ce2412..45fb7f1 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Početni ekran"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podijeljeni ekran"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacije o aplikaciji %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Dodirnite i zadržite da pomjerite vidžet."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvaput dodirnite i zadržite da pomjerite vidžet ili da koristite prilagođene radnje."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index d5eeec5..be80552 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Inici"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Informació de l\'aplicació %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Fes doble toc i mantén premut per moure un widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Fes doble toc i mantén premut per moure un widget o per utilitzar accions personalitzades."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 9e4faeb..3402b75 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Domů"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Rozdělená obrazovka"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Informace o aplikaci %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Widget přesunete klepnutím a podržením."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvojitým klepnutím a podržením přesunete widget, případně použijte vlastní akce."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 26185c7..b8aa02f 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Startskærm"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Opdel skærm"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Appinfo for %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Hold en widget nede for at flytte den."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Tryk to gange, og hold en widget nede for at flytte den eller bruge tilpassede handlinger."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 1fba8e7..199bf54 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Startbildschirm"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Geteilter Bildschirm"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"App-Info für %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Zum Verschieben des Widgets berühren und halten"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Doppeltippen und halten, um ein Widget zu bewegen oder benutzerdefinierte Aktionen zu nutzen."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 34556c0..31fa51e 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Αρχική οθόνη"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Διαχωρισμός οθόνης"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Πληροφορίες εφαρμογής για %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Πατήστε παρατετ. για μετακίνηση γραφ. στοιχείου."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Πατήστε δύο φορές παρατεταμένα για μετακίνηση γραφικού στοιχείου ή χρήση προσαρμοσμένων ενεργειών."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 02f3396..c7b55d7 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Home"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch and hold to move a widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Double-tap &amp; hold to move a widget or use custom actions."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index a36f39a..7a4e094 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Home"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch &amp; hold to move a widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Double-tap &amp; hold to move a widget or use custom actions."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 02f3396..c7b55d7 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Home"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch and hold to move a widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Double-tap &amp; hold to move a widget or use custom actions."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 02f3396..c7b55d7 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Home"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch and hold to move a widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Double-tap &amp; hold to move a widget or use custom actions."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index 9719a96..5324bdf 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎Home‎‏‎‎‏‎"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎Split screen‎‏‎‎‏‎"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎App info for %1$s‎‏‎‎‏‎"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎‏‎‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎Touch &amp; hold to move a widget.‎‏‎‎‏‎"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎‎‎‎‎‏‏‎‎Double-tap &amp; hold to move a widget or use custom actions.‎‏‎‎‏‎"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‎%1$d × %2$d‎‏‎‎‏‎"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 48c422c..1ff063d 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Pantalla principal"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Información de la app de %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Mantén presionado para mover un widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Presiona dos veces y mantén presionado para mover un widget o usar acciones personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index ddde58f..777f4c9 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Inicio"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Información de la aplicación %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Mantén pulsado un widget para moverlo"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toca dos veces y mantén pulsado un widget para moverlo o usar acciones personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index be889cc..91d9352 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Avakuva"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Jagatud ekraanikuva"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Rakenduse teave: %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Vidina teisaldamiseks puudutage ja hoidke all."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Vidina teisaldamiseks või kohandatud toimingute kasutamiseks topeltpuudutage ja hoidke all."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index c11b9ca..66b8679 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Hasierako pantaila"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Zatitu pantaila"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s aplikazioari buruzko informazioa"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Eduki sakatuta widget bat mugitzeko."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Sakatu birritan eta eduki sakatuta widget bat mugitzeko edo ekintza pertsonalizatuak erabiltzeko."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index f33f9a6..42d44ee 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"صفحه اصلی"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"صفحهٔ دونیمه"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"‏اطلاعات برنامه %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"برای جابه‌جا کردن ابزارک، لمس کنید و نگه دارید."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"برای جابه‌جا کردن ابزارک یا استفاده از کنش‌های سفارشی، دوضربه بزنید و نگه دارید."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 9ef7b4b..a6ecd8b 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Etusivu"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Jaettu näyttö"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Sovellustiedot: %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Kosketa pitkään, niin voit siirtää widgetiä."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Kaksoisnapauta ja paina pitkään, niin voit siirtää widgetiä tai käyttää muokattuja toimintoja."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 78470a1..ad60e26 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Accueil"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Écran partagé"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Renseignements sur l\'appli pour %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Maintenez le doigt sur un widget pour le déplacer."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Touchez 2x un widget et maintenez le doigt dessus pour le déplacer ou utiliser des actions personnalisées."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index b8debf7..983d5a9 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Accueil"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Écran partagé"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Infos sur l\'appli pour %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Appuyez de manière prolongée sur un widget pour le déplacer."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Appuyez deux fois et maintenez la pression pour déplacer widget ou utiliser actions personnalisées."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 8ac5b81..c11c514 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Inicio"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Información da aplicación para %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Mantén premido un widget para movelo."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toca dúas veces un widget e manteno premido para movelo ou utiliza accións personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index f6bd907..4b48e7a 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"હોમ સ્ક્રીન"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"સ્ક્રીનને વિભાજિત કરો"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s માટે ઍપ માહિતી"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"વિજેટ ખસેડવા ટચ કરીને થોડી વાર દબાવી રાખો."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"વિજેટ ખસેડવા બે વાર ટૅપ કરીને દબાવી રાખો અથવા કસ્ટમ ક્રિયાઓનો ઉપયોગ કરો."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 32ea26f..be64ff1 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"होम स्क्रीन"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"स्प्लिट स्क्रीन"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s के लिए ऐप्लिकेशन की जानकारी"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"किसी विजेट को एक से दूसरी जगह ले जाने के लिए, उसे दबाकर रखें."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"किसी विजेट को एक से दूसरी जगह ले जाने के लिए, उस पर दो बार टैप करके दबाकर रखें या पसंद के मुताबिक कार्रवाइयां इस्तेमाल करें."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index c6180a9..b757619 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Početni zaslon"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podijeljeni zaslon"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacije o aplikaciji %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Dodirnite i zadržite da biste premjestili widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvaput dodirnite i zadržite pritisak da biste premjestili widget ili upotrijebite prilagođene radnje"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index e084231..d499022 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Kezdőképernyő"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Osztott képernyő"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Alkalmazásinformáció a következőhöz: %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Tartsa lenyomva a modult az áthelyezéshez."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Modul áthelyezéséhez koppintson duplán, tartsa nyomva az ujját, vagy használjon egyéni műveleteket."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index fd75fb2..6881661 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Հիմնական էկրան"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Տրոհել էկրանը"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Տեղեկություններ %1$s հավելվածի մասին"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Հպեք և պահեք՝ վիջեթ տեղափոխելու համար։"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Կրկնակի հպեք և պահեք՝ վիջեթ տեղափոխելու համար, կամ օգտվեք հատուկ գործողություններից։"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 4a6a225..beff9ea 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Layar utama"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Layar terpisah"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Info aplikasi untuk %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Sentuh lama untuk memindahkan widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ketuk dua kali &amp; tahan untuk memindahkan widget atau gunakan tindakan khusus."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index f7824dd..29b11aa 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Heim"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Skipta skjá"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Upplýsingar um forrit fyrir %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Haltu fingri á græju til að færa hana."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ýttu tvisvar og haltu fingri á græju til að færa hana eða notaðu sérsniðnar aðgerðir."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 06d86fe..519cd5c 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Home"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Schermo diviso"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Informazioni sull\'app %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Tocca e tieni premuto per spostare un widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Tocca due volte e tieni premuto per spostare un widget o per usare le azioni personalizzate."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 07f325b..ca3230c 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"בית"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"מסך מפוצל"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"‏פרטים על האפליקציה %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"להעברת ווידג\'ט למקום אחר לוחצים עליו לחיצה ארוכה."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"כדי להעביר ווידג\'ט למקום אחר או להשתמש בפעולות מותאמות אישית, יש ללחוץ פעמיים ולא להרפות."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 471b523..2948525 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"ホーム"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"分割画面"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s のアプリ情報"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"長押ししてウィジェットを移動させます。"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ウィジェットをダブルタップして長押ししながら移動するか、カスタム操作を使用してください。"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$dx%2$d"</string>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 750edce..9937836 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"მთავარი გვერდი"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"ეკრანის გაყოფა"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s-ის აპის ინფო"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"შეხებით აირჩიეთ და გეჭიროთ ვიჯეტის გადასაადგილებლად."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ორმაგი შეხებით აირჩიეთ და გეჭიროთ ვიჯეტის გადასაადგილებლად ან მორგებული მოქმედებების გამოსაყენებლად."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index f0bfaef..a1730eb 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Негізгі экран"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Экранды бөлу"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s қолданбасы туралы ақпарат"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Виджетті жылжыту үшін басып тұрыңыз."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетті жылжыту үшін екі рет түртіңіз де, ұстап тұрыңыз немесе арнаулы әрекеттерді пайдаланыңыз."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 3e87275..b993eaa 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"អេក្រង់ដើម"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"មុខងារ​បំបែកអេក្រង់"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"ព័ត៌មានកម្មវិធី​សម្រាប់ %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ចុចឱ្យជាប់​ដើម្បីផ្លាស់ទី​ធាតុក្រាហ្វិក​។"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ចុចពីរដង រួចសង្កត់ឱ្យជាប់ ដើម្បីផ្លាស់ទី​ធាតុក្រាហ្វិក ឬប្រើ​សកម្មភាព​តាមបំណង​។"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 7237e4e..06af44c 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"ಹೋಮ್"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ಗಾಗಿ ಆ್ಯಪ್ ಮಾಹಿತಿ"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ವಿಜೆಟ್ ಸರಿಸಲು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ವಿಜೆಟ್ ಸರಿಸಲು ಅಥವಾ ಕಸ್ಟಮ್ ಕ್ರಿಯೆಗಳನ್ನು ಬಳಸಲು ಡಬಲ್-ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 8fe07c4..29933e1 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"홈"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"화면 분할"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s 앱 정보"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"길게 터치하여 위젯을 이동하세요."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"두 번 탭한 다음 길게 터치하여 위젯을 이동하거나 맞춤 작업을 사용하세요."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 149c2c1..ecae23a 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Башкы экран"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Экранды бөлүү"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s колдонмосу жөнүндө маалымат"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Виджетти кое бербей басып туруп жылдырыңыз."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетти жылдыруу үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 74f4e85..7158916 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"ໂຮມສະກຣີນ"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"ແບ່ງໜ້າຈໍ"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"ຂໍ້ມູນແອັບສຳລັບ %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ແຕະຄ້າງໄວ້ເພື່ອຍ້າຍວິດເຈັດ."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ແຕະສອງເທື່ອຄ້າງໄວ້ເພື່ອຍ້າຍວິດເຈັດ ຫຼື ໃຊ້ຄຳສັ່ງກຳນົດເອງ."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index e251fd0..81164bd 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Pagrindinis"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Išskaidyto ekrano režimas"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Programos „%1$s“ informacija"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Dukart pal. ir palaik., kad perkeltumėte valdiklį."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dukart palieskite ir palaikykite, kad perkeltumėte valdiklį ar naudotumėte tinkintus veiksmus."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 89a5423..e8e25b8 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Sākums"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Sadalīt ekrānu"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s: informācija par lietotni"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Lai pārvietotu logrīku, pieskarieties un turiet."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Lai pārvietotu logrīku, uz tā veiciet dubultskārienu un turiet. Varat arī veikt pielāgotas darbības."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 9859c8e..1b95dcf 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Почетен екран"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Поделен екран"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Податоци за апликација за %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Допрете и задржете за да преместите виџет."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Допрете двапати и задржете за да преместите виџет или користете приспособени дејства."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 0af89d3..ab04493 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"ഹോം"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"സ്‌ക്രീൻ വിഭജന മോഡ്"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s എന്നതിന്റെ ആപ്പ് വിവരങ്ങൾ"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"വിജറ്റ് നീക്കാൻ സ്‌പർശിച്ച് പിടിക്കുക."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"വിജറ്റ് നീക്കാൻ ഡബിൾ ടാപ്പ് ചെയ്യൂ, ഹോൾഡ് ചെയ്യൂ അല്ലെങ്കിൽ ഇഷ്‌ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കൂ."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index f535bce..511718c 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Нүүр"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Дэлгэцийг хуваах"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s-н аппын мэдээлэл"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Виджетийг зөөх бол хүрээд, удаан дарна уу."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетийг зөөх эсвэл захиалгат үйлдлийг ашиглахын тулд хоёр товшоод, удаан дарна уу."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index ec197d2..893d041 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"होम"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"स्प्लिट स्क्रीन"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s साठी ॲपशी संबंधित माहिती"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"विजेट हलवण्यासाठी स्पर्श करा आणि धरून ठेवा."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"विजेट हलवण्यासाठी किंवा कस्टम कृती वापरण्यासाठी दोनदा टॅप करा आणि धरून ठेवा."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index bc90305..55befdd 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Rumah"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Skrin pisah"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Maklumat apl untuk %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Sentuh &amp; tahan untuk menggerakkan widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ketik dua kali &amp; tahan untuk menggerakkan widget atau menggunakan tindakan tersuai."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 102ddbc..ccdb08e 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"ပင်မစာမျက်နှာ"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"မျက်နှာပြင် ခွဲ၍ပြသခြင်း"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s အတွက် အက်ပ်အချက်အလက်"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ဝိဂျက်ကို ရွှေ့ရန် တို့ပြီး ဖိထားပါ။"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ဝိဂျက်ကို ရွှေ့ရန် (သို့) စိတ်ကြိုက်လုပ်ဆောင်ချက်များကို သုံးရန် နှစ်ချက်တို့ပြီး ဖိထားပါ။"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index c78425a..bb05261 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Startskjerm"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Delt skjerm"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Appinformasjon for %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Trykk og hold for å flytte en modul."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dobbelttrykk og hold inne for å flytte en modul eller bruke tilpassede handlinger."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index b8ddced..3547557 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"होम"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"स्प्लिट स्क्रिन"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s का हकमा एपसम्बन्धी जानकारी"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"कुनै विजेट सार्न डबल ट्याप गरेर छोइराख्नुहोस्।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"कुनै विजेट सार्न वा आफ्नो रोजाइका कारबाही प्रयोग गर्न डबल ट्याप गरेर छोइराख्नुहोस्।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-night-v31/colors.xml b/res/values-night-v31/colors.xml
index f331361..3b85b88 100644
--- a/res/values-night-v31/colors.xml
+++ b/res/values-night-v31/colors.xml
@@ -26,4 +26,6 @@
     <color name="home_settings_track_off_color">@android:color/system_neutral1_700</color>
 
     <color name="all_apps_button_color">@android:color/system_neutral2_200</color>
+
+    <color name="folder_pagination_color">@android:color/system_accent2_100</color>
 </resources>
\ No newline at end of file
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index 17fe419..ee27d99 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -18,4 +18,6 @@
 
 <resources>
     <color name="all_apps_button_color">#BFC8CC</color>
+    <color name="folder_pagination_color">#ffbfebe3</color>
+
 </resources>
\ No newline at end of file
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index f167111..f4c1017 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Startscherm"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Gesplitst scherm"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"App-info voor %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Tik en houd vast om een widget te verplaatsen."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dubbeltik en houd vast om een widget te verplaatsen of aangepaste acties te gebruiken."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index b9b69ae..52560c1 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"ହୋମ"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"ସ୍କ୍ରିନ‌କୁ ସ୍ପ୍ଲିଟ୍ କରନ୍ତୁ"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ପାଇଁ ଆପ ସୂଚନା"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ଦୁଇଥର-ଟାପ୍ କରି ଧରି ରଖନ୍ତୁ କିମ୍ବା କଷ୍ଟମ୍ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index a559c47..0f65479 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"ਮੁੱਖ ਪੰਨਾ"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ਲਈ ਐਪ ਜਾਣਕਾਰੀ"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ਕਿਸੇ ਵਿਜੇਟ ਨੂੰ ਲਿਜਾਉਣ ਲਈ ਸਪਰਸ਼ ਕਰਕੇ ਰੱਖੋ।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ਵਿਜੇਟ ਲਿਜਾਉਣ ਲਈ ਜਾਂ ਵਿਉਂਂਤੀਆਂ ਕਾਰਵਾਈਆਂ ਵਰਤਣ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰਕੇ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 19de527..d8645f0 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Ekran główny"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podziel ekran"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacje o aplikacji: %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Naciśnij i przytrzymaj, aby przenieść widżet."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Naciśnij dwukrotnie i przytrzymaj, aby przenieść widżet lub użyć działań niestandardowych."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 73caaa7..e74feac 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Página inicial"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ecrã dividido"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Informações da app para %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Toque sem soltar para mover um widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toque duas vezes sem soltar para mover um widget ou utilizar ações personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 9cffd85..4373c06 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Início"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Tela dividida"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Informações do app %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Toque e pressione para mover um widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toque duas vezes e mantenha a tela pressionada para mover um widget ou usar ações personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 983bb42..295809d 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Pagina de pornire"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ecran împărțit"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Informații despre aplicație pentru %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Atinge și ține apăsat pentru a muta un widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Atinge de două ori și ține apăsat pentru a muta un widget sau folosește acțiuni personalizate."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index b3dd441..d2dd2d6 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Главный экран"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Разделить экран"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Сведения о приложении \"%1$s\""</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Чтобы переместить виджет, нажмите на него и удерживайте"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Чтобы использовать специальные действия или перенести виджет, нажмите на него дважды и удерживайте."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index e6e067b..bde8ca8 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"මුල් පිටුව"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"බෙදුම් තිරය"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s සඳහා යෙදුම් තතු"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"විජට් එකක් ගෙන යාමට ස්පර්ශ කර අල්ලා ගෙන සිටින්න."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"විජට් එකක් ගෙන යාමට හෝ අභිරුචි ක්‍රියා භාවිත කිරීමට දෙවරක් තට්ටු කර අල්ලා ගෙන සිටින්න."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 1fdd277..3bcc7a2 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Domov"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Rozdeliť obrazovku"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Informácie o aplikácii pre %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Pridržaním presuňte miniaplikáciu."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvojitým klepnutím a pridržaním presuňte miniaplikáciu alebo použite vlastné akcie."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 345e25a..b5d3eb1 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Začetni zaslon"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Razdeljen zaslon"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Podatki o aplikaciji za: %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Pridržite pripomoček, da ga premaknete."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvakrat se dotaknite pripomočka in ga pridržite, da ga premaknete, ali pa uporabite dejanja po meri."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index b590455..02169c8 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Ekrani bazë"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ekrani i ndarë"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacioni i aplikacionit për %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Prek dhe mbaj shtypur një miniaplikacion për ta zhvendosur."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Trokit dy herë dhe mbaje shtypur një miniapliikacion për ta zhvendosur atë ose për të përdorur veprimet e personalizuara."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 7a9e50d..f924fe7 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Почетни екран"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Подељени екран"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Информације о апликацији за: %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Додирните и задржите ради померања виџета."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Двапут додирните и задржите да бисте померали виџет или користите прилагођене радње."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 5454c66..c5b4ae2 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Startskärm"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Delad skärm"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Appinformation för %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Tryck länge för att flytta en widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Tryck snabbt två gånger och håll kvar för att flytta en widget eller använda anpassade åtgärder."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index f49256e..f4621a1 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Skrini ya kwanza"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Gawa skrini"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Maelezo ya programu ya %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Gusa na ushikilie ili usogeze wijeti."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Gusa mara mbili na ushikilie ili usogeze wijeti au utumie vitendo maalum."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml
index b89910d..4d0ac38 100644
--- a/res/values-sw720dp-land/dimens.xml
+++ b/res/values-sw720dp-land/dimens.xml
@@ -31,7 +31,7 @@
 
 <!-- Widget picker-->
     <dimen name="widget_list_horizontal_margin">49dp</dimen>
-    <dimen name="widget_list_horizontal_margin_large_screen">24dp</dimen>
+    <dimen name="widget_list_horizontal_margin_two_pane">24dp</dimen>
 
 <!-- Bottom sheet-->
     <dimen name="bottom_sheet_extra_top_padding">0dp</dimen>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index b22ee7c..56b9a8c 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"முகப்பு"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"திரைப் பிரிப்பு"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$sக்கான ஆப்ஸ் தகவல்கள்"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"விட்ஜெட்டை நகர்த்தத் தொட்டுப் பிடிக்கவும்."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"விட்ஜெட்டை நகர்த்த இருமுறை தட்டிப் பிடிக்கவும் அல்லது பிரத்தியேகச் செயல்களைப் பயன்படுத்தவும்."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 274310e..16b5f5a 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"మొదటి ట్యాబ్"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"స్క్రీన్‌ను విభజించు"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s కోసం యాప్ సమాచారం"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"విడ్జెట్‌ను తరలించడానికి తాకి &amp; నొక్కి ఉంచండి."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"విడ్జెట్‌ను తరలించడానికి లేదా అనుకూల చర్యలను ఉపయోగించడానికి రెండుసార్లు నొక్కండి &amp; హోల్డ్ చేయి."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 619fee0..45c3914 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"หน้าแรก"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"แบ่งหน้าจอ"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"ข้อมูลแอปสำหรับ %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"แตะค้างไว้เพื่อย้ายวิดเจ็ต"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"แตะสองครั้งค้างไว้เพื่อย้ายวิดเจ็ตหรือใช้การดำเนินการที่กำหนดเอง"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index c15b6e5..2d43182 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Home"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Impormasyon ng app para sa %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Pindutin nang matagal para ilipat ang widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"I-double tap at pindutin nang matagal para ilipat ang widget o gumamit ng mga custom na pagkilos."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 01aa4aa..b886cf2 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Ana ekran"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Bölünmüş ekran"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s uygulama bilgileri"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Widget\'ı taşımak için dokunup basılı tutun."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Widget\'ı taşımak veya özel işlemleri kullanmak için iki kez dokunup basılı tutun."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 8288aa4..5758c75 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Головний екран"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Розділити екран"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Інформація про додаток для %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Натисніть і втримуйте, щоб перемістити віджет."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Двічі натисніть і втримуйте віджет, щоб перемістити його або виконати інші дії."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 4e09d54..5a5dcc5 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"ہوم"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"اسپلٹ اسکرین"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"‏%1$s کے لیے ایپ کی معلومات"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ویجیٹ منتقل کرنے کے لیے ٹچ کریں اور پکڑ کر رکھیں۔"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ویجیٹ کو منتقل کرنے یا حسب ضرورت کارروائیاں استعمال کرنے کے لیے دوبار تھپتھپائیں اور پکڑ کر رکھیں۔"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 5df3238..5595179 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Bosh ekran"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ekranni ikkiga ajratish"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ilovasi axboroti"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Vidjetni bosib turgan holatda suring."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ikki marta bosib va bosib turgan holatda vidjetni tanlang yoki maxsus amaldan foydalaning."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -106,7 +108,7 @@
     <string name="allow_rotation_desc" msgid="8662546029078692509">"Telefon burilganda"</string>
     <string name="notification_dots_title" msgid="9062440428204120317">"Bildirishnoma belgilari"</string>
     <string name="notification_dots_desc_on" msgid="1679848116452218908">"Yoniq"</string>
-    <string name="notification_dots_desc_off" msgid="1760796511504341095">"Yoqilmagan"</string>
+    <string name="notification_dots_desc_off" msgid="1760796511504341095">"Oʻchiq"</string>
     <string name="title_missing_notification_access" msgid="7503287056163941064">"Bildirishnomalarga ruxsat berilmagan"</string>
     <string name="msg_missing_notification_access" msgid="281113995110910548">"Bildirishnoma belgilarini ko‘rsatish uchun <xliff:g id="NAME">%1$s</xliff:g> ilovasida bildirishnomalarni yoqing"</string>
     <string name="title_change_settings" msgid="1376365968844349552">"Sozlamalarni o‘zgartirish"</string>
diff --git a/res/values-v31/colors.xml b/res/values-v31/colors.xml
index 054fe47..0c87ff4 100644
--- a/res/values-v31/colors.xml
+++ b/res/values-v31/colors.xml
@@ -41,8 +41,7 @@
     <color name="wallpaper_popup_scrim">@android:color/system_neutral1_900</color>
 
     <color name="folder_dot_color">@android:color/system_accent3_100</color>
-    <color name="folder_pagination_color_light">@android:color/system_accent1_600</color>
-    <color name="folder_pagination_color_dark">@android:color/system_accent2_100</color>
+    <color name="folder_pagination_color">@android:color/system_accent1_600</color>
 
     <color name="home_settings_header_accent">@android:color/system_accent1_600</color>
     <color name="home_settings_header_collapsed">@android:color/system_neutral1_100</color>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 43bdf04..32ea78e 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Màn hình chính"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Chia đôi màn hình"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Thông tin ứng dụng cho %1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Chạm và giữ để di chuyển một tiện ích."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Nhấn đúp và giữ để di chuyển một tiện ích hoặc sử dụng các thao tác tùy chỉnh."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 3e66cb9..2c06691 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"主屏幕"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"分屏"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s 的应用信息"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"轻触并按住即可移动微件。"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"点按两次并按住微件即可移动该微件或使用自定义操作。"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index fac5dc3..d7954de 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"主畫面"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"分割螢幕"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s 的應用程式資料"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"輕觸並按住即可移動小工具。"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"㩒兩下之後㩒住,就可以郁小工具或者用自訂操作。"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 8b96553..30d7860 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"主畫面"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"分割畫面"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"「%1$s」的應用程式資訊"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"按住即可移動小工具。"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"輕觸兩下並按住即可移動小工具或使用自訂操作。"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 97fffd5..ba195b2 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -29,6 +29,8 @@
     <string name="home_screen" msgid="5629429142036709174">"Ikhaya"</string>
     <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Hlukanisa isikrini"</string>
     <string name="split_app_info_accessibility" msgid="5475288491241414932">"Ulwazi lwe-App ye-%1$s"</string>
+    <!-- no translation found for save_app_pair (5647523853662686243) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Thinta uphinde ubambe ukuze uhambise iwijethi."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Thepha kabili uphinde ubambe ukuze uhambise iwijethi noma usebenzise izindlela ezingokwezifiso."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 682153f..82bab56 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -42,7 +42,6 @@
     <attr name="popupNotificationDotColor" format="color" />
 
     <attr name="folderDotColor" format="color" />
-    <attr name="folderPaginationColor" format="color" />
     <attr name="folderPreviewColor" format="color" />
     <attr name="folderBackgroundColor" format="color" />
     <attr name="folderIconRadius" format="float" />
@@ -405,6 +404,16 @@
         <!-- defaults to iconTextSize, if not specified -->
         <attr name="iconTextSizeTwoPanelLandscape" format="float" />
 
+        <!-- If true, used to layout taskbar in 3 button navigation mode. -->
+        <!-- defaults to false if not specified -->
+        <attr name="startAlignTaskbar" format="boolean" />
+        <!-- defaults to startAlignTaskbar, if not specified -->
+        <attr name="startAlignTaskbarLandscape" format="boolean" />
+        <!-- defaults to startAlignTaskbarLandscape, if not specified -->
+        <attr name="startAlignTaskbarTwoPanelLandscape" format="boolean" />
+        <!-- defaults to startAlignTaskbar, if not specified -->
+        <attr name="startAlignTaskbarTwoPanelPortrait" format="boolean" />
+
         <!-- If set, this display option is used to determine the default grid -->
         <attr name="canBeDefault" format="boolean" />
 
@@ -491,4 +500,10 @@
         <!-- The icon drawable of a widget category. -->
         <attr name="sectionDrawable" format="reference" />
     </declare-styleable>
+
+    <!-- Attributes for PagedIndicator -->
+    <declare-styleable name="PagedIndicator">
+        <!-- Color used to draw dots -->
+        <attr name="indicatorDotColor" format="color" />
+    </declare-styleable>
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 8788557..1ef918d 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -67,8 +67,7 @@
     <color name="folder_preview_dark">#464746</color>
 
     <color name="folder_dot_color">?attr/colorPrimary</color>
-    <color name="folder_pagination_color_light">#ff006c5f</color>
-    <color name="folder_pagination_color_dark">#ffbfebe3</color>
+    <color name="folder_pagination_color">#ff006c5f</color>
 
     <color name="text_color_primary_dark">#FFFFFFFF</color>
     <color name="text_color_secondary_dark">#FFFFFFFF</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 68e668f..923883b 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -193,7 +193,7 @@
     <dimen name="widget_list_header_view_vertical_padding">20dp</dimen>
     <dimen name="widget_list_entry_spacing">2dp</dimen>
     <dimen name="widget_list_horizontal_margin">16dp</dimen>
-    <dimen name="widget_list_horizontal_margin_large_screen">24dp</dimen>
+    <dimen name="widget_list_horizontal_margin_two_pane">24dp</dimen>
 
     <dimen name="widget_preview_shadow_blur">0.5dp</dimen>
     <dimen name="widget_preview_key_shadow_distance">1dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f2fb8f5..7552b22 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -42,6 +42,9 @@
     <string name="recent_task_option_split_screen">Split screen</string>
     <string name="split_app_info_accessibility">App info for %1$s</string>
 
+    <!-- App pairs -->
+    <string name="save_app_pair">Save app pair</string>
+
     <!-- Widgets -->
     <!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] -->
     <string name="long_press_widget_to_add">Touch &amp; hold to move a widget.</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 5dc4f0a..517bb87 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -50,7 +50,6 @@
         <item name="workspaceStatusBarScrim">@drawable/workspace_bg</item>
         <item name="widgetsTheme">@style/WidgetContainerTheme</item>
         <item name="folderDotColor">@color/folder_dot_color</item>
-        <item name="folderPaginationColor">@color/folder_pagination_color_light</item>
         <item name="folderPreviewColor">@color/folder_preview_light</item>
         <item name="folderBackgroundColor">@color/folder_background_light</item>
         <item name="folderIconBorderColor">?android:attr/colorPrimary</item>
@@ -104,7 +103,6 @@
         <item name="popupShadeThird">@color/popup_shade_third_dark</item>
         <item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item>
         <item name="folderDotColor">@color/folder_dot_color</item>
-        <item name="folderPaginationColor">@color/folder_pagination_color_dark</item>
         <item name="folderPreviewColor">@color/folder_preview_dark</item>
         <item name="folderBackgroundColor">@color/folder_background_dark</item>
         <item name="folderIconBorderColor">?android:attr/colorPrimary</item>
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index 27c41c2..2083726 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -24,30 +24,29 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.LauncherActivityInfo;
+import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.database.sqlite.SQLiteDatabase;
-import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Process;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.Patterns;
 import android.util.Xml;
 
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.LauncherProvider.SqlArguments;
 import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.icons.GraphicsUtils;
-import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.qsb.QsbContainerView;
+import com.android.launcher3.shortcuts.ShortcutKey;
 import com.android.launcher3.uioverrides.ApiWrapper;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.Partner;
@@ -58,6 +57,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.util.Collections;
 import java.util.Locale;
 import java.util.Map;
 import java.util.function.Supplier;
@@ -135,6 +135,7 @@
     private static final String ATTR_TITLE = "title";
     private static final String ATTR_TITLE_TEXT = "titleText";
     private static final String ATTR_SCREEN = "screen";
+    private static final String ATTR_SHORTCUT_ID = "shortcutId";
 
     // x and y can be specified as negative integers, in which case -1 represents the
     // last row / column, -2 represents the second last, and so on.
@@ -143,8 +144,6 @@
 
     private static final String ATTR_SPAN_X = "spanX";
     private static final String ATTR_SPAN_Y = "spanY";
-    private static final String ATTR_ICON = "icon";
-    private static final String ATTR_URL = "url";
 
     // Attrs for "Include"
     private static final String ATTR_WORKSPACE = "workspace";
@@ -156,10 +155,8 @@
     private static final String HOTSEAT_CONTAINER_NAME =
             Favorites.containerToString(Favorites.CONTAINER_HOTSEAT);
 
-    @Thunk
-    final Context mContext;
-    @Thunk
-    final LauncherWidgetHolder mAppWidgetHolder;
+    protected final Context mContext;
+    protected final LauncherWidgetHolder mAppWidgetHolder;
     protected final LayoutParserCallback mCallback;
 
     protected final PackageManager mPackageManager;
@@ -308,7 +305,15 @@
         mValues.put(Favorites.SPANY, 1);
         mValues.put(Favorites._ID, id);
 
-        maybeReplaceShortcut(intent.getComponent().getPackageName(), type);
+        if (type == ITEM_TYPE_APPLICATION) {
+            ComponentName cn = intent.getComponent();
+            if (cn != null && mActivityOverride.containsKey(cn.getPackageName())) {
+                LauncherActivityInfo replacementInfo = mActivityOverride.get(cn.getPackageName());
+                mValues.put(Favorites.PROFILE_ID, UserCache.INSTANCE.get(mContext)
+                        .getSerialNumberForUser(replacementInfo.getUser()));
+                mValues.put(Favorites.INTENT, AppInfo.makeLaunchIntent(replacementInfo).toUri(0));
+            }
+        }
 
         if (mCallback.insertAndCheck(mDb, mValues) < 0) {
             return -1;
@@ -321,7 +326,7 @@
         ArrayMap<String, TagParser> parsers = new ArrayMap<>();
         parsers.put(TAG_APP_ICON, new AppShortcutParser());
         parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser());
-        parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes));
+        parsers.put(TAG_SHORTCUT, new ShortcutParser());
         return parsers;
     }
 
@@ -332,7 +337,7 @@
         parsers.put(TAG_FOLDER, new FolderParser());
         parsers.put(TAG_APPWIDGET, new PendingWidgetParser());
         parsers.put(TAG_SEARCH_WIDGET, new SearchWidgetParser());
-        parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes));
+        parsers.put(TAG_SHORTCUT, new ShortcutParser());
         return parsers;
     }
 
@@ -420,59 +425,27 @@
     }
 
     /**
-     * Parses a web shortcut. Required attributes url, icon, title
+     * Parses a deep shortcut. Required attributes packageName and shortcutId
      */
     protected class ShortcutParser implements TagParser {
 
-        private final Resources mIconRes;
-
-        public ShortcutParser(Resources iconRes) {
-            mIconRes = iconRes;
-        }
-
         @Override
         public int parseAndAdd(XmlPullParser parser) {
-            final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
-            final int iconId = getAttributeResourceValue(parser, ATTR_ICON, 0);
+            final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
+            final String shortcutId = getAttributeValue(parser, ATTR_SHORTCUT_ID);
 
-            if (titleResId == 0 || iconId == 0) {
-                if (LOGD) Log.d(TAG, "Ignoring shortcut");
-                return -1;
+            try {
+                LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
+                launcherApps.pinShortcuts(packageName, Collections.singletonList(shortcutId),
+                        Process.myUserHandle());
+                Intent intent = ShortcutKey.makeIntent(shortcutId, packageName);
+                mValues.put(Favorites.RESTORED, WorkspaceItemInfo.FLAG_RESTORED_ICON);
+                return addShortcut(null, intent, Favorites.ITEM_TYPE_DEEP_SHORTCUT);
+            } catch (Exception e) {
+                Log.e(TAG, "Unable to pin the shortcut for shortcut id = " + shortcutId
+                        + " and package name = " + packageName, e);
             }
-
-            final Intent intent = parseIntent(parser);
-            if (intent == null) {
-                return -1;
-            }
-
-            Drawable icon = mIconRes.getDrawable(iconId);
-            if (icon == null) {
-                if (LOGD) Log.d(TAG, "Ignoring shortcut, can't load icon");
-                return -1;
-            }
-
-            // Auto installs should always support the current platform version.
-            LauncherIcons li = LauncherIcons.obtain(mContext);
-            mValues.put(LauncherSettings.Favorites.ICON, GraphicsUtils.flattenBitmap(
-                    li.createBadgedIconBitmap(icon).icon));
-            li.recycle();
-
-            mValues.put(Favorites.ICON_PACKAGE, mIconRes.getResourcePackageName(iconId));
-            mValues.put(Favorites.ICON_RESOURCE, mIconRes.getResourceName(iconId));
-
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                    Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-            return addShortcut(mSourceRes.getString(titleResId),
-                    intent, Favorites.ITEM_TYPE_SHORTCUT);
-        }
-
-        protected Intent parseIntent(XmlPullParser parser) {
-            final String url = getAttributeValue(parser, ATTR_URL);
-            if (TextUtils.isEmpty(url) || !Patterns.WEB_URL.matcher(url).matches()) {
-                if (LOGD) Log.d(TAG, "Ignoring shortcut, invalid url: " + url);
-                return null;
-            }
-            return new Intent(Intent.ACTION_VIEW, null).setData(Uri.parse(url));
+            return -1;
         }
     }
 
@@ -728,12 +701,4 @@
         to.put(key, from.getAsInteger(key));
     }
 
-    private void maybeReplaceShortcut(String packageName, int type) {
-        if (mActivityOverride.containsKey(packageName) && type == ITEM_TYPE_APPLICATION) {
-            LauncherActivityInfo replacementInfo = mActivityOverride.get(packageName);
-            mValues.put(Favorites.PROFILE_ID, UserCache.INSTANCE.get(mContext)
-                    .getSerialNumberForUser(replacementInfo.getUser()));
-            mValues.put(Favorites.INTENT, AppInfo.makeLaunchIntent(replacementInfo).toUri(0));
-        }
-    }
 }
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 53d9281..961c254 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -872,7 +872,9 @@
             if (mIcon instanceof PreloadIconDrawable) {
                 preloadIconDrawable = (PreloadIconDrawable) mIcon;
                 preloadIconDrawable.setLevel(progressLevel);
-                preloadIconDrawable.setIsDisabled(!info.isAppStartable());
+                preloadIconDrawable.setIsDisabled(ENABLE_DOWNLOAD_APP_UX_V2.get()
+                        ? info.getProgressLevel() == 0
+                        : !info.isAppStartable());
             } else {
                 preloadIconDrawable = makePreloadIcon();
                 setIcon(preloadIconDrawable);
@@ -897,8 +899,9 @@
         final PreloadIconDrawable preloadDrawable = newPendingIcon(getContext(), info);
 
         preloadDrawable.setLevel(progressLevel);
-        preloadDrawable.setIsDisabled(!info.isAppStartable());
-
+        preloadDrawable.setIsDisabled(ENABLE_DOWNLOAD_APP_UX_V2.get()
+                ? info.getProgressLevel() == 0
+                : !info.isAppStartable());
         return preloadDrawable;
     }
 
diff --git a/src/com/android/launcher3/DefaultLayoutParser.java b/src/com/android/launcher3/DefaultLayoutParser.java
index c69ae4d..c748693 100644
--- a/src/com/android/launcher3/DefaultLayoutParser.java
+++ b/src/com/android/launcher3/DefaultLayoutParser.java
@@ -6,19 +6,15 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.os.Bundle;
-import android.os.Process;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
 
 import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.shortcuts.ShortcutKey;
 import com.android.launcher3.util.Partner;
 import com.android.launcher3.util.Thunk;
 import com.android.launcher3.widget.LauncherWidgetHolder;
@@ -28,7 +24,6 @@
 
 import java.io.IOException;
 import java.net.URISyntaxException;
-import java.util.Collections;
 import java.util.List;
 
 /**
@@ -49,8 +44,6 @@
     private static final String ATTR_CONTAINER = "container";
     private static final String ATTR_SCREEN = "screen";
     private static final String ATTR_FOLDER_ITEMS = "folderItems";
-    private static final String ATTR_SHORTCUT_ID = "shortcutId";
-    private static final String ATTR_PACKAGE_NAME = "packageName";
 
     public static final String RES_PARTNER_FOLDER = "partner_folder";
     public static final String RES_PARTNER_DEFAULT_LAYOUT = "partner_default_layout";
@@ -66,14 +59,9 @@
 
     @Override
     protected ArrayMap<String, TagParser> getFolderElementsMap() {
-        return getFolderElementsMap(mSourceRes);
-    }
-
-    @Thunk
-    ArrayMap<String, TagParser> getFolderElementsMap(Resources res) {
         ArrayMap<String, TagParser> parsers = new ArrayMap<>();
         parsers.put(TAG_FAVORITE, new AppShortcutWithUriParser());
-        parsers.put(TAG_SHORTCUT, new UriShortcutParser(res));
+        parsers.put(TAG_SHORTCUT, new ShortcutParser());
         return parsers;
     }
 
@@ -83,7 +71,7 @@
         parsers.put(TAG_FAVORITE, new AppShortcutWithUriParser());
         parsers.put(TAG_APPWIDGET, new AppWidgetParser());
         parsers.put(TAG_SEARCH_WIDGET, new SearchWidgetParser());
-        parsers.put(TAG_SHORTCUT, new UriShortcutParser(mSourceRes));
+        parsers.put(TAG_SHORTCUT, new ShortcutParser());
         parsers.put(TAG_RESOLVE, new ResolveParser());
         parsers.put(TAG_FOLDER, new MyFolderParser());
         parsers.put(TAG_PARTNER_FOLDER, new PartnerFolderParser());
@@ -190,57 +178,6 @@
     }
 
     /**
-     * Shortcut parser which allows any uri and not just web urls.
-     */
-    public class UriShortcutParser extends ShortcutParser {
-
-        public UriShortcutParser(Resources iconRes) {
-            super(iconRes);
-        }
-
-        @Override
-        public int parseAndAdd(XmlPullParser parser) {
-            final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
-            final String shortcutId = getAttributeValue(parser, ATTR_SHORTCUT_ID);
-            if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(shortcutId)) {
-                return parseAndAddDeepShortcut(shortcutId, packageName);
-            }
-            return super.parseAndAdd(parser);
-        }
-
-        /**
-         * This method parses and adds a deep shortcut.
-         * @return item id if the shortcut is successfully added else -1
-         */
-        private int parseAndAddDeepShortcut(String shortcutId, String packageName) {
-            try {
-                LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
-                launcherApps.pinShortcuts(packageName, Collections.singletonList(shortcutId),
-                        Process.myUserHandle());
-                Intent intent = ShortcutKey.makeIntent(shortcutId, packageName);
-                mValues.put(Favorites.RESTORED, WorkspaceItemInfo.FLAG_RESTORED_ICON);
-                return addShortcut(null, intent, Favorites.ITEM_TYPE_DEEP_SHORTCUT);
-            } catch (Exception e) {
-                Log.e(TAG, "Unable to pin the shortcut for shortcut id = " + shortcutId
-                        + " and package name = " + packageName);
-            }
-            return -1;
-        }
-
-        @Override
-        protected Intent parseIntent(XmlPullParser parser) {
-            String uri = null;
-            try {
-                uri = getAttributeValue(parser, ATTR_URI);
-                return Intent.parseUri(uri, 0);
-            } catch (URISyntaxException e) {
-                Log.w(TAG, "Shortcut has malformed uri: " + uri);
-                return null; // Oh well
-            }
-        }
-    }
-
-    /**
      * Contains a list of <favorite> nodes, and accepts the first successfully parsed node.
      */
     public class ResolveParser implements TagParser {
@@ -284,11 +221,9 @@
             if (partner != null) {
                 final int resId = partner.getXmlResId(RES_PARTNER_FOLDER);
                 if (resId != 0) {
-                    final Resources partnerRes = partner.getResources();
-                    final XmlPullParser partnerParser = partnerRes.getXml(resId);
+                    final XmlPullParser partnerParser = partner.getResources().getXml(resId);
                     beginDocument(partnerParser, TAG_FOLDER);
-
-                    FolderParser folderParser = new FolderParser(getFolderElementsMap(partnerRes));
+                    FolderParser folderParser = new FolderParser(getFolderElementsMap());
                     return folderParser.parseAndAdd(partnerParser);
                 }
             }
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index fcb220e..86c9f16 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -267,6 +267,8 @@
     public final int stashedTaskbarHeight;
     public final int taskbarBottomMargin;
     public final int taskbarIconSize;
+    // If true, used to layout taskbar in 3 button navigation mode.
+    public final boolean startAlignTaskbar;
 
     // DragController
     public int flingToDeleteThresholdVelocity;
@@ -338,12 +340,14 @@
                     res.getDimensionPixelSize(R.dimen.transient_taskbar_stashed_height);
             taskbarBottomMargin =
                     res.getDimensionPixelSize(R.dimen.transient_taskbar_bottom_margin);
+            startAlignTaskbar = false;
         } else {
             taskbarIconSize = pxFromDp(ResourcesCompat.getFloat(res, R.dimen.taskbar_icon_size),
                     mMetrics);
             taskbarHeight = res.getDimensionPixelSize(R.dimen.taskbar_size);
             stashedTaskbarHeight = res.getDimensionPixelSize(R.dimen.taskbar_stashed_size);
             taskbarBottomMargin = 0;
+            startAlignTaskbar = inv.startAlignTaskbar[mTypeIndex];
         }
 
         edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 0c19e4b..4c34648 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -41,7 +41,6 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.SparseArray;
-import android.util.TypedValue;
 import android.util.Xml;
 import android.view.Display;
 
@@ -58,11 +57,9 @@
 import com.android.launcher3.testing.shared.ResourceUtils;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.DisplayController.Info;
-import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.LockedUserState;
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.Partner;
-import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.WindowBounds;
 import com.android.launcher3.util.window.WindowManagerProxy;
 
@@ -76,6 +73,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 
 public class InvariantDeviceProfile {
 
@@ -151,7 +149,7 @@
 
     public float[] transientTaskbarIconSize;
 
-    private SparseArray<TypedValue> mExtraAttrs;
+    public boolean[] startAlignTaskbar;
 
     /**
      * Number of icons inside the hotseat area.
@@ -360,8 +358,6 @@
 
         inlineNavButtonsEndSpacing = closestProfile.inlineNavButtonsEndSpacing;
 
-        mExtraAttrs = closestProfile.extraAttrs;
-
         iconSize = displayOption.iconSizes;
         float maxIconSize = iconSize[0];
         for (int i = 1; i < iconSize.length; i++) {
@@ -400,6 +396,8 @@
 
         transientTaskbarIconSize = displayOption.transientTaskbarIconSize;
 
+        startAlignTaskbar = displayOption.startAlignTaskbar;
+
         // If the partner customization apk contains any grid overrides, apply them
         // Supported overrides: numRows, numColumns, iconSize
         applyPartnerDeviceProfileOverrides(context, metrics);
@@ -495,9 +493,8 @@
                 if ((type == XmlPullParser.START_TAG)
                         && GridOption.TAG_NAME.equals(parser.getName())) {
 
-                    GridOption gridOption = new GridOption(context, Xml.asAttributeSet(parser),
-                            deviceType);
-                    if (gridOption.isEnabled || allowDisabledGrid) {
+                    GridOption gridOption = new GridOption(context, Xml.asAttributeSet(parser));
+                    if (gridOption.isEnabled(deviceType) || allowDisabledGrid) {
                         final int displayDepth = parser.getDepth();
                         while (((type = parser.next()) != XmlPullParser.END_TAG
                                 || parser.getDepth() > displayDepth)
@@ -519,7 +516,7 @@
         if (!TextUtils.isEmpty(gridName)) {
             for (DisplayOption option : profiles) {
                 if (gridName.equals(option.grid.name)
-                        && (option.grid.isEnabled || allowDisabledGrid)) {
+                        && (option.grid.isEnabled(deviceType) || allowDisabledGrid)) {
                     filteredProfiles.add(option);
                 }
             }
@@ -542,6 +539,16 @@
      * @return all the grid options that can be shown on the device
      */
     public List<GridOption> parseAllGridOptions(Context context) {
+        return parseAllDefinedGridOptions(context)
+                .stream()
+                .filter(go -> go.isEnabled(deviceType))
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * @return all the grid options that can be shown on the device
+     */
+    public static List<GridOption> parseAllDefinedGridOptions(Context context) {
         List<GridOption> result = new ArrayList<>();
 
         try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
@@ -551,11 +558,7 @@
                     || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
                 if ((type == XmlPullParser.START_TAG)
                         && GridOption.TAG_NAME.equals(parser.getName())) {
-                    GridOption option =
-                            new GridOption(context, Xml.asAttributeSet(parser), deviceType);
-                    if (option.isEnabled) {
-                        result.add(option);
-                    }
+                    result.add(new GridOption(context, Xml.asAttributeSet(parser)));
                 }
             }
         } catch (IOException | XmlPullParserException e) {
@@ -774,7 +777,7 @@
         public final int numRows;
         public final int numColumns;
         public final int numSearchContainerColumns;
-        public final boolean isEnabled;
+        public final int deviceCategory;
 
         private final int numFolderRows;
         private final int numFolderColumns;
@@ -800,9 +803,7 @@
         private final boolean isScalable;
         private final int devicePaddingId;
 
-        private final SparseArray<TypedValue> extraAttrs;
-
-        public GridOption(Context context, AttributeSet attrs, @DeviceType int deviceType) {
+        public GridOption(Context context, AttributeSet attrs) {
             TypedArray a = context.obtainStyledAttributes(
                     attrs, R.styleable.GridDisplayOption);
             name = a.getString(R.styleable.GridDisplayOption_name);
@@ -859,16 +860,8 @@
                     R.styleable.GridDisplayOption_isScalable, false);
             devicePaddingId = a.getResourceId(
                     R.styleable.GridDisplayOption_devicePaddingId, INVALID_RESOURCE_HANDLE);
-
-            int deviceCategory = a.getInt(R.styleable.GridDisplayOption_deviceCategory,
+            deviceCategory = a.getInt(R.styleable.GridDisplayOption_deviceCategory,
                     DEVICE_CATEGORY_ALL);
-            isEnabled = (deviceType == TYPE_PHONE
-                        && ((deviceCategory & DEVICE_CATEGORY_PHONE) == DEVICE_CATEGORY_PHONE))
-                    || (deviceType == TYPE_TABLET
-                        && ((deviceCategory & DEVICE_CATEGORY_TABLET) == DEVICE_CATEGORY_TABLET))
-                    || (deviceType == TYPE_MULTI_DISPLAY
-                        && ((deviceCategory & DEVICE_CATEGORY_MULTI_DISPLAY)
-                            == DEVICE_CATEGORY_MULTI_DISPLAY));
 
             int inlineForRotation = a.getInt(R.styleable.GridDisplayOption_inlineQsb,
                     DONT_INLINE_QSB);
@@ -884,8 +877,20 @@
                             == INLINE_QSB_FOR_TWO_PANEL_LANDSCAPE;
 
             a.recycle();
-            extraAttrs = Themes.createValueMap(context, attrs,
-                    IntArray.wrap(R.styleable.GridDisplayOption));
+        }
+
+        public boolean isEnabled(@DeviceType int deviceType) {
+            switch (deviceType) {
+                case TYPE_PHONE:
+                    return (deviceCategory & DEVICE_CATEGORY_PHONE) == DEVICE_CATEGORY_PHONE;
+                case TYPE_TABLET:
+                    return (deviceCategory & DEVICE_CATEGORY_TABLET) == DEVICE_CATEGORY_TABLET;
+                case TYPE_MULTI_DISPLAY:
+                    return (deviceCategory & DEVICE_CATEGORY_MULTI_DISPLAY)
+                            == DEVICE_CATEGORY_MULTI_DISPLAY;
+                default:
+                    return false;
+            }
         }
     }
 
@@ -914,6 +919,8 @@
 
         private final float[] transientTaskbarIconSize = new float[COUNT_SIZES];
 
+        private final boolean[] startAlignTaskbar = new boolean[COUNT_SIZES];
+
         DisplayOption(GridOption grid, Context context, AttributeSet attrs) {
             this.grid = grid;
 
@@ -1146,6 +1153,18 @@
                     R.styleable.ProfileDisplayOption_transientTaskbarIconSizeTwoPanelPortrait,
                     transientTaskbarIconSize[INDEX_DEFAULT]);
 
+            startAlignTaskbar[INDEX_DEFAULT] = a.getBoolean(
+                    R.styleable.ProfileDisplayOption_startAlignTaskbar, false);
+            startAlignTaskbar[INDEX_LANDSCAPE] = a.getBoolean(
+                    R.styleable.ProfileDisplayOption_startAlignTaskbarLandscape,
+                    startAlignTaskbar[INDEX_DEFAULT]);
+            startAlignTaskbar[INDEX_TWO_PANEL_LANDSCAPE] = a.getBoolean(
+                    R.styleable.ProfileDisplayOption_startAlignTaskbarTwoPanelLandscape,
+                    startAlignTaskbar[INDEX_LANDSCAPE]);
+            startAlignTaskbar[INDEX_TWO_PANEL_PORTRAIT] = a.getBoolean(
+                    R.styleable.ProfileDisplayOption_startAlignTaskbarTwoPanelPortrait,
+                    startAlignTaskbar[INDEX_DEFAULT]);
+
             a.recycle();
         }
 
@@ -1168,6 +1187,7 @@
                 allAppsIconTextSizes[i] = 0;
                 allAppsBorderSpaces[i] = new PointF();
                 transientTaskbarIconSize[i] = 0;
+                startAlignTaskbar[i] = false;
             }
         }
 
@@ -1212,6 +1232,7 @@
                 allAppsBorderSpaces[i].x += p.allAppsBorderSpaces[i].x;
                 allAppsBorderSpaces[i].y += p.allAppsBorderSpaces[i].y;
                 transientTaskbarIconSize[i] += p.transientTaskbarIconSize[i];
+                startAlignTaskbar[i] |= p.startAlignTaskbar[i];
             }
 
             return this;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 2e382c8..8fcc08d 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -85,7 +85,6 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.database.sqlite.SQLiteDatabase;
-import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.Build;
@@ -289,6 +288,9 @@
     // Type PendingSplitSelectInfo<Parcelable>
     protected static final String PENDING_SPLIT_SELECT_INFO = "launcher.pending_split_select_info";
 
+    public static final String INTENT_ACTION_ALL_APPS_TOGGLE =
+            "launcher.intent_action_all_apps_toggle";
+
     public static final String ON_CREATE_EVT = "Launcher.onCreate";
     public static final String ON_START_EVT = "Launcher.onStart";
     public static final String ON_RESUME_EVT = "Launcher.onResume";
@@ -1353,10 +1355,6 @@
 
         if (SHOW_DOT_PAGINATION.get()) {
             mWorkspace.getPageIndicator().setShouldAutoHide(true);
-            mWorkspace.getPageIndicator().setPaintColor(
-                    Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)
-                            ? Color.BLACK
-                            : Color.WHITE);
         }
     }
 
@@ -1692,6 +1690,8 @@
             handleGestureContract(intent);
         } else if (Intent.ACTION_ALL_APPS.equals(intent.getAction())) {
             showAllAppsFromIntent(alreadyOnHome);
+        } else if (INTENT_ACTION_ALL_APPS_TOGGLE.equals(intent.getAction())) {
+            toggleAllAppsFromIntent(alreadyOnHome);
         } else if (Intent.ACTION_SHOW_WORK_APPS.equals(intent.getAction())) {
             showAllAppsWorkTabFromIntent(alreadyOnHome);
         }
@@ -1699,6 +1699,14 @@
         TraceHelper.INSTANCE.endSection(traceToken);
     }
 
+    protected void toggleAllAppsFromIntent(boolean alreadyOnHome) {
+        if (getStateManager().isInStableState(ALL_APPS)) {
+            getStateManager().goToState(NORMAL, alreadyOnHome);
+        } else {
+            showAllAppsFromIntent(alreadyOnHome);
+        }
+    }
+
     protected void showAllAppsFromIntent(boolean alreadyOnHome) {
         AbstractFloatingView.closeAllOpenViews(this);
         getStateManager().goToState(ALL_APPS, alreadyOnHome);
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 62e7ef3..26ad4b5 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -153,8 +153,8 @@
         Interpolator workspaceFadeInterpolator = config.getInterpolator(ANIM_WORKSPACE_FADE,
                 pageAlphaProvider.interpolator);
         float workspacePageIndicatorAlpha = (elements & WORKSPACE_PAGE_INDICATOR) != 0 ? 1 : 0;
-        propertySetter.setViewAlpha(mLauncher.getWorkspace().getPageIndicator(),
-                workspacePageIndicatorAlpha, workspaceFadeInterpolator);
+        mLauncher.getWorkspace().getPageIndicator().setAlpha(
+                propertySetter, workspacePageIndicatorAlpha, workspaceFadeInterpolator);
         Interpolator hotseatFadeInterpolator = config.getInterpolator(ANIM_HOTSEAT_FADE,
                 workspaceFadeInterpolator);
         float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index c3ac53e..b485780 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -184,7 +184,7 @@
                 this, mActivityContext.getStatsLogManager());
         mAH = Arrays.asList(null, null, null);
         mNavBarScrimPaint = new Paint();
-        mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
+        mNavBarScrimPaint.setColor(Themes.getNavBarScrimColor(mActivityContext));
 
         AllAppsStore.OnUpdateListener onAppsUpdated = this::onAppsUpdated;
         if (TestProtocol.sDebugTracing) {
@@ -192,7 +192,6 @@
                     onAppsUpdated);
         }
         mAllAppsStore.addUpdateListener(onAppsUpdated);
-        mActivityContext.addOnDeviceProfileChangeListener(this);
 
         // This is a focus listener that proxies focus from a view into the list view.  This is to
         // work around the search box from getting first focus and showing the cursor.
@@ -263,6 +262,18 @@
         mSearchUiManager.initializeSearch(this);
     }
 
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mActivityContext.addOnDeviceProfileChangeListener(this);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mActivityContext.removeOnDeviceProfileChangeListener(this);
+    }
+
     public SearchUiManager getSearchUiManager() {
         return mSearchUiManager;
     }
@@ -347,16 +358,10 @@
 
     public boolean shouldContainerScroll(MotionEvent ev) {
         BaseDragLayer dragLayer = mActivityContext.getDragLayer();
-        // IF the MotionEvent is inside the search box, and the container keeps on receiving
-        // touch input, container should move down.
-        if (dragLayer.isEventOverView(mSearchContainer, ev)) {
-            return true;
-        }
-        // Scroll if not within the container view (e.g. over large-screen scrim).
-        if (!dragLayer.isEventOverView(getVisibleContainerView(), ev)) {
-            return true;
-        }
-        if (dragLayer.isEventOverView(mBottomSheetHandleArea, ev)) {
+        // IF the MotionEvent is inside the search box or handle area, and the container keeps on
+        // receiving touch input, container should move down.
+        if (dragLayer.isEventOverView(mSearchContainer, ev)
+                || dragLayer.isEventOverView(mBottomSheetHandleArea, ev)) {
             return true;
         }
         AllAppsRecyclerView rv = getActiveRecyclerView();
@@ -368,10 +373,30 @@
                 && dragLayer.isEventOverView(rv.getScrollbar(), ev)) {
             return false;
         }
+        // Scroll if not within the container view (e.g. over large-screen scrim).
+        if (!dragLayer.isEventOverView(getVisibleContainerView(), ev)) {
+            return true;
+        }
         return rv.shouldContainerScroll(ev, dragLayer);
     }
 
+    /**
+     * Resets the UI to be ready for fresh interactions in the future. Exits search and returns to
+     * A-Z apps list.
+     *
+     * @param animate Whether to animate the header during the reset (e.g. switching profile tabs).
+     **/
     public void reset(boolean animate) {
+        reset(animate, true);
+    }
+
+    /**
+     * Resets the UI to be ready for fresh interactions in the future.
+     *
+     * @param animate Whether to animate the header during the reset (e.g. switching profile tabs).
+     * @param exitSearch Whether to force exit the search state and return to A-Z apps list.
+     **/
+    public void reset(boolean animate, boolean exitSearch) {
         for (int i = 0; i < mAH.size(); i++) {
             if (mAH.get(i).mRecyclerView != null) {
                 mAH.get(i).mRecyclerView.scrollToTop();
@@ -385,10 +410,12 @@
         }
         // Reset the base recycler view after transitioning home.
         updateHeaderScroll(0);
-        // Reset the search bar after transitioning home.
-        mSearchUiManager.resetSearch();
-        // Animate to A-Z with 0 time to reset the animation with proper state management.
-        animateToSearchState(false, 0);
+        if (exitSearch) {
+            // Reset the search bar after transitioning home.
+            mSearchUiManager.resetSearch();
+            // Animate to A-Z with 0 time to reset the animation with proper state management.
+            animateToSearchState(false, 0);
+        }
     }
 
     @Override
@@ -432,7 +459,7 @@
         }
         // Header keeps track of active recycler view to properly render header protection.
         mHeader.setActiveRV(currentActivePage);
-        reset(true /* animate */);
+        reset(true /* animate */, !isSearching() /* exitSearch */);
 
         mWorkManager.onActivePageChanged(currentActivePage);
     }
@@ -453,12 +480,6 @@
             return;
         }
 
-        if (isSearching()) {
-            mUsingTabs = showTabs;
-            mWorkManager.detachWorkModeSwitch();
-            return;
-        }
-
         if (!FeatureFlags.ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES.get()) {
             RecyclerView.ItemDecoration decoration = getMainAdapterProvider().getDecorator();
             getSearchRecyclerView().removeItemDecoration(decoration);
@@ -523,7 +544,7 @@
         mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.SEARCH).mRecyclerView);
     }
 
-    protected View replaceAppsRVContainer(boolean showTabs) {
+    private void replaceAppsRVContainer(boolean showTabs) {
         for (int i = AdapterHolder.MAIN; i <= AdapterHolder.WORK; i++) {
             AdapterHolder adapterHolder = mAH.get(i);
             if (adapterHolder.mRecyclerView != null) {
@@ -577,7 +598,7 @@
             layoutBelowSearchContainer(getSearchRecyclerView(), /* tabs= */ false);
         }
 
-        return rvContainer;
+        updateSearchResultsVisibility();
     }
 
     void setupHeader() {
@@ -810,6 +831,12 @@
             }
         }
         updateBackground(dp);
+
+        int navBarScrimColor = Themes.getNavBarScrimColor(mActivityContext);
+        if (mNavBarScrimPaint.getColor() != navBarScrimColor) {
+            mNavBarScrimPaint.setColor(navBarScrimColor);
+            invalidate();
+        }
     }
 
     protected void updateBackground(DeviceProfile deviceProfile) {
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 85d7a05..4d1006a 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -521,7 +521,6 @@
      */
     private void onProgressAnimationEnd() {
         if (Float.compare(mProgress, 1f) == 0) {
-            mAppsView.reset(false /* animate */);
             if (mShouldControlKeyboard) {
                 mLauncher.getAppsView().getSearchUiManager().getEditText().hideKeyboard();
             }
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index b3ea3ab..330d13d 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -228,7 +228,7 @@
         updateExpectedHeight();
 
         mTabsHidden = tabsHidden;
-        mTabLayout.setVisibility(tabsHidden ? View.GONE : View.VISIBLE);
+        maybeSetTabVisibility(VISIBLE);
         mMainRV = mainRV;
         mWorkRV = workRV;
         mSearchRV = searchRV;
@@ -250,6 +250,12 @@
                 rvType == AdapterHolder.MAIN ? mMainRV
                 : rvType == AdapterHolder.WORK ? mWorkRV : mSearchRV;
         mCurrentRV.addOnScrollListener(mOnScrollListener);
+        maybeSetTabVisibility(rvType == AdapterHolder.SEARCH ? GONE : VISIBLE);
+    }
+
+    /** Update tab visibility to the given state, only if tabs are active (work profile exists). */
+    void maybeSetTabVisibility(int visibility) {
+        mTabLayout.setVisibility(mTabsHidden ? GONE : visibility);
     }
 
     private void updateExpectedHeight() {
diff --git a/src/com/android/launcher3/allapps/SearchTransitionController.java b/src/com/android/launcher3/allapps/SearchTransitionController.java
index 5056782..de65302 100644
--- a/src/com/android/launcher3/allapps/SearchTransitionController.java
+++ b/src/com/android/launcher3/allapps/SearchTransitionController.java
@@ -125,6 +125,7 @@
 
         mAllAppsContainerView.getFloatingHeaderView().setFloatingRowsCollapsed(true);
         mAllAppsContainerView.getFloatingHeaderView().setVisibility(VISIBLE);
+        mAllAppsContainerView.getFloatingHeaderView().maybeSetTabVisibility(VISIBLE);
         mAllAppsContainerView.getAppsRecyclerViewContainer().setVisibility(VISIBLE);
         getSearchRecyclerView().setVisibility(VISIBLE);
         getSearchRecyclerView().setChildAttachedConsumer(this::onSearchChildAttached);
diff --git a/src/com/android/launcher3/allapps/SearchUiManager.java b/src/com/android/launcher3/allapps/SearchUiManager.java
index 228b02b..2174936 100644
--- a/src/com/android/launcher3/allapps/SearchUiManager.java
+++ b/src/com/android/launcher3/allapps/SearchUiManager.java
@@ -65,7 +65,7 @@
      * sets highlight result's title
      */
     default void setFocusedResultTitle(
-            @Nullable CharSequence title, @Nullable CharSequence subtitle) {}
+            @Nullable CharSequence title, @Nullable CharSequence subtitle, boolean showArrow) {}
 
     /** Refresh the currently displayed list of results. */
     default void refreshResults() {}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 2972489..f25d26e 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -16,6 +16,9 @@
 
 package com.android.launcher3.config;
 
+import static com.android.launcher3.config.FeatureFlags.FlagState.DISABLED;
+import static com.android.launcher3.config.FeatureFlags.FlagState.ENABLED;
+import static com.android.launcher3.config.FeatureFlags.FlagState.TEAMFOOD;
 import static com.android.launcher3.uioverrides.flags.FlagsFactory.getDebugFlag;
 import static com.android.launcher3.uioverrides.flags.FlagsFactory.getReleaseFlag;
 
@@ -66,346 +69,320 @@
 
     /**
      * Feature flag to handle define config changes dynamically instead of killing the process.
-     *
+     * <p>
      *
      * To add a new flag that can be toggled through the flags UI:
-     *
+     * <p>
      * Declare a new ToggleableFlag below. Give it a unique key (e.g. "QSB_ON_FIRST_SCREEN"),
      * and set a default value for the flag. This will be the default value on Debug builds.
      */
-    public static final BooleanFlag ENABLE_INPUT_CONSUMER_REASON_LOGGING = getDebugFlag(270390028,
-            "ENABLE_INPUT_CONSUMER_REASON_LOGGING",
-            true,
-            "Log the reason why an Input Consumer was selected for a gesture.");
-
     public static final BooleanFlag ENABLE_GESTURE_ERROR_DETECTION = getDebugFlag(270389990,
-            "ENABLE_GESTURE_ERROR_DETECTION",
-            true,
+            "ENABLE_GESTURE_ERROR_DETECTION", ENABLED,
             "Analyze gesture events and log detected errors");
 
     // When enabled the promise icon is visible in all apps while installation an app.
     public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(270390012,
-            "PROMISE_APPS_IN_ALL_APPS", false, "Add promise icon in all-apps");
+            "PROMISE_APPS_IN_ALL_APPS", DISABLED, "Add promise icon in all-apps");
 
     public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(270390904,
-            "KEYGUARD_ANIMATION", false, "Enable animation for keyguard going away on wallpaper");
+            "KEYGUARD_ANIMATION", DISABLED,
+            "Enable animation for keyguard going away on wallpaper");
 
     public static final BooleanFlag ENABLE_DEVICE_SEARCH = getReleaseFlag(270390907,
-            "ENABLE_DEVICE_SEARCH", true, "Allows on device search in all apps");
+            "ENABLE_DEVICE_SEARCH", ENABLED, "Allows on device search in all apps");
 
     public static final BooleanFlag ENABLE_FLOATING_SEARCH_BAR =
-            getReleaseFlag(270390286, "ENABLE_FLOATING_SEARCH_BAR", false,
-                    "Keep All Apps search bar at the bottom (but above keyboard if open)");
+            getReleaseFlag(270390286, "ENABLE_FLOATING_SEARCH_BAR", DISABLED,
+            "Keep All Apps search bar at the bottom (but above keyboard if open)");
 
     public static final BooleanFlag ENABLE_HIDE_HEADER = getReleaseFlag(270390930,
-            "ENABLE_HIDE_HEADER", true, "Hide header on keyboard before typing in all apps");
+            "ENABLE_HIDE_HEADER", ENABLED, "Hide header on keyboard before typing in all apps");
 
     public static final BooleanFlag ENABLE_EXPANDING_PAUSE_WORK_BUTTON = getDebugFlag(270390779,
-            "ENABLE_EXPANDING_PAUSE_WORK_BUTTON", false,
+            "ENABLE_EXPANDING_PAUSE_WORK_BUTTON", DISABLED,
             "Expand and collapse pause work button while scrolling");
 
     public static final BooleanFlag COLLECT_SEARCH_HISTORY = getReleaseFlag(270391455,
-            "COLLECT_SEARCH_HISTORY", false, "Allow launcher to collect search history for log");
+            "COLLECT_SEARCH_HISTORY", DISABLED, "Allow launcher to collect search history for log");
 
     public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(270390937,
-            "ENABLE_TWOLINE_ALLAPPS", false, "Enables two line label inside all apps.");
+            "ENABLE_TWOLINE_ALLAPPS", DISABLED, "Enables two line label inside all apps.");
 
     public static final BooleanFlag ENABLE_TWOLINE_DEVICESEARCH = getDebugFlag(201388851,
-            "ENABLE_TWOLINE_DEVICESEARCH", false,
+            "ENABLE_TWOLINE_DEVICESEARCH", TEAMFOOD,
             "Enable two line label for icons with labels on device search.");
 
     public static final BooleanFlag ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING = getReleaseFlag(
-            270391397, "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", false,
+            270391397, "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", DISABLED,
             "Allows on device search in all apps logging");
 
     public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(270391693,
-            "IME_STICKY_SNACKBAR_EDU", true, "Show sticky IME edu in AllApps");
+            "IME_STICKY_SNACKBAR_EDU", ENABLED, "Show sticky IME edu in AllApps");
 
     public static final BooleanFlag ENABLE_PEOPLE_TILE_PREVIEW = getDebugFlag(270391653,
-            "ENABLE_PEOPLE_TILE_PREVIEW", false,
+            "ENABLE_PEOPLE_TILE_PREVIEW", DISABLED,
             "Experimental: Shows conversation shortcuts on home screen as search results");
 
     public static final BooleanFlag FOLDER_NAME_MAJORITY_RANKING = getDebugFlag(270391638,
-            "FOLDER_NAME_MAJORITY_RANKING", true,
+            "FOLDER_NAME_MAJORITY_RANKING", ENABLED,
             "Suggests folder names based on majority based ranking.");
 
     public static final BooleanFlag INJECT_FALLBACK_APP_CORPUS_RESULTS = getReleaseFlag(270391706,
-            "INJECT_FALLBACK_APP_CORPUS_RESULTS", false,
+            "INJECT_FALLBACK_APP_CORPUS_RESULTS", DISABLED,
             "Inject fallback app corpus result when AiAi fails to return it.");
 
     public static final BooleanFlag ASSISTANT_GIVES_LAUNCHER_FOCUS = getDebugFlag(270391641,
-            "ASSISTANT_GIVES_LAUNCHER_FOCUS", false,
+            "ASSISTANT_GIVES_LAUNCHER_FOCUS", DISABLED,
             "Allow Launcher to handle nav bar gestures while Assistant is running over it");
 
     public static final BooleanFlag ENABLE_BULK_WORKSPACE_ICON_LOADING = getDebugFlag(270392203,
-            "ENABLE_BULK_WORKSPACE_ICON_LOADING",
-            true,
+            "ENABLE_BULK_WORKSPACE_ICON_LOADING", ENABLED,
             "Enable loading workspace icons in bulk.");
 
-    public static final BooleanFlag ENABLE_BULK_ALL_APPS_ICON_LOADING = getDebugFlag(270392465,
-            "ENABLE_BULK_ALL_APPS_ICON_LOADING",
-            true,
-            "Enable loading all apps icons in bulk.");
-
     public static final BooleanFlag ENABLE_DATABASE_RESTORE = getDebugFlag(270392706,
-            "ENABLE_DATABASE_RESTORE", false,
+            "ENABLE_DATABASE_RESTORE", DISABLED,
             "Enable database restore when new restore session is created");
 
-    public static final BooleanFlag ENABLE_SMARTSPACE_DISMISS = getDebugFlag(270391664,
-            "ENABLE_SMARTSPACE_DISMISS", true,
-            "Adds a menu option to dismiss the current Enhanced Smartspace card.");
-
     public static final BooleanFlag ENABLE_OVERLAY_CONNECTION_OPTIM = getDebugFlag(270392629,
-            "ENABLE_OVERLAY_CONNECTION_OPTIM",
-            false,
+            "ENABLE_OVERLAY_CONNECTION_OPTIM", DISABLED,
             "Enable optimizing overlay service connection");
 
     /**
      * Enables region sampling for text color: Needs system health assessment before turning on
      */
     public static final BooleanFlag ENABLE_REGION_SAMPLING = getDebugFlag(270391669,
-            "ENABLE_REGION_SAMPLING", false,
+            "ENABLE_REGION_SAMPLING", DISABLED,
             "Enable region sampling to determine color of text on screen.");
 
     public static final BooleanFlag ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS =
-            getDebugFlag(270393096,
-                    "ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS", false,
-                    "Always use hardware optimization for folder animations.");
+            getDebugFlag(270393096, "ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS",
+            DISABLED, "Always use hardware optimization for folder animations.");
 
     public static final BooleanFlag SEPARATE_RECENTS_ACTIVITY = getDebugFlag(270392980,
-            "SEPARATE_RECENTS_ACTIVITY", false,
+            "SEPARATE_RECENTS_ACTIVITY", DISABLED,
             "Uses a separate recents activity instead of using the integrated recents+Launcher UI");
 
     public static final BooleanFlag ENABLE_MINIMAL_DEVICE = getDebugFlag(270392984,
-            "ENABLE_MINIMAL_DEVICE", false,
+            "ENABLE_MINIMAL_DEVICE", DISABLED,
             "Allow user to toggle minimal device mode in launcher.");
 
-    public static final BooleanFlag ENABLE_TASKBAR_POPUP_MENU = getDebugFlag(
-            270392477, "ENABLE_TASKBAR_POPUP_MENU", true,
-            "Enables long pressing taskbar icons to show the popup menu.");
-
     public static final BooleanFlag ENABLE_TWO_PANEL_HOME = getDebugFlag(270392643,
-            "ENABLE_TWO_PANEL_HOME", true,
+            "ENABLE_TWO_PANEL_HOME", ENABLED,
             "Uses two panel on home screen. Only applicable on large screen devices.");
 
     public static final BooleanFlag ENABLE_SCRIM_FOR_APP_LAUNCH = getDebugFlag(270393276,
-            "ENABLE_SCRIM_FOR_APP_LAUNCH", false,
-            "Enables scrim during app launch animation.");
+            "ENABLE_SCRIM_FOR_APP_LAUNCH", DISABLED, "Enables scrim during app launch animation.");
 
     public static final BooleanFlag ENABLE_ENFORCED_ROUNDED_CORNERS = getReleaseFlag(270393258,
-            "ENABLE_ENFORCED_ROUNDED_CORNERS", true, "Enforce rounded corners on all App Widgets");
+            "ENABLE_ENFORCED_ROUNDED_CORNERS", ENABLED,
+            "Enforce rounded corners on all App Widgets");
 
-    public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag(
-            270393108, "NOTIFY_CRASHES", false,
-            "Sends a notification whenever launcher encounters an uncaught exception.");
+    public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag(270393108, "NOTIFY_CRASHES",
+            DISABLED, "Sends a notification whenever launcher encounters an uncaught exception.");
 
     public static final BooleanFlag ENABLE_WALLPAPER_SCRIM = getDebugFlag(270393604,
-            "ENABLE_WALLPAPER_SCRIM", false,
+            "ENABLE_WALLPAPER_SCRIM", DISABLED,
             "Enables scrim over wallpaper for text protection.");
 
     public static final BooleanFlag WIDGETS_IN_LAUNCHER_PREVIEW = getDebugFlag(270393268,
-            "WIDGETS_IN_LAUNCHER_PREVIEW", true,
+            "WIDGETS_IN_LAUNCHER_PREVIEW", ENABLED,
             "Enables widgets in Launcher preview for the Wallpaper app.");
 
-    public static final BooleanFlag QUICK_WALLPAPER_PICKER = getDebugFlag(270393112,
-            "QUICK_WALLPAPER_PICKER", true,
-            "Shows quick wallpaper picker in long-press menu");
-
     public static final BooleanFlag ENABLE_BACK_SWIPE_HOME_ANIMATION = getDebugFlag(270393426,
-            "ENABLE_BACK_SWIPE_HOME_ANIMATION", true,
+            "ENABLE_BACK_SWIPE_HOME_ANIMATION", ENABLED,
             "Enables home animation to icon when user swipes back.");
 
     public static final BooleanFlag ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION = getDebugFlag(270614790,
-            "ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION", false,
+            "ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION", DISABLED,
             "Enables predictive back aniamtion from all apps and widgets to home");
 
     public static final BooleanFlag ENABLE_ICON_LABEL_AUTO_SCALING = getDebugFlag(270393294,
-            "ENABLE_ICON_LABEL_AUTO_SCALING", true,
+            "ENABLE_ICON_LABEL_AUTO_SCALING", ENABLED,
             "Enables scaling/spacing for icon labels to make more characters visible");
 
     public static final BooleanFlag ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT = getDebugFlag(270393897,
-            "ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT", false,
+            "ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT", DISABLED,
             "Enables displaying the all apps button in the hotseat.");
 
-    public static final BooleanFlag ENABLE_ALL_APPS_ONE_SEARCH_IN_TASKBAR = getDebugFlag(270393900,
-            "ENABLE_ALL_APPS_ONE_SEARCH_IN_TASKBAR", false,
-            "Enables One Search box in Taskbar All Apps.");
+    public static final BooleanFlag ENABLE_ALL_APPS_SEARCH_IN_TASKBAR = getDebugFlag(270393900,
+            "ENABLE_ALL_APPS_SEARCH_IN_TASKBAR", DISABLED,
+            "Enables Search box in Taskbar All Apps.");
 
     public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE = getDebugFlag(270393906,
-            "ENABLE_SPLIT_FROM_WORKSPACE", true,
+            "ENABLE_SPLIT_FROM_WORKSPACE", ENABLED,
             "Enable initiating split screen from workspace.");
 
     public static final BooleanFlag ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS =
-            getDebugFlag(270394122, "ENABLE_SPLIT_FROM_FULLSCREEN_SHORTCUT", true,
-                    "Enable splitting from fullscreen app with keyboard shortcuts");
+            getDebugFlag(270394122, "ENABLE_SPLIT_FROM_FULLSCREEN_SHORTCUT", ENABLED,
+            "Enable splitting from fullscreen app with keyboard shortcuts");
 
     public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE = getDebugFlag(
-            270393453, "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", false,
+            270393453, "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", DISABLED,
             "Enable initiating split screen from workspace to workspace.");
 
     public static final BooleanFlag ENABLE_NEW_MIGRATION_LOGIC = getDebugFlag(270393455,
-            "ENABLE_NEW_MIGRATION_LOGIC", true,
+            "ENABLE_NEW_MIGRATION_LOGIC", ENABLED,
             "Enable the new grid migration logic, keeping pages when src < dest");
 
     public static final BooleanFlag ENABLE_WIDGET_HOST_IN_BACKGROUND = getDebugFlag(270394384,
-            "ENABLE_WIDGET_HOST_IN_BACKGROUND", true,
+            "ENABLE_WIDGET_HOST_IN_BACKGROUND", ENABLED,
             "Enable background widget updates listening for widget holder");
 
     public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = getReleaseFlag(270394223,
-            "ENABLE_ONE_SEARCH_MOTION", true, "Enables animations in OneSearch.");
+            "ENABLE_ONE_SEARCH_MOTION", ENABLED, "Enables animations in OneSearch.");
 
     public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = getReleaseFlag(
-            270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", false,
+            270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", DISABLED,
             "Enable option to replace decorator-based search result backgrounds with drawables");
 
     public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = getReleaseFlag(
-            270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", false,
+            270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", DISABLED,
             "Enable option to launch search results using the new view container transitions");
 
     public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = getReleaseFlag(
-            270394468, "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", true,
+            270394468, "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", ENABLED,
             "Enable option to show keyboard when going to all-apps");
 
     public static final BooleanFlag USE_LOCAL_ICON_OVERRIDES = getDebugFlag(270394973,
-            "USE_LOCAL_ICON_OVERRIDES", true,
+            "USE_LOCAL_ICON_OVERRIDES", ENABLED,
             "Use inbuilt monochrome icons if app doesn't provide one");
 
     public static final BooleanFlag ENABLE_DISMISS_PREDICTION_UNDO = getDebugFlag(270394476,
-            "ENABLE_DISMISS_PREDICTION_UNDO", false,
+            "ENABLE_DISMISS_PREDICTION_UNDO", DISABLED,
             "Show an 'Undo' snackbar when users dismiss a predicted hotseat item");
 
     public static final BooleanFlag ENABLE_CACHED_WIDGET = getDebugFlag(270395008,
-            "ENABLE_CACHED_WIDGET", true,
+            "ENABLE_CACHED_WIDGET", ENABLED,
             "Show previously cached widgets as opposed to deferred widget where available");
 
     public static final BooleanFlag USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES = getDebugFlag(270395010,
-            "USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES", false,
+            "USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES", DISABLED,
             "Use local overrides for search request timeout");
 
     public static final BooleanFlag CONTINUOUS_VIEW_TREE_CAPTURE = getDebugFlag(270395171,
-            "CONTINUOUS_VIEW_TREE_CAPTURE", true, "Capture View tree every frame");
+            "CONTINUOUS_VIEW_TREE_CAPTURE", ENABLED, "Capture View tree every frame");
 
-    public static final BooleanFlag SECONDARY_DRAG_N_DROP_TO_PIN = getDebugFlag(
-            270395140, "SECONDARY_DRAG_N_DROP_TO_PIN", false,
+    public static final BooleanFlag SECONDARY_DRAG_N_DROP_TO_PIN = getDebugFlag(270395140,
+            "SECONDARY_DRAG_N_DROP_TO_PIN", DISABLED,
             "Enable dragging and dropping to pin apps within secondary display");
 
     public static final BooleanFlag FOLDABLE_WORKSPACE_REORDER = getDebugFlag(270395070,
-            "FOLDABLE_WORKSPACE_REORDER", false,
+            "FOLDABLE_WORKSPACE_REORDER", DISABLED,
             "In foldables, when reordering the icons and widgets, is now going to use both sides");
 
     public static final BooleanFlag ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH = getDebugFlag(270395073,
-            "ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH", false,
+            "ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH", DISABLED,
             "Allow bottom sheet depth to be smaller than 1 for multi-display devices.");
 
-    public static final BooleanFlag SCROLL_TOP_TO_RESET = getReleaseFlag(
-            270395177, "SCROLL_TOP_TO_RESET", true,
+    public static final BooleanFlag SCROLL_TOP_TO_RESET = getReleaseFlag(270395177,
+            "SCROLL_TOP_TO_RESET", ENABLED,
             "Bring up IME and focus on input when scroll to top if 'Always show keyboard'"
                     + " is enabled or in prefix state");
 
     public static final BooleanFlag ENABLE_MATERIAL_U_POPUP = getDebugFlag(270395516,
-            "ENABLE_MATERIAL_U_POPUP", true, "Switch popup UX to use material U");
+            "ENABLE_MATERIAL_U_POPUP", ENABLED, "Switch popup UX to use material U");
 
     public static final BooleanFlag ENABLE_SEARCH_UNINSTALLED_APPS = getReleaseFlag(270395269,
-            "ENABLE_SEARCH_UNINSTALLED_APPS", false, "Search uninstalled app results.");
+            "ENABLE_SEARCH_UNINSTALLED_APPS", DISABLED, "Search uninstalled app results.");
 
     public static final BooleanFlag SHOW_HOME_GARDENING = getDebugFlag(270395183,
-            "SHOW_HOME_GARDENING", false,
-            "Show the new home gardening mode");
+            "SHOW_HOME_GARDENING", DISABLED, "Show the new home gardening mode");
 
     public static final BooleanFlag HOME_GARDENING_WORKSPACE_BUTTONS = getDebugFlag(270395133,
-            "HOME_GARDENING_WORKSPACE_BUTTONS", false,
+            "HOME_GARDENING_WORKSPACE_BUTTONS", DISABLED,
             "Change workspace edit buttons to reflect home gardening");
 
     public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V2 = getReleaseFlag(270395134,
-            "ENABLE_DOWNLOAD_APP_UX_V2", true, "Updates the download app UX"
+            "ENABLE_DOWNLOAD_APP_UX_V2", ENABLED, "Updates the download app UX"
                     + " to have better visuals");
 
     public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V3 = getDebugFlag(270395186,
-            "ENABLE_DOWNLOAD_APP_UX_V3", false, "Updates the download app UX"
+            "ENABLE_DOWNLOAD_APP_UX_V3", DISABLED, "Updates the download app UX"
                     + " to have better visuals, improve contrast, and color");
 
     public static final BooleanFlag FORCE_PERSISTENT_TASKBAR = getDebugFlag(270395077,
-            "FORCE_PERSISTENT_TASKBAR", false, "Forces taskbar to be persistent, even in gesture"
+            "FORCE_PERSISTENT_TASKBAR", DISABLED, "Forces taskbar to be persistent, even in gesture"
                     + " nav mode and when transient taskbar is enabled.");
 
     public static final BooleanFlag FOLDABLE_SINGLE_PAGE = getDebugFlag(270395274,
-            "FOLDABLE_SINGLE_PAGE", true,
-            "Use a single page for the workspace");
+            "FOLDABLE_SINGLE_PAGE", ENABLED, "Use a single page for the workspace");
 
     public static final BooleanFlag ENABLE_TRANSIENT_TASKBAR = getDebugFlag(270395798,
-            "ENABLE_TRANSIENT_TASKBAR", true, "Enables transient taskbar.");
+            "ENABLE_TRANSIENT_TASKBAR", ENABLED, "Enables transient taskbar.");
 
     public static final BooleanFlag ENABLE_TRACKPAD_GESTURE = getDebugFlag(271010401,
-            "ENABLE_TRACKPAD_GESTURE", true, "Enables trackpad gesture.");
+            "ENABLE_TRACKPAD_GESTURE", ENABLED, "Enables trackpad gesture.");
 
     public static final BooleanFlag ENABLE_ICON_IN_TEXT_HEADER = getDebugFlag(270395143,
-            "ENABLE_ICON_IN_TEXT_HEADER", false, "Show icon in textheader");
+            "ENABLE_ICON_IN_TEXT_HEADER", DISABLED, "Show icon in textheader");
 
     public static final BooleanFlag ENABLE_APP_ICON_FOR_INLINE_SHORTCUTS = getDebugFlag(270395087,
-            "ENABLE_APP_ICON_IN_INLINE_SHORTCUTS", false, "Show app icon for inline shortcut");
+            "ENABLE_APP_ICON_IN_INLINE_SHORTCUTS", DISABLED, "Show app icon for inline shortcut");
 
     public static final BooleanFlag SHOW_DOT_PAGINATION = getDebugFlag(270395278,
-            "SHOW_DOT_PAGINATION", true, "Enable showing dot pagination in workspace");
+            "SHOW_DOT_PAGINATION", ENABLED, "Enable showing dot pagination in workspace");
 
     public static final BooleanFlag LARGE_SCREEN_WIDGET_PICKER = getDebugFlag(270395809,
-            "LARGE_SCREEN_WIDGET_PICKER", true, "Enable new widget picker that takes "
+            "LARGE_SCREEN_WIDGET_PICKER", ENABLED, "Enable new widget picker that takes "
                     + "advantage of large screen format");
 
+    public static final BooleanFlag MULTI_SELECT_EDIT_MODE = getDebugFlag(270709220,
+            "MULTI_SELECT_EDIT_MODE", DISABLED, "Enable new multi-select edit mode "
+                    + "for home screen");
+
     public static final BooleanFlag ENABLE_NEW_GESTURE_NAV_TUTORIAL = getDebugFlag(270396257,
-            "ENABLE_NEW_GESTURE_NAV_TUTORIAL", true,
+            "ENABLE_NEW_GESTURE_NAV_TUTORIAL", ENABLED,
             "Enable the redesigned gesture navigation tutorial");
 
     public static final BooleanFlag ENABLE_LAUNCH_FROM_STAGED_APP = getDebugFlag(270395567,
-            "ENABLE_LAUNCH_FROM_STAGED_APP", true,
-            "Enable the ability to tap a staged app during split select to launch it in full screen"
-    );
+            "ENABLE_LAUNCH_FROM_STAGED_APP", ENABLED,
+            "Enable the ability to tap a staged app during split select to launch it in full "
+                    + "screen");
 
     public static final BooleanFlag ENABLE_PREMIUM_HAPTICS_ALL_APPS = getDebugFlag(270396358,
-            "ENABLE_PREMIUM_HAPTICS_ALL_APPS", false,
+            "ENABLE_PREMIUM_HAPTICS_ALL_APPS", DISABLED,
             "Enables haptics opening/closing All apps");
 
     public static final BooleanFlag ENABLE_FORCED_MONO_ICON = getDebugFlag(270396209,
-            "ENABLE_FORCED_MONO_ICON", false,
-            "Enable the ability to generate monochromatic icons, if it is not provided by the app"
-    );
+            "ENABLE_FORCED_MONO_ICON", DISABLED,
+            "Enable the ability to generate monochromatic icons, if it is not provided by the app");
 
     public static final BooleanFlag ENABLE_TASKBAR_EDU_TOOLTIP = getDebugFlag(270396268,
-            "ENABLE_TASKBAR_EDU_TOOLTIP", true,
+            "ENABLE_TASKBAR_EDU_TOOLTIP", ENABLED,
             "Enable the tooltip version of the Taskbar education flow.");
 
     public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(270396680,
-            "ENABLE_MULTI_INSTANCE", false,
+            "ENABLE_MULTI_INSTANCE", DISABLED,
             "Enables creation and filtering of multiple task instances in overview");
 
     public static final BooleanFlag ENABLE_TASKBAR_PINNING = getDebugFlag(270396583,
-            "ENABLE_TASKBAR_PINNING", false,
+            "ENABLE_TASKBAR_PINNING", DISABLED,
             "Enables taskbar pinning to allow user to switch between transient and persistent "
                     + "taskbar flavors");
 
     public static final BooleanFlag ENABLE_WORKSPACE_LOADING_OPTIMIZATION = getDebugFlag(251502424,
-            "ENABLE_WORKSPACE_LOADING_OPTIMIZATION", false, "load the current workspace screen "
-                    + "visible to the user before the rest rather than loading all of them at once."
-    );
+            "ENABLE_WORKSPACE_LOADING_OPTIMIZATION", DISABLED,
+            "load the current workspace screen visible to the user before the rest rather than "
+                    + "loading all of them at once.");
 
     public static final BooleanFlag ENABLE_GRID_ONLY_OVERVIEW = getDebugFlag(270397206,
-            "ENABLE_GRID_ONLY_OVERVIEW", false,
+            "ENABLE_GRID_ONLY_OVERVIEW", DISABLED,
             "Enable a grid-only overview without a focused task.");
 
     public static final BooleanFlag RECEIVE_UNFOLD_EVENTS_FROM_SYSUI = getDebugFlag(270397209,
-            "RECEIVE_UNFOLD_EVENTS_FROM_SYSUI", true,
+            "RECEIVE_UNFOLD_EVENTS_FROM_SYSUI", ENABLED,
             "Enables receiving unfold animation events from sysui instead of calculating "
                     + "them in launcher process using hinge sensor values.");
 
     public static final BooleanFlag ENABLE_KEYBOARD_QUICK_SWITCH = getDebugFlag(270396844,
-            "ENABLE_KEYBOARD_QUICK_SWITCH", true,
-            "Enables keyboard quick switching");
+            "ENABLE_KEYBOARD_QUICK_SWITCH", ENABLED, "Enables keyboard quick switching");
 
     public static final BooleanFlag ENABLE_APP_CLONING_CHANGES_IN_LAUNCHER = getDebugFlag(266177840,
-            "ENABLE_APP_CLONING_CHANGES_IN_LAUNCHER", false,
+            "ENABLE_APP_CLONING_CHANGES_IN_LAUNCHER", DISABLED,
             "Removes clone apps from the work profile tab.");
 
     public static final BooleanFlag ENABLE_APP_PAIRS = getDebugFlag(274189428,
-            "ENABLE_APP_PAIRS", false,
+            "ENABLE_APP_PAIRS", DISABLED,
             "Enables the ability to create and save app pairs on the Home screen for easy"
                     + " split screen launching.");
 
@@ -437,4 +414,13 @@
             return sIntReader.applyAsInt(this);
         }
     }
+
+    /**
+     * Enabled state for a flag
+     */
+    public enum FlagState {
+        ENABLED,
+        DISABLED,
+        TEAMFOOD    // Enabled in team food
+    }
 }
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index d43731b..9fe3c0b 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -45,7 +45,7 @@
 import com.android.launcher3.keyboard.ViewGroupFocusHelper;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.pageindicators.PageIndicatorDots;
+import com.android.launcher3.pageindicators.LauncherDotsPageIndicator;
 import com.android.launcher3.touch.ItemClickHandler;
 import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
 import com.android.launcher3.util.Thunk;
@@ -60,7 +60,7 @@
 import java.util.function.ToIntFunction;
 import java.util.stream.Collectors;
 
-public class FolderPagedView extends PagedView<PageIndicatorDots> implements ClipPathView {
+public class FolderPagedView extends PagedView<LauncherDotsPageIndicator> implements ClipPathView {
 
     private static final String TAG = "FolderPagedView";
 
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index 5a50569..0fe79e7 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -27,16 +27,11 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.PathMeasure;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
-import android.os.SystemClock;
 import android.util.Property;
 
 import com.android.launcher3.R;
@@ -47,10 +42,6 @@
 import com.android.launcher3.icons.GraphicsUtils;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.util.Themes;
-import com.android.launcher3.util.window.RefreshRateTracker;
-
-import java.util.WeakHashMap;
-import java.util.function.Function;
 
 /**
  * Extension of {@link FastBitmapDrawable} which shows a progress bar around the icon.
@@ -91,14 +82,6 @@
     private static final int PRELOAD_ACCENT_COLOR_INDEX = 0;
     private static final int PRELOAD_BACKGROUND_COLOR_INDEX = 1;
 
-    private static final int ALPHA_DURATION_MILLIS = 3000;
-    private static final int OVERLAY_ALPHA_RANGE = 191;
-    private static final long WAVE_MOTION_DELAY_FACTOR_MILLIS = 100;
-    private static final WeakHashMap<Integer, PorterDuffColorFilter> COLOR_FILTER_MAP =
-            new WeakHashMap<>();
-    public static final Function<Integer, PorterDuffColorFilter> FILTER_FACTORY =
-            currArgb -> new PorterDuffColorFilter(currArgb, PorterDuff.Mode.SRC_ATOP);
-
     private final Matrix mTmpMatrix = new Matrix();
     private final PathMeasure mPathMeasure = new PathMeasure();
 
@@ -119,7 +102,6 @@
     private float mTrackLength;
 
     private boolean mRanFinishAnimation;
-    private final int mRefreshRateMillis;
 
     // Progress of the internal state. [0, 1] indicates the fraction of completed progress,
     // [1, (1 + COMPLETE_ANIM_FRACTION)] indicates the progress of zoom animation.
@@ -138,7 +120,6 @@
                 IconPalette.getPreloadProgressColor(context, info.bitmap.color),
                 getPreloadColors(context),
                 Utilities.isDarkTheme(context),
-                getRefreshRateMillis(context),
                 GraphicsUtils.getShapePath(context, DEFAULT_PATH_SIZE));
     }
 
@@ -147,7 +128,6 @@
             int indicatorColor,
             int[] preloadColors,
             boolean isDarkMode,
-            int refreshRateMillis,
             Path shapePath) {
         super(info.bitmap);
         mItem = info;
@@ -162,13 +142,14 @@
         mSystemAccentColor = preloadColors[PRELOAD_ACCENT_COLOR_INDEX];
         mSystemBackgroundColor = preloadColors[PRELOAD_BACKGROUND_COLOR_INDEX];
         mIsDarkMode = isDarkMode;
-        mRefreshRateMillis = refreshRateMillis;
 
         // If it's a pending app we will animate scale and alpha when it's no longer pending.
         mIconScaleMultiplier.updateValue(info.getProgressLevel() == 0 ? 0 : 1);
 
         setLevel(info.getProgressLevel());
-        setIsStartable(info.isAppStartable());
+        if (!ENABLE_DOWNLOAD_APP_UX_V2.get()) {
+            setIsStartable(info.isAppStartable());
+        }
     }
 
     @Override
@@ -223,20 +204,16 @@
                 : SMALL_SCALE;
         canvas.scale(scale, scale, bounds.exactCenterX(), bounds.exactCenterY());
 
-        ColorFilter filter = getOverlayFilter();
-        mPaint.setColorFilter(filter);
         super.drawInternal(canvas, bounds);
         canvas.restoreToCount(saveCount);
-
-        if (ENABLE_DOWNLOAD_APP_UX_V2.get() && filter != null) {
-            reschedule();
-        }
     }
 
     @Override
     protected void updateFilter() {
         if (!ENABLE_DOWNLOAD_APP_UX_V2.get()) {
             setAlpha(mIsDisabled ? DISABLED_ICON_ALPHA : MAX_PAINT_ALPHA);
+        } else {
+            super.updateFilter();
         }
     }
 
@@ -317,7 +294,7 @@
     /**
      * Sets the internal progress and updates the UI accordingly
      *   for progress <= 0:
-     *     - icon with pending motion
+     *     - icon is pending
      *     - progress track is not visible
      *     - progress bar is not visible
      *   for progress < 1:
@@ -367,11 +344,6 @@
 
         return preloadColors;
     }
-
-    private static int getRefreshRateMillis(Context context) {
-        return RefreshRateTracker.getSingleFrameMs(context);
-    }
-
     /**
      * Returns a FastBitmapDrawable with the icon.
      */
@@ -388,55 +360,9 @@
                 mIndicatorColor,
                 new int[] {mSystemAccentColor, mSystemBackgroundColor},
                 mIsDarkMode,
-                mRefreshRateMillis,
                 mShapePath);
     }
 
-    @Override
-    public boolean setVisible(boolean visible, boolean restart) {
-        if (!visible) {
-            unscheduleSelf(mInvalidateRunnable);
-        }
-        return super.setVisible(visible, restart);
-    }
-
-    private void reschedule() {
-        unscheduleSelf(mInvalidateRunnable);
-        if (!isVisible()) {
-            return;
-        }
-        final long upTime = SystemClock.uptimeMillis();
-        scheduleSelf(mInvalidateRunnable,
-                upTime - ((upTime % mRefreshRateMillis)) + mRefreshRateMillis);
-    }
-
-    /**
-     * Returns a color filter to be used as an overlay on the pending icon with cascading motion
-     * based on its position.
-     */
-    private ColorFilter getOverlayFilter() {
-        if (!ENABLE_DOWNLOAD_APP_UX_V2.get() || mInternalStateProgress > 0) {
-            // If the download has started, we do no need to animate
-            return null;
-        }
-        long waveMotionDelay = (mItem.cellX * WAVE_MOTION_DELAY_FACTOR_MILLIS)
-                + (mItem.cellY * WAVE_MOTION_DELAY_FACTOR_MILLIS);
-        long time = SystemClock.uptimeMillis();
-        int alpha = (int) Utilities.mapBoundToRange(
-                (int) ((time + waveMotionDelay) % ALPHA_DURATION_MILLIS),
-                0,
-                ALPHA_DURATION_MILLIS,
-                0,
-                OVERLAY_ALPHA_RANGE * 2,
-                LINEAR);
-        if (alpha > OVERLAY_ALPHA_RANGE) {
-            alpha = (OVERLAY_ALPHA_RANGE - (alpha % OVERLAY_ALPHA_RANGE));
-        }
-        int overlayColor = mIsDarkMode ? 0 : 255;
-        int currArgb = Color.argb(alpha, overlayColor, overlayColor, overlayColor);
-        return COLOR_FILTER_MAP.computeIfAbsent(currArgb, FILTER_FACTORY);
-    }
-
     protected static class PreloadIconConstantState extends FastBitmapConstantState {
 
         protected final ItemInfoWithIcon mInfo;
@@ -444,7 +370,6 @@
         protected final int[] mPreloadColors;
         protected final boolean mIsDarkMode;
         protected final int mLevel;
-        protected final int mRefreshRateMillis;
         private final Path mShapePath;
 
         public PreloadIconConstantState(
@@ -454,7 +379,6 @@
                 int indicatorColor,
                 int[] preloadColors,
                 boolean isDarkMode,
-                int refreshRateMillis,
                 Path shapePath) {
             super(bitmap, iconColor);
             mInfo = info;
@@ -462,7 +386,6 @@
             mPreloadColors = preloadColors;
             mIsDarkMode = isDarkMode;
             mLevel = info.getProgressLevel();
-            mRefreshRateMillis = refreshRateMillis;
             mShapePath = shapePath;
         }
 
@@ -473,7 +396,6 @@
                     mIndicatorColor,
                     mPreloadColors,
                     mIsDarkMode,
-                    mRefreshRateMillis,
                     mShapePath);
         }
     }
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 3c63f26..1e3b003 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -46,10 +46,10 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 import androidx.core.util.Pair;
 
 import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.LauncherFiles;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic;
 import com.android.launcher3.icons.cache.BaseIconCache;
@@ -105,10 +105,6 @@
 
     private int mPendingIconRequestCount = 0;
 
-    public IconCache(Context context, InvariantDeviceProfile idp) {
-        this(context, idp, LauncherFiles.APP_ICONS_DB, new IconProvider(context));
-    }
-
     public IconCache(Context context, InvariantDeviceProfile idp, String dbFileName,
             IconProvider iconProvider) {
         super(context, dbFileName, MODEL_EXECUTOR.getLooper(),
@@ -254,30 +250,37 @@
      * Returns the badging info for the shortcut
      */
     public BitmapInfo getShortcutInfoBadge(ShortcutInfo shortcutInfo) {
-        ComponentName cn = shortcutInfo.getActivity();
-        if (cn != null) {
-            // Get the app info for the source activity.
-            AppInfo appInfo = new AppInfo();
-            appInfo.user = shortcutInfo.getUserHandle();
-            appInfo.componentName = cn;
-            appInfo.intent = new Intent(Intent.ACTION_MAIN)
-                    .addCategory(Intent.CATEGORY_LAUNCHER)
-                    .setComponent(cn);
-            getTitleAndIcon(appInfo, false);
-            return appInfo.bitmap;
+        return getShortcutInfoBadgeItem(shortcutInfo).bitmap;
+    }
+
+    @VisibleForTesting
+    protected ItemInfoWithIcon getShortcutInfoBadgeItem(ShortcutInfo shortcutInfo) {
+        // Check for badge override first.
+        String pkg = shortcutInfo.getPackage();
+        String override = shortcutInfo.getExtras() == null ? null
+                : shortcutInfo.getExtras().getString(EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE);
+        if (!TextUtils.isEmpty(override)
+                && InstallSessionHelper.INSTANCE.get(mContext)
+                .isTrustedPackage(pkg, shortcutInfo.getUserHandle())) {
+            pkg = override;
         } else {
-            String pkg = shortcutInfo.getPackage();
-            String override = shortcutInfo.getExtras() == null ? null
-                    : shortcutInfo.getExtras().getString(EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE);
-            if (!TextUtils.isEmpty(override)
-                    && InstallSessionHelper.INSTANCE.get(mContext)
-                            .isTrustedPackage(pkg, shortcutInfo.getUserHandle())) {
-                pkg = override;
+            // Try component based badge before trying the normal package badge
+            ComponentName cn = shortcutInfo.getActivity();
+            if (cn != null) {
+                // Get the app info for the source activity.
+                AppInfo appInfo = new AppInfo();
+                appInfo.user = shortcutInfo.getUserHandle();
+                appInfo.componentName = cn;
+                appInfo.intent = new Intent(Intent.ACTION_MAIN)
+                        .addCategory(Intent.CATEGORY_LAUNCHER)
+                        .setComponent(cn);
+                getTitleAndIcon(appInfo, false);
+                return appInfo;
             }
-            PackageItemInfo pkgInfo = new PackageItemInfo(pkg, shortcutInfo.getUserHandle());
-            getTitleAndIconForApp(pkgInfo, false);
-            return pkgInfo.bitmap;
         }
+        PackageItemInfo pkgInfo = new PackageItemInfo(pkg, shortcutInfo.getUserHandle());
+        getTitleAndIconForApp(pkgInfo, false);
+        return pkgInfo;
     }
 
     /**
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index da9be49..3e99772 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -960,7 +960,7 @@
                 iconRequestInfos.add(new IconRequestInfo<>(
                         appInfo, app, /* useLowResIcon= */ false));
                 mBgAllAppsList.add(
-                        appInfo, app, !FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get());
+                        appInfo, app, false);
             }
             allActivityList.addAll(apps);
         }
@@ -973,7 +973,7 @@
                 AppInfo promiseAppInfo = mBgAllAppsList.addPromiseApp(
                         mApp.getContext(),
                         PackageInstallInfo.fromInstallingState(info),
-                        !FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get());
+                        false);
 
                 if (promiseAppInfo != null) {
                     iconRequestInfos.add(new IconRequestInfo<>(
@@ -984,15 +984,13 @@
             }
         }
 
-        if (FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get()) {
-            Trace.beginSection("LoadAllAppsIconsInBulk");
-            try {
-                mIconCache.getTitlesAndIconsInBulk(iconRequestInfos);
-                iconRequestInfos.forEach(iconRequestInfo ->
-                        mBgAllAppsList.updateSectionName(iconRequestInfo.itemInfo));
-            } finally {
-                Trace.endSection();
-            }
+        Trace.beginSection("LoadAllAppsIconsInBulk");
+        try {
+            mIconCache.getTitlesAndIconsInBulk(iconRequestInfos);
+            iconRequestInfos.forEach(iconRequestInfo ->
+                    mBgAllAppsList.updateSectionName(iconRequestInfo.itemInfo));
+        } finally {
+            Trace.endSection();
         }
 
         mBgAllAppsList.setFlags(FLAG_QUIET_MODE_ENABLED,
diff --git a/src/com/android/launcher3/pageindicators/LauncherDotsPageIndicator.java b/src/com/android/launcher3/pageindicators/LauncherDotsPageIndicator.java
new file mode 100644
index 0000000..8a21d13
--- /dev/null
+++ b/src/com/android/launcher3/pageindicators/LauncherDotsPageIndicator.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.pageindicators;
+
+import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
+import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
+
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.ViewConfiguration;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.Alarm;
+import com.android.launcher3.Insettable;
+import com.android.launcher3.anim.PropertySetter;
+import com.android.launcher3.util.MultiValueAlpha;
+
+/**
+ * Extension of {@link PageIndicatorDots} with Launcher specific page-indicator functionality
+ */
+public class LauncherDotsPageIndicator extends PageIndicatorDots
+        implements Insettable, PageIndicator {
+
+    private static final int PAGINATION_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay();
+    private static final int PAGINATION_FADE_IN_DURATION = 83;
+    private static final int PAGINATION_FADE_OUT_DURATION = 167;
+
+    private static final int INDEX_VIEW_ALPHA = 0;
+    private static final int INDEX_AUTO_HIDE = 1;
+    private static final int ALPHA_CHANNEL_COUNT = 2;
+
+    private final Alarm mAutoHideAlarm;
+    private final MultiValueAlpha mMultiValueAlpha;
+
+    private @Nullable ObjectAnimator mAlphaAnimator;
+    private boolean mShouldAutoHide;
+    private float mTargetAutoHideAlpha;
+
+    private boolean mIsSettled = true;
+    private int mTotalScroll;
+
+    public LauncherDotsPageIndicator(Context context) {
+        this(context, null);
+    }
+
+    public LauncherDotsPageIndicator(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public LauncherDotsPageIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        mMultiValueAlpha = new MultiValueAlpha(this, ALPHA_CHANNEL_COUNT);
+        mMultiValueAlpha.setUpdateVisibility(true);
+
+        mTargetAutoHideAlpha = mMultiValueAlpha.get(INDEX_AUTO_HIDE).getValue();
+
+        mAutoHideAlarm = new Alarm();
+        mAutoHideAlarm.setOnAlarmListener(a -> animatePaginationToAlpha(0));
+    }
+
+    @Override
+    public void setScroll(int currentScroll, int totalScroll) {
+        mTotalScroll = totalScroll;
+        super.setScroll(currentScroll, totalScroll);
+    }
+
+    @Override
+    public void setShouldAutoHide(boolean shouldAutoHide) {
+        mShouldAutoHide = shouldAutoHide;
+        mAutoHideAlarm.cancelAlarm();
+        if (!mIsSettled || !mShouldAutoHide) {
+            animatePaginationToAlpha(1);
+        } else {
+            mAutoHideAlarm.setAlarm(PAGINATION_FADE_DELAY);
+        }
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mShouldAutoHide && mTotalScroll == 0) {
+            return;
+        }
+        super.onDraw(canvas);
+    }
+
+    @Override
+    public void setActiveMarker(int activePage) {
+        super.setActiveMarker(activePage);
+    }
+
+    @Override
+    public void setMarkersCount(int numMarkers) {
+        super.setMarkersCount(numMarkers);
+    }
+
+    @Override
+    public void pauseAnimations() {
+        if (mAlphaAnimator != null) {
+            mAlphaAnimator.pause();
+        }
+    }
+
+    @Override
+    public void skipAnimationsToEnd() {
+        if (mAlphaAnimator != null) {
+            mAlphaAnimator.end();
+        }
+    }
+
+    @Override
+    protected void onAnimationStateChanged(boolean isSettled) {
+        mIsSettled = isSettled;
+        if (!mShouldAutoHide) {
+            return;
+        }
+        mAutoHideAlarm.cancelAlarm();
+        if (isSettled) {
+            mAutoHideAlarm.setAlarm(PAGINATION_FADE_DELAY);
+        } else {
+            animatePaginationToAlpha(1f);
+        }
+    }
+
+    private void animatePaginationToAlpha(float targetAlpha) {
+        if (mTargetAutoHideAlpha == targetAlpha) {
+            // Ignore the new animation if it is going to the same alpha as the current animation.
+            return;
+        }
+
+        if (mAlphaAnimator != null) {
+            mAlphaAnimator.cancel();
+        }
+        mAlphaAnimator = ObjectAnimator.ofFloat(mMultiValueAlpha.get(INDEX_AUTO_HIDE),
+                MULTI_PROPERTY_VALUE, targetAlpha);
+        // If we are animating to decrease the alpha, then it's a fade out animation
+        // whereas if we are animating to increase the alpha, it's a fade in animation.
+        mAlphaAnimator.setDuration(targetAlpha == 0
+                ? PAGINATION_FADE_OUT_DURATION
+                : PAGINATION_FADE_IN_DURATION);
+        mAlphaAnimator.addListener(forEndCallback(() -> mAlphaAnimator = null));
+        mAlphaAnimator.start();
+        mTargetAutoHideAlpha = targetAlpha;
+    }
+
+
+    @Override
+    public void stopAllAnimations() {
+        super.stopAllAnimations();
+    }
+
+    @Override
+    public void prepareEntryAnimation() {
+        super.prepareEntryAnimation();
+    }
+
+    @Override
+    public void playEntryAnimation() {
+        super.playEntryAnimation();
+    }
+
+    /**
+     * We need to override setInsets to prevent InsettableFrameLayout from applying different
+     * margins on the pagination.
+     */
+    @Override
+    public void setInsets(Rect insets) {
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+
+    @Override
+    public void setAlpha(PropertySetter setter, float alpha, TimeInterpolator interpolator) {
+        setter.setFloat(mMultiValueAlpha.get(INDEX_VIEW_ALPHA),
+                MULTI_PROPERTY_VALUE, alpha, interpolator);
+    }
+}
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index 570d6ff..193f50d 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -15,6 +15,11 @@
  */
 package com.android.launcher3.pageindicators;
 
+import android.animation.TimeInterpolator;
+import android.view.View;
+
+import com.android.launcher3.anim.PropertySetter;
+
 /**
  * Base class for a page indicator.
  */
@@ -48,9 +53,9 @@
     }
 
     /**
-     * Sets the paint color.
+     * Sets the provided alpha on the pageIndicator
      */
-    default void setPaintColor(int color) {
-        // No-op by default
+    default void setAlpha(PropertySetter setter, float alpha, TimeInterpolator interpolator) {
+        setter.setViewAlpha((View) this, alpha, interpolator);
     }
 }
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index b2c64b3..95452b9 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -25,42 +25,30 @@
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
+import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.Paint.Style;
-import android.graphics.Rect;
 import android.graphics.RectF;
-import android.os.Handler;
-import android.os.Looper;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
-import android.util.IntProperty;
 import android.view.View;
-import android.view.ViewConfiguration;
 import android.view.ViewOutlineProvider;
 import android.view.animation.Interpolator;
 import android.view.animation.OvershootInterpolator;
 
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.util.Themes;
 
 /**
  * {@link PageIndicator} which shows dots per page. The active page is shown with the current
  * accent color.
  */
-public class PageIndicatorDots extends View implements Insettable, PageIndicator {
+public class PageIndicatorDots extends View {
 
     private static final float SHIFT_PER_ANIMATION = 0.5f;
     private static final float SHIFT_THRESHOLD = 0.1f;
     private static final long ANIMATION_DURATION = 150;
-    private static final int PAGINATION_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay();
-    private static final int PAGINATION_FADE_IN_DURATION = 83;
-    private static final int PAGINATION_FADE_OUT_DURATION = 167;
 
     private static final int ENTER_ANIMATION_START_DELAY = 300;
     private static final int ENTER_ANIMATION_STAGGERED_DELAY = 150;
@@ -70,9 +58,6 @@
     private static final int DOT_ALPHA = 128;
     private static final float DOT_ALPHA_FRACTION = 0.5f;
     private static final int DOT_GAP_FACTOR = SHOW_DOT_PAGINATION.get() ? 4 : 3;
-    private static final int VISIBLE_ALPHA = 255;
-    private static final int INVISIBLE_ALPHA = 0;
-    private Paint mPaginationPaint;
 
     // This value approximately overshoots to 1.5 times the original size.
     private static final float ENTER_ANIMATION_OVERSHOOT_TENSION = 4.9f;
@@ -94,30 +79,14 @@
                 }
     };
 
-    private static final IntProperty<PageIndicatorDots> PAGINATION_ALPHA =
-            new IntProperty<PageIndicatorDots>("pagination_alpha") {
-        @Override
-        public Integer get(PageIndicatorDots obj) {
-            return obj.mPaginationPaint.getAlpha();
-        }
-
-        @Override
-        public void setValue(PageIndicatorDots obj, int alpha) {
-            obj.mPaginationPaint.setAlpha(alpha);
-            obj.invalidate();
-        }
-    };
-
-    private final Handler mDelayedPaginationFadeHandler = new Handler(Looper.getMainLooper());
     private final float mDotRadius;
     private final float mCircleGap;
     private final boolean mIsRtl;
 
+    private final Paint mPaginationPaint;
+
     private int mNumPages;
     private int mActivePage;
-    private int mTotalScroll;
-    private boolean mShouldAutoHide;
-    private int mToAlpha;
 
     /**
      * The current position of the active dot including the animation progress.
@@ -131,13 +100,9 @@
     private float mCurrentPosition;
     private float mFinalPosition;
     private ObjectAnimator mAnimator;
-    private @Nullable ObjectAnimator mAlphaAnimator;
 
     private float[] mEntryAnimationRadiusFactors;
 
-    private final Runnable mHidePaginationRunnable =
-            () -> animatePaginationToAlpha(INVISIBLE_ALPHA);
-
     public PageIndicatorDots(Context context) {
         this(context, null);
     }
@@ -151,37 +116,34 @@
 
         mPaginationPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mPaginationPaint.setStyle(Style.FILL);
-        mPaginationPaint.setColor(Themes.getAttrColor(context, R.attr.folderPaginationColor));
+
+        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PagedIndicator);
+        mPaginationPaint.setColor(ta.getColor(R.styleable.PagedIndicator_indicatorDotColor, 0));
+        ta.recycle();
+
         mDotRadius = (SHOW_DOT_PAGINATION.get()
                 ? getResources().getDimension(R.dimen.page_indicator_dot_size_v2)
                 : getResources().getDimension(R.dimen.page_indicator_dot_size))
                 / 2;
         mCircleGap = DOT_GAP_FACTOR * mDotRadius;
         setOutlineProvider(new MyOutlineProver());
-        mIsRtl = Utilities.isRtl(getResources());
+        mIsRtl = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
     }
 
-    @Override
     public void setScroll(int currentScroll, int totalScroll) {
         if (SHOW_DOT_PAGINATION.get() && mActivePage != 0 && currentScroll == 0) {
             CURRENT_POSITION.set(this, (float) mActivePage);
             return;
         }
 
-        if (mNumPages <= 1) {
+        if (mNumPages <= 1 || totalScroll == 0) {
             return;
         }
 
-        if (mShouldAutoHide) {
-            animatePaginationToAlpha(VISIBLE_ALPHA);
-        }
-
         if (mIsRtl) {
             currentScroll = totalScroll - currentScroll;
         }
 
-        mTotalScroll = totalScroll;
-
         int scrollPerPage = totalScroll / (mNumPages - 1);
         int pageToLeft = scrollPerPage == 0 ? 0 : currentScroll / scrollPerPage;
         int pageToLeftScroll = pageToLeft * scrollPerPage;
@@ -191,87 +153,12 @@
         if (currentScroll < pageToLeftScroll + scrollThreshold) {
             // scroll is within the left page's threshold
             animateToPosition(pageToLeft);
-            if (mShouldAutoHide) {
-                hideAfterDelay();
-            }
         } else if (currentScroll > pageToRightScroll - scrollThreshold) {
             // scroll is far enough from left page to go to the right page
             animateToPosition(pageToLeft + 1);
-            if (mShouldAutoHide) {
-                hideAfterDelay();
-            }
         } else {
             // scroll is between left and right page
             animateToPosition(pageToLeft + SHIFT_PER_ANIMATION);
-            if (mShouldAutoHide) {
-                mDelayedPaginationFadeHandler.removeCallbacksAndMessages(null);
-            }
-        }
-    }
-
-    @Override
-    public void setShouldAutoHide(boolean shouldAutoHide) {
-        mShouldAutoHide = shouldAutoHide && SHOW_DOT_PAGINATION.get();
-        if (shouldAutoHide && mPaginationPaint.getAlpha() > INVISIBLE_ALPHA) {
-            hideAfterDelay();
-        } else if (!shouldAutoHide) {
-            mDelayedPaginationFadeHandler.removeCallbacksAndMessages(null);
-        }
-    }
-
-    @Override
-    public void setPaintColor(int color) {
-        mPaginationPaint.setColor(color);
-    }
-
-    private void hideAfterDelay() {
-        mDelayedPaginationFadeHandler.removeCallbacksAndMessages(null);
-        mDelayedPaginationFadeHandler.postDelayed(mHidePaginationRunnable, PAGINATION_FADE_DELAY);
-    }
-
-    private void animatePaginationToAlpha(int alpha) {
-        if (alpha == mToAlpha) {
-            // Ignore the new animation if it is going to the same alpha as the current animation.
-            return;
-        }
-
-        if (mAlphaAnimator != null) {
-            mAlphaAnimator.cancel();
-        }
-        mAlphaAnimator = ObjectAnimator.ofInt(this, PAGINATION_ALPHA,
-                alpha);
-        // If we are animating to decrease the alpha, then it's a fade out animation
-        // whereas if we are animating to increase the alpha, it's a fade in animation.
-        mAlphaAnimator.setDuration(alpha < mToAlpha
-                ? PAGINATION_FADE_OUT_DURATION
-                : PAGINATION_FADE_IN_DURATION);
-        mAlphaAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mAlphaAnimator = null;
-            }
-        });
-        mAlphaAnimator.start();
-        mToAlpha = alpha;
-    }
-
-    /**
-     * Pauses all currently running animations.
-     */
-    @Override
-    public void pauseAnimations() {
-        if (mAlphaAnimator != null) {
-            mAlphaAnimator.pause();
-        }
-    }
-
-    /**
-     * Force-ends all currently running or paused animations.
-     */
-    @Override
-    public void skipAnimationsToEnd() {
-        if (mAlphaAnimator != null) {
-            mAlphaAnimator.end();
         }
     }
 
@@ -281,15 +168,25 @@
             mCurrentPosition = mFinalPosition;
         }
         if (mAnimator == null && Float.compare(mCurrentPosition, mFinalPosition) != 0) {
+            onAnimationStateChanged(false);
             float positionForThisAnim = mCurrentPosition > mFinalPosition ?
                     mCurrentPosition - SHIFT_PER_ANIMATION : mCurrentPosition + SHIFT_PER_ANIMATION;
             mAnimator = ObjectAnimator.ofFloat(this, CURRENT_POSITION, positionForThisAnim);
             mAnimator.addListener(new AnimationCycleListener());
             mAnimator.setDuration(ANIMATION_DURATION);
             mAnimator.start();
+        } else if (mAnimator == null) {
+            // The state is only settled if the indicator lands on a int value
+            onAnimationStateChanged(Float.compare(Math.round(mFinalPosition), mFinalPosition) == 0);
         }
     }
 
+    /**
+     * Called when the animation state of the page indicator changes.
+     * @param isSettled true if the page indicator has settled at its final position
+     */
+    protected void onAnimationStateChanged(boolean isSettled) { }
+
     public void stopAllAnimations() {
         if (mAnimator != null) {
             mAnimator.cancel();
@@ -345,14 +242,10 @@
         animSet.start();
     }
 
-    @Override
     public void setActiveMarker(int activePage) {
-        if (mActivePage != activePage) {
-            mActivePage = activePage;
-        }
+        mActivePage = activePage;
     }
 
-    @Override
     public void setMarkersCount(int numMarkers) {
         mNumPages = numMarkers;
         requestLayout();
@@ -374,11 +267,6 @@
             return;
         }
 
-        if (mShouldAutoHide && mTotalScroll == 0) {
-            mPaginationPaint.setAlpha(INVISIBLE_ALPHA);
-            return;
-        }
-
         // Draw all page indicators;
         float circleGap = mCircleGap;
         float startX = (getWidth() - (mNumPages * circleGap) + mDotRadius) / 2;
@@ -480,20 +368,9 @@
         @Override
         public void onAnimationEnd(Animator animation) {
             if (!mCancelled) {
-                if (mShouldAutoHide && SHOW_DOT_PAGINATION.get()) {
-                    hideAfterDelay();
-                }
                 mAnimator = null;
                 animateToPosition(mFinalPosition);
             }
         }
     }
-
-    /**
-     * We need to override setInsets to prevent InsettableFrameLayout from applying different
-     * margins on the pagination.
-     */
-    @Override
-    public void setInsets(Rect insets) {
-    }
 }
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index 7ca3b11..125b4ce 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -181,9 +181,10 @@
     public boolean isTrustedPackage(String pkg, UserHandle user) {
         synchronized (mSessionVerifiedMap) {
             if (!mSessionVerifiedMap.containsKey(pkg)) {
-                boolean hasSystemFlag = new PackageManagerHelper(mAppContext).getApplicationInfo(
-                        pkg, user, ApplicationInfo.FLAG_SYSTEM) != null;
-                mSessionVerifiedMap.put(pkg, DEBUG || hasSystemFlag);
+                boolean hasSystemFlag = DEBUG || mAppContext.getPackageName().equals(pkg)
+                        || new PackageManagerHelper(mAppContext)
+                                .getApplicationInfo(pkg, user, ApplicationInfo.FLAG_SYSTEM) != null;
+                mSessionVerifiedMap.put(pkg, hasSystemFlag);
             }
         }
         return mSessionVerifiedMap.get(pkg);
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 0edf292..5b493c2 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -109,7 +109,7 @@
     protected final int mArrowPointRadius;
     protected final View mArrow;
 
-    private final int mMargin;
+    protected final int mChildContainerMargin;
 
     protected boolean mIsLeftAligned;
     protected boolean mIsAboveIcon;
@@ -145,7 +145,7 @@
         // Initialize arrow view
         final Resources resources = getResources();
         mArrowColor = getColorStateList(getContext(), R.color.popup_shade_first).getDefaultColor();
-        mMargin = resources.getDimensionPixelSize(R.dimen.popup_margin);
+        mChildContainerMargin = resources.getDimensionPixelSize(R.dimen.popup_margin);
         mArrowWidth = resources.getDimensionPixelSize(R.dimen.popup_arrow_width);
         mArrowHeight = resources.getDimensionPixelSize(R.dimen.popup_arrow_height);
         mArrow = new View(context);
@@ -249,7 +249,7 @@
             if (view.getVisibility() == VISIBLE) {
                 if (lastView != null) {
                     MarginLayoutParams mlp = (MarginLayoutParams) lastView.getLayoutParams();
-                    mlp.bottomMargin = mMargin;
+                    mlp.bottomMargin = mChildContainerMargin;
                 }
                 lastView = view;
                 MarginLayoutParams mlp = (MarginLayoutParams) lastView.getLayoutParams();
@@ -441,7 +441,7 @@
                 numVisibleChildren++;
             }
         }
-        int childMargins = (numVisibleChildren - 1) * mMargin;
+        int childMargins = (numVisibleChildren - 1) * mChildContainerMargin;
         int height = getMeasuredHeight() + extraVerticalSpace + childMargins;
         int width = getMeasuredWidth() + getPaddingLeft() + getPaddingRight();
 
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 3f75ecc..9cca29a 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -95,6 +95,8 @@
 
     private static final int SHORTCUT_COLLAPSE_THRESHOLD = 6;
 
+    private final float mShortcutHeight;
+
     private BubbleTextView mOriginalIcon;
     private int mNumNotifications;
     private NotificationContainer mNotificationContainer;
@@ -112,6 +114,7 @@
         mStartDragThreshold = getResources().getDimensionPixelSize(
                 R.dimen.deep_shortcuts_start_drag_threshold);
         mContainerWidth = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_width);
+        mShortcutHeight = getResources().getDimension(R.dimen.system_shortcut_header_height);
     }
 
     public PopupContainerWithArrow(Context context, AttributeSet attrs) {
@@ -387,16 +390,18 @@
      */
     private void addAllShortcutsMaterialU(int deepShortcutCount,
             List<SystemShortcut> systemShortcuts) {
-
         if (deepShortcutCount + systemShortcuts.size() <= SHORTCUT_COLLAPSE_THRESHOLD) {
             // add all system shortcuts including widgets shortcut to same container
             addSystemShortcutsMaterialU(systemShortcuts,
                     R.layout.system_shortcut_rows_container_material_u,
                     R.layout.system_shortcut);
-            addDeepShortcutsMaterialU(deepShortcutCount);
+            float currentHeight = (mShortcutHeight * systemShortcuts.size())
+                    + mChildContainerMargin;
+            addDeepShortcutsMaterialU(deepShortcutCount, currentHeight);
             return;
         }
 
+        float currentHeight = mShortcutHeight + mChildContainerMargin;
         List<SystemShortcut> nonWidgetSystemShortcuts =
                 getNonWidgetSystemShortcuts(systemShortcuts);
         // If total shortcuts over threshold, collapse system shortcuts to single row
@@ -411,8 +416,9 @@
             mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container_material_u,
                     this);
             initializeWidgetShortcut(mWidgetContainer, widgetShortcutOpt.get());
+            currentHeight += mShortcutHeight + mChildContainerMargin;
         }
-        addDeepShortcutsMaterialU(deepShortcutCount);
+        addDeepShortcutsMaterialU(deepShortcutCount, currentHeight);
     }
 
     /**
@@ -497,10 +503,14 @@
     /**
      * Inflates and adds [deepShortcutCount] number of DeepShortcutView for the  to a new container
      * @param deepShortcutCount number of DeepShortcutView instances to add
+     * @param currentHeight height of popup before adding deep shortcuts
      */
-    private void addDeepShortcutsMaterialU(int deepShortcutCount) {
+    private void addDeepShortcutsMaterialU(int deepShortcutCount, float currentHeight) {
         mDeepShortcutContainer = inflateAndAdd(R.layout.deep_shortcut_container, this);
         for (int i = deepShortcutCount; i > 0; i--) {
+            currentHeight += mShortcutHeight;
+            // when there is limited vertical screen space, limit total popup rows to fit
+            if (currentHeight >= mActivityContext.getDeviceProfile().availableHeightPx) break;
             DeepShortcutView v = inflateAndAdd(R.layout.deep_shortcut_material_u,
                     mDeepShortcutContainer);
             v.getLayoutParams().width = mContainerWidth;
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 3d455d8..02ebb15 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -23,6 +23,7 @@
 import static com.android.launcher3.config.FeatureFlags.ENABLE_TRANSIENT_TASKBAR;
 import static com.android.launcher3.config.FeatureFlags.FORCE_PERSISTENT_TASKBAR;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.FlagDebugUtils.appendFlag;
 import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH;
 
 import android.annotation.SuppressLint;
@@ -55,6 +56,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.StringJoiner;
 
 /**
  * Utility class to cache properties of default display to avoid a system RPC on every call.
@@ -66,6 +68,9 @@
     private static final boolean DEBUG = false;
     private static boolean sTransientTaskbarStatusForTests;
 
+    // TODO(b/254119092) remove all logs with this tag
+    public static final String TASKBAR_NOT_DESTROYED_TAG = "b/254119092";
+
     public static final MainThreadInitializedObject<DisplayController> INSTANCE =
             new MainThreadInitializedObject<>(DisplayController::new);
 
@@ -206,6 +211,7 @@
     @Override
     @TargetApi(Build.VERSION_CODES.S)
     public final void onConfigurationChanged(Configuration config) {
+        Log.d(TASKBAR_NOT_DESTROYED_TAG, "DisplayController#onConfigurationChanged: " + config);
         Display display = mWindowContext.getDisplay();
         if (config.densityDpi != mInfo.densityDpi
                 || config.fontScale != mInfo.fontScale
@@ -272,7 +278,7 @@
             change |= CHANGE_SUPPORTED_BOUNDS;
         }
         if (DEBUG) {
-            Log.d(TAG, "handleInfoChange - change: 0b" + Integer.toBinaryString(change));
+            Log.d(TAG, "handleInfoChange - change: " + getChangeFlagsString(change));
         }
 
         if (change != 0) {
@@ -386,12 +392,33 @@
             return dpiFromPx(Math.min(bounds.bounds.width(), bounds.bounds.height()), densityDpi);
         }
 
+        /**
+         * Returns all displays for the device
+         */
+        public Set<CachedDisplayInfo> getAllDisplays() {
+            return Collections.unmodifiableSet(mPerDisplayBounds.keySet());
+        }
+
         public int getDensityDpi() {
             return densityDpi;
         }
     }
 
     /**
+     * Returns the given binary flags as a human-readable string.
+     * @see #CHANGE_ALL
+     */
+    public String getChangeFlagsString(int change) {
+        StringJoiner result = new StringJoiner("|");
+        appendFlag(result, change, CHANGE_ACTIVE_SCREEN, "CHANGE_ACTIVE_SCREEN");
+        appendFlag(result, change, CHANGE_ROTATION, "CHANGE_ROTATION");
+        appendFlag(result, change, CHANGE_DENSITY, "CHANGE_DENSITY");
+        appendFlag(result, change, CHANGE_SUPPORTED_BOUNDS, "CHANGE_SUPPORTED_BOUNDS");
+        appendFlag(result, change, CHANGE_NAVIGATION_MODE, "CHANGE_NAVIGATION_MODE");
+        return result.toString();
+    }
+
+    /**
      * Dumps the current state information
      */
     public void dump(PrintWriter pw) {
diff --git a/src/com/android/launcher3/util/SplitConfigurationOptions.java b/src/com/android/launcher3/util/SplitConfigurationOptions.java
index 8c5e782..1ae43d0 100644
--- a/src/com/android/launcher3/util/SplitConfigurationOptions.java
+++ b/src/com/android/launcher3/util/SplitConfigurationOptions.java
@@ -200,8 +200,8 @@
         /** Keep in sync w/ ActivityTaskManager#INVALID_TASK_ID (unreference-able) */
         private static final int INVALID_TASK_ID = -1;
 
-        public final View view;
-        public final Drawable drawable;
+        private View view;
+        private Drawable drawable;
         public final Intent intent;
         public final SplitPositionOption position;
         public final ItemInfo itemInfo;
@@ -224,5 +224,13 @@
             this.itemInfo = itemInfo;
             this.splitEvent = splitEvent;
         }
+
+        public Drawable getDrawable() {
+            return drawable;
+        }
+
+        public View getView() {
+            return view;
+        }
     }
 }
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
index 5526839..a5c663f 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -32,10 +32,13 @@
 import android.util.SparseArray;
 import android.util.TypedValue;
 
+import androidx.annotation.ColorInt;
+
 import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.icons.GraphicsUtils;
+import com.android.launcher3.views.ActivityContext;
 
 /**
  * Various utility methods associated with theming.
@@ -198,4 +201,12 @@
 
         return result;
     }
+
+    /** Returns the desired navigation bar scrim color depending on the {@code DeviceProfile}. */
+    @ColorInt
+    public static <T extends Context & ActivityContext> int getNavBarScrimColor(T context) {
+        return context.getDeviceProfile().isTaskbarPresent
+                ? context.getColor(R.color.taskbar_background)
+                : Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor);
+    }
 }
diff --git a/src/com/android/launcher3/util/ViewOnDrawExecutor.java b/src/com/android/launcher3/util/ViewOnDrawExecutor.java
index 5d90291..3fa5799 100644
--- a/src/com/android/launcher3/util/ViewOnDrawExecutor.java
+++ b/src/com/android/launcher3/util/ViewOnDrawExecutor.java
@@ -16,11 +16,13 @@
 
 package com.android.launcher3.util;
 
+import android.util.Log;
 import android.view.View;
 import android.view.View.OnAttachStateChangeListener;
 import android.view.ViewTreeObserver.OnDrawListener;
 
 import com.android.launcher3.Launcher;
+import com.android.launcher3.testing.shared.TestProtocol;
 
 import java.util.function.Consumer;
 
@@ -42,12 +44,21 @@
     private boolean mCancelled;
 
     public ViewOnDrawExecutor(RunnableList tasks) {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.FLAKY_BINDING, "Initialize ViewOnDrawExecutor");
+        }
         mTasks = tasks;
     }
 
     public void attachTo(Launcher launcher) {
         mOnClearCallback = launcher::clearPendingExecutor;
         mAttachedView = launcher.getWorkspace();
+
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.FLAKY_BINDING, "ViewOnDrawExecutor.attachTo: launcher=" + launcher
+                    + ", isAttachedToWindow=" + mAttachedView.isAttachedToWindow());
+        }
+
         mAttachedView.addOnAttachStateChangeListener(this);
 
         if (mAttachedView.isAttachedToWindow()) {
@@ -56,6 +67,10 @@
     }
 
     private void attachObserver() {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.FLAKY_BINDING,
+                    "ViewOnDrawExecutor.attachObserver: mCompleted=" + mCompleted);
+        }
         if (!mCompleted) {
             mAttachedView.getViewTreeObserver().addOnDrawListener(this);
         }
@@ -63,6 +78,9 @@
 
     @Override
     public void onViewAttachedToWindow(View v) {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.FLAKY_BINDING, "ViewOnDrawExecutor.onViewAttachedToWindow");
+        }
         attachObserver();
     }
 
@@ -71,11 +89,19 @@
 
     @Override
     public void onDraw() {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.FLAKY_BINDING, "ViewOnDrawExecutor.onDraw");
+        }
         mFirstDrawCompleted = true;
         mAttachedView.post(this);
     }
 
     public void onLoadAnimationCompleted() {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.FLAKY_BINDING,
+                    "ViewOnDrawExecutor.onLoadAnimationCompleted: mAttachedView != null="
+                            + (mAttachedView != null));
+        }
         mLoadAnimationCompleted = true;
         if (mAttachedView != null) {
             mAttachedView.post(this);
@@ -84,6 +110,12 @@
 
     @Override
     public void run() {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.FLAKY_BINDING,
+                    "ViewOnDrawExecutor.run: mLoadAnimationCompleted=" + mLoadAnimationCompleted
+                            + ", mFirstDrawCompleted=" + mFirstDrawCompleted
+                            + ", mCompleted=" + mCompleted);
+        }
         // Post the pending tasks after both onDraw and onLoadAnimationCompleted have been called.
         if (mLoadAnimationCompleted && mFirstDrawCompleted && !mCompleted) {
             markCompleted();
@@ -94,6 +126,12 @@
      * Executes all tasks immediately
      */
     public void markCompleted() {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.FLAKY_BINDING,
+                    "ViewOnDrawExecutor.markCompleted: mCancelled=" + mCancelled
+                            + ", mOnClearCallback != null=" + (mOnClearCallback != null)
+                            + ", mAttachedView != null=" + (mAttachedView != null));
+        }
         if (!mCancelled) {
             mTasks.executeAllAndDestroy();
         }
@@ -108,6 +146,9 @@
     }
 
     public void cancel() {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.FLAKY_BINDING, "ViewOnDrawExecutor.cancel");
+        }
         mCancelled = true;
         markCompleted();
     }
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index a941833..c0b24fa 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -333,6 +333,7 @@
         }
     }
 
+    @Override
     public void onDraw(Canvas canvas) {
         if (mThumbOffsetY < 0 || mRv == null) {
             return;
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 07c6ba4..c3f26fa 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -37,6 +37,7 @@
 import androidx.core.view.ViewCompat;
 
 import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
 import com.android.launcher3.DragSource;
 import com.android.launcher3.DropTarget.DragObject;
 import com.android.launcher3.Insettable;
@@ -60,7 +61,7 @@
  */
 public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
         implements OnClickListener, OnLongClickListener, DragSource,
-        PopupDataProvider.PopupDataChangeListener, Insettable {
+        PopupDataProvider.PopupDataChangeListener, Insettable, OnDeviceProfileChangeListener {
     /** The default number of cells that can fit horizontally in a widget sheet. */
     public static final int DEFAULT_MAX_HORIZONTAL_SPANS = 4;
 
@@ -84,7 +85,7 @@
         mWidgetCellHorizontalPadding = getResources().getDimensionPixelSize(
                 R.dimen.widget_cell_horizontal_padding);
         mNavBarScrimPaint = new Paint();
-        mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
+        mNavBarScrimPaint.setColor(Themes.getNavBarScrimColor(mActivityContext));
     }
 
     protected int getScrimColor(Context context) {
@@ -98,12 +99,23 @@
                 .normalizeWindowInsets(getContext(), getRootWindowInsets(), new Rect());
         mNavBarScrimHeight = getNavBarScrimHeight(windowInsets);
         mActivityContext.getPopupDataProvider().setChangeListener(this);
+        mActivityContext.addOnDeviceProfileChangeListener(this);
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         mActivityContext.getPopupDataProvider().setChangeListener(null);
+        mActivityContext.removeOnDeviceProfileChangeListener(this);
+    }
+
+    @Override
+    public void onDeviceProfileChanged(DeviceProfile dp) {
+        int navBarScrimColor = Themes.getNavBarScrimColor(mActivityContext);
+        if (mNavBarScrimPaint.getColor() != navBarScrimColor) {
+            mNavBarScrimPaint.setColor(navBarScrimColor);
+            invalidate();
+        }
     }
 
     @Override
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 5293c3d..5e165df 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -110,6 +110,7 @@
             entry -> !mCurrentUser.equals(entry.mPkgItem.user)
                     && !mUserManagerState.isUserQuiet(entry.mPkgItem.user);
     protected final boolean mHasWorkProfile;
+    protected boolean mHasRecommendedWidgets;
     protected final SparseArray<AdapterHolder> mAdapters = new SparseArray();
     @Nullable private ArrowTipView mLatestEducationalTip;
     private final OnLayoutChangeListener mLayoutChangeListenerToShowTips =
@@ -537,7 +538,6 @@
     public void onSearchResults(List<WidgetsListBaseEntry> entries) {
         mAdapters.get(AdapterHolder.SEARCH).mWidgetsListAdapter.setWidgetsOnSearch(entries);
         updateRecyclerViewVisibility(mAdapters.get(AdapterHolder.SEARCH));
-        mAdapters.get(AdapterHolder.SEARCH).mWidgetsRecyclerView.scrollToTop();
     }
 
     protected void setViewVisibilityBasedOnSearch(boolean isInSearchMode) {
@@ -574,7 +574,8 @@
         }
         List<WidgetItem> recommendedWidgets =
                 mActivityContext.getPopupDataProvider().getRecommendedWidgets();
-        if (recommendedWidgets.size() > 0) {
+        mHasRecommendedWidgets = recommendedWidgets.size() > 0;
+        if (mHasRecommendedWidgets) {
             float noWidgetsViewHeight = 0;
             if (mIsNoWidgetsViewNeeded) {
                 // Make sure recommended section leaves enough space for noWidgetsView.
@@ -603,14 +604,10 @@
             mRecommendedWidgetsTable.setRecommendedWidgets(
                     recommendedWidgetsInTable, maxTableHeight);
         } else {
-            hideRecommendations();
+            mRecommendedWidgetsTable.setVisibility(GONE);
         }
     }
 
-    protected void hideRecommendations() {
-        mRecommendedWidgetsTable.setVisibility(GONE);
-    }
-
     protected float getMaxTableHeight(float noWidgetsViewHeight) {
         return (mContent.getMeasuredHeight()
                 - mTabsHeight - getHeaderViewHeight()
@@ -686,12 +683,13 @@
     public static WidgetsFullSheet show(Launcher launcher, boolean animate) {
         boolean isTwoPane = LARGE_SCREEN_WIDGET_PICKER.get()
                 && launcher.getDeviceProfile().isTablet
-                && launcher.getDeviceProfile().isLandscape;
+                && launcher.getDeviceProfile().isLandscape
+                && !launcher.getDeviceProfile().isTwoPanels;
 
         WidgetsFullSheet sheet;
         if (isTwoPane) {
             sheet = (WidgetsTwoPaneSheet) launcher.getLayoutInflater().inflate(
-                    R.layout.widgets_full_sheet_large_screen,
+                    R.layout.widgets_two_pane_sheet,
                     launcher.getDragLayer(),
                     false);
         } else {
@@ -896,7 +894,7 @@
         final WidgetsListAdapter mWidgetsListAdapter;
         private final DefaultItemAnimator mWidgetsListItemAnimator;
 
-        private WidgetsRecyclerView mWidgetsRecyclerView;
+        WidgetsRecyclerView mWidgetsRecyclerView;
 
         AdapterHolder(int adapterType) {
             mAdapterType = adapterType;
diff --git a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
index 2199473..d85737b 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
@@ -54,6 +54,7 @@
 
     private ScrollView mRightPaneScrollView;
     private WidgetsListTableViewHolderBinder mWidgetsListTableViewHolderBinder;
+    private int mActivePage = -1;
 
     private final ViewOutlineProvider mViewOutlineProviderRightPane = new ViewOutlineProvider() {
         @Override
@@ -63,7 +64,7 @@
                     0,
                     view.getMeasuredWidth(),
                     view.getMeasuredHeight() - getResources().getDimensionPixelSize(
-                            R.dimen.widget_list_horizontal_margin_large_screen),
+                            R.dimen.widget_list_horizontal_margin_two_pane),
                     view.getResources().getDimensionPixelSize(
                             R.dimen.widget_list_top_bottom_corner_radius)
             );
@@ -90,8 +91,8 @@
 
         LayoutInflater layoutInflater = LayoutInflater.from(getContext());
 
-        int contentLayoutRes = mHasWorkProfile ? R.layout.widgets_full_sheet_paged_view_large_screen
-                : R.layout.widgets_full_sheet_recyclerview_large_screen;
+        int contentLayoutRes = mHasWorkProfile ? R.layout.widgets_two_pane_sheet_paged_view
+                : R.layout.widgets_two_pane_sheet_recyclerview;
         layoutInflater.inflate(contentLayoutRes, findViewById(R.id.recycler_view_container), true);
 
         setupViews();
@@ -107,7 +108,6 @@
         mRightPaneScrollView = mContent.findViewById(R.id.right_pane_scroll_view);
         mRightPaneScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER);
 
-        setupSuggestedWidgets(layoutInflater);
         onRecommendedWidgetsBound();
         onWidgetsBound();
         setUpEducationViewsIfNeeded();
@@ -117,9 +117,13 @@
     }
 
     @Override
-    protected void hideRecommendations() {
-        super.hideRecommendations();
-        mSuggestedWidgetsContainer.setVisibility(GONE);
+    public void onRecommendedWidgetsBound() {
+        super.onRecommendedWidgetsBound();
+
+        if (mSuggestedWidgetsContainer == null && mHasRecommendedWidgets) {
+            setupSuggestedWidgets(LayoutInflater.from(getContext()));
+            mSuggestedWidgetsHeader.callOnClick();
+        }
     }
 
     private void setupSuggestedWidgets(LayoutInflater layoutInflater) {
@@ -168,13 +172,21 @@
 
     @Override
     public void onActivePageChanged(int currentActivePage) {
-        // if the current active page changes to personal or work we set suggestions
-        // to be the selected widget
-        if (currentActivePage == PERSONAL_TAB || currentActivePage == WORK_TAB) {
-            mSuggestedWidgetsHeader.callOnClick();
+        super.onActivePageChanged(currentActivePage);
+
+        // If active page didn't change then we don't want to update the header.
+        if (mActivePage == currentActivePage) {
+            return;
         }
 
-        super.onActivePageChanged(currentActivePage);
+        mActivePage = currentActivePage;
+
+        if (mSuggestedWidgetsHeader == null) {
+            mAdapters.get(currentActivePage).mWidgetsListAdapter.selectFirstHeaderEntry();
+            mAdapters.get(currentActivePage).mWidgetsRecyclerView.scrollToTop();
+        } else if (currentActivePage == PERSONAL_TAB || currentActivePage == WORK_TAB) {
+            mSuggestedWidgetsHeader.callOnClick();
+        }
     }
 
     @Override
@@ -188,15 +200,10 @@
     }
 
     @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mSuggestedWidgetsContainer.setVisibility(VISIBLE);
-    }
-
-    @Override
     public void onSearchResults(List<WidgetsListBaseEntry> entries) {
         super.onSearchResults(entries);
         mAdapters.get(AdapterHolder.SEARCH).mWidgetsListAdapter.selectFirstHeaderEntry();
+        mAdapters.get(AdapterHolder.SEARCH).mWidgetsRecyclerView.scrollToTop();
     }
 
     @Override
@@ -208,13 +215,19 @@
 
     @Override
     protected void setViewVisibilityBasedOnSearch(boolean isInSearchMode) {
-        if (isInSearchMode) {
-            mSuggestedWidgetsContainer.setVisibility(GONE);
-        } else {
-            mSuggestedWidgetsContainer.setVisibility(VISIBLE);
-            mSuggestedWidgetsHeader.callOnClick();
-        }
         super.setViewVisibilityBasedOnSearch(isInSearchMode);
+
+        if (mSuggestedWidgetsHeader != null && mSuggestedWidgetsContainer != null) {
+            if (!isInSearchMode) {
+                mSuggestedWidgetsContainer.setVisibility(VISIBLE);
+                mSuggestedWidgetsHeader.callOnClick();
+            } else {
+                mSuggestedWidgetsContainer.setVisibility(GONE);
+            }
+        } else if (!isInSearchMode) {
+            mAdapters.get(mActivePage).mWidgetsListAdapter.selectFirstHeaderEntry();
+        }
+
     }
 
     @Override
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/flags/FlagsFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/flags/FlagsFactory.java
index 4463adc..eb0494e 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/flags/FlagsFactory.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/flags/FlagsFactory.java
@@ -16,7 +16,10 @@
 
 package com.android.launcher3.uioverrides.flags;
 
+import static com.android.launcher3.config.FeatureFlags.FlagState.ENABLED;
+
 import com.android.launcher3.config.FeatureFlags.BooleanFlag;
+import com.android.launcher3.config.FeatureFlags.FlagState;
 import com.android.launcher3.config.FeatureFlags.IntFlag;
 
 import java.io.PrintWriter;
@@ -31,16 +34,16 @@
      * Creates a new debug flag
      */
     public static BooleanFlag getDebugFlag(
-            int bugId, String key, boolean defaultValue, String description) {
-        return new BooleanFlag(defaultValue);
+            int bugId, String key, FlagState flagState, String description) {
+        return new BooleanFlag(flagState == ENABLED);
     }
 
     /**
      * Creates a new debug flag
      */
     public static BooleanFlag getReleaseFlag(
-            int bugId, String key, boolean defaultValueInCode, String description) {
-        return new BooleanFlag(defaultValueInCode);
+            int bugId, String key, FlagState flagState, String description) {
+        return new BooleanFlag(flagState == ENABLED);
     }
 
     /**
diff --git a/tests/res/raw/devices.json b/tests/res/raw/devices.json
deleted file mode 100644
index a78dd86..0000000
--- a/tests/res/raw/devices.json
+++ /dev/null
@@ -1,45 +0,0 @@
-{
-  "pixel6pro": {
-    "width": 1440,
-    "height": 3120,
-    "density": 560,
-    "name": "pixel6pro",
-    "cutout": "0, 130, 0, 0",
-    "grids": [
-      "normal",
-      "reasonable",
-      "practical",
-      "big",
-      "crazy_big"
-    ],
-    "resourceOverrides": {
-      "status_bar_height": 98,
-      "navigation_bar_height_landscape": 56,
-      "navigation_bar_height": 56,
-      "navigation_bar_width": 56
-    }
-  },
-  "test": {
-    "data needs updating": 0
-  },
-  "pixel5": {
-    "width": 1080,
-    "height": 2340,
-    "density": 440,
-    "name": "pixel5",
-    "cutout": "0, 136, 0, 0",
-    "grids": [
-      "normal",
-      "reasonable",
-      "practical",
-      "big",
-      "crazy_big"
-    ],
-    "resourceOverrides": {
-      "status_bar_height": 66,
-      "navigation_bar_height_landscape": 44,
-      "navigation_bar_height": 44,
-      "navigation_bar_width": 44
-    }
-  }
-}
diff --git a/tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt b/tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
index a5f33c0..c22cf40 100644
--- a/tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
+++ b/tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
@@ -153,6 +153,9 @@
 
                 isScalable = true
 
+                transientTaskbarIconSize = FloatArray(4) { 44f }
+                startAlignTaskbar = BooleanArray(4) { false }
+
                 inlineQsb = BooleanArray(4) { false }
 
                 devicePaddingId = R.xml.paddings_handhelds
@@ -233,6 +236,9 @@
                 isScalable = true
                 devicePaddingId = R.xml.paddings_6x5
 
+                transientTaskbarIconSize = FloatArray(4) { 44f }
+                startAlignTaskbar = booleanArrayOf(true, false, true, true)
+
                 inlineQsb = booleanArrayOf(false, true, false, false)
 
                 devicePaddingId = R.xml.paddings_handhelds
@@ -308,6 +314,9 @@
 
                 isScalable = true
 
+                transientTaskbarIconSize = FloatArray(4) { 44f }
+                startAlignTaskbar = BooleanArray(4) { true }
+
                 inlineQsb = booleanArrayOf(false, false, false, false)
 
                 devicePaddingId = R.xml.paddings_handhelds
diff --git a/tests/src/com/android/launcher3/deviceemulator/DisplayEmulator.java b/tests/src/com/android/launcher3/deviceemulator/DisplayEmulator.java
deleted file mode 100644
index e2ed65f..0000000
--- a/tests/src/com/android/launcher3/deviceemulator/DisplayEmulator.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.deviceemulator;
-
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.net.Uri;
-import android.os.UserHandle;
-import android.view.Display;
-import android.view.IWindowManager;
-import android.view.WindowManagerGlobal;
-
-import androidx.test.uiautomator.UiDevice;
-
-import com.android.launcher3.deviceemulator.models.DeviceEmulationData;
-import com.android.launcher3.tapl.LauncherInstrumentation;
-import com.android.launcher3.util.window.WindowManagerProxy;
-
-import java.util.concurrent.Callable;
-
-
-public class DisplayEmulator {
-    Context mContext;
-    LauncherInstrumentation mLauncher;
-    DisplayEmulator(Context context, LauncherInstrumentation launcher) {
-        mContext = context;
-        mLauncher = launcher;
-    }
-
-    /**
-     * By changing the WindowManagerProxy we can override the window insets information
-     **/
-    private IWindowManager changeWindowManagerInstance(DeviceEmulationData deviceData) {
-        WindowManagerProxy.INSTANCE.initializeForTesting(new TestWindowManagerProxy(deviceData));
-        return WindowManagerGlobal.getWindowManagerService();
-    }
-
-    public <T> T emulate(DeviceEmulationData device, String grid, Callable<T> runInEmulation)
-            throws Exception {
-        WindowManagerProxy original = WindowManagerProxy.INSTANCE.get(mContext);
-        // Set up emulation
-        final int userId = UserHandle.myUserId();
-        WindowManagerProxy.INSTANCE.initializeForTesting(new TestWindowManagerProxy(device));
-        IWindowManager wm = changeWindowManagerInstance(device);
-        // Change density twice to force display controller to reset its state
-        wm.setForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY, device.density / 2, userId);
-        wm.setForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY, device.density, userId);
-        wm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, device.width, device.height);
-        wm.setForcedDisplayScalingMode(Display.DEFAULT_DISPLAY, 1);
-
-        // Set up grid
-        setGrid(grid);
-        try {
-            return runInEmulation.call();
-        } finally {
-            // Clear emulation
-            WindowManagerProxy.INSTANCE.initializeForTesting(original);
-            UiDevice.getInstance(getInstrumentation()).executeShellCommand("cmd window reset");
-        }
-    }
-
-    private void setGrid(String gridType) {
-        // When the grid changes, the desktop arrangement get stored in SQL and we need to wait to
-        // make sure there is no SQL operations running and get SQL_BUSY error, that's why we need
-        // to call mLauncher.waitForLauncherInitialized();
-        mLauncher.waitForLauncherInitialized();
-        String testProviderAuthority = mContext.getPackageName() + ".grid_control";
-        Uri gridUri = new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(testProviderAuthority)
-                .appendPath("default_grid")
-                .build();
-        ContentValues values = new ContentValues();
-        values.put("name", gridType);
-        mContext.getContentResolver().update(gridUri, values, null, null);
-    }
-}
diff --git a/tests/src/com/android/launcher3/deviceemulator/TestWindowManagerProxy.java b/tests/src/com/android/launcher3/deviceemulator/TestWindowManagerProxy.java
deleted file mode 100644
index 2d6bbcc..0000000
--- a/tests/src/com/android/launcher3/deviceemulator/TestWindowManagerProxy.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.deviceemulator;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.view.WindowInsets;
-
-import com.android.launcher3.deviceemulator.models.DeviceEmulationData;
-import com.android.launcher3.util.RotationUtils;
-import com.android.launcher3.util.WindowBounds;
-import com.android.launcher3.util.window.CachedDisplayInfo;
-import com.android.launcher3.util.window.WindowManagerProxy;
-
-public class TestWindowManagerProxy extends WindowManagerProxy {
-
-    private final DeviceEmulationData mDevice;
-
-    public TestWindowManagerProxy(DeviceEmulationData device) {
-        super(true);
-        mDevice = device;
-    }
-
-    @Override
-    protected int getDimenByName(Resources res, String resName) {
-        Integer mock = mDevice.resourceOverrides.get(resName);
-        return mock != null ? mock : super.getDimenByName(res, resName);
-    }
-
-    @Override
-    protected int getDimenByName(Resources res, String resName, String fallback) {
-        return getDimenByName(res, resName);
-    }
-
-    @Override
-    public CachedDisplayInfo getDisplayInfo(Context displayInfoContext) {
-        int rotation = getRotation(displayInfoContext);
-        Point size = new Point(mDevice.width, mDevice.height);
-        RotationUtils.rotateSize(size, rotation);
-        Rect cutout = new Rect(mDevice.cutout);
-        RotationUtils.rotateRect(cutout, rotation);
-        return new CachedDisplayInfo(size, rotation, cutout);
-    }
-
-    @Override
-    public WindowBounds getRealBounds(Context displayInfoContext, CachedDisplayInfo info) {
-        return estimateInternalDisplayBounds(displayInfoContext).get(
-                getDisplayInfo(displayInfoContext))[getDisplay(displayInfoContext).getRotation()];
-    }
-
-    @Override
-    public WindowInsets normalizeWindowInsets(Context context, WindowInsets oldInsets,
-            Rect outInsets) {
-        outInsets.set(getRealBounds(context, getDisplayInfo(context)).insets);
-        return oldInsets;
-    }
-}
diff --git a/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java b/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java
deleted file mode 100644
index 55b7bf1..0000000
--- a/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.deviceemulator.models;
-
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import static com.android.launcher3.testing.shared.ResourceUtils.NAVBAR_HEIGHT;
-import static com.android.launcher3.testing.shared.ResourceUtils.NAVBAR_HEIGHT_LANDSCAPE;
-import static com.android.launcher3.testing.shared.ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE;
-import static com.android.launcher3.testing.shared.ResourceUtils.getDimenByName;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Rect;
-import android.os.Build;
-import android.util.ArrayMap;
-
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.IOUtils;
-import com.android.launcher3.util.IntArray;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Map;
-
-public class DeviceEmulationData {
-
-    public final int width;
-    public final int height;
-    public final int density;
-    public final String name;
-    public final String[] grids;
-    public final Rect cutout;
-    public final Map<String, Integer> resourceOverrides;
-
-    private static final String[] EMULATED_SYSTEM_RESOURCES = new String[]{
-            NAVBAR_HEIGHT,
-            NAVBAR_HEIGHT_LANDSCAPE,
-            NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE,
-            "status_bar_height",
-    };
-
-    public DeviceEmulationData(int width, int height, int density, Rect cutout, String name,
-            String[] grid,
-            Map<String, Integer> resourceOverrides) {
-        this.width = width;
-        this.height = height;
-        this.density = density;
-        this.name = name;
-        this.grids = grid;
-        this.cutout = cutout;
-        this.resourceOverrides = resourceOverrides;
-    }
-
-    public static DeviceEmulationData deviceFromJSON(JSONObject json) throws JSONException {
-        int width = json.getInt("width");
-        int height = json.getInt("height");
-        int density = json.getInt("density");
-        String name = json.getString("name");
-
-        JSONArray gridArray = json.getJSONArray("grids");
-        String[] grids = new String[gridArray.length()];
-        for (int i = 0, count = grids.length; i < count; i++) {
-            grids[i] = gridArray.getString(i);
-        }
-
-        IntArray deviceCutout = IntArray.fromConcatString(json.getString("cutout"));
-        Rect cutout = new Rect(deviceCutout.get(0), deviceCutout.get(1), deviceCutout.get(2),
-                deviceCutout.get(3));
-
-
-        JSONObject resourceOverridesJson = json.getJSONObject("resourceOverrides");
-        Map<String, Integer> resourceOverrides = new ArrayMap<>();
-        for (String key : resourceOverridesJson.keySet()) {
-            resourceOverrides.put(key, resourceOverridesJson.getInt(key));
-        }
-        return new DeviceEmulationData(width, height, density, cutout, name, grids,
-                resourceOverrides);
-    }
-
-    @Override
-    public String toString() {
-        JSONObject json = new JSONObject();
-        try {
-            json.put("width", width);
-            json.put("height", height);
-            json.put("density", density);
-            json.put("name", name);
-            json.put("cutout", IntArray.wrap(
-                    cutout.left, cutout.top, cutout.right, cutout.bottom).toConcatString());
-
-            JSONArray gridArray = new JSONArray();
-            Arrays.stream(grids).forEach(gridArray::put);
-            json.put("grids", gridArray);
-
-
-            JSONObject resourceOverrides = new JSONObject();
-            for (Map.Entry<String, Integer> e : this.resourceOverrides.entrySet()) {
-                resourceOverrides.put(e.getKey(), e.getValue());
-            }
-            json.put("resourceOverrides", resourceOverrides);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return json.toString();
-    }
-
-    public static DeviceEmulationData getCurrentDeviceData(Context context) {
-        DisplayController.Info info = DisplayController.INSTANCE.get(context).getInfo();
-        String[] grids = InvariantDeviceProfile.INSTANCE.get(context)
-                .parseAllGridOptions(context).stream()
-                .map(go -> go.name).toArray(String[]::new);
-        String code = Build.MODEL.replaceAll("\\s", "").toLowerCase();
-
-        Map<String, Integer> resourceOverrides = new ArrayMap<>();
-        for (String s : EMULATED_SYSTEM_RESOURCES) {
-            resourceOverrides.put(s, getDimenByName(s, context.getResources(), 0));
-        }
-        return new DeviceEmulationData(info.currentSize.x, info.currentSize.y,
-                info.getDensityDpi(), info.cutout, code, grids, resourceOverrides);
-    }
-
-    public static DeviceEmulationData getDevice(String deviceCode) throws Exception {
-        return DeviceEmulationData.deviceFromJSON(readJSON().getJSONObject(deviceCode));
-    }
-
-    private static JSONObject readJSON() throws Exception {
-        Context context = getInstrumentation().getContext();
-        Resources myRes = context.getResources();
-        int resId = myRes.getIdentifier("devices", "raw", context.getPackageName());
-        try (InputStream is = myRes.openRawResource(resId)) {
-            return new JSONObject(new String(IOUtils.toByteArray(is)));
-        }
-    }
-
-}
diff --git a/tests/src/com/android/launcher3/icons/IconCacheTest.java b/tests/src/com/android/launcher3/icons/IconCacheTest.java
new file mode 100644
index 0000000..08d6df3
--- /dev/null
+++ b/tests/src/com/android/launcher3/icons/IconCacheTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.icons;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.launcher3.icons.IconCache.EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutInfo.Builder;
+import android.os.PersistableBundle;
+import android.text.TextUtils;
+
+import androidx.annotation.Nullable;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.model.data.ItemInfoWithIcon;
+import com.android.launcher3.model.data.PackageItemInfo;
+import com.android.launcher3.settings.SettingsActivity;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class IconCacheTest {
+
+    private Context mContext;
+    private IconCache mIconCache;
+
+    private ComponentName mMyComponent;
+
+    @Before
+    public void setup() {
+        mContext = getInstrumentation().getTargetContext();
+        mMyComponent = new ComponentName(mContext, SettingsActivity.class);
+
+        // In memory icon cache
+        mIconCache = new IconCache(mContext,
+                InvariantDeviceProfile.INSTANCE.get(mContext), null,
+                new LauncherIconProvider(mContext));
+    }
+
+    @Test
+    public void getShortcutInfoBadge_nullComponent_overrideAllowed() throws Exception {
+        String overridePackage = "com.android.settings";
+        ItemInfoWithIcon item = getBadgingInfo(mContext, null, overridePackage);
+        assertTrue(item instanceof PackageItemInfo);
+        assertEquals(((PackageItemInfo) item).packageName, overridePackage);
+    }
+
+    @Test
+    public void getShortcutInfoBadge_withComponent_overrideAllowed() throws Exception {
+        String overridePackage = "com.android.settings";
+        ItemInfoWithIcon item = getBadgingInfo(mContext, mMyComponent, overridePackage);
+        assertTrue(item instanceof PackageItemInfo);
+        assertEquals(((PackageItemInfo) item).packageName, overridePackage);
+    }
+
+    @Test
+    public void getShortcutInfoBadge_nullComponent() throws Exception {
+        ItemInfoWithIcon item = getBadgingInfo(mContext, null, null);
+        assertTrue(item instanceof PackageItemInfo);
+        assertEquals(((PackageItemInfo) item).packageName, mContext.getPackageName());
+    }
+
+    @Test
+    public void getShortcutInfoBadge_withComponent() throws Exception {
+        ItemInfoWithIcon item = getBadgingInfo(mContext, mMyComponent, null);
+        assertTrue(item instanceof AppInfo);
+        assertEquals(((AppInfo) item).componentName, mMyComponent);
+    }
+
+    @Test
+    public void getShortcutInfoBadge_overrideNotAllowed() throws Exception {
+        String overridePackage = "com.android.settings";
+        String otherPackage = mContext.getPackageName() + ".does.not.exist";
+        Context otherContext = new ContextWrapper(mContext) {
+            @Override
+            public String getPackageName() {
+                return otherPackage;
+            }
+        };
+        ItemInfoWithIcon item = getBadgingInfo(otherContext, null, overridePackage);
+        assertTrue(item instanceof PackageItemInfo);
+        // Badge is set to the original package, and not the override package
+        assertEquals(((PackageItemInfo) item).packageName, otherPackage);
+    }
+
+    private ItemInfoWithIcon getBadgingInfo(Context context,
+            @Nullable ComponentName cn, @Nullable String badgeOverride) throws Exception {
+        Builder builder = new Builder(context, "test-shortcut")
+                .setIntent(new Intent(Intent.ACTION_VIEW))
+                .setTitle("Test");
+        if (cn != null) {
+            builder.setActivity(cn);
+        }
+        if (!TextUtils.isEmpty(badgeOverride)) {
+            PersistableBundle extras = new PersistableBundle();
+            extras.putString(EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE, badgeOverride);
+            builder.setExtras(extras);
+        }
+        ShortcutInfo info = builder.build();
+        return MODEL_EXECUTOR.submit(() -> mIconCache.getShortcutInfoBadgeItem(info)).get();
+    }
+}
diff --git a/tests/src/com/android/launcher3/model/DefaultLayoutProviderTest.java b/tests/src/com/android/launcher3/model/DefaultLayoutProviderTest.java
index 004ed06..2b89321 100644
--- a/tests/src/com/android/launcher3/model/DefaultLayoutProviderTest.java
+++ b/tests/src/com/android/launcher3/model/DefaultLayoutProviderTest.java
@@ -20,8 +20,10 @@
 import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
 
 import android.content.Context;
+import android.content.pm.LauncherApps;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageInstaller.SessionParams;
 
@@ -127,6 +129,38 @@
         assertEquals(2, info.spanY);
     }
 
+    @Test
+    public void testCustomProfileLoaded_with_shortcut_on_hotseat() throws Exception {
+        assumeTrue(mTargetContext.getSystemService(LauncherApps.class).hasShortcutHostPermission());
+        writeLayoutAndLoad(new LauncherLayoutBuilder().atHotseat(0)
+                .putShortcut(TEST_PACKAGE, "shortcut2"));
+
+        // Verify one item in hotseat
+        assertEquals(1, mModelHelper.getBgDataModel().workspaceItems.size());
+        ItemInfo info = mModelHelper.getBgDataModel().workspaceItems.get(0);
+        assertEquals(LauncherSettings.Favorites.CONTAINER_HOTSEAT, info.container);
+        assertEquals(LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT, info.itemType);
+    }
+
+    @Test
+    public void testCustomProfileLoaded_with_shortcut_in_folder() throws Exception {
+        assumeTrue(mTargetContext.getSystemService(LauncherApps.class).hasShortcutHostPermission());
+        writeLayoutAndLoad(new LauncherLayoutBuilder().atHotseat(0).putFolder(android.R.string.copy)
+                .addApp(TEST_PACKAGE, TEST_ACTIVITY)
+                .addApp(TEST_PACKAGE, TEST_ACTIVITY)
+                .addShortcut(TEST_PACKAGE, "shortcut2")
+                .build());
+
+        // Verify folder
+        assertEquals(1, mModelHelper.getBgDataModel().workspaceItems.size());
+        FolderInfo info = (FolderInfo) mModelHelper.getBgDataModel().workspaceItems.get(0);
+        assertEquals(3, info.contents.size());
+
+        // Verify last icon
+        assertEquals(LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT,
+                info.contents.get(info.contents.size() - 1).itemType);
+    }
+
     private void writeLayoutAndLoad(LauncherLayoutBuilder builder) throws Exception {
         mModelHelper.setupDefaultLayoutProvider(builder).loadModelSync();
     }
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index ae12861..217bec3 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -51,7 +51,6 @@
 import com.android.launcher3.tapl.FolderIcon;
 import com.android.launcher3.tapl.HomeAllApps;
 import com.android.launcher3.tapl.HomeAppIcon;
-import com.android.launcher3.tapl.HomeAppIconMenu;
 import com.android.launcher3.tapl.HomeAppIconMenuItem;
 import com.android.launcher3.tapl.Widgets;
 import com.android.launcher3.tapl.Workspace;
@@ -391,23 +390,14 @@
                 .switchToAllApps();
         allApps.freeze();
         try {
-            final HomeAppIconMenu menu = allApps
+            final HomeAppIconMenuItem menuItem = allApps
                     .getAppIcon(APP_NAME)
-                    .openDeepShortcutMenu();
-            final HomeAppIconMenuItem menuItem0 = menu.getMenuItem(0);
-            final HomeAppIconMenuItem menuItem2 = menu.getMenuItem(2);
+                    .openDeepShortcutMenu()
+                    .getMenuItem(0);
+            final String actualShortcutName = menuItem.getText();
+            final String expectedShortcutName = "Shortcut 1";
 
-            final HomeAppIconMenuItem menuItem;
-
-            final String expectedShortcutName = "Shortcut 3";
-            if (menuItem0.getText().equals(expectedShortcutName)) {
-                menuItem = menuItem0;
-            } else {
-                final String shortcutName2 = menuItem2.getText();
-                assertEquals("Wrong menu item", expectedShortcutName, shortcutName2);
-                menuItem = menuItem2;
-            }
-
+            assertEquals(expectedShortcutName, actualShortcutName);
             menuItem.dragToWorkspace(false, false);
             mLauncher.getWorkspace().getWorkspaceAppIcon(expectedShortcutName)
                     .launch(getAppPackageName());
@@ -525,14 +515,8 @@
         try {
             Workspace workspace = mLauncher.getWorkspace();
             final HomeAllApps allApps = workspace.switchToAllApps();
-            allApps.freeze();
-            try {
-                workspace = allApps.getAppIcon(DUMMY_APP_NAME).uninstall();
-                // After the toast clears, then the model tries to commit the uninstall transaction
-                mLauncher.waitForModelQueueCleared();
-            } finally {
-                allApps.unfreeze();
-            }
+            workspace = allApps.getAppIcon(DUMMY_APP_NAME).uninstall();
+            waitForLauncherUIUpdate();
             verifyAppUninstalledFromAllApps(workspace, DUMMY_APP_NAME);
         } finally {
             TestUtil.uninstallDummyApp();
@@ -633,6 +617,10 @@
 
     private void installDummyAppAndWaitForUIUpdate() throws IOException {
         TestUtil.installDummyApp();
+        waitForLauncherUIUpdate();
+    }
+
+    private void waitForLauncherUIUpdate() {
         // Wait for model thread completion as it may be processing
         // the install event from the SystemService
         mLauncher.waitForModelQueueCleared();
diff --git a/tests/src/com/android/launcher3/ui/WorkProfileTest.java b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
index b783d91..54da7de 100644
--- a/tests/src/com/android/launcher3/ui/WorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
@@ -177,6 +177,7 @@
     }
 
     @Test
+    @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/243688989
     public void testEdu() {
         assumeTrue(mWorkProfileSetupSuccessful);
         waitForWorkTabSetup();
diff --git a/tests/src/com/android/launcher3/util/LauncherLayoutBuilder.java b/tests/src/com/android/launcher3/util/LauncherLayoutBuilder.java
index 4e21dce..ba01b04 100644
--- a/tests/src/com/android/launcher3/util/LauncherLayoutBuilder.java
+++ b/tests/src/com/android/launcher3/util/LauncherLayoutBuilder.java
@@ -39,6 +39,7 @@
     private static final String TAG_AUTO_INSTALL = "autoinstall";
     private static final String TAG_FOLDER = "folder";
     private static final String TAG_APPWIDGET = "appwidget";
+    private static final String TAG_SHORTCUT = "shortcut";
     private static final String TAG_EXTRA = "extra";
 
     private static final String ATTR_CONTAINER = "container";
@@ -49,6 +50,7 @@
     private static final String ATTR_TITLE = "title";
     private static final String ATTR_TITLE_TEXT = "titleText";
     private static final String ATTR_SCREEN = "screen";
+    private static final String ATTR_SHORTCUT_ID = "shortcutId";
 
     // x and y can be specified as negative integers, in which case -1 represents the
     // last row / column, -2 represents the second last, and so on.
@@ -135,6 +137,13 @@
             return LauncherLayoutBuilder.this;
         }
 
+        public LauncherLayoutBuilder putShortcut(String packageName, String shortcutId) {
+            items.put(ATTR_PACKAGE_NAME, packageName);
+            items.put(ATTR_SHORTCUT_ID, shortcutId);
+            mNodes.add(Pair.create(TAG_SHORTCUT, items));
+            return LauncherLayoutBuilder.this;
+        }
+
         public LauncherLayoutBuilder putWidget(String packageName, String className,
                 int spanX, int spanY) {
             items.put(ATTR_PACKAGE_NAME, packageName);
@@ -175,6 +184,14 @@
             return this;
         }
 
+        public FolderBuilder addShortcut(String packageName, String shortcutId) {
+            HashMap<String, Object> items = new HashMap<>();
+            items.put(ATTR_PACKAGE_NAME, packageName);
+            items.put(ATTR_SHORTCUT_ID, shortcutId);
+            mChildren.add(Pair.create(TAG_SHORTCUT, items));
+            return this;
+        }
+
         public LauncherLayoutBuilder build() {
             return LauncherLayoutBuilder.this;
         }
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index 2d4d2cd..885707c 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -147,6 +147,9 @@
                                 getAppsListRecyclerBottomPadding());
                         verifyActiveContainer();
                         final int newScroll = getAllAppsScroll();
+                        LauncherInstrumentation.log(
+                                String.format("tryGetAppIcon: scrolled from %d to %d", scroll,
+                                        newScroll));
                         mLauncher.assertTrue(
                                 "Scrolled in a wrong direction in AllApps: from " + scroll + " to "
                                         + newScroll, newScroll >= scroll);
@@ -259,8 +262,7 @@
     }
 
     private int getAllAppsScroll() {
-        return mLauncher.getTestInfo(
-                TestProtocol.REQUEST_APPS_LIST_SCROLL_Y)
+        return mLauncher.getTestInfo(TestProtocol.REQUEST_APPS_LIST_SCROLL_Y)
                 .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
     }
 
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java
index 8cdc8a0..54be3c3 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java
@@ -49,4 +49,10 @@
             }
         }
     }
+
+    /** Returns true if an item matching the given string is present in the menu. */
+    public boolean hasMenuItem(String expectedMenuItemText) {
+        UiObject2 menuItem = mLauncher.findObjectInContainer(mMenu, By.text(expectedMenuItemText));
+        return menuItem != null;
+    }
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/Widgets.java b/tests/tapl/com/android/launcher3/tapl/Widgets.java
index c1c26ec..79b54ba 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widgets.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widgets.java
@@ -182,12 +182,6 @@
             UiObject2 widgetListView = verifyActiveContainer();
             UiObject2 header = mLauncher.waitForObjectInContainer(widgetListView,
                     headerSelector);
-            // If we are in a tablet in landscape mode then we will have a two pane view and we use
-            // the right pane to display the widgets table.
-            UiObject2 rightPane = mLauncher.findObjectInContainer(
-                    widgetPicker,
-                    widgetsContainerSelector);
-
             // If a header is barely visible in the bottom edge of the screen, its height could be
             // too small for a scroll gesture. Since all header should have roughly the same height,
             // let's pick the max height we have seen so far.
@@ -209,6 +203,12 @@
                     mLauncher.clickLauncherObject(headerTitle);
                 }
 
+                // If we are in a tablet in landscape mode then we will have a two pane view and we
+                // use the right pane to display the widgets table.
+                UiObject2 rightPane = mLauncher.findObjectInContainer(
+                        widgetPicker,
+                        widgetsContainerSelector);
+
                 // Look for a widgets list.
                 UiObject2 widgetsContainer = mLauncher.findObjectInContainer(
                         rightPane != null ? rightPane : widgetListView,
@@ -219,6 +219,13 @@
                 }
             }
             log("Finding test widget package - scroll with distance: " + scrollDistance);
+
+            // If we are in a tablet in landscape mode then we will have a two pane view and we use
+            // the right pane to display the widgets table.
+            UiObject2 rightPane = mLauncher.findObjectInContainer(
+                    widgetPicker,
+                    widgetsContainerSelector);
+
             mLauncher.scrollDownByDistance(hasHeaderExpanded && rightPane != null
                     ? rightPane
                     : widgetListView, scrollDistance);