Merge "Fixes SettingsChangeLoggerTest failures" into main
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index 21b9863..a779641 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -316,3 +316,16 @@
     description: "Archived apps will use new icon in app title"
     bug: "350758155"
 }
+
+flag {
+    name: "enable_multi_instance_menu_taskbar"
+    namespace: "launcher"
+    description: "Menu in Taskbar with options to launch and manage multiple instances of the same app"
+    bug: "355237285"
+}
+flag {
+    name: "navigate_to_child_preference"
+    namespace: "launcher"
+    description: "Settings screen supports navigating to child preference if the key is not on the screen"
+    bug: "293390881"
+}
diff --git a/quickstep/Android.bp b/quickstep/Android.bp
index f14cebd..1b9c661 100644
--- a/quickstep/Android.bp
+++ b/quickstep/Android.bp
@@ -52,6 +52,14 @@
         "tests/src/com/android/quickstep/TaplOverviewIconTest.java",
         "tests/src/com/android/quickstep/TaplTestsQuickstep.java",
         "tests/src/com/android/quickstep/TaplTestsSplitscreen.java",
-        "tests/src/com/android/launcher3/testcomponent/ExcludeFromRecentsTestActivity.java"
+        "tests/src/com/android/launcher3/testcomponent/ExcludeFromRecentsTestActivity.java",
+    ],
+}
+
+filegroup {
+    name: "launcher3-quickstep-screenshot-tests-src",
+    path: "tests/multivalentScreenshotTests",
+    srcs: [
+        "tests/multivalentScreenshotTests/src/**/*.kt",
     ],
 }
diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml
index 80d8154..c6e2d8c 100644
--- a/quickstep/AndroidManifest-launcher.xml
+++ b/quickstep/AndroidManifest-launcher.xml
@@ -48,7 +48,7 @@
             android:stateNotNeeded="true"
             android:windowSoftInputMode="adjustPan"
             android:screenOrientation="unspecified"
-            android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
+            android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
             android:resizeableActivity="true"
             android:resumeWhilePausing="true"
             android:taskAffinity=""
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index 4abf6e1..bf198b6 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -80,7 +80,7 @@
              android:stateNotNeeded="true"
              android:theme="@style/LauncherTheme"
              android:screenOrientation="behind"
-             android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
+             android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
              android:resizeableActivity="true"
              android:resumeWhilePausing="true"
              android:enableOnBackInvokedCallback="false"
diff --git a/quickstep/res/layout/task_thumbnail.xml b/quickstep/res/layout/task_thumbnail.xml
index b1fe89e..784a094 100644
--- a/quickstep/res/layout/task_thumbnail.xml
+++ b/quickstep/res/layout/task_thumbnail.xml
@@ -39,4 +39,16 @@
         android:background="@color/overview_foreground_scrim_color"
         android:alpha="0" />
 
+    <FrameLayout
+        android:id="@+id/splash_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="gone">
+        <ImageView
+            android:id="@+id/splash_icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:importantForAccessibility="no" />
+    </FrameLayout>
 </com.android.quickstep.task.thumbnail.TaskThumbnailView>
\ No newline at end of file
diff --git a/quickstep/res/layout/taskbar.xml b/quickstep/res/layout/taskbar.xml
index 736706a..e8f3d9d 100644
--- a/quickstep/res/layout/taskbar.xml
+++ b/quickstep/res/layout/taskbar.xml
@@ -35,6 +35,18 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"/>
 
+    <com.android.launcher3.taskbar.bubbles.BubbleBarView
+        android:id="@+id/taskbar_bubbles"
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/bubblebar_size_with_pointer"
+        android:layout_marginHorizontal="@dimen/transient_taskbar_bottom_margin"
+        android:paddingTop="@dimen/bubblebar_pointer_visible_size"
+        android:visibility="gone"
+        android:gravity="center"
+        android:layout_gravity="bottom"
+        android:clipChildren="false"
+        android:elevation="@dimen/bubblebar_elevation" />
+
     <com.android.launcher3.taskbar.navbutton.NearestTouchFrame
         android:id="@+id/navbuttons_view"
         android:layout_width="match_parent"
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index 8c3b953..f8c8977 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Kitsinstellings"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Taakbalk"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taakbalk word gewys"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taakbalk is versteek"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigasiebalk"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Wys altyd Taakbalk"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Verander navigasiemodus"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Oorvloei"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> vanaf <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> en nog <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Skuif links"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Skuif regs"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Maak almal toe"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"vou <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> uit"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"vou <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> in"</string>
 </resources>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index fd8b206..f5cef7b 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"የተግባር አሞሌ ተደብቋል"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"የአሰሳ አሞሌ"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"ሁልጊዜ የተግባር አሞሌ ያሳዩ"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"የአሰሳ ሁነታን ይለውጡ"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"ትርፍ ፍሰት"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ከ<xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> እና <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> ተጨማሪ"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"ወደ ግራ ያንቀሳቅሱ"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"ወደ ቀኝ ያንቀሳቅሱ"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"ሁሉንም አሰናብት"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>ን ዘርጋ"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>ን ሰብስብ"</string>
 </resources>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index c53e427..52a18e9 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"تم إخفاء شريط التطبيقات"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"شريط التنقل"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"إظهار شريط التطبيقات دائمًا"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"تغيير وضع التنقل"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"القائمة الكاملة"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"‫\"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>\" من \"<xliff:g id="APP_NAME">%2$s</xliff:g>\""</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"‫\"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g>\" و<xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> غيرها"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"نقل لليسار"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"نقل لليمين"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"إغلاق الكل"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"توسيع <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"تصغير <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index e82cad2..d811543 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -130,7 +130,10 @@
     <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_shown_with_bubbles_left_title" msgid="4242431789851790046">"টাস্কবাৰ আৰু বাবল বাওঁফালে দেখুওৱা হৈছে"</string>
+    <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"টাস্কবাৰ আৰু বাবল সোঁফালে দেখুওৱা হৈছে"</string>
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"টাস্কবাৰ লুকুৱাই থোৱা হৈছে"</string>
+    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"টাস্কবাৰ আৰু বাবল লুকুওৱা হৈছে"</string>
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"নেভিগেশ্বনৰ দণ্ড"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"টাস্কবাৰ সদায় দেখুৱাওক"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"নেভিগেশ্বন ম’ড সলনি কৰক"</string>
@@ -144,10 +147,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"অ’ভাৰফ্ল’"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g>ৰ পৰা <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> আৰু <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> টা"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"বাওঁফাললৈ নিয়ক"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"সোঁফাললৈ নিয়ক"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"সকলো অগ্ৰাহ্য কৰক"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> বিস্তাৰ কৰক"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> সংকোচন কৰক"</string>
 </resources>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 1da7f55..3108ffe 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Sürətli Ayarlar"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Tapşırıq paneli"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"İşləmə paneli göstərilir"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"İşləmə paneli gizlədilib"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Naviqasiya paneli"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"İşləmə paneli həmişə görünsün"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Naviqasiya rejimini dəyişin"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Kənara çıxma"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> və daha <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> yumrucuq"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Sola köçürün"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Sağa köçürün"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Hamısını kənarlaşdırın"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"genişləndirin: <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"yığcamlaşdırın: <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 303f0d8..e6074b0 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Brza podešavanja"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Traka zadataka"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Traka zadataka je prikazana"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Traka zadataka je skrivena"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Traka za navigaciju"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Uvek prikazuj traku zadataka"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Promeni režim navigacije"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Preklopni"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> – <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> i još <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Pomeri nalevo"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Pomeri nadesno"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Odbaci sve"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"proširite oblačić <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"skupite oblačić <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 2be8e5c..5b871d4 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Панэль задач схавана"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Панэль навігацыі"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Заўсёды паказваць панэль задач"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Змяніць рэжым навігацыі"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Меню з пашырэннем"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, крыніца: <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> і яшчэ <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Перамясціць улева"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Перамясціць управа"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Закрыць усе"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>: разгарнуць"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>: згарнуць"</string>
 </resources>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index b71d3cf..dd87de8 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Лентата на задачите е скрита"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Лента за навигация"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Лентата на задачите винаги да се показва"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Промяна на режима на навигация"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Препълване"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> от <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> и още <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Преместване наляво"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Преместване надясно"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Отхвърляне на всички"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"разгъване на <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"свиване на <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index 59f9d7a..99a815f 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"\'টাস্কবার\' লুকানো রয়েছে"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"নেভিগেশন বার"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"সবসময় টাস্কবার দেখুন"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"\'নেভিগেশন\' মোড পরিবর্তন করুন"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"ওভারফ্লো"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> থেকে <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> এবং আরও <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>টি"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"বাঁদিকে সরান"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"ডানদিকে সরান"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"সব বাতিল করুন"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> বড় করুন"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> আড়াল করুন"</string>
 </resources>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 946c08c..5f445ab 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Brze postavke"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Traka zadataka"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Traka zadataka je prikazana"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Traka zadataka je sakrivena"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigaciona traka"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Uvijek prikaži traku zadataka"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Promijeni način navigacije"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Preklopni meni"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> iz aplikacije <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> i još <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Pomjeranje ulijevo"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Pomjeranje udesno"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Odbacivanje svega"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"proširivanje oblačića <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"sužavanje oblačića <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index 6850656..2b8fadf 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Config. ràpida"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra de tasques"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Es mostra la Barra de tasques"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"S\'ha amagat la Barra de tasques"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegació"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Barra de tasques sempre visible"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Canvia el mode de navegació"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Desbordament"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> i <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> més"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Mou cap a l\'esquerra"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Mou cap a la dreta"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Ignora-ho tot"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"desplega <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"replega <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index 9fd843a..6e432de 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Rychlé nastavení"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Panel aplikací"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Panel aplikací je zobrazen"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Panel aplikací je skrytý"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigační panel"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Vždy zobrazovat panel aplikací"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Změnit režim navigace"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Rozbalovací nabídka"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> z aplikace <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> a ještě <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Přesunout doleva"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Přesunout doprava"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Zavřít vše"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"rozbalit <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"sbalit <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index 823c071..c73f49c 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Kvikmenu"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Proceslinje"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Proceslinjen vises"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Proceslinjen er skjult"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigationslinje"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Vis altid proceslinjen"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Skift navigationstilstand"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Overløb"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> fra <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> og <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> mere"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Flyt til venstre"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Flyt til højre"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Afvis alle"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"udvid <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"skjul <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index c9b288c..8f571ce 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Schnelleinstellungen"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskleiste"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskleiste eingeblendet"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskleiste ausgeblendet"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigationsleiste"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Taskleiste immer anzeigen"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Navigationsmodus ändern"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Weitere Optionen"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"„<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>“ aus <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> und <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> weitere"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Nach links bewegen"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Nach rechts bewegen"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Alle schließen"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"„<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>“ maximieren"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"„<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>“ minimieren"</string>
 </resources>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 9f0480c..011c800 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Η γραμμή εργαλείων είναι κρυφή"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Γραμμή πλοήγησης"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Εμφάνιση Γραμμής εργαλείων"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Αλλαγή τρόπου πλοήγησης"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Υπερχείλιση"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> από <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> και <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> ακόμα"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Μετακίνηση αριστερά"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Μετακίνηση δεξιά"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Παράβλεψη όλων"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"ανάπτυξη <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"σύμπτυξη <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index ae915ed..c63e094 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskbar"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Overflow"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> from <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> and <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> more"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Move left"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Move right"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Dismiss all"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"expand <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"collapse <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index 3302a5a..2183919 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -130,7 +130,10 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskbar"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
+    <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Taskbar &amp; bubbles left shown"</string>
+    <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Taskbar &amp; bubbles right shown"</string>
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
+    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Taskbar &amp; bubbles hidden"</string>
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
@@ -144,10 +147,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Overflow"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> from <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> and <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> more"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Move left"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Move right"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Dismiss all"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"expand <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"collapse <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index ae915ed..c63e094 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskbar"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Overflow"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> from <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> and <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> more"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Move left"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Move right"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Dismiss all"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"expand <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"collapse <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index ae915ed..c63e094 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskbar"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Overflow"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> from <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> and <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> more"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Move left"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Move right"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Dismiss all"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"expand <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"collapse <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index 24a7919..ba55585 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -130,7 +130,10 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‎‏‏‎‎‏‎‎‎‏‏‎‏‏‎‏‏‏‎‎‎‏‎‎‎‎‎‎‎‏‏‎‎‎‎‏‏‏‏‎Quick Settings‎‏‎‎‏‎"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‎‏‎‎‏‏‎‎Taskbar‎‏‎‎‏‎"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‎‎‏‏‎‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‏‏‏‏‎‎‎‏‎Taskbar shown‎‏‎‎‏‎"</string>
+    <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‏‎‎‏‎‎‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‏‎‏‏‎‏‏‏‏‎‎Taskbar &amp; bubbles left shown‎‏‎‎‏‎"</string>
+    <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‎Taskbar &amp; bubbles right shown‎‏‎‎‏‎"</string>
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‎‎‎‎‏‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎Taskbar hidden‎‏‎‎‏‎"</string>
+    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‏‎‏‎‎‏‎‎‏‏‎‎‎‎‏‎‎‏‏‏‏‏‎‏‏‏‎Taskbar &amp; bubbles hidden‎‏‎‎‏‎"</string>
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‎‎‏‏‎Navigation bar‎‏‎‎‏‎"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎Always show Taskbar‎‏‎‎‏‎"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‏‏‏‎‎‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎Change navigation mode‎‏‎‎‏‎"</string>
@@ -144,10 +147,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎Overflow‎‏‎‎‏‎"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ from ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎<xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more‎‏‎‎‏‎"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‎‎‏‎‎‏‎‎‎‏‏‎‎‎‏‏‏‏‎‎‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‎‎‎‏‎‎‎‎‎‏‎‎‎‏‏‎‎Move left‎‏‎‎‏‎"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‎‎‏‏‎‎‏‏‎Move right‎‏‎‎‏‎"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‎‏‏‎‏‎‎‎Dismiss all‎‏‎‎‏‎"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎‎expand ‎‏‎‎‏‏‎<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‎‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎collapse ‎‏‎‎‏‏‎<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
 </resources>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index b8d50d0..7df97ef 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Config. rápida"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra de tareas"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tareas visible"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tareas oculta"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegación"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Barra de tareas visible"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Cambiar el modo de navegación"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Ampliada"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> y <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> más"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Mover hacia la izquierda"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Mover hacia la derecha"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Descartar todo"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"expandir <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"contraer <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index ad9f731..353ff4c 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Ajustes rápidos"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra de tareas"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tareas visible"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tareas oculta"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegación"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Barra de tareas visible"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Cambiar el modo de navegación"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Menú adicional"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> y <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> más"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Mover hacia la izquierda"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Mover hacia la derecha"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Cerrar todo"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"desplegar <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"contraer <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index da16bdc..6b78c1f 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Kiirseaded"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Tegumiriba"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Tegumiriba on kuvatud"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Tegumiriba on peidetud"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigeerimisriba"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Kuva tegumiriba alati"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Navigeerimisrežiimi muutmine"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Ületäide"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> – <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> ja veel <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> mulli"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Liigu vasakule"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Liigu paremale"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Loobu kõigist"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"Toiminguriba <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> laiendamine"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"Toiminguriba <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> ahendamine"</string>
 </resources>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index bc8b285..058ade5 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Ezarpen bizkorrak"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Zereginen barra"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Zereginen barra ikusgai dago"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Zereginen barra itxita dago"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Nabigazio-barra"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Erakutsi beti zereginen barra"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Aldatu nabigazio modua"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Luzapena"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> (<xliff:g id="APP_NAME">%2$s</xliff:g>)"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> eta beste <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Eraman ezkerrera"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Eraman eskuinera"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Baztertu guztiak"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"zabaldu <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"tolestu <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index 2d82376..f6f51b7 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"نوار وظیفه پنهان است"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"نوار پیمایش"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"نوار وظیفه همیشه نشان داده شود"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"تغییر حالت پیمایش"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"سرریز"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> از <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> و <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> حبابک دیگر"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"انتقال به چپ"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"انتقال به راست"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"رد کردن همه"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"ازهم باز کردن <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"جمع کردن <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index fe54f09..91f64ed 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Pika-asetukset"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Tehtäväpalkki"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Tehtäväpalkki näkyvissä"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Tehtäväpalkki piilotettu"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigointipalkki"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Näytä tehtäväpalkki aina"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Vaihda navigointitilaa"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Ylivuoto"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>: <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> ja <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> muuta"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Siirrä vasemmalle"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Siirrä oikealle"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Hylkää kaikki"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"laajenna <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"tiivistä <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 8385f50..e567239 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Paramètres rapides"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Barre des tâches"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barre des tâches affichée"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barre des tâches masquée"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barre de navigation"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Tjrs afficher barre des tâches"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Changer de mode de navigation"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Bulle à développer"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> et <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> autres"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Déplacer vers la gauche"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Déplacer vers la droite"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Tout ignorer"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"Développer <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"Réduire <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 519fcc1..ddab232 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Réglages rapides"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Barre des tâches"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barre des tâches affichée"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barre des tâches masquée"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barre de navigation"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Barre des tâches tjs visible"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Modifier le mode de navigation"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Dépassement"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> (<xliff:g id="APP_NAME">%2$s</xliff:g>)"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> et <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> autre(s)"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Déplacer vers la gauche"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Déplacer vers la droite"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Tout fermer"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"Développer <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"Réduire <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 0f09368..053a48f 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Configuración rápida"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra de tarefas"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Estase mostrando a barra de tarefas"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Non se está mostrando a barra de tarefas"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegación"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Ver sempre a barra de tarefas"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Cambiar modo de navegación"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Menú adicional"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> e <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> máis"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Mover cara á esquerda"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Mover cara á dereita"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Pechar todo"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"despregar <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"contraer <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 1db3dcb..a081ab5 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ટાસ્કબાર છુપાવવામાં આવ્યો"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"નૅવિગેશન બાર"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"હંમેશાં ટાસ્કબાર બતાવો"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"નૅવિગેશન મોડ બદલો"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"ઓવરફ્લો"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g>થી <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> અને વધુ <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"ડાબે ખસેડો"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"જમણે ખસેડો"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"તમામ છોડી દો"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> મોટો કરો"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> નાનો કરો"</string>
 </resources>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index 40bb511..1e74c4a 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"टास्कबार छिपाया गया"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"नेविगेशन बार"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"टास्कबार हमेशा दिखाएं"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"नेविगेशन का मोड बदलें"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"ओवरफ़्लो"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> की <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> वाली सूचना"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> और <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> अन्य"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"बाईं ओर ले जाएं"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"दाईं ओर ले जाएं"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"सभी खारिज करें"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> को बड़ा करें"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> को छोटा करें"</string>
 </resources>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index f8412a8..fc85be9 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Brze postavke"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Traka sa zadacima"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Traka sa zadacima prikazana"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Traka sa zadacima skrivena"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigacijska traka"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Uvijek prikaži traku zadataka"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Promijeni način navigacije"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Dodatni izbornik"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> i još <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Pomakni ulijevo"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Pomakni udesno"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Odbaci sve"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"proširite oblačić <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"sažmite oblačić <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 3958bc5..3a539d4 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Gyorsbeállítások"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Tálca"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Feladatsáv megjelenítve"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Feladatsáv elrejtve"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigációs sáv"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Mindig megjelenő Feladatsáv"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Navigációs mód módosítása"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Túlcsordulás"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, forrás: <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> és <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> további"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Mozgatás balra"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Mozgatás jobbra"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Az összes elvetése"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> kibontása"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> összecsukása"</string>
 </resources>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index d82c93e..d8503f3 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Խնդրագոտին թաքցված է"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Նավիգացիայի գոտի"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Միշտ ցույց տալ վահանակը"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Փոխել նավիգացիայի ռեժիմը"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Լրացուցիչ ընտրացանկ"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>՝ <xliff:g id="APP_NAME">%2$s</xliff:g> հավելվածից"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> ու ևս <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> ամպիկ"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Տեղափոխել ձախ"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Տեղափոխել աջ"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Փակել բոլորը"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>. ծավալել"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>. ծալել"</string>
 </resources>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index b35eade..d4def8d 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Setelan Cepat"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskbar"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar ditampilkan"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar disembunyikan"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Menu navigasi"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Selalu tampilkan Taskbar"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Ubah mode navigasi"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Tambahan"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> dari <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> dan <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> lainnya"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Pindahkan ke kiri"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Pindahkan ke kanan"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Tutup semua"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"luaskan <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"ciutkan <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 2794ddc..f2dd60c 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Flýtistillingar"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Verkstika"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Forritastika sýnd"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Forritastika falin"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Yfirlitsstika"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Alltaf sýna forritastiku"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Breyta leiðsagnarstillingu"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Yfirflæði"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> frá <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> og <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> í viðbót"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Færa til vinstri"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Færa til hægri"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Hunsa allt"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"stækka <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"minnka <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 04b4489..9ed28c1 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -130,7 +130,10 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Impostazioni rapide"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra delle applicazioni"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra delle app visualizzata"</string>
+    <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Barra app e bolle most. sinis."</string>
+    <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Barra app e bolle most. destr."</string>
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra delle app nascosta"</string>
+    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Barra app e bolle nascoste"</string>
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra di navigazione"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Mostra sempre barra app"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Cambia modalità di navigazione"</string>
@@ -144,10 +147,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Extra"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> da <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> e altri <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Sposta a sinistra"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Sposta a destra"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Ignora tutte"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"espandi <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"comprimi <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 2ac80e0..da8b37d 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"סרגל האפליקציות מוסתר"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"סרגל הניווט"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"סרגל האפליקציות מוצג תמיד"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"שינוי מצב הניווט"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"אפשרויות נוספות"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"‫<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> מתוך <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"‫<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> ועוד <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"הזזה שמאלה"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"הזזה ימינה"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"ביטול של הכול"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"הרחבה של <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"כיווץ של <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 4ad992b..54f51da 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -130,7 +130,10 @@
     <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_shown_with_bubbles_left_title" msgid="4242431789851790046">"タスクバーとバブルを表示"</string>
+    <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"タスクバーとバブルを右側に表示"</string>
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"タスクバー非表示"</string>
+    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"タスクバーとバブルを非表示"</string>
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ナビゲーション バー"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"常にタスクバーを表示する"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"ナビゲーション モードを変更"</string>
@@ -144,10 +147,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"オーバーフロー"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>(<xliff:g id="APP_NAME">%2$s</xliff:g>)"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g>、他 <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> 件"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"左に移動"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"右に移動"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"すべて解除"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>を開きます"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>を閉じます"</string>
 </resources>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index 4ade09e..5328012 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ამოცანათა ზოლი დამალულია"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ნავიგაციის ზოლი"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"ამოცანათა ზოლის მუდამ ჩვენება"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"შეცვალეთ ნავიგაციის რეჟიმი"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"გადავსება"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>: <xliff:g id="APP_NAME">%2$s</xliff:g>-იდან"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> და <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> სხვა"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"მარცხნივ გადატანა"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"მარჯვნივ გადატანა"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"ყველას დახურვა"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>-ის გაფართოება"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>-ის ჩაკეცვა"</string>
 </resources>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index e10ad21..54c1795 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Тапсырмалар жолағы жасырылды"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Навигация жолағы"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Тапсырма жолағын үнемі көрсету"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Навигация режимін өзгерту"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Қосымша мәзір"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> ұсынатын <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> және тағы <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Солға жылжыту"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Оңға жылжыту"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Барлығын жабу"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>: жаю"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>: жию"</string>
 </resources>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index 33c0738..698f33c 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"បានលាក់របារកិច្ចការ"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"របាររុករក"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"បង្ហាញរបារកិច្ចការជានិច្ច"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"ប្ដូរ​មុខងាររុករក"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"ម៉ឺនុយបន្ថែម"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ពី <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> និង <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> នាក់ទៀត"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"ផ្លាស់ទី​ទៅ​ឆ្វេង"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"ផ្លាស់ទីទៅស្ដាំ"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"ច្រានចោលទាំងអស់"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"ពង្រីក <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"បង្រួម <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 18ef7e1..6a86e38 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ಟಾಸ್ಕ್‌ಬಾರ್ ಮರೆಮಾಡಲಾಗಿದೆ"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ನ್ಯಾವಿಗೇಷನ್ ಬಾರ್"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"ಯಾವಾಗಲೂ ಟಾಸ್ಕ್‌ಬಾರ್ ತೋರಿಸಿ"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"ನ್ಯಾವಿಗೇಶನ್ ಮೋಡ್ ಬದಲಾಯಿಸಿ"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"ಓವರ್‌ಫ್ಲೋ"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> ನಿಂದ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> ಮತ್ತು ಇನ್ನೂ <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"ಎಡಕ್ಕೆ ಸರಿಸಿ"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"ಬಲಕ್ಕೆ ಸರಿಸಿ"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"ಎಲ್ಲವನ್ನು ವಜಾಗೊಳಿಸಿ"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> ಅನ್ನು ವಿಸ್ತೃತಗೊಳಿಸಿ"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> ಅನ್ನು ಕುಗ್ಗಿಸಿ"</string>
 </resources>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index 3b48d06..31942fb 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"태스크 바 숨김"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"탐색 메뉴"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"태스크 바 항상 표시"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"탐색 모드 변경"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"더보기"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g>의 <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> 외 <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>개"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"왼쪽으로 이동"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"오른쪽으로 이동"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"모두 닫기"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> 펼치기"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> 접기"</string>
 </resources>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 413d135..8805bd0 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Тапшырмалар панели жашырылды"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Чабыттоо тилкеси"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Такта ар дайым көрүнсүн"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Өтүү режимин өзгөртүү"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Кошумча меню"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> колдонмосунан <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> жана дагы <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Солго жылдыруу"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Оңго жылдыруу"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Баарын четке кагуу"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> жайып көрсөтүү"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> жыйыштыруу"</string>
 </resources>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index c2418b6..9e70a5c 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ແຖບໜ້າວຽກທີ່ເຊື່ອງໄວ້ຢູ່"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ແຖບການນຳທາງ"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"ສະແດງແຖບໜ້າວຽກສະເໝີ"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"ປ່ຽນໂໝດການນຳທາງ"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"ລາຍການເພີ່ມເຕີມ"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ຈາກ <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> ແລະ ອີກ <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> ລາຍການ"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"ຍ້າຍໄປຊ້າຍ"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"ຍ້າຍໄປຂວາ"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"ປິດທັງໝົດ"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"ຂະຫຍາຍ <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"ຫຍໍ້ <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> ລົງ"</string>
 </resources>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 59bda55..f78fa30 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Spartieji nustatymai"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Užduočių juosta"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Užduočių juosta rodoma"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Užduočių juosta paslėpta"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Naršymo juosta"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Visada rodyti užduočių juostą"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Keisti naršymo režimą"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Perpildymas"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"„<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>“ iš „<xliff:g id="APP_NAME">%2$s</xliff:g>“"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"„<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g>“ ir dar <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Perkelti kairėn"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Perkelti dešinėn"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Atsisakyti visų"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"išskleisti „<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>“"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"sutraukti „<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>“"</string>
 </resources>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index ede41c3..799e8d1 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Ātrie iestatīj."</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Uzdevumu josla"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Uzdevumu josla tiek rādīta"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Uzdevumu josla paslēpta"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigācijas josla"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Vienmēr rādīt uzdevumu joslu"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Mainīt navigācijas režīmu"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Pārpilde"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> no lietotnes <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> un vēl <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Pārvietot pa kreisi"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Pārvietot pa labi"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Nerādīt nevienu"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"izvērst “<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>”"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"sakļaut “<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>”"</string>
 </resources>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index 5787da3..04f35ba 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Лентата со задачи е скриена"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Лента за навигација"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Секогаш прикажувај „Лента“"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Променете режим на навигација"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Проширено балонче"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> од <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> и уште <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Премести налево"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Премести надесно"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Отфрли ги сите"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"прошири <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"собери <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index 61dcce0..0db3e1f 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ടാസ്‌ക്ബാർ മറച്ചിരിക്കുന്നു"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"നാവിഗേഷൻ ബാർ"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"ടാസ്‌ക്ബാർ എപ്പോഴും കാണിക്കൂ"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"നാവിഗേഷൻ മോഡ് മാറ്റുക"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"ഓവർഫ്ലോ"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> എന്നതിൽ നിന്നുള്ള <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> എന്നതും മറ്റ് <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> എണ്ണവും"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"ഇടത്തേക്ക് നീക്കുക"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"വലത്തേക്ക് നീക്കുക"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"എല്ലാം ഡിസ്മിസ് ചെയ്യുക"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> വികസിപ്പിക്കുക"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> ചുരുക്കുക"</string>
 </resources>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 22f4390..a76117a 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Ажлын хэсгийг нуусан"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Навигацын самбар"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Ажлын хэсгийг үргэлж харуулах"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Навигацын горимыг өөрчлөх"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Илүү хэсэг"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g>-с ирсэн <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> болон бусад <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Зүүн тийш зөөх"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Баруун тийш зөөх"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Бүгдийг үл хэрэгсэх"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>-г дэлгэх"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>-г хураах"</string>
 </resources>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index d7143a1..09f40ab 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"टास्कबार लपवलेले आहे"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"नेव्हिगेशन बार"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"नेहमी टास्कबार दाखवा"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"नेव्हिगेशन मोड बदला"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"ओव्हरफ्लो"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> वरील <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> आणि आणखी <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"डावीकडे हलवा"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"उजवीकडे हलवा"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"सर्व डिसमिस करा"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> चा विस्तार करा"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> कोलॅप्स करा"</string>
 </resources>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index ce2367d..72887ef 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -130,7 +130,10 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Tetapan Pantas"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Bar Tugas"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Bar Tugas dipaparkan"</string>
+    <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Bar Tugas &amp; gelembung dipaparkan di sebelah kiri"</string>
+    <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Bar Tugas &amp; gelembung dipaparkan di sebelah kanan"</string>
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Bar Tugas disembunyikan"</string>
+    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Bar Tugas &amp; gelembung disembunyikan"</string>
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Bar navigasi"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Papar Bar Tugas selalu"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Tukar mod navigasi"</string>
@@ -144,10 +147,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Limpahan"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> daripada <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> dan <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> lagi"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Alih ke kiri"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Alih ke kanan"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Ketepikan semua"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"kembangkan <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"kuncupkan <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index 357f2f8..749c1b5 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -130,7 +130,13 @@
     <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">"Taskbar ပြထားသည်"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar ဖျောက်ထားသည်"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"လမ်းညွှန်ဘား"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Taskbar အမြဲပြရန်"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"ရွှေ့ကြည့်သည့်မုဒ် ပြောင်းရန်"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"မီနူးအပို"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> မှ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> နှင့် နောက်ထပ် <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> ခု"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"ဘယ်သို့ရွှေ့ရန်"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"ညာသို့ရွှေ့ရန်"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"အားလုံးကို ပယ်ရန်"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> ကို ပိုပြပါ"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> ကို လျှော့ပြပါ"</string>
 </resources>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index e075be9..245945b 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Hurtiginnst."</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Oppgavelinje"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Oppgavelinjen vises"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Oppgavelinjen er skjult"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigasjonsrad"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Vis alltid oppgavelinjen"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Endre navigasjonsmodus"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Overflyt"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> fra <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> og <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> andre"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Flytt til venstre"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Flytt til høyre"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Lukk alle"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"vis <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"skjul <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 456c1c3..f881637 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"टास्कबार लुकाइएको छ"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"नेभिगेसन बार"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"टास्कबार सधैँ देखाउनुहोस्"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"नेभिगेसन मोड बदल्नुहोस्"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"ओभरफ्लो"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> मा देखाइएका <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> र थप <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"बायाँतिर सार्नुहोस्"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"दायाँतिर सार्नुहोस्"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"सबै हटाउनुहोस्"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> एक्स्पान्ड गर्नुहोस्"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> कोल्याप्स गर्नुहोस्"</string>
 </resources>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index b6321de..09f8aca 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Snelle instellingen"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Taakbalk"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taakbalk wordt getoond"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taakbalk is verborgen"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigatiebalk"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Taakbalk altijd tonen"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Navigatiemodus wijzigen"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Overloop"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> van <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> en nog <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Naar links verplaatsen"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Naar rechts verplaatsen"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Alles sluiten"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> uitvouwen"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> samenvouwen"</string>
 </resources>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index b7d42ef..83522f3 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ଟାସ୍କବାର ଲୁଚାଯାଇଛି"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ନାଭିଗେସନ ବାର"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"ସର୍ବଦା ଟାସ୍କବାର ଦେଖାନ୍ତୁ"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"ନାଭିଗେସନ ମୋଡ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"ଓଭରଫ୍ଲୋ"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g>ରୁ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> ଏବଂ ଅଧିକ <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"ବାମକୁ ମୁଭ କରନ୍ତୁ"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"ଡାହାଣକୁ ମୁଭ କରନ୍ତୁ"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"ସବୁ ଖାରଜ କରନ୍ତୁ"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> ବିସ୍ତାର କରନ୍ତୁ"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> ସଙ୍କୁଚିତ କରନ୍ତୁ"</string>
 </resources>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index d83d744..197fc6c 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ਟਾਸਕਬਾਰ ਨੂੰ ਲੁਕਾਇਆ ਗਿਆ"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ਨੈਵੀਗੇਸ਼ਨ ਵਾਲੀ ਪੱਟੀ"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"ਹਮੇਸ਼ਾਂ ਟਾਸਕਬਾਰ ਦਿਖਾਓ"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"ਨੈਵੀਗੇਸ਼ਨ ਮੋਡ ਬਦਲੋ"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"ਓਵਰਫ਼ਲੋ"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> ਤੋਂ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> ਅਤੇ <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> ਹੋਰ"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"ਖੱਬੇ ਲਿਜਾਓ"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"ਸੱਜੇ ਲਿਜਾਓ"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"ਸਭ ਖਾਰਜ ਕਰੋ"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> ਦਾ ਵਿਸਤਾਰ ਕਰੋ"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> ਨੂੰ ਸਮੇਟੋ"</string>
 </resources>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 064ba19..5d6d927 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -91,7 +91,7 @@
     <string name="allset_hint" msgid="459504134589971527">"Aby przejść na stronę główną, przesuń w górę"</string>
     <string name="allset_button_hint" msgid="2395219947744706291">"Kliknij przycisk ekranu głównego, aby otworzyć ekran główny"</string>
     <string name="allset_description_generic" msgid="5385500062202019855">"<xliff:g id="DEVICE">%1$s</xliff:g> jest gotowe – możesz zacząć z niego korzystać"</string>
-    <string name="default_device_name" msgid="6660656727127422487">"urządzenie"</string>
+    <string name="default_device_name" msgid="6660656727127422487">"Urządzenie"</string>
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Ustawienia nawigacji w systemie"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Udostępnij"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Zrzut ekranu"</string>
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Szybkie ustawienia"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Pasek aplikacji"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Pasek aplikacji widoczny"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Pasek aplikacji ukryty"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Pasek nawigacyjny"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Zawsze pokazuj pasek aplikacji"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Zmień tryb nawigacji"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Rozwijany"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> z aplikacji <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> i jeszcze <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Przenieś w lewo"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Przenieś w prawo"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Zamknij wszystkie"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"rozwiń dymek: <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"zwiń dymek: <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index dc8bceb..4787ec3 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Definiç. rápidas"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra de tarefas"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tarefas apresentada"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tarefas ocultada"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegação"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Ver sempre Barra de tarefas"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Alterar modo de navegação"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Menu adicional"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> da app <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> e mais <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> pessoas"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Mover para a esquerda"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Mover para a direita"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Ignorar tudo"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"expandir <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"reduzir <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index 3a5ee73..cb45f07 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Config. rápidas"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra de tarefas"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tarefas visível"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tarefas oculta"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegação"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Sempre mostrar a Barra de tarefas"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Mudar o modo de navegação"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Balão flutuante"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> do app <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> e mais <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Mover para esquerda"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Mover para direita"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Dispensar todos"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"abrir <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"fechar <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index 46322ed..31b1951 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Setări rapide"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Bară de activități"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Bara de activități este afișată"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Bara de activități este ascunsă"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Bară de navigare"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Afișează mereu bara"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Schimbă modul de navigare"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Suplimentar"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de la <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> și încă <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Deplasează spre stânga"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Deplasează spre dreapta"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Închide-le pe toate"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"extinde <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"restrânge <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index ec03374..72559f6 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Панель задач скрыта"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Панель навигации"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Всегда показывать панель задач"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Изменить режим навигации"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Дополнительное меню"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"\"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>\" из приложения \"<xliff:g id="APP_NAME">%2$s</xliff:g>\""</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> и ещё <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Переместить влево"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Переместить вправо"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Закрыть все"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"Развернуто: <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"Свернуто: <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index 7f4754f..6e7aabb 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"කාර්ය තීරුව සඟවා ඇත"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"සංචලන තීරුව"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"සෑම විටම කාර්ය තීරුව පෙන්වන්න"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"සංචාලන ප්‍රකාරය වෙනස් කරන්න"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"පිටාර යාම"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> සිට <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> හා තව <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>ක්"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"වමට ගෙන යන්න"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"දකුණට ගෙන යන්න"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"සියල්ල ඉවතලන්න"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> දිග හරින්න"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> හකුළන්න"</string>
 </resources>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index 42faef3..5fbe4f1 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Rýchle nastavenia"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Panel aplikácií"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Panel aplikácií je zobrazený"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Panel aplikácií je skrytý"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigačný panel"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Zobrazovať panel aplikácií"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Zmeniť režim navigácie"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Rozbaľovacia ponuka"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> z aplikácie <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> a ešte <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Posunúť doľava"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Posunúť doprava"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Zavrieť všetko"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"rozbaliť <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"zbaliť <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index c824fc0..62c0c3c 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Hitre nastavitve"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Opravilna vrstica"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Opravilna vrstica je prikazana"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Opravilna vrstica je skrita"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Vrstica za krmarjenje"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Stalen prikaz oprav. vrstice"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Spreminjanje načina navigacije"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Oblaček z dodatnimi elementi"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> iz aplikacije <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> in še <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Premik v levo"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Premik v desno"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Opusti vse"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"razširitev oblačka <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"strnitev oblačka <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index cb793af..78f2733 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Cilësimet shpejt"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Shiriti i detyrave"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Shiriti i detyrave i shfaqur"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Shiriti i detyrave i fshehur"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Shiriti i navigimit"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Shfaq gjithmonë shiritin e detyrave"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Ndrysho modalitetin e navigimit"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Tejkalimi"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"\"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>\" nga <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"\"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g>\" dhe <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> të tjera"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Lëviz majtas"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Lëviz djathtas"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Hiqi të gjitha"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"zgjero <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"palos <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index c8819c8..ee3a467 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Трака задатака је скривена"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Трака за навигацију"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Увек приказуј траку задатака"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Промени режим навигације"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Преклопни"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> – <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> и још <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Помери налево"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Помери надесно"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Одбаци све"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"проширите облачић <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"скупите облачић <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index 6cc637b..e2cf71f 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Snabbinställn."</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Aktivitetsfält"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Aktivitetsfältet visas"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Aktivitetsfältet är dolt"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigeringsfält"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Visa alltid aktivitetsfältet"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Ändra navigeringsläge"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Fler alternativ"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> från <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> och <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> till"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Flytta åt vänster"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Flytta åt höger"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Stäng alla"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"utöka <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"komprimera <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index aac394a..66feb58 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Mipangilio ya Haraka"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Upauzana"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Upauzana umeonyeshwa"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Upauzana umefichwa"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Sehemu ya viungo muhimu"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Onyesha Zana kila wakati"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Badilisha hali ya usogezaji"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Kiputo cha vipengee vya ziada"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> kutoka <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> na vingine <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Sogeza kushoto"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Sogeza kulia"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Ondoa vyote"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"panua <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"kunja <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index a20d23c..43e12ee 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"செயல் பட்டி மறைக்கப்பட்டுள்ளது"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"வழிசெலுத்தல் பட்டி"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"செயல் பட்டியை எப்போதும் காட்டு"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"வழிசெலுத்தல் பயன்முறையை மாற்று"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"கூடுதல் விருப்பங்களைக் காட்டும்"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> வழங்கும் <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> மற்றும் <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"இடதுபுறம் நகர்த்தும்"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"வலதுபுறம் நகர்த்தும்"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"அனைத்தையும் மூடும்"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> ஐ விரிவாக்கும்"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> ஐச் சுருக்கும்"</string>
 </resources>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index c96412e..fbe67dc 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -130,7 +130,10 @@
     <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_shown_with_bubbles_left_title" msgid="4242431789851790046">"టాస్క్‌బార్, బబుల్స్ ఎడమవైపున చూపబడ్డాయి"</string>
+    <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"టాస్క్‌బార్, బబుల్స్ కుడివైపున చూపబడ్డాయి"</string>
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"టాస్క్‌బార్ దాచబడింది"</string>
+    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"టాస్క్‌బార్, బబుల్స్ దాచబడినవి"</string>
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"నావిగేషన్ బార్"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"టాస్క్‌బార్‌ను నిరంతరం చూపండి"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"నావిగేషన్ మోడ్‌ను మార్చండి"</string>
@@ -144,10 +147,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"ఓవర్‌ఫ్లో"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> నుండి <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g>, మరో <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"ఎడమ వైపుగా జరపండి"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"కుడి వైపుగా జరపండి"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"అన్నింటినీ విస్మరించండి"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>ను విస్తరించండి"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>ను కుదించండి"</string>
 </resources>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 080e032..7816628 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"แถบงานซ่อนอยู่"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"แถบนำทาง"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"แสดงแถบงานเสมอ"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"เปลี่ยนโหมดการนําทาง"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"การดำเนินการเพิ่มเติม"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> จาก <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> และอีก <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> รายการ"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"ย้ายไปทางซ้าย"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"ย้ายไปทางขวา"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"ปิดทั้งหมด"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"ขยาย <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"ยุบ <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index 194a81f..e1a77a5 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskbar"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Ipinapakita ang taskbar"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Nakatago ang taskbar"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Ipakita lagi ang Taskbar"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Magpalit ng navigation mode"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Overflow"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> mula sa <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> at <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> pa"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Ilipat pakaliwa"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Ilipat pakanan"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"I-dismiss lahat"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"i-expand ang <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"i-collapse ang <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 0c64537..ef8f50d 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Hızlı Ayarlar"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Görev çubuğu."</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Görev çubuğu gösteriliyor"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Görev çubuğu gizlendi"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Gezinme çubuğu"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Görev çubuğunu daima göster"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Gezinme modunu değiştir"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Taşma"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> uygulamasından <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> ve <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> tane daha"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Sola taşı"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Sağa taşı"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Tümünü kapat"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"genişlet: <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"daralt: <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 9bb0064..201ac18 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Панель завдань приховано"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Панель навігації"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Завжди показув. панель завдань"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Змінити режим навігації"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Додаткове повідомлення"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> з додатка <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> і ще <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Перемістити вліво"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Перемістити вправо"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Закрити все"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"розгорнути \"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>\""</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"згорнути \"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>\""</string>
 </resources>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 63fe0cb..b2a5c88 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ٹاسک بار چھپایا گیا"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"نیویگیشن بار"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"ہمیشہ ٹاسک بار دکھائیں"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"نیویگیشن موڈ تبدیل کریں"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"اوورفلو"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> سے <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> اور <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> مزید"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"بائیں منتقل کریں"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"دائیں منتقل کریں"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"سبھی کو برخاست کریں"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> کو پھیلائیں"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g> کو سکیڑیں"</string>
 </resources>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 94a23c0..6df0b31 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Tezkor sozlamalar"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Vazifalar paneli"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Vazifalar paneli ochiq"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Vazifalar paneli yopiq"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigatsiya paneli"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Vazifalar paneli doim chiqarilsin"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Navigatsiya rejimini oʻzgartirish"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Kengaytirish"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> (<xliff:g id="APP_NAME">%2$s</xliff:g>)"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> va yana <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> kishi"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Chapga siljitish"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Oʻngga siljitish"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Hammasini yopish"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>ni yoyish"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>ni yigʻish"</string>
 </resources>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index 2fe1d14..76eec0c 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Cài đặt nhanh"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"Thanh tác vụ"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Đã hiện thanh thao tác"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Đã ẩn thanh thao tác"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Thanh điều hướng"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Luôn hiện Thanh tác vụ"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Thay đổi chế độ điều hướng"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Bong bóng bổ sung"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> từ <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> và <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> bong bóng khác"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Di chuyển sang trái"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Di chuyển sang phải"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Đóng tất cả"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"mở rộng <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"thu gọn <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index e649e39..b5ae26d 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"任务栏已隐藏"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"导航栏"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"始终显示任务栏"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"更改导航模式"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"溢出式气泡框"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"来自“<xliff:g id="APP_NAME">%2$s</xliff:g>”的<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g>以及另外 <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> 个"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"左移"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"右移"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"全部关闭"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"展开“<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>”"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"收起“<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>”"</string>
 </resources>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index e554148..dd52065 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"隱藏咗工作列"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"導覽列"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"一律顯示工作列"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"變更導覽模式"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"展開式"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="APP_NAME">%2$s</xliff:g> 的「<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>」通知"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g>和其他 <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> 則通知"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"向左移"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"向右移"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"全部關閉"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"打開<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"收埋<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index e598332..6d7652a 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -130,7 +130,13 @@
     <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>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"已隱藏工作列"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"導覽列"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"一律顯示工作列"</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"變更操作模式"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"溢位"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"「<xliff:g id="APP_NAME">%2$s</xliff:g>」的「<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>」通知"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g>和另外 <xliff:g id="BUBBLE_COUNT">%2$d</xliff:g> 則通知"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"向左移"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"向右移"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"全部關閉"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"展開「<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>」"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"收合「<xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>」"</string>
 </resources>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index eb2e9b3..973ce80 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -130,7 +130,13 @@
     <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Amasethingi Asheshayo"</string>
     <string name="taskbar_a11y_title" msgid="6432169809852243110">"I-Taskbar"</string>
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Ibha yomsebenzi ibonisiwe"</string>
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_left_title (4242431789851790046) -->
+    <skip />
+    <!-- no translation found for taskbar_a11y_shown_with_bubbles_right_title (8219065376188180113) -->
+    <skip />
     <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Ibha yomsebenzi ifihliwe"</string>
+    <!-- no translation found for taskbar_a11y_hidden_with_bubbles_title (7397395993149508087) -->
+    <skip />
     <string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Ibha yokufuna"</string>
     <string name="always_show_taskbar" msgid="3608801276107751229">"Bonisa i-Taskbar njalo."</string>
     <string name="change_navigation_mode" msgid="9088393078736808968">"Shintsha imodi yokufuna"</string>
@@ -144,10 +150,9 @@
     <string name="bubble_bar_overflow_description" msgid="8617628132733151708">"Ukugcwala kakhulu"</string>
     <string name="bubble_bar_bubble_description" msgid="1882466152448446446">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> kusuka ku-<xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_bar_description_multiple_bubbles" msgid="3922207715357143648">"<xliff:g id="BUBBLE_BAR_BUBBLE_DESCRIPTION">%1$s</xliff:g> nokunye okungu-<xliff:g id="BUBBLE_COUNT">%2$d</xliff:g>"</string>
-    <!-- no translation found for bubble_bar_action_move_left (3306922475737714758) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_move_right (3455099638571411251) -->
-    <skip />
-    <!-- no translation found for bubble_bar_action_dismiss_all (3290722022983403060) -->
-    <skip />
+    <string name="bubble_bar_action_move_left" msgid="3306922475737714758">"Iya kwesokunxele"</string>
+    <string name="bubble_bar_action_move_right" msgid="3455099638571411251">"Iya kwesokudla"</string>
+    <string name="bubble_bar_action_dismiss_all" msgid="3290722022983403060">"Chitha konke"</string>
+    <string name="bubble_bar_accessibility_announce_expand" msgid="1503192695527477102">"nweba <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
+    <string name="bubble_bar_accessibility_announce_collapse" msgid="928284600086798791">"goqa <xliff:g id="BUBBLE_DESCRIPTION">%1$s</xliff:g>"</string>
 </resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 63412e9..8bcbb33 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -299,10 +299,16 @@
     <string name="taskbar_button_quick_settings">Quick Settings</string>
     <!-- Accessibility title for the Taskbar window. [CHAR_LIMIT=NONE] -->
     <string name="taskbar_a11y_title">Taskbar</string>
-    <!-- Accessibility title for the Taskbar window appeared. [CHAR_LIMIT=NONE] -->
+    <!-- Accessibility title for the Taskbar window appeared. [CHAR_LIMIT=30] -->
     <string name="taskbar_a11y_shown_title">Taskbar shown</string>
-    <!-- Accessibility title for the Taskbar window being close. [CHAR_LIMIT=NONE] -->
+    <!-- Accessibility title for the Taskbar window appearing together with bubble bar on left. [CHAR_LIMIT=30] -->
+    <string name="taskbar_a11y_shown_with_bubbles_left_title">Taskbar &#38; bubbles left shown</string>
+    <!-- Accessibility title for the Taskbar window appearing together with bubble bar on right. [CHAR_LIMIT=30] -->
+    <string name="taskbar_a11y_shown_with_bubbles_right_title">Taskbar &#38; bubbles right shown</string>
+    <!-- Accessibility title for the Taskbar window being closed. [CHAR_LIMIT=30] -->
     <string name="taskbar_a11y_hidden_title">Taskbar hidden</string>
+    <!-- Accessibility title for the Taskbar window being closed together with bubble bar. [CHAR_LIMIT=30] -->
+    <string name="taskbar_a11y_hidden_with_bubbles_title">Taskbar &#38; bubbles hidden</string>
     <!-- Accessibility title for the Taskbar window on phones. [CHAR_LIMIT=NONE] -->
     <string name="taskbar_phone_a11y_title">Navigation bar</string>
     <!-- Text in popup dialog for user to switch between always showing Taskbar or not. [CHAR LIMIT=30] -->
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 44601b7..fe1b403 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1252,15 +1252,25 @@
         TransitionFilter homeCheck = new TransitionFilter();
         // No need to handle the transition that also dismisses keyguard.
         homeCheck.mNotFlags = TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
+
         homeCheck.mRequirements =
                 new TransitionFilter.Requirement[]{new TransitionFilter.Requirement(),
+                        new TransitionFilter.Requirement(),
                         new TransitionFilter.Requirement()};
+
         homeCheck.mRequirements[0].mActivityType = ACTIVITY_TYPE_HOME;
         homeCheck.mRequirements[0].mTopActivity = mLauncher.getComponentName();
         homeCheck.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
         homeCheck.mRequirements[0].mOrder = CONTAINER_ORDER_TOP;
+
         homeCheck.mRequirements[1].mActivityType = ACTIVITY_TYPE_STANDARD;
         homeCheck.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
+
+        homeCheck.mRequirements[2].mNot = true;
+        homeCheck.mRequirements[2].mCustomAnimation = true;
+        homeCheck.mRequirements[2].mMustBeTask = true;
+        homeCheck.mRequirements[2].mMustBeIndependent = true;
+
         SystemUiProxy.INSTANCE.get(mLauncher)
                 .registerRemoteTransition(mLauncherOpenTransition, homeCheck);
         if (mBackAnimationController != null) {
diff --git a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java
index 0b18633..e925af6 100644
--- a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java
+++ b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java
@@ -28,7 +28,6 @@
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ClipData;
 import android.content.ClipDescription;
-import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
@@ -48,11 +47,11 @@
 import com.android.launcher3.model.WidgetsModel;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.PackageItemInfo;
-import com.android.launcher3.popup.PopupDataProvider;
 import com.android.launcher3.widget.WidgetCell;
 import com.android.launcher3.widget.model.WidgetsListBaseEntriesBuilder;
 import com.android.launcher3.widget.model.WidgetsListBaseEntry;
 import com.android.launcher3.widget.picker.WidgetsFullSheet;
+import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -110,8 +109,8 @@
     private WidgetsModel mModel;
     private LauncherAppState mApp;
     private WidgetPredictionsRequester mWidgetPredictionsRequester;
-    private final PopupDataProvider mPopupDataProvider = new PopupDataProvider(i -> {
-    });
+    private final WidgetPickerDataProvider mWidgetPickerDataProvider =
+            new WidgetPickerDataProvider();
 
     private int mDesiredWidgetWidth;
     private int mDesiredWidgetHeight;
@@ -215,8 +214,8 @@
 
     @NonNull
     @Override
-    public PopupDataProvider getPopupDataProvider() {
-        return mPopupDataProvider;
+    public WidgetPickerDataProvider getWidgetPickerDataProvider() {
+        return mWidgetPickerDataProvider;
     }
 
     @Override
@@ -293,8 +292,6 @@
     private void refreshAndBindWidgets() {
         MODEL_EXECUTOR.execute(() -> {
             LauncherAppState app = LauncherAppState.getInstance(this);
-            Context context = app.getContext();
-
             mModel.update(app, null);
             bindWidgets(mModel.getWidgetsByPackageItem());
             // Open sheet once widgets are available, so that it doesn't interrupt the open
@@ -317,7 +314,8 @@
                 shouldShowDefaultWidgets() ? builder.build(widgets,
                         mDefaultWidgetsFilter) : List.of();
 
-        MAIN_EXECUTOR.execute(() -> mPopupDataProvider.setAllWidgets(allWidgets, defaultWidgets));
+        MAIN_EXECUTOR.execute(
+                () -> mWidgetPickerDataProvider.setWidgets(allWidgets, defaultWidgets));
     }
 
     private void openWidgetsSheet() {
@@ -332,7 +330,7 @@
     private void bindRecommendedWidgets(List<ItemInfo> recommendedWidgets) {
         // Bind recommendations once picker has finished open animation.
         MAIN_EXECUTOR.getHandler().postDelayed(
-                () -> mPopupDataProvider.setRecommendedWidgets(recommendedWidgets),
+                () -> mWidgetPickerDataProvider.setWidgetRecommendations(recommendedWidgets),
                 mDeviceProfile.bottomSheetOpenDuration);
     }
 
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index a16031d..92d9516 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -290,6 +290,9 @@
         writer.println(prefix + "\tmPredictionsEnabled: " + mPredictionsEnabled);
         writer.println(prefix + "\tmPredictionUiUpdatePaused: " + mPredictionUiUpdatePaused);
         writer.println(prefix + "\tmNumPredictedAppsPerRow: " + mNumPredictedAppsPerRow);
-        writer.println(prefix + "\tmPredictedApps: " + mPredictedApps);
+        writer.println(prefix + "\tmPredictedApps: " + mPredictedApps.size());
+        for (WorkspaceItemInfo info : mPredictedApps) {
+            writer.println(prefix + "\t\t" + info);
+        }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index de974ec..c50e82d 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -536,6 +536,9 @@
         writer.println(prefix + "HotseatPredictionController");
         writer.println(prefix + "\tFlags: " + getStateString(mPauseFlags));
         writer.println(prefix + "\tmHotSeatItemsCount: " + mHotSeatItemsCount);
-        writer.println(prefix + "\tmPredictedItems: " + mPredictedItems);
+        writer.println(prefix + "\tmPredictedItems: " + mPredictedItems.size());
+        for (ItemInfo info : mPredictedItems) {
+            writer.println(prefix + "\t\t" + info);
+        }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 93a023d..3981e43 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -25,6 +25,7 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
+import android.graphics.Rect;
 import android.window.RemoteTransition;
 
 import androidx.annotation.NonNull;
@@ -181,6 +182,24 @@
     }
 
     /**
+     * Returns the bounds of launcher's hotseat.
+     */
+    public void getHotseatBounds(Rect hotseatBoundsOut) {
+        DeviceProfile launcherDP = mLauncher.getDeviceProfile();
+        if (launcherDP.isQsbInline) {
+            // Not currently supported.
+            hotseatBoundsOut.setEmpty();
+            return;
+        }
+        int left = (launcherDP.widthPx - launcherDP.getHotseatWidthPx()
+                - mLauncher.getHotseat().getUnusedHorizontalSpace()) / 2;
+        int right = left + launcherDP.getHotseatWidthPx();
+        int bottom = launcherDP.getHotseatLayoutPadding(mLauncher).bottom;
+        int top = bottom - launcherDP.hotseatCellHeightPx;
+        hotseatBoundsOut.set(left, top, right, bottom);
+    }
+
+    /**
      * Should be called from onResume() and onPause(), and animates the Taskbar accordingly.
      */
     @Override
@@ -272,6 +291,10 @@
      * app launch animation.
      */
     public void setIgnoreInAppFlagForSync(boolean enabled) {
+        if (mControllers == null) {
+            // This method can be called before init() is called.
+            return;
+        }
         mControllers.taskbarStashController.updateStateForFlag(FLAG_IGNORE_IN_APP, enabled);
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index 252f2a8..266d0b9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -207,8 +207,11 @@
      * Creates and returns a {@link RevealOutlineAnimation} Animator that updates the stashed handle
      * shape and size. When stashed, the shape is a thin rounded pill. When unstashed, the shape
      * morphs into the size of where the taskbar icons will be.
+     *
+     * @param taskbarToHotseatOffsets A Rect of offsets used to transform the bounds of the
+     *                                stashed handle to wrap around the hotseat items.
      */
-    public Animator createRevealAnimToIsStashed(boolean isStashed) {
+    public Animator createRevealAnimToIsStashed(boolean isStashed, Rect taskbarToHotseatOffsets) {
         Rect visualBounds = new Rect(mControllers.taskbarViewController.getIconLayoutBounds());
         float startRadius = mStashedHandleRadius;
 
@@ -219,6 +222,13 @@
             visualBounds.bottom += heightDiff;
 
             startRadius = visualBounds.height() / 2f;
+
+            // We use these offsets to create a larger stashed handle to wrap around the items
+            // of the hotseat. This is only used for certain animations.
+            visualBounds.top +=  taskbarToHotseatOffsets.top;
+            visualBounds.bottom += taskbarToHotseatOffsets.bottom;
+            visualBounds.left += taskbarToHotseatOffsets.left;
+            visualBounds.right += taskbarToHotseatOffsets.right;
         }
 
         final RevealOutlineAnimation handleRevealProvider = new RoundedRectRevealOutlineProvider(
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 18becbb..e4f7262 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -28,6 +28,7 @@
 import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
 import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_OVERLAY_PROXY;
 import static com.android.launcher3.Flags.enableCursorHoverStates;
+import static com.android.launcher3.Flags.enableTaskbarCustomization;
 import static com.android.launcher3.Utilities.calculateTextHeight;
 import static com.android.launcher3.Utilities.isRunningInTestHarness;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
@@ -110,8 +111,12 @@
 import com.android.launcher3.taskbar.bubbles.BubbleDismissController;
 import com.android.launcher3.taskbar.bubbles.BubbleDragController;
 import com.android.launcher3.taskbar.bubbles.BubblePinController;
-import com.android.launcher3.taskbar.bubbles.BubbleStashController;
 import com.android.launcher3.taskbar.bubbles.BubbleStashedHandleViewController;
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController;
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController.TaskbarHotseatDimensionsProvider;
+import com.android.launcher3.taskbar.bubbles.stashing.DeviceProfileDimensionsProviderAdapter;
+import com.android.launcher3.taskbar.bubbles.stashing.PersistentBubbleStashController;
+import com.android.launcher3.taskbar.bubbles.stashing.TransientBubbleStashController;
 import com.android.launcher3.taskbar.customization.TaskbarFeatureEvaluator;
 import com.android.launcher3.taskbar.customization.TaskbarSpecsEvaluator;
 import com.android.launcher3.taskbar.navbutton.NearestTouchFrame;
@@ -140,6 +145,7 @@
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.DesktopTask;
 import com.android.quickstep.util.GroupTask;
+import com.android.quickstep.views.DesktopTaskView;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task;
@@ -149,6 +155,7 @@
 import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 import com.android.systemui.unfold.updates.RotationChangeProvider;
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
+import com.android.wm.shell.Flags;
 
 import java.io.PrintWriter;
 import java.util.Collections;
@@ -207,9 +214,9 @@
 
     private final LauncherPrefs mLauncherPrefs;
 
-    private final TaskbarFeatureEvaluator mTaskbarFeatureEvaluator;
+    private TaskbarFeatureEvaluator mTaskbarFeatureEvaluator;
 
-    private final TaskbarSpecsEvaluator mTaskbarSpecsEvaluator;
+    private TaskbarSpecsEvaluator mTaskbarSpecsEvaluator;
 
     public TaskbarActivityContext(Context windowContext,
             @Nullable Context navigationBarPanelContext, DeviceProfile launcherDp,
@@ -221,12 +228,14 @@
         applyDeviceProfile(launcherDp);
         final Resources resources = getResources();
 
-        mTaskbarFeatureEvaluator = TaskbarFeatureEvaluator.getInstance(this);
-        mTaskbarSpecsEvaluator = new TaskbarSpecsEvaluator(
-                this,
-                mTaskbarFeatureEvaluator,
-                mDeviceProfile.inv.numRows,
-                mDeviceProfile.inv.numColumns);
+        if (enableTaskbarCustomization()) {
+            mTaskbarFeatureEvaluator = TaskbarFeatureEvaluator.getInstance(this);
+            mTaskbarSpecsEvaluator = new TaskbarSpecsEvaluator(
+                    this,
+                    mTaskbarFeatureEvaluator,
+                    mDeviceProfile.inv.numRows,
+                    mDeviceProfile.inv.numColumns);
+        }
 
         mImeDrawsImeNavBar = getBoolByName(IME_DRAWS_IME_NAV_BAR_RES_NAME, resources, false);
         mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode",
@@ -247,15 +256,18 @@
         mWindowManager = c.getSystemService(WindowManager.class);
 
         // Inflate views.
-        int taskbarLayout = DisplayController.isTransientTaskbar(this) && !isPhoneMode()
-                ? R.layout.transient_taskbar
-                : R.layout.taskbar;
+        final boolean isTransientTaskbar = DisplayController.isTransientTaskbar(this)
+                && !isPhoneMode();
+        int taskbarLayout = isTransientTaskbar ? R.layout.transient_taskbar : R.layout.taskbar;
         mDragLayer = (TaskbarDragLayer) mLayoutInflater.inflate(taskbarLayout, null, false);
         TaskbarView taskbarView = mDragLayer.findViewById(R.id.taskbar_view);
         TaskbarScrimView taskbarScrimView = mDragLayer.findViewById(R.id.taskbar_scrim);
         NearestTouchFrame navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view);
         StashedHandleView stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle);
-        BubbleBarView bubbleBarView = mDragLayer.findViewById(R.id.taskbar_bubbles);
+        BubbleBarView bubbleBarView = null;
+        if (isTransientTaskbar || Flags.enableBubbleBarInPersistentTaskBar()) {
+            bubbleBarView = mDragLayer.findViewById(R.id.taskbar_bubbles);
+        }
         StashedHandleView bubbleHandleView = mDragLayer.findViewById(R.id.stashed_bubble_handle);
 
         mAccessibilityDelegate = new TaskbarShortcutMenuAccessibilityDelegate(this);
@@ -264,11 +276,21 @@
         Optional<BubbleControllers> bubbleControllersOptional = Optional.empty();
         BubbleBarController.onTaskbarRecreated();
         if (BubbleBarController.isBubbleBarEnabled() && bubbleBarView != null) {
+            Optional<BubbleStashedHandleViewController> bubbleHandleController = Optional.empty();
+            if (isTransientTaskbar) {
+                bubbleHandleController = Optional.of(
+                        new BubbleStashedHandleViewController(this, bubbleHandleView));
+            }
+            TaskbarHotseatDimensionsProvider dimensionsProvider =
+                    new DeviceProfileDimensionsProviderAdapter(this);
+            BubbleStashController bubbleStashController = isTransientTaskbar
+                    ? new TransientBubbleStashController(dimensionsProvider, getResources())
+                    : new PersistentBubbleStashController(dimensionsProvider);
             bubbleControllersOptional = Optional.of(new BubbleControllers(
                     new BubbleBarController(this, bubbleBarView),
                     new BubbleBarViewController(this, bubbleBarView),
-                    new BubbleStashController(this),
-                    new BubbleStashedHandleViewController(this, bubbleHandleView),
+                    bubbleStashController,
+                    bubbleHandleController,
                     new BubbleDragController(this),
                     new BubbleDismissController(this, mDragLayer),
                     new BubbleBarPinController(this, mDragLayer,
@@ -340,6 +362,38 @@
     }
 
     /**
+     * Calculate the offsets needed to transform the transient taskbar bounds to the hotseat bounds.
+     * @return The offsets will be stored in a Rect
+     */
+    public Rect calculateTaskbarToHotseatOffsets(Rect hotseatBounds) {
+        Rect taskbar = getTransientTaskbarBounds();
+        Rect offsets = new Rect();
+
+        offsets.left = hotseatBounds.left - taskbar.left;
+        offsets.right = hotseatBounds.right - taskbar.right;
+
+        int heightDiff = hotseatBounds.height() - taskbar.height();
+        offsets.top = (taskbar.height() - heightDiff) / 2;
+
+        int gleanedTaskbarPadding = (mDeviceProfile.taskbarHeight
+                - getTransientTaskbarBounds().height()) / 2;
+        offsets.left -= gleanedTaskbarPadding;
+        offsets.top -= gleanedTaskbarPadding;
+        offsets.right += gleanedTaskbarPadding;
+
+        // Bottom is relative to the bottom of layout, so we can calculate it with padding included.
+        offsets.bottom = (hotseatBounds.height() - taskbar.height()) / 2;
+
+        // Update bounds in taskbar background
+        if (hotseatBounds.isEmpty()) {
+            mDragLayer.getTaskbarToHotseatOffsetRect().setEmpty();
+        } else {
+            mDragLayer.getTaskbarToHotseatOffsetRect().set(offsets);
+        }
+        return offsets;
+    }
+
+    /**
      * Copy the original DeviceProfile, match the number of hotseat icons and qsb width and update
      * the icon size
      */
@@ -814,6 +868,11 @@
      */
     public void setUIController(@NonNull TaskbarUIController uiController) {
         mControllers.setUiController(uiController);
+        if (BubbleBarController.isBubbleBarEnabled() && mControllers.bubbleControllers.isEmpty()) {
+            // if the bubble bar was visible in a previous configuration of taskbar and is being
+            // recreated now without bubbles, clean up any bubble bar adjustments from hotseat
+            bubbleBarVisibilityChanged(/* isVisible= */ false);
+        }
     }
 
     /**
@@ -885,8 +944,9 @@
         mControllers.uiController.updateStateForSysuiFlags(systemUiStateFlags);
         mControllers.bubbleControllers.ifPresent(controllers -> {
             controllers.bubbleBarController.updateStateForSysuiFlags(systemUiStateFlags);
-            controllers.bubbleStashedHandleViewController.setIsHomeButtonDisabled(
-                    mControllers.navbarButtonsViewController.isHomeDisabled());
+            controllers.bubbleStashedHandleViewController.ifPresent(controller ->
+                    controller.setIsHomeButtonDisabled(
+                            mControllers.navbarButtonsViewController.isHomeDisabled()));
         });
     }
 
@@ -924,6 +984,7 @@
     public void onTransitionModeUpdated(int barMode, boolean checkBarModes) {
         mControllers.navbarButtonsViewController.onTransitionModeUpdated(barMode, checkBarModes);
     }
+
     public void onNavButtonsDarkIntensityChanged(float darkIntensity) {
         mControllers.navbarButtonsViewController.getTaskbarNavButtonDarkIntensity()
                 .updateValue(darkIntensity);
@@ -1352,7 +1413,8 @@
                     if (foundTask != null) {
                         TaskView foundTaskView = recents.getTaskViewByTaskId(foundTask.key.id);
                         if (foundTaskView != null
-                                && foundTaskView.isVisibleToUser()) {
+                                && foundTaskView.isVisibleToUser()
+                                && !(foundTaskView instanceof DesktopTaskView)) {
                             TestLogging.recordEvent(
                                     TestProtocol.SEQUENCE_MAIN, "start: taskbarAppIcon");
                             foundTaskView.launchTasks();
@@ -1403,7 +1465,6 @@
                         return;
                     }
                 }
-
                 startActivity(intent);
             } else {
                 getSystemService(LauncherApps.class).startMainActivity(
@@ -1611,6 +1672,18 @@
     }
 
     /**
+     * Returns the bounds of launcher's hotseat (if exists).
+     */
+    public void getHotseatBounds(Rect hotseatBoundsOut) {
+        TaskbarUIController uiController = mControllers.uiController;
+        if (uiController instanceof LauncherTaskbarUIController launcherController) {
+            launcherController.getHotseatBounds(hotseatBoundsOut);
+        } else {
+            hotseatBoundsOut.setEmpty();
+        }
+    }
+
+    /**
      * Called when we determine the touchable region.
      *
      * @param exclude {@code true} then the magnification region computation will omit the window.
@@ -1658,10 +1731,12 @@
         return mControllers.taskbarStashController.isInStashedLauncherState();
     }
 
+    @Nullable
     public TaskbarFeatureEvaluator getTaskbarFeatureEvaluator() {
         return mTaskbarFeatureEvaluator;
     }
 
+    @Nullable
     public TaskbarSpecsEvaluator getTaskbarSpecsEvaluator() {
         return mTaskbarSpecsEvaluator;
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index 2737cbd..ee64060 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -21,6 +21,7 @@
 import android.graphics.Color
 import android.graphics.Paint
 import android.graphics.Path
+import android.graphics.Rect
 import android.graphics.RectF
 import com.android.app.animation.Interpolators
 import com.android.launcher3.R
@@ -58,6 +59,9 @@
     var translationYForSwipe = 0f
     var translationYForStash = 0f
 
+    // When not empty, we can use this to transform transient taskbar background to hotseat bounds.
+    val taskbarToHotseatOffsetRect = Rect()
+
     private val transientBackgroundBounds = context.transientTaskbarBounds
 
     private val shadowAlpha: Float
@@ -218,6 +222,12 @@
         val radius = newBackgroundHeight / 2f
         val bottomMarginProgress = bottomMargin * ((1f - progress) / 2f)
 
+        // Used to transform the background so that it wraps around the items on the hotseat.
+        val hotseatOffsetLeft = taskbarToHotseatOffsetRect.left * progress
+        val hotseatOffsetTop = taskbarToHotseatOffsetRect.top * progress
+        val hotseatOffsetRight = taskbarToHotseatOffsetRect.right * progress
+        val hotseatOffsetBottom = taskbarToHotseatOffsetRect.bottom * progress
+
         // Aligns the bottom with the bottom of the stashed handle.
         val bottom =
             canvas.height - bottomMargin +
@@ -242,10 +252,10 @@
         strokePaint.alpha = (paint.alpha * strokeAlpha) / 255
 
         lastDrawnTransientRect.set(
-            transientBackgroundBounds.left + halfWidthDelta,
-            bottom - newBackgroundHeight,
-            transientBackgroundBounds.right - halfWidthDelta,
-            bottom
+            transientBackgroundBounds.left + halfWidthDelta + hotseatOffsetLeft,
+            bottom - newBackgroundHeight + hotseatOffsetTop,
+            transientBackgroundBounds.right - halfWidthDelta + hotseatOffsetRight,
+            bottom + hotseatOffsetBottom
         )
         val horizontalInset = fullWidth * widthInsetPercentage
         lastDrawnTransientRect.inset(horizontalInset, 0f)
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 0645972..d94d9175 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -165,6 +165,7 @@
         taskbarOverlayController.init(this);
         taskbarAllAppsController.init(this, sharedState.allAppsVisible);
         navButtonController.init(this);
+        bubbleControllers.ifPresent(controllers -> controllers.init(this));
         taskbarInsetsController.init(this);
         voiceInteractionWindowController.init(this);
         taskbarRecentAppsController.init(this);
@@ -172,7 +173,6 @@
         taskbarEduTooltipController.init(this);
         keyboardQuickSwitchController.init(this);
         taskbarPinningController.init(this, mSharedState);
-        bubbleControllers.ifPresent(controllers -> controllers.init(this));
 
         mControllersToLog = new LoggableTaskbarController[] {
                 taskbarDragController, navButtonController, navbarButtonsViewController,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index a9b34d2..a090956 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -22,6 +22,7 @@
 
 import android.content.Context;
 import android.graphics.Canvas;
+import android.graphics.Rect;
 import android.graphics.RectF;
 import android.media.permission.SafeCloseable;
 import android.util.AttributeSet;
@@ -259,6 +260,11 @@
         return mBackgroundRenderer.getLastDrawnTransientRect();
     }
 
+    /** Returns the rect used to transform transient taskbar to the hotseat */
+    public Rect getTaskbarToHotseatOffsetRect() {
+        return mBackgroundRenderer.getTaskbarToHotseatOffsetRect();
+    }
+
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
         TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index d57c483..06376d3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -33,6 +33,7 @@
 import android.widget.TextView
 import androidx.annotation.IntDef
 import androidx.annotation.LayoutRes
+import androidx.annotation.VisibleForTesting
 import androidx.core.text.HtmlCompat
 import androidx.core.view.updateLayoutParams
 import com.airbnb.lottie.LottieAnimationView
@@ -87,7 +88,7 @@
                 !activityContext.isTinyTaskbar
         }
 
-    private val isOpen: Boolean
+    val isTooltipOpen: Boolean
         get() = tooltip?.isOpen ?: false
 
     val isBeforeTooltipFeaturesStep: Boolean
@@ -96,7 +97,8 @@
     private lateinit var controllers: TaskbarControllers
 
     // Keep track of whether the user has seen the Search Edu
-    private var userHasSeenSearchEdu: Boolean
+    @VisibleForTesting
+    var userHasSeenSearchEdu: Boolean
         get() {
             return TASKBAR_SEARCH_EDU_SEEN.get(activityContext)
         }
@@ -409,7 +411,7 @@
     override fun dumpLogs(prefix: String?, pw: PrintWriter?) {
         pw?.println(prefix + "TaskbarEduTooltipController:")
         pw?.println("$prefix\tisTooltipEnabled=$isTooltipEnabled")
-        pw?.println("$prefix\tisOpen=$isOpen")
+        pw?.println("$prefix\tisOpen=$isTooltipOpen")
         pw?.println("$prefix\ttooltipStep=$tooltipStep")
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 2103ebb..4c5564e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -131,7 +131,7 @@
         val taskbarTouchableHeight = controllers.taskbarStashController.touchableHeight
         val bubblesTouchableHeight =
             if (controllers.bubbleControllers.isPresent) {
-                controllers.bubbleControllers.get().bubbleStashController.touchableHeight
+                controllers.bubbleControllers.get().bubbleStashController.getTouchableHeight()
             } else {
                 0
             }
@@ -139,7 +139,7 @@
 
         if (
             controllers.bubbleControllers.isPresent &&
-                controllers.bubbleControllers.get().bubbleStashController.isBubblesShowingOnHome
+                controllers.bubbleControllers.get().bubbleStashController.isBubbleBarVisible()
         ) {
             val iconBounds =
                 controllers.bubbleControllers.get().bubbleBarViewController.bubbleBarBounds
@@ -162,8 +162,7 @@
                 controllers.bubbleControllers
                     .getOrNull()
                     ?.bubbleBarViewController
-                    ?.isAnimatingNewBubble
-                    ?: false
+                    ?.isAnimatingNewBubble ?: false
             if (isAnimatingNewBubble) {
                 val iconBounds =
                     controllers.bubbleControllers.get().bubbleBarViewController.bubbleBarBounds
@@ -358,13 +357,6 @@
      */
     fun updateInsetsTouchability(insetsInfo: ViewTreeObserver.InternalInsetsInfo) {
         insetsInfo.touchableRegion.setEmpty()
-        // Always have nav buttons be touchable
-        controllers.navbarButtonsViewController.addVisibleButtonsRegion(
-            context.dragLayer,
-            insetsInfo.touchableRegion
-        )
-        debugTouchableRegion.lastSetTouchableBounds.set(insetsInfo.touchableRegion.bounds)
-
         val bubbleBarVisible =
             controllers.bubbleControllers.isPresent &&
                 controllers.bubbleControllers.get().bubbleBarViewController.isBubbleBarVisible()
@@ -443,6 +435,12 @@
             debugTouchableRegion.lastSetTouchableReason =
                 "Icons are not visible, but other components such as 3 buttons might be"
         }
+        // Always have nav buttons be touchable
+        controllers.navbarButtonsViewController.addVisibleButtonsRegion(
+            context.dragLayer,
+            insetsInfo.touchableRegion
+        )
+        debugTouchableRegion.lastSetTouchableBounds.set(insetsInfo.touchableRegion.bounds)
         context.excludeFromMagnificationRegion(insetsIsTouchableRegion)
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index cb9f24a..20ab32e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -250,7 +250,7 @@
 
         applyState(0);
 
-        mCanSyncViews = true;
+        mCanSyncViews = !mControllers.taskbarActivityContext.isPhoneMode();
         mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
         updateOverviewDragState(mLauncherState);
     }
@@ -263,7 +263,7 @@
         mLauncher.getHotseat().setIconsAlpha(1f);
         mLauncher.getStateManager().removeStateListener(mStateListener);
 
-        mCanSyncViews = true;
+        mCanSyncViews = !mControllers.taskbarActivityContext.isPhoneMode();
         mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
     }
 
@@ -743,8 +743,7 @@
         if (firstFrameVisChanged && mCanSyncViews && !Utilities.isRunningInTestHarness()) {
             ViewRootSync.synchronizeNextDraw(mLauncher.getHotseat(),
                     mControllers.taskbarActivityContext.getDragLayer(),
-                    () -> {
-                    });
+                    () -> {});
         }
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
index 49fc0dd..1a168a9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
@@ -27,8 +27,8 @@
 import com.android.quickstep.RecentsModel
 import com.android.quickstep.util.DesktopTask
 import com.android.quickstep.util.GroupTask
-import com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps
-import com.android.wm.shell.shared.desktopmode.DesktopModeFlags.DESKTOP_WINDOWING_MODE
+import com.android.wm.shell.shared.desktopmode.DesktopModeFlags
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
 import java.io.PrintWriter
 
 /**
@@ -44,9 +44,9 @@
     private val desktopVisibilityControllerProvider: () -> DesktopVisibilityController?,
 ) : LoggableTaskbarController {
 
-    // TODO(b/335401172): unify DesktopMode checks in Launcher.
     var canShowRunningApps =
-        DESKTOP_WINDOWING_MODE.isEnabled(context) && enableDesktopWindowingTaskbarRunningApps()
+        DesktopModeStatus.canEnterDesktopMode(context) &&
+            DesktopModeFlags.TASKBAR_RUNNING_APPS.isEnabled(context)
         @VisibleForTesting
         set(isEnabledFromTest) {
             field = isEnabledFromTest
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
index 48d2bc2..5e7c7ce 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -20,8 +20,8 @@
 import static com.android.launcher3.taskbar.bubbles.BubbleBarController.isBubbleBarEnabled;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED;
-import static com.android.wm.shell.common.bubbles.BubbleConstants.BUBBLE_EXPANDED_SCRIM_ALPHA;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
+import static com.android.wm.shell.common.bubbles.BubbleConstants.BUBBLE_EXPANDED_SCRIM_ALPHA;
 
 import android.animation.ObjectAnimator;
 import android.view.animation.Interpolator;
@@ -65,6 +65,7 @@
      */
     public void init(TaskbarControllers controllers) {
         mControllers = controllers;
+        onTaskbarVisibilityChanged(mControllers.taskbarViewController.getTaskbarVisibility());
     }
 
     /**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 0c5ad42..5d6fdc1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -42,6 +42,7 @@
 import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
 import android.app.RemoteAction;
+import android.graphics.Rect;
 import android.graphics.drawable.Icon;
 import android.os.SystemClock;
 import android.util.Log;
@@ -202,6 +203,7 @@
      * by not scaling the height of the taskbar background.
      */
     private static final int TRANSITION_UNSTASH_SUW_MANUAL = 3;
+    private static final Rect EMPTY_RECT = new Rect();
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(value = {
@@ -713,7 +715,7 @@
         }
 
         fullLengthAnimatorSet.play(mControllers.stashedHandleViewController
-                .createRevealAnimToIsStashed(isStashed));
+                .createRevealAnimToIsStashed(isStashed, EMPTY_RECT));
         // 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.
         fullLengthAnimatorSet.play(mTaskbarStashedHandleHintScale.animateToValue(1f));
@@ -763,6 +765,19 @@
             }
         }
 
+
+        Rect taskbarToHotseatOffsets = new Rect();
+        if (enableScalingRevealHomeAnimation() && animationType == TRANSITION_HOME_TO_APP) {
+            Rect hotseatRect = new Rect();
+            mActivity.getHotseatBounds(hotseatRect);
+
+            // Calculate and store offsets so that we can sync with the taskbar stashed handle
+            taskbarToHotseatOffsets.set(
+                    mActivity.calculateTaskbarToHotseatOffsets(hotseatRect));
+            as.addListener(AnimatorListeners.forEndCallback(
+                    () -> mActivity.calculateTaskbarToHotseatOffsets(EMPTY_RECT)));
+        }
+
         play(as, mTaskbarStashedHandleAlpha.animateToValue(stashedHandleAlphaTarget),
                 backgroundAndHandleAlphaStartDelay,
                 backgroundAndHandleAlphaDuration, LINEAR);
@@ -808,10 +823,12 @@
         }
 
         mControllers.taskbarViewController.addRevealAnimToIsStashed(skippable, isStashed, duration,
-                EMPHASIZED, animationType == TRANSITION_UNSTASH_SUW_MANUAL);
+                EMPHASIZED, animationType == TRANSITION_UNSTASH_SUW_MANUAL,
+                animationType == TRANSITION_HOME_TO_APP);
 
         play(skippable, mControllers.stashedHandleViewController
-                .createRevealAnimToIsStashed(isStashed), 0, duration, EMPHASIZED);
+                .createRevealAnimToIsStashed(isStashed, taskbarToHotseatOffsets), 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.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
index 144c0c2..5a5d6d0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
@@ -95,7 +95,8 @@
         mControllers.taskbarDragLayerController.setTranslationYForSwipe(transY);
         mControllers.bubbleControllers.ifPresent(controllers -> {
             controllers.bubbleBarViewController.setTranslationYForSwipe(transY);
-            controllers.bubbleStashedHandleViewController.setTranslationYForSwipe(transY);
+            controllers.bubbleStashedHandleViewController.ifPresent(
+                    controller -> controller.setTranslationYForSwipe(transY));
         });
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index a2278ec..2ada5ba 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -174,11 +174,11 @@
                 || mControllers.navbarButtonsViewController.isEventOverAnyItem(ev);
     }
 
-    /** Checks if the given {@link MotionEvent} is over the bubble bar stash handle. */
-    public boolean isEventOverBubbleBarStashHandle(MotionEvent ev) {
+    /** Checks if the given {@link MotionEvent} is over the bubble bar views. */
+    public boolean isEventOverBubbleBarViews(MotionEvent ev) {
         return mControllers.bubbleControllers.map(
                 bubbleControllers ->
-                        bubbleControllers.bubbleStashController.isEventOverStashHandle(ev))
+                        bubbleControllers.bubbleStashController.isEventOverBubbleBarViews(ev))
                 .orElse(false);
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index c42d6c6..e58069a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -72,6 +72,7 @@
 import com.android.quickstep.util.DesktopTask;
 import com.android.quickstep.util.GroupTask;
 import com.android.systemui.shared.recents.model.Task;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
 
 import java.util.List;
 import java.util.function.Predicate;
@@ -246,12 +247,34 @@
     @Override
     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
         if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) {
-            announceForAccessibility(mContext.getString(R.string.taskbar_a11y_shown_title));
+            announceTaskbarShown();
         } else if (action == AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS) {
-            announceForAccessibility(mContext.getString(R.string.taskbar_a11y_hidden_title));
+            announceTaskbarHidden();
         }
         return super.performAccessibilityActionInternal(action, arguments);
+    }
 
+    private void announceTaskbarShown() {
+        BubbleBarLocation bubbleBarLocation = mControllerCallbacks.getBubbleBarLocationIfVisible();
+        if (bubbleBarLocation == null) {
+            announceForAccessibility(mContext.getString(R.string.taskbar_a11y_shown_title));
+        } else if (bubbleBarLocation.isOnLeft(isLayoutRtl())) {
+            announceForAccessibility(
+                    mContext.getString(R.string.taskbar_a11y_shown_with_bubbles_left_title));
+        } else {
+            announceForAccessibility(
+                    mContext.getString(R.string.taskbar_a11y_shown_with_bubbles_right_title));
+        }
+    }
+
+    private void announceTaskbarHidden() {
+        BubbleBarLocation bubbleBarLocation = mControllerCallbacks.getBubbleBarLocationIfVisible();
+        if (bubbleBarLocation == null) {
+            announceForAccessibility(mContext.getString(R.string.taskbar_a11y_hidden_title));
+        } else {
+            announceForAccessibility(
+                    mContext.getString(R.string.taskbar_a11y_hidden_with_bubbles_title));
+        }
     }
 
     protected void announceAccessibilityChanges() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
index 3c646cb..e6cac2f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
@@ -23,8 +23,12 @@
 import android.view.MotionEvent;
 import android.view.View;
 
+import androidx.annotation.Nullable;
+
 import com.android.internal.jank.Cuj;
+import com.android.launcher3.taskbar.bubbles.BubbleBarViewController;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
 
 /**
  * Callbacks for {@link TaskbarView} to interact with its controller.
@@ -104,4 +108,18 @@
         mControllers.taskbarScrimViewController.onTaskbarVisibilityChanged(
                 mTaskbarView.getVisibility());
     }
+
+    /**
+     * Get current location of bubble bar, if it is visible.
+     * Returns {@code null} if bubble bar is not shown.
+     */
+    @Nullable
+    public BubbleBarLocation getBubbleBarLocationIfVisible() {
+        BubbleBarViewController bubbleBarViewController =
+                mControllers.bubbleControllers.map(c -> c.bubbleBarViewController).orElse(null);
+        if (bubbleBarViewController != null && bubbleBarViewController.isBubbleBarVisible()) {
+            return bubbleBarViewController.getBubbleBarLocation();
+        }
+        return null;
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index b21c414..ffa4819 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -33,6 +33,7 @@
 import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_ALIGNMENT_ANIM;
 import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_PINNING_ANIM;
 import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_REVEAL_ANIM;
+import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
@@ -232,6 +233,13 @@
         mActivity.removeOnDeviceProfileChangeListener(mDeviceProfileChangeListener);
     }
 
+    /**
+     * Gets the taskbar {@link View.Visibility visibility}.
+     */
+    public int getTaskbarVisibility() {
+        return mTaskbarView.getVisibility();
+    }
+
     public boolean areIconsVisible() {
         return mTaskbarView.areIconsVisible();
     }
@@ -574,7 +582,8 @@
      * @param interpolator The interpolator to use for all animations.
      */
     public void addRevealAnimToIsStashed(AnimatorSet as, boolean isStashed, long duration,
-            Interpolator interpolator, boolean dispatchOnAnimationStart) {
+            Interpolator interpolator, boolean dispatchOnAnimationStart,
+            boolean isHomeToAppAnimation) {
         AnimatorSet reveal = new AnimatorSet();
 
         Rect stashedBounds = new Rect();
@@ -623,8 +632,21 @@
                 reveal.play(ObjectAnimator.ofFloat(mtd.getTranslationX(INDEX_TASKBAR_REVEAL_ANIM),
                         MULTI_PROPERTY_VALUE, transX)
                         .setDuration(duration));
-                reveal.play(ObjectAnimator.ofFloat(mtd.getTranslationY(INDEX_TASKBAR_REVEAL_ANIM),
-                        MULTI_PROPERTY_VALUE, transY));
+
+                if (enableScalingRevealHomeAnimation()) {
+                    // Delay y-translation by 1 frame to keep icons within the bounds of the bg.
+                    int delay = isHomeToAppAnimation ? getSingleFrameMs(mActivity) : 0;
+                    ObjectAnimator yAnimator =
+                            ObjectAnimator.ofFloat(mtd.getTranslationY(INDEX_TASKBAR_REVEAL_ANIM),
+                                            MULTI_PROPERTY_VALUE, transY)
+                                    .setDuration(Math.max(0, duration - delay));
+                    yAnimator.setStartDelay(delay);
+                    reveal.play(yAnimator);
+                } else {
+                    reveal.play(
+                            ObjectAnimator.ofFloat(mtd.getTranslationY(INDEX_TASKBAR_REVEAL_ANIM),
+                                    MULTI_PROPERTY_VALUE, transY));
+                }
                 as.addListener(forEndCallback(() ->
                         mtd.setTranslation(INDEX_TASKBAR_REVEAL_ANIM, 0, 0)));
             } else {
diff --git a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
index 5a5ff8e..619c9c4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
@@ -41,7 +41,8 @@
 class VoiceInteractionWindowController(val context: TaskbarActivityContext) :
     TaskbarControllers.LoggableTaskbarController, TaskbarControllers.BackgroundRendererController {
 
-    private val isSeparateBackgroundEnabled = !DisplayController.isTransientTaskbar(context)
+    private val isSeparateBackgroundEnabled =
+        !DisplayController.isTransientTaskbar(context) && !context.isPhoneMode
     private val taskbarBackgroundRenderer = TaskbarBackgroundRenderer(context)
     private val nonTouchableInsetsComputer =
         ViewTreeObserver.OnComputeInternalInsetsListener {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubbleIconsFactory.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubbleIconsFactory.kt
new file mode 100644
index 0000000..4330c5b
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubbleIconsFactory.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar.bubbles
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.drawable.Drawable
+import com.android.launcher3.icons.BaseIconFactory
+
+/** Bubble icons factory for the bubble bar. */
+class BubbleBarBubbleIconsFactory(context: Context, bubbleSize: Int) :
+    BaseIconFactory(context, context.resources.configuration.densityDpi, bubbleSize) {
+
+    /** Creates shadowed icon for the bubble bar. */
+    fun createShadowedIconBitmap(
+        icon: Drawable,
+        scale: Float,
+    ): Bitmap = super.createIconBitmap(icon, scale, MODE_WITH_SHADOW)
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index 5be0171..58cd042 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -63,6 +63,7 @@
 import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.icons.BubbleIconFactory;
 import com.android.launcher3.shortcuts.ShortcutRequest;
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController;
 import com.android.launcher3.util.Executors.SimpleThreadFactory;
 import com.android.quickstep.SystemUiProxy;
 import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
@@ -76,6 +77,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 
@@ -144,7 +146,7 @@
     private ImeVisibilityChecker mImeVisibilityChecker;
     private BubbleBarViewController mBubbleBarViewController;
     private BubbleStashController mBubbleStashController;
-    private BubbleStashedHandleViewController mBubbleStashedHandleViewController;
+    private Optional<BubbleStashedHandleViewController> mBubbleStashedHandleViewController;
     private BubblePinController mBubblePinController;
 
     // Cache last sent top coordinate to avoid sending duplicate updates to shell
@@ -221,8 +223,9 @@
         bubbleControllers.runAfterInit(() -> {
             mBubbleBarViewController.setHiddenForBubbles(
                     !sBubbleBarEnabled || mBubbles.isEmpty());
-            mBubbleStashedHandleViewController.setHiddenForBubbles(
-                    !sBubbleBarEnabled || mBubbles.isEmpty());
+            mBubbleStashedHandleViewController.ifPresent(
+                    controller -> controller.setHiddenForBubbles(
+                            !sBubbleBarEnabled || mBubbles.isEmpty()));
             mBubbleBarViewController.setUpdateSelectedBubbleAfterCollapse(
                     key -> setSelectedBubbleInternal(mBubbles.get(key)));
             mBubbleBarViewController.setBoundsChangeListener(this::onBubbleBarBoundsChanged);
@@ -258,10 +261,11 @@
         mBubbleBarViewController.setHiddenForSysui(hideBubbleBar);
 
         boolean hideHandleView = (flags & MASK_HIDE_HANDLE_VIEW) != 0;
-        mBubbleStashedHandleViewController.setHiddenForSysui(hideHandleView);
+        mBubbleStashedHandleViewController.ifPresent(
+                controller -> controller.setHiddenForSysui(hideHandleView));
 
         boolean sysuiLocked = (flags & MASK_SYSUI_LOCKED) != 0;
-        mBubbleStashController.onSysuiLockedStateChange(sysuiLocked);
+        mBubbleStashController.setSysuiLocked(sysuiLocked);
     }
 
     //
@@ -387,7 +391,8 @@
 
         // Adds and removals have happened, update visibility before any other visual changes.
         mBubbleBarViewController.setHiddenForBubbles(mBubbles.isEmpty());
-        mBubbleStashedHandleViewController.setHiddenForBubbles(mBubbles.isEmpty());
+        mBubbleStashedHandleViewController.ifPresent(
+                controller -> controller.setHiddenForBubbles(mBubbles.isEmpty()));
 
         if (mBubbles.isEmpty()) {
             // all bubbles were removed. clear the selected bubble
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt
index 9e5ffc9..a6b0860 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt
@@ -27,6 +27,7 @@
 import android.widget.FrameLayout
 import androidx.core.view.updateLayoutParams
 import com.android.launcher3.R
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController
 import com.android.wm.shell.common.bubbles.BaseBubblePinController
 import com.android.wm.shell.common.bubbles.BubbleBarLocation
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index 5d550ae..7d27a90 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -959,11 +959,14 @@
             float fullElevationForChild = (MAX_BUBBLES * mBubbleElevation) - i;
             bv.setZ(fullElevationForChild * elevationState);
 
-            // only update the dot scale if we're expanding or collapsing
+            // only update the dot and badge scale if we're expanding or collapsing
             if (mWidthAnimator.isRunning()) {
                 // The dot for the selected bubble scales in the opposite direction of the expansion
                 // animation.
                 bv.showDotIfNeeded(bv == mSelectedBubbleView ? 1 - widthState : widthState);
+                // The badge for the selected bubble is always at full scale. All other bubbles
+                // scale according to the expand animation.
+                bv.setBadgeScale(bv == mSelectedBubbleView ? 1 : widthState);
             }
 
             if (mIsBarExpanded) {
@@ -972,16 +975,12 @@
                 // where the bubble will end up when the animation ends
                 final float targetX = expandedX + expandedBarShift;
                 bv.setTranslationX(widthState * (targetX - collapsedX) + collapsedX);
-                // When we're expanded, the badge is visible for all bubbles
-                bv.updateBadgeVisibility(/* show= */ true);
                 bv.setAlpha(1);
             } else {
                 // If bar is on the right, account for bubble bar expanding and shifting left
                 final float collapsedBarShift = onLeft ? 0 : currentWidth - collapsedWidth;
                 final float targetX = collapsedX + collapsedBarShift;
                 bv.setTranslationX(widthState * (expandedX - targetX) + targetX);
-                // The badge is always visible for the first bubble
-                bv.updateBadgeVisibility(/* show= */ i == 0);
                 // If we're fully collapsed, hide all bubbles except for the first 2. If there are
                 // only 2 bubbles, hide the second bubble as well because it's the overflow.
                 if (widthState == 0) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index 9270f68..916b7b1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -39,6 +39,7 @@
 import com.android.launcher3.taskbar.TaskbarInsetsController;
 import com.android.launcher3.taskbar.TaskbarStashController;
 import com.android.launcher3.taskbar.bubbles.animation.BubbleBarViewAnimator;
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController;
 import com.android.launcher3.util.MultiPropertyFactory;
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.quickstep.SystemUiProxy;
@@ -92,7 +93,7 @@
 
     private BubbleBarViewAnimator mBubbleBarViewAnimator;
 
-    private TimeSource mTimeSource = System::currentTimeMillis;
+    private final TimeSource mTimeSource = System::currentTimeMillis;
 
     @Nullable
     private BubbleBarBoundsChangeListener mBoundsChangeListener;
@@ -386,7 +387,8 @@
         int newIconSize;
         int newPadding;
         Resources res = mActivity.getResources();
-        if (mBubbleStashController.isBubblesShowingOnHome()) {
+        if (mBubbleStashController.isBubblesShowingOnHome()
+                || mBubbleStashController.isTransientTaskBar()) {
             newIconSize = getBubbleBarIconSizeFromDeviceProfile(res);
             newPadding = getBubbleBarPaddingFromDeviceProfile(res);
         } else {
@@ -507,7 +509,8 @@
                 // the bubble bar and handle are initialized as part of the first bubble animation.
                 // if the animation is suppressed, immediately stash or show the bubble bar to
                 // ensure they've been initialized.
-                if (mTaskbarStashController.isInApp()) {
+                if (mTaskbarStashController.isInApp()
+                        && mBubbleStashController.isTransientTaskBar()) {
                     mBubbleStashController.stashBubbleBarImmediate();
                 } else {
                     mBubbleStashController.showBubbleBarImmediate();
@@ -530,14 +533,15 @@
             mBubbleBarViewAnimator.animateToInitialState(bubble, isInApp, isExpanding);
             return;
         }
-
-        if (mBubbleStashController.isBubblesShowingOnHome() && !isExpanding && !isExpanded()) {
+        boolean persistentTaskbarOrOnHome = mBubbleStashController.isBubblesShowingOnHome()
+                || !mBubbleStashController.isTransientTaskBar();
+        if (persistentTaskbarOrOnHome && !isExpanding && !isExpanded()) {
             mBubbleBarViewAnimator.animateBubbleBarForCollapsed(bubble);
             return;
         }
 
-        // only animate the new bubble if we're in an app and not auto expanding
-        if (isInApp && !isExpanding && !isExpanded()) {
+        // only animate the new bubble if we're in an app, have handle view and not auto expanding
+        if (isInApp && !isExpanding && mBubbleStashController.getHasHandleView() && !isExpanded()) {
             mBubbleBarViewAnimator.animateBubbleInForStashed(bubble);
         }
     }
@@ -598,6 +602,7 @@
     /**
      * Updates the dragged bubble view in the bubble bar view, and notifies SystemUI
      * that a bubble is being dragged to dismiss.
+     *
      * @param bubbleView dragged bubble view
      */
     public void onBubbleDragStart(@NonNull BubbleView bubbleView) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
index 03140fe..a5243fa 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
@@ -16,19 +16,19 @@
 package com.android.launcher3.taskbar.bubbles;
 
 import com.android.launcher3.taskbar.TaskbarControllers;
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController;
 import com.android.launcher3.util.RunnableList;
 
 import java.io.PrintWriter;
+import java.util.Optional;
 
-/**
- * Hosts various bubble controllers to facilitate passing between one another.
- */
+/** Hosts various bubble controllers to facilitate passing between one another. */
 public class BubbleControllers {
 
     public final BubbleBarController bubbleBarController;
     public final BubbleBarViewController bubbleBarViewController;
     public final BubbleStashController bubbleStashController;
-    public final BubbleStashedHandleViewController bubbleStashedHandleViewController;
+    public final Optional<BubbleStashedHandleViewController> bubbleStashedHandleViewController;
     public final BubbleDragController bubbleDragController;
     public final BubbleDismissController bubbleDismissController;
     public final BubbleBarPinController bubbleBarPinController;
@@ -45,7 +45,7 @@
             BubbleBarController bubbleBarController,
             BubbleBarViewController bubbleBarViewController,
             BubbleStashController bubbleStashController,
-            BubbleStashedHandleViewController bubbleStashedHandleViewController,
+            Optional<BubbleStashedHandleViewController> bubbleStashedHandleViewController,
             BubbleDragController bubbleDragController,
             BubbleDismissController bubbleDismissController,
             BubbleBarPinController bubbleBarPinController,
@@ -68,9 +68,15 @@
     public void init(TaskbarControllers taskbarControllers) {
         bubbleBarController.init(this,
                 taskbarControllers.navbarButtonsViewController::isImeVisible);
-        bubbleBarViewController.init(taskbarControllers, this);
-        bubbleStashedHandleViewController.init(taskbarControllers, this);
-        bubbleStashController.init(taskbarControllers, this);
+        bubbleStashedHandleViewController.ifPresent(
+                controller -> controller.init(/* bubbleControllers = */ this));
+        bubbleStashController.init(
+                taskbarControllers.taskbarInsetsController,
+                bubbleBarViewController,
+                bubbleStashedHandleViewController.orElse(null),
+                taskbarControllers::runAfterInit
+        );
+        bubbleBarViewController.init(taskbarControllers, /* bubbleControllers = */ this);
         bubbleDragController.init(/* bubbleControllers = */ this);
         bubbleDismissController.init(/* bubbleControllers = */ this);
         bubbleBarPinController.init(this);
@@ -93,7 +99,7 @@
      * Cleans up all controllers.
      */
     public void onDestroy() {
-        bubbleStashedHandleViewController.onDestroy();
+        bubbleStashedHandleViewController.ifPresent(BubbleStashedHandleViewController::onDestroy);
         bubbleBarController.onDestroy();
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubblePinController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubblePinController.kt
index a77e685..1341b53 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubblePinController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubblePinController.kt
@@ -27,6 +27,7 @@
 import android.widget.FrameLayout
 import androidx.core.view.updateLayoutParams
 import com.android.launcher3.R
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController
 import com.android.wm.shell.common.bubbles.BaseBubblePinController
 import com.android.wm.shell.common.bubbles.BubbleBarLocation
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
deleted file mode 100644
index 74f58ac..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.taskbar.bubbles;
-
-import static java.lang.Math.abs;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.annotation.Nullable;
-import android.view.InsetsController;
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.android.launcher3.R;
-import com.android.launcher3.anim.AnimatedFloat;
-import com.android.launcher3.taskbar.StashedHandleViewController;
-import com.android.launcher3.taskbar.TaskbarActivityContext;
-import com.android.launcher3.taskbar.TaskbarControllers;
-import com.android.launcher3.taskbar.TaskbarInsetsController;
-import com.android.launcher3.taskbar.TaskbarStashController;
-import com.android.launcher3.util.MultiPropertyFactory;
-import com.android.wm.shell.common.bubbles.BubbleBarLocation;
-import com.android.wm.shell.shared.animation.PhysicsAnimator;
-
-import java.io.PrintWriter;
-
-/**
- * Coordinates between controllers such as BubbleBarView and BubbleHandleViewController to
- * create a cohesive animation between stashed/unstashed states.
- */
-public class BubbleStashController {
-
-    private static final String TAG = "BubbleStashController";
-
-    /**
-     * How long to stash/unstash.
-     */
-    public static final long BAR_STASH_DURATION = InsetsController.ANIMATION_DURATION_RESIZE;
-
-    /**
-     * The scale bubble bar animates to when being stashed.
-     */
-    private static final float STASHED_BAR_SCALE = 0.5f;
-
-    protected final TaskbarActivityContext mActivity;
-
-    // Initialized in init.
-    private TaskbarControllers mControllers;
-    private TaskbarInsetsController mTaskbarInsetsController;
-    private BubbleBarViewController mBarViewController;
-    private BubbleStashedHandleViewController mHandleViewController;
-    private TaskbarStashController mTaskbarStashController;
-
-    private MultiPropertyFactory.MultiProperty mIconAlphaForStash;
-    private AnimatedFloat mIconScaleForStash;
-    private AnimatedFloat mIconTranslationYForStash;
-    private MultiPropertyFactory.MultiProperty mBubbleStashedHandleAlpha;
-
-    private boolean mRequestedStashState;
-    private boolean mRequestedExpandedState;
-
-    private boolean mIsStashed;
-    private int mStashedHeight;
-    private int mUnstashedHeight;
-    private boolean mBubblesShowingOnHome;
-    private boolean mBubblesShowingOnOverview;
-    private boolean mIsSysuiLocked;
-
-    private final float mHandleCenterFromScreenBottom;
-
-    @Nullable
-    private AnimatorSet mAnimator;
-
-    public BubbleStashController(TaskbarActivityContext activity) {
-        mActivity = activity;
-        // the handle is centered within the stashed taskbar area
-        mHandleCenterFromScreenBottom =
-                mActivity.getResources().getDimensionPixelSize(R.dimen.bubblebar_stashed_size) / 2f;
-    }
-
-    public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
-        mControllers = controllers;
-        mTaskbarInsetsController = controllers.taskbarInsetsController;
-        mBarViewController = bubbleControllers.bubbleBarViewController;
-        mHandleViewController = bubbleControllers.bubbleStashedHandleViewController;
-        mTaskbarStashController = controllers.taskbarStashController;
-
-        mIconAlphaForStash = mBarViewController.getBubbleBarAlpha().get(0);
-        mIconScaleForStash = mBarViewController.getBubbleBarScale();
-        mIconTranslationYForStash = mBarViewController.getBubbleBarTranslationY();
-
-        mBubbleStashedHandleAlpha = mHandleViewController.getStashedHandleAlpha().get(
-                StashedHandleViewController.ALPHA_INDEX_STASHED);
-
-        mStashedHeight = mHandleViewController.getStashedHeight();
-        mUnstashedHeight = mHandleViewController.getUnstashedHeight();
-    }
-
-    /**
-     * Returns the touchable height of the bubble bar based on it's stashed state.
-     */
-    public int getTouchableHeight() {
-        return mIsStashed ? mStashedHeight : mUnstashedHeight;
-    }
-
-    /**
-     * Returns whether the bubble bar is currently stashed.
-     */
-    public boolean isStashed() {
-        return mIsStashed;
-    }
-
-    /**
-     * Animates the handle (or bubble bar depending on state) to be visible after the device is
-     * unlocked.
-     *
-     * <p>Normally either the bubble bar or the handle is visible,
-     * and {@link #showBubbleBar(boolean)} and {@link #stashBubbleBar()} are used to transition
-     * between these two states. But the transition from the state where both the bar and handle
-     * are invisible is slightly different.
-     */
-    private void animateAfterUnlock() {
-        AnimatorSet animatorSet = new AnimatorSet();
-        if (mBubblesShowingOnHome || mBubblesShowingOnOverview) {
-            mIsStashed = false;
-            animatorSet.playTogether(mIconScaleForStash.animateToValue(1),
-                    mIconTranslationYForStash.animateToValue(getBubbleBarTranslationY()),
-                    mIconAlphaForStash.animateToValue(1));
-        } else {
-            mIsStashed = true;
-            animatorSet.playTogether(mBubbleStashedHandleAlpha.animateToValue(1));
-        }
-
-        animatorSet.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                onIsStashedChanged();
-            }
-        });
-        animatorSet.setDuration(BAR_STASH_DURATION).start();
-    }
-
-    /**
-     * Called when launcher enters or exits the home page. Bubbles are unstashed on home.
-     */
-    public void setBubblesShowingOnHome(boolean onHome) {
-        if (mBubblesShowingOnHome != onHome) {
-            mBubblesShowingOnHome = onHome;
-
-            if (!mBarViewController.hasBubbles()) {
-                // if there are no bubbles, there's nothing to show, so just return.
-                return;
-            }
-
-            if (mBubblesShowingOnHome) {
-                showBubbleBar(/* expanded= */ false);
-                // When transitioning from app to home the stash animator may already have been
-                // created, so we need to animate the bubble bar here to align with hotseat.
-                if (!mIsStashed) {
-                    mIconTranslationYForStash.animateToValue(getBubbleBarTranslationYForHotseat())
-                            .start();
-                }
-                // If the bubble bar is already unstashed, the taskbar touchable region won't be
-                // updated correctly, so force an update here.
-                mControllers.runAfterInit(() ->
-                        mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged());
-            } else if (!mBarViewController.isExpanded()) {
-                stashBubbleBar();
-            }
-        }
-    }
-
-    /** Whether bubbles are showing on the launcher home page. */
-    public boolean isBubblesShowingOnHome() {
-        boolean hasBubbles = mBarViewController != null && mBarViewController.hasBubbles();
-        return mBubblesShowingOnHome && hasBubbles;
-    }
-
-    // TODO: when tapping on an app in overview, this is a bit delayed compared to taskbar stashing
-    /** Called when launcher enters or exits overview. Bubbles are unstashed on overview. */
-    public void setBubblesShowingOnOverview(boolean onOverview) {
-        if (mBubblesShowingOnOverview != onOverview) {
-            mBubblesShowingOnOverview = onOverview;
-            if (!mBubblesShowingOnOverview && !mBarViewController.isExpanded()) {
-                stashBubbleBar();
-            } else {
-                // When transitioning to overview the stash animator may already have been
-                // created, so we need to animate the bubble bar here to align with taskbar.
-                mIconTranslationYForStash.animateToValue(getBubbleBarTranslationYForTaskbar())
-                        .start();
-            }
-        }
-    }
-
-    /** Whether bubbles are showing on Overview. */
-    public boolean isBubblesShowingOnOverview() {
-        return mBubblesShowingOnOverview;
-    }
-
-    /** Called when sysui locked state changes, when locked, bubble bar is stashed. */
-    public void onSysuiLockedStateChange(boolean isSysuiLocked) {
-        if (isSysuiLocked != mIsSysuiLocked) {
-            mIsSysuiLocked = isSysuiLocked;
-            if (!mIsSysuiLocked && mBarViewController.hasBubbles()) {
-                animateAfterUnlock();
-            }
-        }
-    }
-
-    /**
-     * Stashes the bubble bar if allowed based on other state (e.g. on home and overview the
-     * bar does not stash).
-     */
-    public void stashBubbleBar() {
-        mRequestedStashState = true;
-        mRequestedExpandedState = false;
-        updateStashedAndExpandedState();
-    }
-
-    /**
-     * Shows the bubble bar, and expands bubbles depending on {@param expandBubbles}.
-     */
-    public void showBubbleBar(boolean expandBubbles) {
-        mRequestedStashState = false;
-        mRequestedExpandedState = expandBubbles;
-        updateStashedAndExpandedState();
-    }
-
-    private void updateStashedAndExpandedState() {
-        if (mBarViewController.isHiddenForNoBubbles()) {
-            // If there are no bubbles the bar and handle are invisible, nothing to do here.
-            return;
-        }
-        boolean isStashed = mRequestedStashState
-                && !mBubblesShowingOnHome
-                && !mBubblesShowingOnOverview;
-        if (mIsStashed != isStashed) {
-            // notify the view controller that the stash state is about to change so that it can
-            // cancel an ongoing animation if there is one.
-            // note that this has to be called before updating mIsStashed with the new value,
-            // otherwise interrupting an ongoing animation may update it again with the wrong state
-            mBarViewController.onStashStateChanging();
-            mIsStashed = isStashed;
-            if (mAnimator != null) {
-                mAnimator.cancel();
-            }
-            mAnimator = createStashAnimator(mIsStashed, BAR_STASH_DURATION);
-            mAnimator.start();
-            onIsStashedChanged();
-        }
-        if (mBarViewController.isExpanded() != mRequestedExpandedState) {
-            mBarViewController.setExpanded(mRequestedExpandedState);
-        }
-    }
-
-    /**
-     * Create a stash animation.
-     *
-     * @param isStashed whether it's a stash animation or an unstash animation
-     * @param duration duration of the animation
-     * @return the animation
-     */
-    private AnimatorSet createStashAnimator(boolean isStashed, long duration) {
-        AnimatorSet animatorSet = new AnimatorSet();
-
-        AnimatorSet fullLengthAnimatorSet = new AnimatorSet();
-        // Not exactly half and may overlap. See [first|second]HalfDurationScale below.
-        AnimatorSet firstHalfAnimatorSet = new AnimatorSet();
-        AnimatorSet secondHalfAnimatorSet = new AnimatorSet();
-
-        final float firstHalfDurationScale;
-        final float secondHalfDurationScale;
-
-        if (isStashed) {
-            firstHalfDurationScale = 0.75f;
-            secondHalfDurationScale = 0.5f;
-
-            fullLengthAnimatorSet.play(
-                    mIconTranslationYForStash.animateToValue(getStashTranslation()));
-
-            firstHalfAnimatorSet.playTogether(
-                    mIconAlphaForStash.animateToValue(0),
-                    mIconScaleForStash.animateToValue(STASHED_BAR_SCALE));
-            secondHalfAnimatorSet.playTogether(
-                    mBubbleStashedHandleAlpha.animateToValue(1));
-        } else  {
-            firstHalfDurationScale = 0.5f;
-            secondHalfDurationScale = 0.75f;
-
-            final float translationY = getBubbleBarTranslationY();
-
-            fullLengthAnimatorSet.playTogether(
-                    mIconScaleForStash.animateToValue(1),
-                    mIconTranslationYForStash.animateToValue(translationY));
-
-            firstHalfAnimatorSet.playTogether(
-                    mBubbleStashedHandleAlpha.animateToValue(0)
-            );
-            secondHalfAnimatorSet.playTogether(
-                    mIconAlphaForStash.animateToValue(1)
-            );
-        }
-
-        fullLengthAnimatorSet.play(mHandleViewController.createRevealAnimToIsStashed(isStashed));
-
-        fullLengthAnimatorSet.setDuration(duration);
-        firstHalfAnimatorSet.setDuration((long) (duration * firstHalfDurationScale));
-        secondHalfAnimatorSet.setDuration((long) (duration * secondHalfDurationScale));
-        secondHalfAnimatorSet.setStartDelay((long) (duration * (1 - secondHalfDurationScale)));
-
-        animatorSet.playTogether(fullLengthAnimatorSet, firstHalfAnimatorSet,
-                secondHalfAnimatorSet);
-        animatorSet.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mAnimator = null;
-                mControllers.runAfterInit(() -> {
-                    if (isStashed) {
-                        mBarViewController.setExpanded(false);
-                    }
-                    mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
-                });
-            }
-        });
-        return animatorSet;
-    }
-
-    private float getStashTranslation() {
-        return (mUnstashedHeight - mStashedHeight) / 2f;
-    }
-
-    private void onIsStashedChanged() {
-        mControllers.runAfterInit(() -> {
-            mHandleViewController.onIsStashedChanged();
-            mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
-        });
-    }
-
-    public float getBubbleBarTranslationYForTaskbar() {
-        return -mActivity.getDeviceProfile().taskbarBottomMargin;
-    }
-
-    private float getBubbleBarTranslationYForHotseat() {
-        final float hotseatBottomSpace = mActivity.getDeviceProfile().hotseatBarBottomSpacePx;
-        final float hotseatCellHeight = mActivity.getDeviceProfile().hotseatCellHeightPx;
-        return -hotseatBottomSpace - hotseatCellHeight + mUnstashedHeight - abs(
-                hotseatCellHeight - mUnstashedHeight) / 2;
-    }
-
-    public float getBubbleBarTranslationY() {
-        // If we're on home, adjust the translation so the bubble bar aligns with hotseat.
-        // Otherwise we're either showing in an app or in overview. In either case adjust it so
-        // the bubble bar aligns with the taskbar.
-        return mBubblesShowingOnHome ? getBubbleBarTranslationYForHotseat()
-                : getBubbleBarTranslationYForTaskbar();
-    }
-
-    /**
-     * The difference on the Y axis between the center of the handle and the center of the bubble
-     * bar.
-     */
-    public float getDiffBetweenHandleAndBarCenters() {
-        // the difference between the centers of the handle and the bubble bar is the difference
-        // between their distance from the bottom of the screen.
-
-        float barCenter = mBarViewController.getBubbleBarCollapsedHeight() / 2f;
-        return mHandleCenterFromScreenBottom - barCenter;
-    }
-
-    /** The distance the handle moves as part of the new bubble animation. */
-    public float getStashedHandleTranslationForNewBubbleAnimation() {
-        // the should move up to the top of the stashed taskbar area. it is centered within it so
-        // it should move the same distance as it is away from the bottom.
-        return -mHandleCenterFromScreenBottom;
-    }
-
-    /** Checks whether the motion event is over the stash handle. */
-    public boolean isEventOverStashHandle(MotionEvent ev) {
-        return mHandleViewController.isEventOverHandle(ev);
-    }
-
-    /** Set a bubble bar location */
-    public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
-        mHandleViewController.setBubbleBarLocation(bubbleBarLocation);
-    }
-
-    /** Returns the [PhysicsAnimator] for the stashed handle view. */
-    public PhysicsAnimator<View> getStashedHandlePhysicsAnimator() {
-        return mHandleViewController.getPhysicsAnimator();
-    }
-
-    /** Notifies taskbar that it should update its touchable region. */
-    public void updateTaskbarTouchRegion() {
-        mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
-    }
-
-    /** Shows the bubble bar immediately without animation. */
-    public void showBubbleBarImmediate() {
-        mHandleViewController.setTranslationYForSwipe(0);
-        mIconTranslationYForStash.updateValue(getBubbleBarTranslationY());
-        mIconAlphaForStash.setValue(1);
-        mIconScaleForStash.updateValue(1);
-        mIsStashed = false;
-        onIsStashedChanged();
-    }
-
-    /** Stashes the bubble bar immediately without animation. */
-    public void stashBubbleBarImmediate() {
-        mHandleViewController.setTranslationYForSwipe(0);
-        mBubbleStashedHandleAlpha.setValue(1);
-        mIconAlphaForStash.setValue(0);
-        mIconTranslationYForStash.updateValue(getStashTranslation());
-        mIconScaleForStash.updateValue(STASHED_BAR_SCALE);
-        mIsStashed = true;
-        onIsStashedChanged();
-    }
-
-    /**
-     * Updates the values of the internal animators after the new bubble animation was interrupted
-     *
-     * @param isStashed whether the current state should be stashed
-     * @param bubbleBarTranslationY the current bubble bar translation. this is only used if the
-     *                              bubble bar is showing to ensure that the stash animator runs
-     *                              smoothly.
-     */
-    public void onNewBubbleAnimationInterrupted(boolean isStashed, float bubbleBarTranslationY) {
-        if (isStashed) {
-            mBubbleStashedHandleAlpha.setValue(1);
-            mIconAlphaForStash.setValue(0);
-            mIconScaleForStash.updateValue(STASHED_BAR_SCALE);
-            mIconTranslationYForStash.updateValue(getStashTranslation());
-        } else {
-            mBubbleStashedHandleAlpha.setValue(0);
-            mHandleViewController.setTranslationYForSwipe(0);
-            mIconAlphaForStash.setValue(1);
-            mIconScaleForStash.updateValue(1);
-            mIconTranslationYForStash.updateValue(bubbleBarTranslationY);
-        }
-        mIsStashed = isStashed;
-        onIsStashedChanged();
-    }
-
-    /** Set the translation Y for the stashed handle. */
-    public void setHandleTranslationY(float ty) {
-        mHandleViewController.setTranslationYForSwipe(ty);
-    }
-
-    /** Dumps the state of BubbleStashController. */
-    public void dump(PrintWriter pw) {
-        pw.println("Bubble stash controller state:");
-        pw.println("  mIsStashed: " + mIsStashed);
-        pw.println("  mBubblesShowingOnOverview: " + mBubblesShowingOnOverview);
-        pw.println("  mBubblesShowingOnHome: " + mBubblesShowingOnHome);
-        pw.println("  mIsSysuiLocked: " + mIsSysuiLocked);
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
index 91103d7..52f5a29 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
@@ -33,7 +33,7 @@
 import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
 import com.android.launcher3.taskbar.StashedHandleView;
 import com.android.launcher3.taskbar.TaskbarActivityContext;
-import com.android.launcher3.taskbar.TaskbarControllers;
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController;
 import com.android.launcher3.util.Executors;
 import com.android.launcher3.util.MultiPropertyFactory;
 import com.android.launcher3.util.MultiValueAlpha;
@@ -79,7 +79,8 @@
         mStashedHandleAlpha = new MultiValueAlpha(mStashedHandleView, 1);
     }
 
-    public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
+    /** Initialize controller. */
+    public void init(BubbleControllers bubbleControllers) {
         mBarViewController = bubbleControllers.bubbleBarViewController;
         mBubbleStashController = bubbleControllers.bubbleStashController;
 
@@ -117,7 +118,7 @@
                     public Rect getSampledRegion(View sampledView) {
                         return mStashedHandleView.getSampledRegion();
                     }
-                }, Executors.UI_HELPER_EXECUTOR);
+                }, Executors.MAIN_EXECUTOR, Executors.UI_HELPER_EXECUTOR);
 
         mStashedHandleView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) ->
                 updateBounds(mBarViewController.getBubbleBarLocation()));
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
index 3bcaa16..09da3e0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
@@ -20,15 +20,13 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Outline;
 import android.graphics.Path;
 import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewOutlineProvider;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ImageView;
 
@@ -36,7 +34,6 @@
 
 import com.android.launcher3.R;
 import com.android.launcher3.icons.DotRenderer;
-import com.android.launcher3.icons.IconNormalizer;
 import com.android.wm.shell.animation.Interpolators;
 import com.android.wm.shell.common.bubbles.BubbleBarLocation;
 import com.android.wm.shell.common.bubbles.BubbleInfo;
@@ -70,15 +67,22 @@
     // The current scale value of the dot
     private float mDotScale;
 
+    private boolean mProvideShadowOutline = true;
+
     // TODO: (b/273310265) handle RTL
     // Whether the bubbles are positioned on the left or right side of the screen
     private boolean mOnLeft = false;
 
     private BubbleBarItem mBubble;
 
+    private Bitmap mIcon;
+
     @Nullable
     private Controller mController;
 
+    @Nullable
+    private BubbleBarBubbleIconsFactory mIconFactory = null;
+
     public BubbleView(Context context) {
         this(context, null);
     }
@@ -105,25 +109,14 @@
 
         setFocusable(true);
         setClickable(true);
-        setOutlineProvider(new ViewOutlineProvider() {
-            @Override
-            public void getOutline(View view, Outline outline) {
-                BubbleView.this.getOutline(outline);
-            }
-        });
-    }
-
-    private void getOutline(Outline outline) {
-        updateBubbleSizeAndDotRender();
-        final int normalizedSize = IconNormalizer.getNormalizedCircleSize(mBubbleSize);
-        final int inset = (mBubbleSize - normalizedSize) / 2;
-        outline.setOval(inset, inset, inset + normalizedSize, inset + normalizedSize);
     }
 
     private void updateBubbleSizeAndDotRender() {
         int updatedBubbleSize = Math.min(getWidth(), getHeight());
         if (updatedBubbleSize == mBubbleSize) return;
         mBubbleSize = updatedBubbleSize;
+        mIconFactory = new BubbleBarBubbleIconsFactory(mContext, mBubbleSize);
+        updateBubbleIcon();
         if (mBubble == null || mBubble instanceof BubbleBarOverflow) return;
         Path dotPath = ((BubbleBarBubble) mBubble).getDotPath();
         mDotRenderer = new DotRenderer(mBubbleSize, dotPath, DEFAULT_PATH_SIZE);
@@ -241,7 +234,8 @@
     /** Sets the bubble being rendered in this view. */
     public void setBubble(BubbleBarBubble bubble) {
         mBubble = bubble;
-        mBubbleIcon.setImageBitmap(bubble.getIcon());
+        mIcon = bubble.getIcon();
+        updateBubbleIcon();
         mAppIcon.setImageBitmap(bubble.getBadge());
         mDotColor = bubble.getDotColor();
         mDotRenderer = new DotRenderer(mBubbleSize, bubble.getDotPath(), DEFAULT_PATH_SIZE);
@@ -257,6 +251,18 @@
         setContentDescription(contentDesc);
     }
 
+    private void updateBubbleIcon() {
+        Bitmap icon = null;
+        if (mIcon != null) {
+            icon = mIcon;
+            if (mIconFactory != null) {
+                BitmapDrawable iconDrawable = new BitmapDrawable(getResources(), icon);
+                icon = mIconFactory.createShadowedIconBitmap(iconDrawable, /* scale = */ 1f);
+            }
+        }
+        mBubbleIcon.setImageBitmap(icon);
+    }
+
     /**
      * Sets that this bubble represents the overflow. The overflow appears in the list of bubbles
      * but does not represent app content, instead it shows recent bubbles that couldn't fit into
@@ -265,7 +271,8 @@
      */
     public void setOverflow(BubbleBarOverflow overflow, Bitmap bitmap) {
         mBubble = overflow;
-        mBubbleIcon.setImageBitmap(bitmap);
+        mIcon = bitmap;
+        updateBubbleIcon();
         mAppIcon.setVisibility(GONE); // Overflow doesn't show the app badge
         setContentDescription(getResources().getString(R.string.bubble_bar_overflow_description));
     }
@@ -287,18 +294,9 @@
         }
     }
 
-    void updateBadgeVisibility(boolean show) {
-        if (mBubble instanceof BubbleBarOverflow) {
-            // The overflow bubble does not have a badge, so just bail.
-            return;
-        }
-        BubbleBarBubble bubble = (BubbleBarBubble) mBubble;
-        Bitmap appBadgeBitmap = bubble.getBadge();
-        int translationX = mOnLeft
-                ? -(bubble.getIcon().getWidth() - appBadgeBitmap.getWidth())
-                : 0;
-        mAppIcon.setTranslationX(translationX);
-        mAppIcon.setVisibility(show ? VISIBLE : GONE);
+    void setBadgeScale(float fraction) {
+        mAppIcon.setScaleX(fraction);
+        mAppIcon.setScaleY(fraction);
     }
 
     boolean hasUnseenContent() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
index feff9fd..0a0cfd0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
@@ -26,8 +26,8 @@
 import com.android.launcher3.R
 import com.android.launcher3.taskbar.bubbles.BubbleBarBubble
 import com.android.launcher3.taskbar.bubbles.BubbleBarView
-import com.android.launcher3.taskbar.bubbles.BubbleStashController
 import com.android.launcher3.taskbar.bubbles.BubbleView
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController
 import com.android.wm.shell.shared.animation.PhysicsAnimator
 
 /** Handles animations for bubble bar bubbles. */
@@ -138,19 +138,20 @@
         // handle. when the handle becomes invisible and we start animating in the bubble bar,
         // the translation y is offset by this value to make the transition from the handle to the
         // bar smooth.
-        val offset = bubbleStashController.diffBetweenHandleAndBarCenters
-        val stashedHandleTranslationY =
-            bubbleStashController.stashedHandleTranslationForNewBubbleAnimation
+        val offset: Float = bubbleStashController.getDiffBetweenHandleAndBarCenters()
+        val stashedHandleTranslationY: Float =
+            bubbleStashController.getStashedHandleTranslationForNewBubbleAnimation()
 
         // this is the total distance that both the stashed handle and the bubble will be traveling
         // at the end of the animation the bubble bar will be positioned in the same place when it
         // shows while we're in an app.
         val totalTranslationY = bubbleStashController.bubbleBarTranslationYForTaskbar + offset
-        val animator = bubbleStashController.stashedHandlePhysicsAnimator
+        val animator = bubbleStashController.getStashedHandlePhysicsAnimator() ?: return@Runnable
         animator.setDefaultSpringConfig(springConfig)
         animator.spring(DynamicAnimation.TRANSLATION_Y, totalTranslationY)
         animator.addUpdateListener { handle, values ->
-            val ty = values[DynamicAnimation.TRANSLATION_Y]?.value ?: return@addUpdateListener
+            val ty: Float =
+                values[DynamicAnimation.TRANSLATION_Y]?.value ?: return@addUpdateListener
             when {
                 ty >= stashedHandleTranslationY -> {
                     // we're in the first leg of the animation. only animate the handle. the bubble
@@ -226,13 +227,13 @@
      */
     private fun buildBubbleBarToHandleAnimation() = Runnable {
         if (animatingBubble == null) return@Runnable
-        val offset = bubbleStashController.diffBetweenHandleAndBarCenters
+        val offset = bubbleStashController.getStashedHandleTranslationForNewBubbleAnimation()
         val stashedHandleTranslationY =
-            bubbleStashController.stashedHandleTranslationForNewBubbleAnimation
+            bubbleStashController.getStashedHandleTranslationForNewBubbleAnimation()
         // this is the total distance that both the stashed handle and the bar will be traveling
         val totalTranslationY = bubbleStashController.bubbleBarTranslationYForTaskbar + offset
         bubbleStashController.setHandleTranslationY(totalTranslationY)
-        val animator = bubbleStashController.stashedHandlePhysicsAnimator
+        val animator = bubbleStashController.getStashedHandlePhysicsAnimator() ?: return@Runnable
         animator.setDefaultSpringConfig(springConfig)
         animator.spring(DynamicAnimation.TRANSLATION_Y, 0f)
         animator.addUpdateListener { handle, values ->
@@ -363,7 +364,7 @@
     /** Handles touching the animating bubble bar. */
     fun onBubbleBarTouchedWhileAnimating() {
         PhysicsAnimator.getInstance(bubbleBarView).cancelIfRunning()
-        bubbleStashController.stashedHandlePhysicsAnimator.cancelIfRunning()
+        bubbleStashController.getStashedHandlePhysicsAnimator().cancelIfRunning()
         val hideAnimation = animatingBubble?.hideAnimation ?: return
         scheduler.cancel(hideAnimation)
         bubbleBarView.onAnimatingBubbleCompleted()
@@ -376,7 +377,7 @@
         val hideAnimation = animatingBubble?.hideAnimation ?: return
         scheduler.cancel(hideAnimation)
         animatingBubble = null
-        bubbleStashController.stashedHandlePhysicsAnimator.cancel()
+        bubbleStashController.getStashedHandlePhysicsAnimator().cancelIfRunning()
         bubbleBarView.onAnimatingBubbleCompleted()
         bubbleBarView.relativePivotY = 1f
         bubbleStashController.onNewBubbleAnimationInterrupted(
@@ -385,8 +386,8 @@
         )
     }
 
-    private fun <T> PhysicsAnimator<T>.cancelIfRunning() {
-        if (isRunning()) cancel()
+    private fun <T> PhysicsAnimator<T>?.cancelIfRunning() {
+        if (this?.isRunning() == true) cancel()
     }
 
     private fun ObjectAnimator.withDuration(duration: Long): ObjectAnimator {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleStashController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleStashController.kt
index e42b6d6..0f43744 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleStashController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleStashController.kt
@@ -52,7 +52,7 @@
     /** Execute passed action only after controllers are initiated. */
     interface ControllersAfterInitAction {
         /** Execute action after controllers are initiated. */
-        fun runAfterInit(action: () -> Unit)
+        fun runAfterInit(action: Runnable)
     }
 
     /** Whether bubble bar is currently stashed */
@@ -81,12 +81,7 @@
         controllersAfterInitAction: ControllersAfterInitAction
     )
 
-    /** Sets stashed and expanded state of the bubble bar */
-    fun updateStashedAndExpandedState(stash: Boolean = false, expand: Boolean = false)
-
-    /**
-     * Shows the bubble bar at [getBubbleBarTranslationY] position immediately without animation.
-     */
+    /** Shows the bubble bar at [bubbleBarTranslationY] position immediately without animation. */
     fun showBubbleBarImmediate()
 
     /** Shows the bubble bar at [bubbleBarTranslationY] position immediately without animation. */
@@ -120,21 +115,17 @@
      * Stashes the bubble bar (transform to the handle view), or just shrink width of the expanded
      * bubble bar based on the controller implementation.
      */
-    fun stashBubbleBar() {
-        updateStashedAndExpandedState(stash = true, expand = false)
-    }
+    fun stashBubbleBar()
 
     /** Shows the bubble bar, and expands bubbles depending on [expandBubbles]. */
-    fun showBubbleBar(expandBubbles: Boolean) {
-        updateStashedAndExpandedState(stash = false, expandBubbles)
-    }
+    fun showBubbleBar(expandBubbles: Boolean)
 
     // TODO(b/354218264): Move to BubbleBarViewAnimator
     /**
      * The difference on the Y axis between the center of the handle and the center of the bubble
      * bar.
      */
-    fun getSlideInAnimationDistanceY(): Float
+    fun getDiffBetweenHandleAndBarCenters(): Float
 
     // TODO(b/354218264): Move to BubbleBarViewAnimator
     /** The distance the handle moves as part of the new bubble animation. */
@@ -190,13 +181,5 @@
 
         /** The scale bubble bar animates to when being stashed. */
         const val STASHED_BAR_SCALE = 0.5f
-
-        /** Creates new instance of [BubbleStashController] */
-        @JvmStatic
-        fun newInstance(
-            taskbarHotseatDimensionsProvider: TaskbarHotseatDimensionsProvider
-        ): BubbleStashController {
-            return PersistentTaskbarStashController(taskbarHotseatDimensionsProvider)
-        }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/DeviceProfileDimensionsProviderAdapter.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/DeviceProfileDimensionsProviderAdapter.kt
new file mode 100644
index 0000000..a55763b
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/DeviceProfileDimensionsProviderAdapter.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.bubbles.stashing
+
+import com.android.launcher3.DeviceProfile
+import com.android.launcher3.taskbar.TaskbarActivityContext
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController.TaskbarHotseatDimensionsProvider
+
+/**
+ * Implementation of the [TaskbarHotseatDimensionsProvider] that take sizes from the
+ * [DeviceProfile].
+ */
+class DeviceProfileDimensionsProviderAdapter(
+    private val taskbarActivityContext: TaskbarActivityContext
+) : TaskbarHotseatDimensionsProvider {
+    override fun getTaskbarBottomSpace(): Int = deviceProfile().taskbarBottomMargin
+
+    override fun getTaskbarHeight(): Int = deviceProfile().taskbarHeight
+
+    override fun getHotseatBottomSpace(): Int = deviceProfile().hotseatBarBottomSpacePx
+
+    override fun getHotseatHeight(): Int = deviceProfile().hotseatCellHeightPx
+
+    private fun deviceProfile(): DeviceProfile = taskbarActivityContext.deviceProfile
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentTaskbarStashController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashController.kt
similarity index 94%
rename from quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentTaskbarStashController.kt
rename to quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashController.kt
index 4a05a5e..62fe221 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentTaskbarStashController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashController.kt
@@ -33,7 +33,7 @@
 import com.android.wm.shell.common.bubbles.BubbleBarLocation
 import com.android.wm.shell.shared.animation.PhysicsAnimator
 
-class PersistentTaskbarStashController(
+class PersistentBubbleStashController(
     private val taskbarHotseatDimensionsProvider: TaskbarHotseatDimensionsProvider,
 ) : BubbleStashController {
 
@@ -54,7 +54,7 @@
             }
             if (onHome) {
                 // When transition to home we should show collapse the bubble bar
-                updateStashedAndExpandedState(stash = false, expand = false)
+                updateExpandedState(expand = false)
             }
             animateBubbleBarY()
             bubbleBarViewController.onBubbleBarConfigurationChanged(/* animate= */ true)
@@ -66,7 +66,7 @@
             field = onOverview
             if (!onOverview) {
                 // When transition from overview we should show collapse the bubble bar
-                updateStashedAndExpandedState(stash = false, expand = false)
+                updateExpandedState(expand = false)
             }
             bubbleBarViewController.onBubbleBarConfigurationChanged(/* animate= */ true)
         }
@@ -114,7 +114,8 @@
         this.bubbleBarViewController = bubbleBarViewController
         this.controllersAfterInitAction = controllersAfterInitAction
         bubbleBarTranslationYAnimator = bubbleBarViewController.bubbleBarTranslationY
-        bubbleBarAlphaAnimator = bubbleBarViewController.bubbleBarAlpha.get(0)
+        // bubble bar has only alpha property, getting it at index 0
+        bubbleBarAlphaAnimator = bubbleBarViewController.bubbleBarAlpha.get(/* index= */ 0)
         bubbleBarScaleAnimator = bubbleBarViewController.bubbleBarScale
     }
 
@@ -131,16 +132,6 @@
         animatorSet.setDuration(BAR_STASH_DURATION).start()
     }
 
-    override fun updateStashedAndExpandedState(stash: Boolean, expand: Boolean) {
-        if (bubbleBarViewController.isHiddenForNoBubbles) {
-            // If there are no bubbles the bar is invisible, nothing to do here.
-            return
-        }
-        if (bubbleBarViewController.isExpanded != expand) {
-            bubbleBarViewController.isExpanded = expand
-        }
-    }
-
     override fun showBubbleBarImmediate() = showBubbleBarImmediate(bubbleBarTranslationY)
 
     override fun showBubbleBarImmediate(bubbleBarTranslationY: Float) {
@@ -154,6 +145,14 @@
         // operation is performed.
     }
 
+    override fun stashBubbleBar() {
+        updateExpandedState(expand = false)
+    }
+
+    override fun showBubbleBar(expandBubbles: Boolean) {
+        updateExpandedState(expandBubbles)
+    }
+
     override fun stashBubbleBarImmediate() {
         // When the bubble bar is shown for the persistent task bar, there is no handle view, so no
         // operation is performed.
@@ -176,7 +175,7 @@
     override fun isEventOverBubbleBarViews(ev: MotionEvent): Boolean =
         bubbleBarViewController.isEventOverAnyItem(ev)
 
-    override fun getSlideInAnimationDistanceY(): Float {
+    override fun getDiffBetweenHandleAndBarCenters(): Float {
         // distance from the bottom of the screen and the bubble bar center.
         return -bubbleBarViewController.bubbleBarCollapsedHeight / 2f
     }
@@ -199,6 +198,16 @@
         // no op since does not have a handle view
     }
 
+    private fun updateExpandedState(expand: Boolean) {
+        if (bubbleBarViewController.isHiddenForNoBubbles) {
+            // If there are no bubbles the bar is invisible, nothing to do here.
+            return
+        }
+        if (bubbleBarViewController.isExpanded != expand) {
+            bubbleBarViewController.isExpanded = expand
+        }
+    }
+
     /** Animates bubble bar Y accordingly to the showing mode */
     private fun animateBubbleBarY() {
         val animator =
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt
new file mode 100644
index 0000000..23e009b
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.bubbles.stashing
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.AnimatorSet
+import android.content.res.Resources
+import android.view.MotionEvent
+import android.view.View
+import androidx.annotation.VisibleForTesting
+import com.android.launcher3.R
+import com.android.launcher3.anim.AnimatedFloat
+import com.android.launcher3.taskbar.StashedHandleViewController
+import com.android.launcher3.taskbar.TaskbarInsetsController
+import com.android.launcher3.taskbar.bubbles.BubbleBarViewController
+import com.android.launcher3.taskbar.bubbles.BubbleStashedHandleViewController
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController.Companion.BAR_STASH_DURATION
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController.Companion.BAR_TRANSLATION_DURATION
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController.Companion.STASHED_BAR_SCALE
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController.ControllersAfterInitAction
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController.TaskbarHotseatDimensionsProvider
+import com.android.launcher3.util.MultiPropertyFactory
+import com.android.wm.shell.common.bubbles.BubbleBarLocation
+import com.android.wm.shell.shared.animation.PhysicsAnimator
+
+class TransientBubbleStashController(
+    private val taskbarHotseatDimensionsProvider: TaskbarHotseatDimensionsProvider,
+    resources: Resources
+) : BubbleStashController {
+
+    private lateinit var bubbleBarViewController: BubbleBarViewController
+    private lateinit var taskbarInsetsController: TaskbarInsetsController
+    private lateinit var controllersAfterInitAction: ControllersAfterInitAction
+
+    // stash view properties
+    private var bubbleStashedHandleViewController: BubbleStashedHandleViewController? = null
+    private var stashHandleViewAlpha: MultiPropertyFactory<View>.MultiProperty? = null
+    private var stashedHeight: Int = 0
+
+    // bubble bar properties
+    private lateinit var bubbleBarAlpha: MultiPropertyFactory<View>.MultiProperty
+    private lateinit var bubbleBarTranslationYAnimator: AnimatedFloat
+    private lateinit var bubbleBarScale: AnimatedFloat
+    private val mHandleCenterFromScreenBottom =
+        resources.getDimensionPixelSize(R.dimen.bubblebar_stashed_size) / 2f
+
+    private var animator: AnimatorSet? = null
+
+    override var isStashed: Boolean = false
+        @VisibleForTesting set
+
+    override var isBubblesShowingOnHome: Boolean = false
+        set(onHome) {
+            if (field == onHome) return
+            field = onHome
+            if (!bubbleBarViewController.hasBubbles()) {
+                // if there are no bubbles, there's nothing to show, so just return.
+                return
+            }
+            if (onHome) {
+                updateStashedAndExpandedState(stash = false, expand = false)
+                // When transitioning from app to home we need to animate the bubble bar
+                // here to align with hotseat center.
+                animateBubbleBarYToHotseat()
+            } else if (!bubbleBarViewController.isExpanded) {
+                updateStashedAndExpandedState(stash = true, expand = false)
+            }
+            bubbleBarViewController.onBubbleBarConfigurationChanged(/* animate= */ true)
+        }
+
+    override var isBubblesShowingOnOverview: Boolean = false
+        set(onOverview) {
+            if (field == onOverview) return
+            field = onOverview
+            if (onOverview) {
+                // When transitioning to overview we need to animate the bubble bar to align with
+                // the taskbar bottom.
+                animateBubbleBarYToTaskbar()
+            } else {
+                updateStashedAndExpandedState(stash = true, expand = false)
+            }
+            bubbleBarViewController.onBubbleBarConfigurationChanged(/* animate= */ true)
+        }
+
+    override var isSysuiLocked: Boolean = false
+        set(isLocked) {
+            if (field == isLocked) return
+            field = isLocked
+            if (!isLocked && bubbleBarViewController.hasBubbles()) {
+                animateAfterUnlock()
+            }
+        }
+
+    override val isTransientTaskBar: Boolean = true
+
+    override val bubbleBarTranslationYForHotseat: Float
+        get() {
+            val hotseatBottomSpace = taskbarHotseatDimensionsProvider.getHotseatBottomSpace()
+            val hotseatCellHeight = taskbarHotseatDimensionsProvider.getHotseatHeight()
+            val bubbleBarHeight: Float = bubbleBarViewController.bubbleBarCollapsedHeight
+            return -hotseatBottomSpace - (hotseatCellHeight - bubbleBarHeight) / 2
+        }
+
+    override val bubbleBarTranslationYForTaskbar: Float =
+        -taskbarHotseatDimensionsProvider.getTaskbarBottomSpace().toFloat()
+
+    /** Check if we have handle view controller */
+    override val hasHandleView: Boolean
+        get() = bubbleStashedHandleViewController != null
+
+    override fun init(
+        taskbarInsetsController: TaskbarInsetsController,
+        bubbleBarViewController: BubbleBarViewController,
+        bubbleStashedHandleViewController: BubbleStashedHandleViewController?,
+        controllersAfterInitAction: ControllersAfterInitAction
+    ) {
+        this.taskbarInsetsController = taskbarInsetsController
+        this.bubbleBarViewController = bubbleBarViewController
+        this.bubbleStashedHandleViewController = bubbleStashedHandleViewController
+        this.controllersAfterInitAction = controllersAfterInitAction
+        bubbleBarTranslationYAnimator = bubbleBarViewController.bubbleBarTranslationY
+        // bubble bar has only alpha property, getting it at index 0
+        bubbleBarAlpha = bubbleBarViewController.bubbleBarAlpha.get(/* index= */ 0)
+        bubbleBarScale = bubbleBarViewController.bubbleBarScale
+        stashedHeight = bubbleStashedHandleViewController?.stashedHeight ?: 0
+        stashHandleViewAlpha =
+            bubbleStashedHandleViewController
+                ?.stashedHandleAlpha
+                ?.get(StashedHandleViewController.ALPHA_INDEX_STASHED)
+    }
+
+    private fun animateAfterUnlock() {
+        val animatorSet = AnimatorSet()
+        if (isBubblesShowingOnHome || isBubblesShowingOnOverview) {
+            isStashed = false
+            animatorSet.playTogether(
+                bubbleBarScale.animateToValue(1f),
+                bubbleBarTranslationYAnimator.animateToValue(bubbleBarTranslationY),
+                bubbleBarAlpha.animateToValue(1f)
+            )
+        } else {
+            isStashed = true
+            stashHandleViewAlpha?.let { animatorSet.playTogether(it.animateToValue(1f)) }
+        }
+        animatorSet.updateTouchRegionOnAnimationEnd().setDuration(BAR_STASH_DURATION).start()
+    }
+
+    override fun showBubbleBarImmediate() {
+        showBubbleBarImmediate(bubbleBarTranslationY)
+    }
+
+    override fun showBubbleBarImmediate(bubbleBarTranslationY: Float) {
+        bubbleStashedHandleViewController?.setTranslationYForSwipe(0f)
+        stashHandleViewAlpha?.value = 0f
+        this.bubbleBarTranslationYAnimator.updateValue(bubbleBarTranslationY)
+        bubbleBarAlpha.setValue(1f)
+        bubbleBarScale.updateValue(1f)
+        isStashed = false
+        onIsStashedChanged()
+    }
+
+    override fun stashBubbleBarImmediate() {
+        bubbleStashedHandleViewController?.setTranslationYForSwipe(0f)
+        stashHandleViewAlpha?.value = 1f
+        this.bubbleBarTranslationYAnimator.updateValue(getStashTranslation())
+        bubbleBarAlpha.setValue(0f)
+        bubbleBarScale.updateValue(STASHED_BAR_SCALE)
+        isStashed = true
+        onIsStashedChanged()
+    }
+
+    override fun getTouchableHeight(): Int =
+        when {
+            isStashed -> stashedHeight
+            isBubbleBarVisible() -> bubbleBarViewController.bubbleBarCollapsedHeight.toInt()
+            else -> 0
+        }
+
+    override fun isBubbleBarVisible(): Boolean = bubbleBarViewController.hasBubbles() && !isStashed
+
+    override fun onNewBubbleAnimationInterrupted(isStashed: Boolean, bubbleBarTranslationY: Float) =
+        if (isStashed) {
+            stashBubbleBarImmediate()
+        } else {
+            showBubbleBarImmediate(bubbleBarTranslationY)
+        }
+
+    /** Check if [ev] belongs to the stash handle or the bubble bar views. */
+    override fun isEventOverBubbleBarViews(ev: MotionEvent): Boolean {
+        val isOverHandle = bubbleStashedHandleViewController?.isEventOverHandle(ev) ?: false
+        return isOverHandle || bubbleBarViewController.isEventOverAnyItem(ev)
+    }
+
+    /** Set the bubble bar stash handle location . */
+    override fun setBubbleBarLocation(bubbleBarLocation: BubbleBarLocation) {
+        bubbleStashedHandleViewController?.setBubbleBarLocation(bubbleBarLocation)
+    }
+
+    override fun stashBubbleBar() {
+        updateStashedAndExpandedState(stash = true, expand = false)
+    }
+
+    override fun showBubbleBar(expandBubbles: Boolean) {
+        updateStashedAndExpandedState(stash = false, expandBubbles)
+    }
+
+    override fun getDiffBetweenHandleAndBarCenters(): Float {
+        // the difference between the centers of the handle and the bubble bar is the difference
+        // between their distance from the bottom of the screen.
+        val barCenter: Float = bubbleBarViewController.bubbleBarCollapsedHeight / 2f
+        return mHandleCenterFromScreenBottom - barCenter
+    }
+
+    override fun getStashedHandleTranslationForNewBubbleAnimation(): Float {
+        return -mHandleCenterFromScreenBottom
+    }
+
+    override fun getStashedHandlePhysicsAnimator(): PhysicsAnimator<View>? {
+        return bubbleStashedHandleViewController?.physicsAnimator
+    }
+
+    override fun updateTaskbarTouchRegion() {
+        taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
+    }
+
+    override fun setHandleTranslationY(translationY: Float) {
+        bubbleStashedHandleViewController?.setTranslationYForSwipe(translationY)
+    }
+
+    private fun getStashTranslation(): Float {
+        return (bubbleBarViewController.bubbleBarCollapsedHeight - stashedHeight) / 2f
+    }
+
+    /**
+     * Create a stash animation.
+     *
+     * @param isStashed whether it's a stash animation or an unstash animation
+     * @param duration duration of the animation
+     * @return the animation
+     */
+    @Suppress("SameParameterValue")
+    private fun createStashAnimator(isStashed: Boolean, duration: Long): AnimatorSet {
+        val animatorSet = AnimatorSet()
+        val fullLengthAnimatorSet = AnimatorSet()
+        // Not exactly half and may overlap. See [first|second]HalfDurationScale below.
+        val firstHalfAnimatorSet = AnimatorSet()
+        val secondHalfAnimatorSet = AnimatorSet()
+        val firstHalfDurationScale: Float
+        val secondHalfDurationScale: Float
+        val stashHandleAlphaValue: Float
+        if (isStashed) {
+            firstHalfDurationScale = 0.75f
+            secondHalfDurationScale = 0.5f
+            stashHandleAlphaValue = 1f
+            fullLengthAnimatorSet.play(
+                bubbleBarTranslationYAnimator.animateToValue(getStashTranslation())
+            )
+            firstHalfAnimatorSet.playTogether(
+                bubbleBarAlpha.animateToValue(0f),
+                bubbleBarScale.animateToValue(STASHED_BAR_SCALE)
+            )
+        } else {
+            firstHalfDurationScale = 0.5f
+            secondHalfDurationScale = 0.75f
+            stashHandleAlphaValue = 0f
+            fullLengthAnimatorSet.playTogether(
+                bubbleBarScale.animateToValue(1f),
+                bubbleBarTranslationYAnimator.animateToValue(bubbleBarTranslationY)
+            )
+            secondHalfAnimatorSet.playTogether(bubbleBarAlpha.animateToValue(1f))
+        }
+        stashHandleViewAlpha?.let {
+            secondHalfAnimatorSet.playTogether(it.animateToValue(stashHandleAlphaValue))
+        }
+        bubbleStashedHandleViewController?.createRevealAnimToIsStashed(isStashed)?.let {
+            fullLengthAnimatorSet.play(it)
+        }
+        fullLengthAnimatorSet.setDuration(duration)
+        firstHalfAnimatorSet.setDuration((duration * firstHalfDurationScale).toLong())
+        secondHalfAnimatorSet.setDuration((duration * secondHalfDurationScale).toLong())
+        secondHalfAnimatorSet.startDelay = (duration * (1 - secondHalfDurationScale)).toLong()
+        animatorSet.playTogether(fullLengthAnimatorSet, firstHalfAnimatorSet, secondHalfAnimatorSet)
+        animatorSet.addListener(
+            object : AnimatorListenerAdapter() {
+                override fun onAnimationEnd(animation: Animator) {
+                    animator = null
+                    controllersAfterInitAction.runAfterInit {
+                        if (isStashed) {
+                            bubbleBarViewController.isExpanded = false
+                        }
+                        taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
+                    }
+                }
+            }
+        )
+        return animatorSet
+    }
+
+    private fun onIsStashedChanged() {
+        controllersAfterInitAction.runAfterInit {
+            taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
+            bubbleStashedHandleViewController?.onIsStashedChanged()
+        }
+    }
+
+    private fun animateBubbleBarYToHotseat() {
+        translateBubbleBarYUpdateTouchRegionOnCompletion(bubbleBarTranslationYForHotseat)
+    }
+
+    private fun animateBubbleBarYToTaskbar() {
+        translateBubbleBarYUpdateTouchRegionOnCompletion(bubbleBarTranslationYForTaskbar)
+    }
+
+    private fun translateBubbleBarYUpdateTouchRegionOnCompletion(toY: Float) {
+        bubbleBarViewController.bubbleBarTranslationY
+            .animateToValue(toY)
+            .updateTouchRegionOnAnimationEnd()
+            .setDuration(BAR_TRANSLATION_DURATION)
+            .start()
+    }
+
+    @VisibleForTesting
+    fun updateStashedAndExpandedState(stash: Boolean, expand: Boolean) {
+        if (bubbleBarViewController.isHiddenForNoBubbles) {
+            // If there are no bubbles the bar and handle are invisible, nothing to do here.
+            return
+        }
+        val isStashed = stash && !isBubblesShowingOnHome && !isBubblesShowingOnOverview
+        if (this.isStashed != isStashed) {
+            this.isStashed = isStashed
+            // notify the view controller that the stash state is about to change so that it can
+            // cancel an ongoing animation if there is one.
+            // note that this has to be called before updating mIsStashed with the new value,
+            // otherwise interrupting an ongoing animation may update it again with the wrong state
+            bubbleBarViewController.onStashStateChanging()
+            animator?.cancel()
+            animator =
+                createStashAnimator(isStashed, BAR_STASH_DURATION).apply {
+                    updateTouchRegionOnAnimationEnd()
+                    start()
+                }
+        }
+        if (bubbleBarViewController.isExpanded != expand) {
+            bubbleBarViewController.isExpanded = expand
+        }
+    }
+
+    private fun Animator.updateTouchRegionOnAnimationEnd(): Animator {
+        this.addListener(
+            object : AnimatorListenerAdapter() {
+                override fun onAnimationEnd(animation: Animator) {
+                    onIsStashedChanged()
+                }
+            }
+        )
+        return this
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarAllAppsButtonContainer.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarAllAppsButtonContainer.kt
index 415a051..7d2d36d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarAllAppsButtonContainer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarAllAppsButtonContainer.kt
@@ -47,7 +47,7 @@
 
     override val spaceNeeded: Int
         get() {
-            return dpToPx(activityContext.taskbarSpecsEvaluator.taskbarIconSize.size.toFloat())
+            return dpToPx(activityContext.taskbarSpecsEvaluator!!.taskbarIconSize.size.toFloat())
         }
 
     init {
@@ -58,15 +58,15 @@
     private fun setUpIcon() {
         val drawable =
             resources.getDrawable(
-                getAllAppsButton(activityContext.taskbarFeatureEvaluator.isTransient)
+                getAllAppsButton(activityContext.taskbarFeatureEvaluator!!.isTransient)
             )
-        val padding = activityContext.taskbarSpecsEvaluator.taskbarIconPadding
+        val padding = activityContext.taskbarSpecsEvaluator!!.taskbarIconPadding
 
         allAppsButton.setIconDrawable(drawable)
-        allAppsButton.setPadding(/* left= */ padding)
+        allAppsButton.setPadding(padding)
         allAppsButton.setForegroundTint(activityContext.getColor(R.color.all_apps_button_color))
 
-        // TODO(jagrutdesai) : add click listeners in future cl
+        // TODO(b/356465292) : add click listeners in future cl
         addView(allAppsButton)
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarDividerContainer.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarDividerContainer.kt
new file mode 100644
index 0000000..26e71f7
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarDividerContainer.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.customization
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.widget.LinearLayout
+import androidx.core.view.setPadding
+import com.android.launcher3.R
+import com.android.launcher3.Utilities.dpToPx
+import com.android.launcher3.taskbar.TaskbarActivityContext
+import com.android.launcher3.views.ActivityContext
+import com.android.launcher3.views.IconButtonView
+
+/** Taskbar divider view container for customizable taskbar. */
+class TaskbarDividerContainer
+@JvmOverloads
+constructor(
+    context: Context,
+    attrs: AttributeSet? = null,
+    defStyleAttr: Int = 0,
+) : LinearLayout(context, attrs), TaskbarContainer {
+
+    private val taskbarDivider: IconButtonView =
+        LayoutInflater.from(context).inflate(R.layout.taskbar_divider, this, false)
+            as IconButtonView
+    private val activityContext: TaskbarActivityContext = ActivityContext.lookupContext(context)
+
+    override val spaceNeeded: Int
+        get() {
+            return dpToPx(activityContext.taskbarSpecsEvaluator!!.taskbarIconSize.size.toFloat())
+        }
+
+    init {
+        setUpIcon()
+    }
+
+    @SuppressLint("UseCompatLoadingForDrawables")
+    fun setUpIcon() {
+        val drawable = resources.getDrawable(R.drawable.taskbar_divider_button)
+        val padding = activityContext.taskbarSpecsEvaluator!!.taskbarIconPadding
+
+        taskbarDivider.setIconDrawable(drawable)
+        taskbarDivider.setPadding(padding)
+
+        // TODO(b/356465292):: add click listeners in future cl
+        addView(taskbarDivider)
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 5176d74..b2cc369 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -67,7 +67,6 @@
 import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.WALLPAPER_ACTIVITY;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50;
-import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.DESKTOP_WINDOWING_MODE;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -200,6 +199,7 @@
 import com.android.systemui.unfold.dagger.UnfoldMain;
 import com.android.systemui.unfold.progress.RemoteUnfoldTransitionReceiver;
 import com.android.systemui.unfold.updates.RotationChangeProvider;
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
 
 import kotlin.Unit;
 
@@ -258,6 +258,8 @@
 
     private boolean mCanShowAllAppsEducationView;
 
+    private boolean mIsOverlayVisible;
+
     public static QuickstepLauncher getLauncher(Context context) {
         return fromContext(context);
     }
@@ -278,7 +280,7 @@
         // TODO(b/337863494): Explore use of the same OverviewComponentObserver across launcher
         OverviewComponentObserver overviewComponentObserver = new OverviewComponentObserver(
                 asContext(), deviceState);
-        if (DESKTOP_WINDOWING_MODE.isEnabled(this)) {
+        if (DesktopModeStatus.canEnterDesktopMode(this)) {
             mDesktopRecentsTransitionController = new DesktopRecentsTransitionController(
                     getStateManager(), systemUiProxy, getIApplicationThread(),
                     getDepthController());
@@ -298,7 +300,7 @@
 
         mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
         mDepthController = new DepthController(this);
-        if (DESKTOP_WINDOWING_MODE.isEnabled(this)) {
+        if (DesktopModeStatus.canEnterDesktopMode(this)) {
             mDesktopVisibilityController = new DesktopVisibilityController(this);
             mDesktopVisibilityController.registerSystemUiListener();
             mSplitSelectStateController.initSplitFromDesktopController(this,
@@ -495,7 +497,8 @@
                     (getActivityFlags() & ACTIVITY_STATE_USER_WILL_BE_ACTIVE) != 0;
             boolean visible = (state == NORMAL || state == OVERVIEW)
                     && (willUserBeActive || isUserActive())
-                    && !profile.isVerticalBarLayout();
+                    && !profile.isVerticalBarLayout()
+                    && !mIsOverlayVisible;
             SystemUiProxy.INSTANCE.get(this)
                     .setLauncherKeepClearAreaHeight(visible, profile.hotseatBarSizePx);
         }
@@ -505,6 +508,12 @@
     }
 
     @Override
+    public void onOverlayVisibilityChanged(boolean visible) {
+        super.onOverlayVisibilityChanged(visible);
+        mIsOverlayVisible = visible;
+    }
+
+    @Override
     public void bindExtraContainerItems(FixedContainerItems item) {
         if (item.containerId == Favorites.CONTAINER_PREDICTION) {
             mAllAppsPredictions = item;
@@ -515,7 +524,7 @@
         } else if (item.containerId == Favorites.CONTAINER_HOTSEAT_PREDICTION) {
             mHotseatPredictionController.setPredictedItems(item);
         } else if (item.containerId == Favorites.CONTAINER_WIDGETS_PREDICTION) {
-            getPopupDataProvider().setRecommendedWidgets(item.items);
+            getWidgetPickerDataProvider().setWidgetRecommendations(item.items);
         }
     }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index 5377983..d1aa472 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -88,6 +88,7 @@
     private ObjectAnimator mNormalToHintOverviewScrimAnimator;
 
     private final QuickstepLauncher mLauncher;
+    private boolean mIsTrackpadSwipe;
 
     /**
      * @param cancelSplitRunnable Called when split placeholder view needs to be cancelled.
@@ -106,9 +107,9 @@
 
     @Override
     protected boolean canInterceptTouch(MotionEvent ev) {
-        boolean isTrackpadEvent = isTrackpadMotionEvent(ev);
-        mLauncher.setCanShowAllAppsEducationView(!isTrackpadEvent);
-        if (!isTrackpadEvent && DisplayController.getNavigationMode(mLauncher)
+        mIsTrackpadSwipe = isTrackpadMotionEvent(ev);
+        mLauncher.setCanShowAllAppsEducationView(!mIsTrackpadSwipe);
+        if (!mIsTrackpadSwipe && DisplayController.getNavigationMode(mLauncher)
                 == THREE_BUTTONS) {
             return false;
         }
@@ -152,6 +153,7 @@
         super.onDragStart(start, startDisplacement);
 
         mMotionPauseDetector.clear();
+        mMotionPauseDetector.setIsTrackpadGesture(mIsTrackpadSwipe);
 
         if (handlingOverviewAnim()) {
             InteractionJankMonitorWrapper.begin(mRecentsView, Cuj.CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS,
@@ -195,6 +197,7 @@
         }
 
         mMotionPauseDetector.clear();
+        mIsTrackpadSwipe = false;
         mNormalToHintOverviewScrimAnimator = null;
         if (mLauncher.isInState(OVERVIEW)) {
             // Normally we would cleanup the state based on mCurrentAnimation, but since we stop
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index ab277b6..0da7b2d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -121,6 +121,7 @@
     private AnimatorPlaybackController mNonOverviewAnim;
     private AnimatorPlaybackController mXOverviewAnim;
     private AnimatedFloat mYOverviewAnim;
+    private boolean mIsTrackpadSwipe;
 
     public NoButtonQuickSwitchTouchController(QuickstepLauncher launcher) {
         mLauncher = launcher;
@@ -177,7 +178,8 @@
             return false;
         }
         if (isTrackpadMultiFingerSwipe(ev)) {
-            return isTrackpadFourFingerSwipe(ev);
+            mIsTrackpadSwipe = isTrackpadFourFingerSwipe(ev);
+            return mIsTrackpadSwipe;
         }
         return true;
     }
@@ -185,6 +187,7 @@
     @Override
     public void onDragStart(boolean start) {
         mMotionPauseDetector.clear();
+        mMotionPauseDetector.setIsTrackpadGesture(mIsTrackpadSwipe);
         if (start) {
             InteractionJankMonitorWrapper.begin(mRecentsView, Cuj.CUJ_LAUNCHER_QUICK_SWITCH);
             InteractionJankMonitorWrapper.begin(mRecentsView, Cuj.CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS,
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 5a03ae6..3c9bd0f 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -62,7 +62,6 @@
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.ON_SETTLED_ON_END_TARGET;
 import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
-import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.DESKTOP_WINDOWING_MODE;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -151,6 +150,7 @@
 import com.android.systemui.shared.system.TaskStackChangeListeners;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.shared.desktopmode.DesktopModeFlags;
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
 import com.android.wm.shell.startingsurface.SplashScreenExitAnimationUtils;
 
 import kotlin.Unit;
@@ -1273,7 +1273,7 @@
         TaskView currentPageTaskView = mRecentsView != null
                 ? mRecentsView.getCurrentPageTaskView() : null;
 
-        if (DESKTOP_WINDOWING_MODE.isEnabled(mContext)
+        if (DesktopModeStatus.canEnterDesktopMode(mContext)
                 && !(DesktopModeFlags.WALLPAPER_ACTIVITY.isEnabled(mContext)
                 && DesktopModeFlags.QUICK_SWITCH.isEnabled(mContext))) {
             if ((nextPageTaskView instanceof DesktopTaskView
@@ -1446,7 +1446,7 @@
             setClampScrollOffset(false);
         };
 
-        if (DESKTOP_WINDOWING_MODE.isEnabled(mContext)
+        if (DesktopModeStatus.canEnterDesktopMode(mContext)
                 && !(DesktopModeFlags.WALLPAPER_ACTIVITY.isEnabled(mContext)
                 && DesktopModeFlags.QUICK_SWITCH.isEnabled(mContext))) {
             if (mRecentsView != null && (mRecentsView.getCurrentPageTaskView() != null
@@ -2100,7 +2100,6 @@
             // If there are no targets, then we don't need to capture anything
             mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
         } else {
-            boolean finishTransitionPosted = false;
             // If we already have cached screenshot(s) from running tasks, skip update
             boolean shouldUpdate = false;
             int[] runningTaskIds = mGestureState.getRunningTaskIds(mIsSwipeForSplit);
@@ -2124,45 +2123,32 @@
                         }
 
                         MAIN_EXECUTOR.execute(() -> {
-                            if (!updateThumbnail(false /* refreshView */)) {
-                                setScreenshotCapturedState();
-                            }
+                            updateThumbnail();
+                            setScreenshotCapturedState();
                         });
                     });
                     return;
                 }
 
-                finishTransitionPosted = updateThumbnail(false /* refreshView */);
+                updateThumbnail();
             }
 
-            if (!finishTransitionPosted) {
-                setScreenshotCapturedState();
-            }
+            setScreenshotCapturedState();
         }
     }
 
     // Returns whether finish transition was posted.
-    private boolean updateThumbnail(boolean refreshView) {
+    private void updateThumbnail() {
         if (mGestureState.getEndTarget() == HOME
                 || mGestureState.getEndTarget() == NEW_TASK
                 || mGestureState.getEndTarget() == ALL_APPS
                 || mRecentsView == null) {
             // Capture the screenshot before finishing the transition to home or quickswitching to
             // ensure it's taken in the correct orientation, but no need to update the thumbnail.
-            return false;
+            return;
         }
 
-        boolean finishTransitionPosted = false;
-        TaskView updatedTaskView = mRecentsView.updateThumbnail(mTaskSnapshotCache, refreshView);
-        if (updatedTaskView != null && refreshView && !mCanceled) {
-            // Defer finishing the animation until the next launcher frame with the
-            // new thumbnail
-            finishTransitionPosted = ViewUtils.postFrameDrawn(updatedTaskView,
-                    () -> mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED),
-                    this::isCanceled);
-        }
-
-        return finishTransitionPosted;
+        mRecentsView.updateThumbnail(mTaskSnapshotCache);
     }
 
     private void setScreenshotCapturedState() {
@@ -2294,7 +2280,7 @@
                     mRecentsAnimationController, mRecentsAnimationTargets);
         });
 
-        if (DESKTOP_WINDOWING_MODE.isEnabled(mContext)
+        if (DesktopModeStatus.canEnterDesktopMode(mContext)
                 && !(DesktopModeFlags.WALLPAPER_ACTIVITY.isEnabled(mContext)
                         && DesktopModeFlags.QUICK_SWITCH.isEnabled(mContext))) {
             if (mRecentsView.getNextPageTaskView() instanceof DesktopTaskView
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 00cd60b..293944d 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -31,7 +31,6 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
-import android.graphics.Color;
 import android.view.MotionEvent;
 
 import androidx.annotation.Nullable;
@@ -133,7 +132,7 @@
     public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
         TaskbarUIController controller = getTaskbarController();
         boolean isEventOverBubbleBarStashHandle =
-                controller != null && controller.isEventOverBubbleBarStashHandle(ev);
+                controller != null && controller.isEventOverBubbleBarViews(ev);
         return deviceState.isInDeferredGestureRegion(ev) || deviceState.isImeRenderingNavButtons()
                 || isTrackpadMultiFingerSwipe(ev) || isEventOverBubbleBarStashHandle;
     }
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index 95c86fa..e66da52 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -20,7 +20,6 @@
 
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.quickstep.util.SplitScreenUtils.convertShellSplitBoundsToLauncher;
-import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.DESKTOP_WINDOWING_MODE;
 import static com.android.wm.shell.util.GroupedRecentTaskInfo.TYPE_FREEFORM;
 
 import android.app.ActivityManager;
@@ -41,6 +40,7 @@
 import com.android.quickstep.util.GroupTask;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.wm.shell.recents.IRecentTasksListener;
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
 import com.android.wm.shell.util.GroupedRecentTaskInfo;
 
 import java.io.PrintWriter;
@@ -329,9 +329,9 @@
         int numVisibleTasks = 0;
         for (GroupedRecentTaskInfo rawTask : rawTasks) {
             if (rawTask.getType() == TYPE_FREEFORM) {
-                // TYPE_FREEFORM tasks is only created whenDESKTOP_WINDOWING_MODE.isEnabled is true,
+                // TYPE_FREEFORM tasks is only created when desktop mode can be entered,
                 // leftover TYPE_FREEFORM tasks created when flag was on should be ignored.
-                if (DESKTOP_WINDOWING_MODE.isEnabled(mContext)) {
+                if (DesktopModeStatus.canEnterDesktopMode(mContext)) {
                     GroupTask desktopTask = createDesktopTask(rawTask);
                     if (desktopTask != null) {
                         allTasks.add(desktopTask);
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index e84200d..6d5cb4b 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -27,7 +27,6 @@
 import static com.android.quickstep.OverviewComponentObserver.startHomeIntentSafely;
 import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
 import static com.android.quickstep.TaskViewUtils.createRecentsWindowAnimator;
-import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.DESKTOP_WINDOWING_MODE;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -57,6 +56,7 @@
 import com.android.launcher3.LauncherAnimationRunner;
 import com.android.launcher3.LauncherAnimationRunner.AnimationResult;
 import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory;
+import com.android.launcher3.LauncherRootView;
 import com.android.launcher3.R;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.PendingAnimation;
@@ -87,6 +87,7 @@
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.RecentsViewContainer;
 import com.android.quickstep.views.TaskView;
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -139,15 +140,15 @@
                         null /* depthController */, getStatsLogManager(),
                         systemUiProxy, RecentsModel.INSTANCE.get(this),
                         null /*activityBackCallback*/);
+        // Setup root and child views
         inflateRootView(R.layout.fallback_recents_activity);
-        setContentView(getRootView());
-        mDragLayer = findViewById(R.id.drag_layer);
-        mScrimView = findViewById(R.id.scrim_view);
-        mFallbackRecentsView = findViewById(R.id.overview_panel);
-        mActionsView = findViewById(R.id.overview_actions_view);
-        getRootView().getSysUiScrim().getSysUIProgress().updateValue(0);
-        mDragLayer.recreateControllers();
-        if (DESKTOP_WINDOWING_MODE.isEnabled(this)) {
+        LauncherRootView rootView = getRootView();
+        mDragLayer = rootView.findViewById(R.id.drag_layer);
+        mScrimView = rootView.findViewById(R.id.scrim_view);
+        mFallbackRecentsView = rootView.findViewById(R.id.overview_panel);
+        mActionsView = rootView.findViewById(R.id.overview_actions_view);
+
+        if (DesktopModeStatus.canEnterDesktopMode(this)) {
             mDesktopRecentsTransitionController = new DesktopRecentsTransitionController(
                     getStateManager(), systemUiProxy, getIApplicationThread(),
                     null /* depthController */
@@ -156,6 +157,10 @@
         mFallbackRecentsView.init(mActionsView, mSplitSelectStateController,
                 mDesktopRecentsTransitionController);
 
+        setContentView(rootView);
+        rootView.getSysUiScrim().getSysUIProgress().updateValue(0);
+        mDragLayer.recreateControllers();
+
         mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
     }
 
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java
index d104911..cf7e499 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java
@@ -18,14 +18,14 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 
-import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.DESKTOP_WINDOWING_MODE;
-
 import android.app.WindowConfiguration;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.view.RemoteAnimationTarget;
 
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
+
 import java.io.PrintWriter;
 
 /**
@@ -56,7 +56,7 @@
      * @return {@code true} if at least one target app is a desktop task
      */
     public boolean hasDesktopTasks(Context context) {
-        if (!DESKTOP_WINDOWING_MODE.isEnabled(context)) {
+        if (!DesktopModeStatus.canEnterDesktopMode(context)) {
             return false;
         }
         for (RemoteAnimationTarget target : apps) {
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index f2db5af..673de14 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -23,8 +23,6 @@
 import static com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.RECENT_TASKS_MISSING;
 import static com.android.quickstep.util.LogUtils.splitFailureMessage;
-import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps;
-import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.DESKTOP_WINDOWING_MODE;
 
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
@@ -96,6 +94,8 @@
 import com.android.wm.shell.recents.IRecentTasks;
 import com.android.wm.shell.recents.IRecentTasksListener;
 import com.android.wm.shell.shared.IShellTransitions;
+import com.android.wm.shell.shared.desktopmode.DesktopModeFlags;
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
 import com.android.wm.shell.splitscreen.ISplitScreen;
 import com.android.wm.shell.splitscreen.ISplitScreenListener;
 import com.android.wm.shell.splitscreen.ISplitSelectListener;
@@ -1443,9 +1443,8 @@
     }
 
     private boolean shouldEnableRunningTasksForDesktopMode() {
-        // TODO(b/335401172): unify DesktopMode checks in Launcher
-        return DESKTOP_WINDOWING_MODE.isEnabled(mContext)
-                && enableDesktopWindowingTaskbarRunningApps();
+        return DesktopModeStatus.canEnterDesktopMode(mContext)
+                && DesktopModeFlags.TASKBAR_RUNNING_APPS.isEnabled(mContext);
     }
 
     private boolean handleMessageAsync(Message msg) {
diff --git a/quickstep/src/com/android/quickstep/TopTaskTracker.java b/quickstep/src/com/android/quickstep/TopTaskTracker.java
index 6ed05c8..3cf0542 100644
--- a/quickstep/src/com/android/quickstep/TopTaskTracker.java
+++ b/quickstep/src/com/android/quickstep/TopTaskTracker.java
@@ -28,7 +28,6 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.content.Context;
-import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -48,7 +47,6 @@
 import com.android.systemui.shared.system.TaskStackChangeListeners;
 import com.android.wm.shell.splitscreen.ISplitScreenListener;
 
-import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -63,10 +61,6 @@
 public class TopTaskTracker extends ISplitScreenListener.Stub
         implements TaskStackChangeListener, SafeCloseable {
 
-    private static final String TAG = "TopTaskTracker";
-
-    private static final boolean DEBUG = true;
-
     public static MainThreadInitializedObject<TopTaskTracker> INSTANCE =
             new MainThreadInitializedObject<>(TopTaskTracker::new);
 
@@ -98,19 +92,10 @@
     @Override
     public void onTaskRemoved(int taskId) {
         mOrderedTaskList.removeIf(rto -> rto.taskId == taskId);
-        if (DEBUG) {
-            Log.i(TAG, "onTaskRemoved: taskId=" + taskId);
-        }
     }
 
     @Override
     public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
-        if (!mOrderedTaskList.isEmpty()
-                && mOrderedTaskList.getFirst().taskId != taskInfo.taskId
-                && DEBUG) {
-            Log.i(TAG, "onTaskMovedToFront: (moved taskInfo to front) taskId=" + taskInfo.taskId
-                    + ", baseIntent=" + taskInfo.baseIntent);
-        }
         mOrderedTaskList.removeIf(rto -> rto.taskId == taskInfo.taskId);
         mOrderedTaskList.addFirst(taskInfo);
 
@@ -121,11 +106,6 @@
             final RunningTaskInfo topTaskOnHomeDisplay = mOrderedTaskList.stream()
                     .filter(rto -> rto.displayId == DEFAULT_DISPLAY).findFirst().orElse(null);
             if (topTaskOnHomeDisplay != null) {
-                if (DEBUG) {
-                    Log.i(TAG, "onTaskMovedToFront: (removing top task on home display) taskId="
-                            + topTaskOnHomeDisplay.taskId
-                            + ", baseIntent=" + topTaskOnHomeDisplay.baseIntent);
-                }
                 mOrderedTaskList.removeIf(rto -> rto.taskId == topTaskOnHomeDisplay.taskId);
                 mOrderedTaskList.addFirst(topTaskOnHomeDisplay);
             }
@@ -139,10 +119,6 @@
                 if (info.taskId != taskInfo.taskId
                         && info.taskId != mMainStagePosition.taskId
                         && info.taskId != mSideStagePosition.taskId) {
-                    if (DEBUG) {
-                        Log.i(TAG, "onTaskMovedToFront: (removing task list overflow) taskId="
-                                + taskInfo.taskId + ", baseIntent=" + taskInfo.baseIntent);
-                    }
                     itr.remove();
                     return;
                 }
@@ -152,9 +128,6 @@
 
     @Override
     public void onStagePositionChanged(@StageType int stage, @StagePosition int position) {
-        if (DEBUG) {
-            Log.i(TAG, "onStagePositionChanged: stage=" + stage + ", position=" + position);
-        }
         if (stage == SplitConfigurationOptions.STAGE_TYPE_MAIN) {
             mMainStagePosition.stagePosition = position;
         } else {
@@ -164,10 +137,6 @@
 
     @Override
     public void onTaskStageChanged(int taskId, @StageType int stage, boolean visible) {
-        if (DEBUG) {
-            Log.i(TAG, "onTaskStageChanged: taskId=" + taskId
-                    + ", stage=" + stage + ", visible=" + visible);
-        }
         // If a task is not visible anymore or has been moved to undefined, stop tracking it.
         if (!visible || stage == SplitConfigurationOptions.STAGE_TYPE_UNDEFINED) {
             if (mMainStagePosition.taskId == taskId) {
@@ -187,18 +156,11 @@
 
     @Override
     public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
-        if (DEBUG) {
-            Log.i(TAG, "onActivityPinned: packageName=" + packageName
-                    + ", userId=" + userId + ", stackId=" + stackId);
-        }
         mPinnedTaskId = taskId;
     }
 
     @Override
     public void onActivityUnpinned() {
-        if (DEBUG) {
-            Log.i(TAG, "onActivityUnpinned");
-        }
         mPinnedTaskId = INVALID_TASK_ID;
     }
 
@@ -250,21 +212,6 @@
         return new CachedTaskInfo(tasks);
     }
 
-    public void dump(String prefix, PrintWriter writer) {
-        writer.println(prefix + "TopTaskTracker:");
-
-        writer.println(prefix + "\tmOrderedTaskList=[");
-        for (RunningTaskInfo taskInfo : mOrderedTaskList) {
-            writer.println(prefix + "\t\t(taskId=" + taskInfo.taskId
-                    + "; baseIntent=" + taskInfo.baseIntent
-                    + "; isRunning=" + taskInfo.isRunning + ")");
-        }
-        writer.println(prefix + "\t]");
-        writer.println(prefix + "\tmMainStagePosition=" + mMainStagePosition);
-        writer.println(prefix + "\tmSideStagePosition=" + mSideStagePosition);
-        writer.println(prefix + "\tmPinnedTaskId=" + mPinnedTaskId);
-    }
-
     /**
      * Class to provide information about a task which can be safely cached and do not change
      * during the lifecycle of the task.
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 2896979..5c940a3 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -1610,7 +1610,6 @@
         pw.println("\tmConsumer=" + mConsumer.getName());
         ActiveGestureLog.INSTANCE.dump("", pw);
         RecentsModel.INSTANCE.get(this).dump("", pw);
-        TopTaskTracker.INSTANCE.get(this).dump("", pw);
         if (mTaskAnimationManager != null) {
             mTaskAnimationManager.dump("", pw);
         }
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 13b6447..69d3bc9 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -409,6 +409,7 @@
         mInteractionHandler = mHandlerFactory.newHandler(mGestureState, touchTimeMs);
         mInteractionHandler.setGestureEndCallback(this::onInteractionGestureFinished);
         mMotionPauseDetector.setOnMotionPauseListener(mInteractionHandler.getMotionPauseListener());
+        mMotionPauseDetector.setIsTrackpadGesture(mGestureState.isTrackpadGesture());
         mInteractionHandler.initWhenReady(
                 "OtherActivityInputConsumer.startTouchTrackingForWindowAnimation");
 
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
index 95295b0..9a99d4a 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
@@ -321,8 +321,9 @@
         if (controllers == null) {
             return false;
         }
-        if (controllers.bubbleStashController.isStashed()) {
-            return controllers.bubbleStashedHandleViewController.containsX((int) x);
+        if (controllers.bubbleStashController.isStashed()
+                && controllers.bubbleStashedHandleViewController.isPresent()) {
+            return controllers.bubbleStashedHandleViewController.get().containsX((int) x);
         } else {
             Rect bubbleBarBounds = controllers.bubbleBarViewController.getBubbleBarBounds();
             return x >= bubbleBarBounds.left && x <= bubbleBarBounds.right;
diff --git a/quickstep/src/com/android/quickstep/recents/data/RecentTasksRepository.kt b/quickstep/src/com/android/quickstep/recents/data/RecentTasksRepository.kt
index 9c4248c..4f7a541 100644
--- a/quickstep/src/com/android/quickstep/recents/data/RecentTasksRepository.kt
+++ b/quickstep/src/com/android/quickstep/recents/data/RecentTasksRepository.kt
@@ -41,4 +41,10 @@
      * populated e.g. icons/thumbnails etc.
      */
     fun setVisibleTasks(visibleTaskIdList: List<Int>)
+
+    /**
+     * Override [ThumbnailData] with a map of taskId to [ThumbnailData]. The override only applies
+     * if the tasks are already visible, and will be invalidated when tasks become invisible.
+     */
+    fun addOrUpdateThumbnailOverride(thumbnailOverride: Map<Int, ThumbnailData>)
 }
diff --git a/quickstep/src/com/android/quickstep/recents/data/RecentsDeviceProfile.kt b/quickstep/src/com/android/quickstep/recents/data/RecentsDeviceProfile.kt
new file mode 100644
index 0000000..feed2fd
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/recents/data/RecentsDeviceProfile.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 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.recents.data
+
+/**
+ * Container to hold [com.android.launcher3.DeviceProfile] related to Recents.
+ *
+ * @property isLargeScreen whether the current device posture has a large screen
+ */
+data class RecentsDeviceProfile(
+    val isLargeScreen: Boolean,
+    val widthPx: Int,
+    val heightPx: Int,
+)
diff --git a/quickstep/src/com/android/quickstep/recents/data/RecentsDeviceProfileRepository.kt b/quickstep/src/com/android/quickstep/recents/data/RecentsDeviceProfileRepository.kt
index adf904c..13cf56d 100644
--- a/quickstep/src/com/android/quickstep/recents/data/RecentsDeviceProfileRepository.kt
+++ b/quickstep/src/com/android/quickstep/recents/data/RecentsDeviceProfileRepository.kt
@@ -16,21 +16,6 @@
 
 package com.android.quickstep.recents.data
 
-import com.android.quickstep.views.RecentsViewContainer
-
-/**
- * Repository for shrink down version of [com.android.launcher3.DeviceProfile] that only contains
- * data related to Recents.
- */
-class RecentsDeviceProfileRepository(private val container: RecentsViewContainer) {
-
-    fun getRecentsDeviceProfile() =
-        with(container.deviceProfile) { RecentsDeviceProfile(isLargeScreen = isTablet) }
-
-    /**
-     * Container to hold [com.android.launcher3.DeviceProfile] related to Recents.
-     *
-     * @property isLargeScreen whether the current device posture has a large screen
-     */
-    data class RecentsDeviceProfile(val isLargeScreen: Boolean)
+interface RecentsDeviceProfileRepository {
+    fun getRecentsDeviceProfile(): RecentsDeviceProfile
 }
diff --git a/quickstep/src/com/android/quickstep/recents/data/RecentsDeviceProfileRepositoryImpl.kt b/quickstep/src/com/android/quickstep/recents/data/RecentsDeviceProfileRepositoryImpl.kt
new file mode 100644
index 0000000..ce39ff1
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/recents/data/RecentsDeviceProfileRepositoryImpl.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 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.recents.data
+
+import com.android.quickstep.views.RecentsViewContainer
+
+/**
+ * Repository for shrink down version of [com.android.launcher3.DeviceProfile] that only contains
+ * data related to Recents.
+ */
+class RecentsDeviceProfileRepositoryImpl(private val container: RecentsViewContainer) :
+    RecentsDeviceProfileRepository {
+
+    override fun getRecentsDeviceProfile() =
+        with(container.deviceProfile) {
+            RecentsDeviceProfile(isLargeScreen = isTablet, widthPx = widthPx, heightPx = heightPx)
+        }
+}
diff --git a/quickstep/src/com/android/quickstep/recents/data/RecentsRotationState.kt b/quickstep/src/com/android/quickstep/recents/data/RecentsRotationState.kt
new file mode 100644
index 0000000..2c2a744
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/recents/data/RecentsRotationState.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 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.recents.data
+
+import android.view.Surface
+
+/**
+ * Container to hold orientation/rotation related information related to Recents.
+ *
+ * @property activityRotation rotation of the activity hosting RecentsView
+ */
+data class RecentsRotationState(
+    @Surface.Rotation val activityRotation: Int,
+    @Surface.Rotation val orientationHandlerRotation: Int,
+)
diff --git a/quickstep/src/com/android/quickstep/recents/data/RecentsRotationStateRepository.kt b/quickstep/src/com/android/quickstep/recents/data/RecentsRotationStateRepository.kt
index 6ead704..ed074d2 100644
--- a/quickstep/src/com/android/quickstep/recents/data/RecentsRotationStateRepository.kt
+++ b/quickstep/src/com/android/quickstep/recents/data/RecentsRotationStateRepository.kt
@@ -16,20 +16,6 @@
 
 package com.android.quickstep.recents.data
 
-import com.android.quickstep.util.RecentsOrientedState
-
-/**
- * Repository for [RecentsRotationState] which holds orientation/rotation related information
- * related to Recents
- */
-class RecentsRotationStateRepository(private val state: RecentsOrientedState) {
-    fun getRecentsRotationState() =
-        with(state) { RecentsRotationState(activityRotation = recentsActivityRotation) }
-
-    /**
-     * Container to hold orientation/rotation related information related to Recents.
-     *
-     * @property activityRotation rotation of the activity hosting RecentsView
-     */
-    data class RecentsRotationState(val activityRotation: Int)
+interface RecentsRotationStateRepository {
+    fun getRecentsRotationState(): RecentsRotationState
 }
diff --git a/quickstep/src/com/android/quickstep/recents/data/RecentsRotationStateRepositoryImpl.kt b/quickstep/src/com/android/quickstep/recents/data/RecentsRotationStateRepositoryImpl.kt
new file mode 100644
index 0000000..8417b06
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/recents/data/RecentsRotationStateRepositoryImpl.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 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.recents.data
+
+import com.android.quickstep.util.RecentsOrientedState
+
+/**
+ * Repository for [RecentsRotationState] which holds orientation/rotation related information
+ * related to Recents
+ */
+class RecentsRotationStateRepositoryImpl(private val state: RecentsOrientedState) :
+    RecentsRotationStateRepository {
+    override fun getRecentsRotationState() =
+        with(state) {
+            RecentsRotationState(
+                activityRotation = recentsActivityRotation,
+                orientationHandlerRotation = orientationHandler.rotation
+            )
+        }
+}
diff --git a/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt b/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt
index f73db5a..6acc940 100644
--- a/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt
+++ b/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt
@@ -45,15 +45,18 @@
     private val _taskData =
         groupedTaskData.map { groupTaskList -> groupTaskList.flatMap { it.tasks } }
     private val visibleTaskIds = MutableStateFlow(emptySet<Int>())
+    private val thumbnailOverride = MutableStateFlow(mapOf<Int, ThumbnailData>())
 
     private val taskData: Flow<List<Task>> =
-        combine(_taskData, getThumbnailQueryResults(), getIconQueryResults()) {
+        combine(_taskData, getThumbnailQueryResults(), getIconQueryResults(), thumbnailOverride) {
             tasks,
             thumbnailQueryResults,
-            iconQueryResults ->
+            iconQueryResults,
+            thumbnailOverride ->
             tasks.forEach { task ->
-                // Add retrieved thumbnails + remove unnecessary thumbnails
-                task.thumbnail = thumbnailQueryResults[task.key.id]
+                // Add retrieved thumbnails + remove unnecessary thumbnails (e.g. invisible)
+                task.thumbnail =
+                    thumbnailOverride[task.key.id] ?: thumbnailQueryResults[task.key.id]
 
                 // TODO(b/352331675) don't load icons for DesktopTaskView
                 // Add retrieved icons + remove unnecessary icons
@@ -79,6 +82,15 @@
 
     override fun setVisibleTasks(visibleTaskIdList: List<Int>) {
         this.visibleTaskIds.value = visibleTaskIdList.toSet()
+        addOrUpdateThumbnailOverride(emptyMap())
+    }
+
+    override fun addOrUpdateThumbnailOverride(thumbnailOverride: Map<Int, ThumbnailData>) {
+        this.thumbnailOverride.value =
+            this.thumbnailOverride.value
+                .toMutableMap()
+                .apply { putAll(thumbnailOverride) }
+                .filterKeys(this.visibleTaskIds.value::contains)
     }
 
     /** Flow wrapper for [TaskThumbnailDataSource.getThumbnailInBackground] api */
@@ -130,9 +142,15 @@
                                 icon,
                                 contentDescription,
                                 title ->
-                                continuation.resume(
-                                    TaskIconQueryResponse(icon, contentDescription, title)
-                                )
+                                icon.constantState?.let {
+                                    continuation.resume(
+                                        TaskIconQueryResponse(
+                                            it.newDrawable().mutate(),
+                                            contentDescription,
+                                            title
+                                        )
+                                    )
+                                }
                             }
                         continuation.invokeOnCancellation { cancellableTask?.cancel() }
                     }
@@ -157,7 +175,7 @@
     }
 }
 
-private data class TaskIconQueryResponse(
+data class TaskIconQueryResponse(
     val icon: Drawable,
     val contentDescription: String,
     val title: String
diff --git a/quickstep/src/com/android/quickstep/recents/di/RecentsDependencies.kt b/quickstep/src/com/android/quickstep/recents/di/RecentsDependencies.kt
index 3a6d5c0..eba7688 100644
--- a/quickstep/src/com/android/quickstep/recents/di/RecentsDependencies.kt
+++ b/quickstep/src/com/android/quickstep/recents/di/RecentsDependencies.kt
@@ -26,6 +26,9 @@
 import com.android.quickstep.recents.usecase.GetThumbnailUseCase
 import com.android.quickstep.recents.usecase.SysUiStatusNavFlagsUseCase
 import com.android.quickstep.recents.viewmodel.RecentsViewData
+import com.android.quickstep.task.thumbnail.GetSplashSizeUseCase
+import com.android.quickstep.task.thumbnail.SplashAlphaUseCase
+import com.android.quickstep.task.thumbnail.TaskThumbnailViewData
 import com.android.quickstep.task.viewmodel.TaskContainerData
 import com.android.quickstep.task.viewmodel.TaskOverlayViewModel
 import com.android.quickstep.task.viewmodel.TaskThumbnailViewModel
@@ -33,7 +36,6 @@
 import com.android.quickstep.task.viewmodel.TaskViewModel
 import com.android.quickstep.views.TaskViewType
 import com.android.systemui.shared.recents.model.Task
-import java.util.logging.Level
 
 internal typealias RecentsScopeId = String
 
@@ -145,13 +147,16 @@
                     TaskViewData(taskViewType)
                 }
                 TaskContainerData::class.java -> TaskContainerData()
+                TaskThumbnailViewData::class.java -> TaskThumbnailViewData()
                 TaskThumbnailViewModel::class.java ->
                     TaskThumbnailViewModel(
                         recentsViewData = inject(),
                         taskViewData = inject(scopeId, extras),
-                        taskContainerData = inject(),
+                        taskContainerData = inject(scopeId),
                         getThumbnailPositionUseCase = inject(),
-                        tasksRepository = inject()
+                        tasksRepository = inject(),
+                        splashAlphaUseCase = inject(scopeId),
+                        getSplashSizeUseCase = inject(scopeId),
                     )
                 TaskOverlayViewModel::class.java -> {
                     val task = extras["Task"] as Task
@@ -171,6 +176,20 @@
                         rotationStateRepository = inject(),
                         tasksRepository = inject()
                     )
+                SplashAlphaUseCase::class.java ->
+                    SplashAlphaUseCase(
+                        recentsViewData = inject(),
+                        taskContainerData = inject(scopeId),
+                        taskThumbnailViewData = inject(scopeId),
+                        tasksRepository = inject(),
+                        rotationStateRepository = inject(),
+                    )
+                GetSplashSizeUseCase::class.java ->
+                    GetSplashSizeUseCase(
+                        taskThumbnailViewData = inject(scopeId),
+                        taskViewData = inject(scopeId, extras),
+                        deviceProfileRepository = inject(),
+                    )
                 else -> {
                     log("Factory for ${modelClass.simpleName} not defined!", Log.ERROR)
                     error("Factory for ${modelClass.simpleName} not defined!")
diff --git a/quickstep/src/com/android/quickstep/recents/viewmodel/RecentsViewData.kt b/quickstep/src/com/android/quickstep/recents/viewmodel/RecentsViewData.kt
index fdb62df..87446b0 100644
--- a/quickstep/src/com/android/quickstep/recents/viewmodel/RecentsViewData.kt
+++ b/quickstep/src/com/android/quickstep/recents/viewmodel/RecentsViewData.kt
@@ -31,4 +31,15 @@
 
     // The settled set of visible taskIds that is updated after RecentsView scroll settles.
     val settledFullyVisibleTaskIds = MutableStateFlow(emptySet<Int>())
+
+    // Color tint on foreground scrim
+    val tintAmount = MutableStateFlow(0f)
+
+    val thumbnailSplashProgress = MutableStateFlow(0f)
+
+    // A list of taskIds that are associated with a RecentsAnimationController. */
+    val runningTaskIds = MutableStateFlow(emptySet<Int>())
+
+    // Whether we should use static screenshot instead of live tile for taskIds in [runningTaskIds]
+    val runningTaskShowScreenshot = MutableStateFlow(false)
 }
diff --git a/quickstep/src/com/android/quickstep/recents/viewmodel/RecentsViewModel.kt b/quickstep/src/com/android/quickstep/recents/viewmodel/RecentsViewModel.kt
index 8b03a84..54e34a0 100644
--- a/quickstep/src/com/android/quickstep/recents/viewmodel/RecentsViewModel.kt
+++ b/quickstep/src/com/android/quickstep/recents/viewmodel/RecentsViewModel.kt
@@ -17,6 +17,10 @@
 package com.android.quickstep.recents.viewmodel
 
 import com.android.quickstep.recents.data.RecentTasksRepository
+import com.android.systemui.shared.recents.model.ThumbnailData
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.first
 
 class RecentsViewModel(
     private val recentsTasksRepository: RecentTasksRepository,
@@ -45,4 +49,43 @@
     fun setOverlayEnabled(isOverlayEnabled: Boolean) {
         recentsViewData.overlayEnabled.value = isOverlayEnabled
     }
+
+    fun setTintAmount(tintAmount: Float) {
+        recentsViewData.tintAmount.value = tintAmount
+    }
+
+    fun updateThumbnailSplashProgress(taskThumbnailSplashAlpha: Float) {
+        recentsViewData.thumbnailSplashProgress.value = taskThumbnailSplashAlpha
+    }
+
+    fun addOrUpdateThumbnailOverride(thumbnailOverride: Map<Int, ThumbnailData>) {
+        recentsTasksRepository.addOrUpdateThumbnailOverride(thumbnailOverride)
+    }
+
+    suspend fun waitForThumbnailsToUpdate(updatedThumbnails: Map<Int, ThumbnailData>) {
+        combine(
+                updatedThumbnails.map {
+                    recentsTasksRepository.getThumbnailById(it.key).filter { thumbnailData ->
+                        thumbnailData == it.value
+                    }
+                }
+            ) {}
+            .first()
+    }
+
+    suspend fun waitForRunningTaskShowScreenshotToUpdate() {
+        recentsViewData.runningTaskShowScreenshot.filter { it }.first()
+    }
+
+    fun onReset() {
+        updateVisibleTasks(emptyList())
+    }
+
+    fun updateRunningTask(taskIds: Set<Int>) {
+        recentsViewData.runningTaskIds.value = taskIds
+    }
+
+    fun setRunningTaskShowScreenshot(showScreenshot: Boolean) {
+        recentsViewData.runningTaskShowScreenshot.value = showScreenshot
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/recents/viewmodel/TaskContainerViewModel.kt b/quickstep/src/com/android/quickstep/recents/viewmodel/TaskContainerViewModel.kt
index 8b8bc3e..168c1e0 100644
--- a/quickstep/src/com/android/quickstep/recents/viewmodel/TaskContainerViewModel.kt
+++ b/quickstep/src/com/android/quickstep/recents/viewmodel/TaskContainerViewModel.kt
@@ -19,13 +19,20 @@
 import android.graphics.Bitmap
 import com.android.quickstep.recents.usecase.GetThumbnailUseCase
 import com.android.quickstep.recents.usecase.SysUiStatusNavFlagsUseCase
+import com.android.quickstep.task.thumbnail.SplashAlphaUseCase
+import kotlinx.coroutines.flow.firstOrNull
+import kotlinx.coroutines.runBlocking
 
 class TaskContainerViewModel(
     private val sysUiStatusNavFlagsUseCase: SysUiStatusNavFlagsUseCase,
-    private val getThumbnailUseCase: GetThumbnailUseCase
+    private val getThumbnailUseCase: GetThumbnailUseCase,
+    private val splashAlphaUseCase: SplashAlphaUseCase,
 ) {
     fun getThumbnail(taskId: Int): Bitmap? = getThumbnailUseCase.run(taskId)
 
     fun getSysUiStatusNavFlags(taskId: Int) =
         sysUiStatusNavFlagsUseCase.getSysUiStatusNavFlags(taskId)
+
+    fun shouldShowThumbnailSplash(taskId: Int): Boolean =
+        (runBlocking { splashAlphaUseCase.execute(taskId).firstOrNull() } ?: 0f) > 0f
 }
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/GetSplashSizeUseCase.kt b/quickstep/src/com/android/quickstep/task/thumbnail/GetSplashSizeUseCase.kt
new file mode 100644
index 0000000..145957a
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/GetSplashSizeUseCase.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 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.task.thumbnail
+
+import android.graphics.Point
+import android.graphics.drawable.Drawable
+import com.android.quickstep.recents.data.RecentsDeviceProfileRepository
+import com.android.quickstep.task.viewmodel.TaskViewData
+import kotlin.math.min
+
+class GetSplashSizeUseCase(
+    private val taskThumbnailViewData: TaskThumbnailViewData,
+    private val taskViewData: TaskViewData,
+    private val deviceProfileRepository: RecentsDeviceProfileRepository,
+) {
+    fun execute(splashImage: Drawable): Point {
+        val recentsDeviceProfile = deviceProfileRepository.getRecentsDeviceProfile()
+        val screenWidth = recentsDeviceProfile.widthPx
+        val screenHeight = recentsDeviceProfile.heightPx
+        val scaleAtFullscreen =
+            min(
+                screenWidth / taskThumbnailViewData.width.value,
+                screenHeight / taskThumbnailViewData.height.value,
+            )
+        val scaleFactor: Float = 1f / taskViewData.nonGridScale.value / scaleAtFullscreen
+        return Point(
+            (splashImage.intrinsicWidth * scaleFactor / taskThumbnailViewData.scaleX.value).toInt(),
+            (splashImage.intrinsicHeight * scaleFactor / taskThumbnailViewData.scaleY.value)
+                .toInt(),
+        )
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/SplashAlphaUseCase.kt b/quickstep/src/com/android/quickstep/task/thumbnail/SplashAlphaUseCase.kt
new file mode 100644
index 0000000..7673c71
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/SplashAlphaUseCase.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2024 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.task.thumbnail
+
+import android.graphics.Bitmap
+import android.view.Surface
+import com.android.quickstep.recents.data.RecentTasksRepository
+import com.android.quickstep.recents.data.RecentsRotationStateRepository
+import com.android.quickstep.recents.viewmodel.RecentsViewData
+import com.android.quickstep.task.viewmodel.TaskContainerData
+import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
+import com.android.systemui.shared.recents.utilities.Utilities
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+
+class SplashAlphaUseCase(
+    private val recentsViewData: RecentsViewData,
+    private val taskContainerData: TaskContainerData,
+    private val taskThumbnailViewData: TaskThumbnailViewData,
+    private val tasksRepository: RecentTasksRepository,
+    private val rotationStateRepository: RecentsRotationStateRepository,
+) {
+    fun execute(taskId: Int): Flow<Float> =
+        combine(
+                taskThumbnailViewData.width,
+                taskThumbnailViewData.height,
+                tasksRepository.getThumbnailById(taskId),
+                taskContainerData.thumbnailSplashProgress,
+                recentsViewData.thumbnailSplashProgress
+            ) { width, height, thumbnailData, taskSplashProgress, globalSplashProgress ->
+                val thumbnail = thumbnailData?.thumbnail
+                when {
+                    thumbnail == null -> 0f
+                    taskSplashProgress > 0f -> taskSplashProgress
+                    globalSplashProgress > 0f &&
+                        isInaccurateThumbnail(thumbnail, thumbnailData.rotation, width, height) ->
+                        globalSplashProgress
+                    else -> 0f
+                }
+            }
+            .distinctUntilChanged()
+
+    private fun isInaccurateThumbnail(
+        thumbnail: Bitmap,
+        thumbnailRotation: Int,
+        width: Int,
+        height: Int
+    ): Boolean {
+        return isThumbnailAspectRatioDifferentFromThumbnailData(thumbnail, width, height) ||
+            isThumbnailRotationDifferentFromTask(thumbnailRotation)
+    }
+
+    private fun isThumbnailAspectRatioDifferentFromThumbnailData(
+        thumbnail: Bitmap,
+        viewWidth: Int,
+        viewHeight: Int
+    ): Boolean {
+        val viewAspect: Float = viewWidth / viewHeight.toFloat()
+        val thumbnailAspect: Float = thumbnail.width / thumbnail.height.toFloat()
+        return Utilities.isRelativePercentDifferenceGreaterThan(
+            viewAspect,
+            thumbnailAspect,
+            PreviewPositionHelper.MAX_PCT_BEFORE_ASPECT_RATIOS_CONSIDERED_DIFFERENT
+        )
+    }
+
+    private fun isThumbnailRotationDifferentFromTask(thumbnailRotation: Int): Boolean {
+        val rotationState = rotationStateRepository.getRecentsRotationState()
+        return if (rotationState.orientationHandlerRotation == Surface.ROTATION_0) {
+            (rotationState.activityRotation - thumbnailRotation) % 2 != 0
+        } else {
+            rotationState.orientationHandlerRotation != thumbnailRotation
+        }
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailUiState.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailUiState.kt
index 3b3a811..a6be9f6 100644
--- a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailUiState.kt
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailUiState.kt
@@ -17,6 +17,9 @@
 package com.android.quickstep.task.thumbnail
 
 import android.graphics.Bitmap
+import android.graphics.Point
+import android.graphics.drawable.Drawable
+import android.view.Surface
 import androidx.annotation.ColorInt
 
 sealed class TaskThumbnailUiState {
@@ -26,8 +29,19 @@
 
     data class BackgroundOnly(@ColorInt val backgroundColor: Int) : TaskThumbnailUiState()
 
-    data class Snapshot(val bitmap: Bitmap, @ColorInt val backgroundColor: Int) :
-        TaskThumbnailUiState()
-}
+    data class SnapshotSplash(
+        val snapshot: Snapshot,
+        val splash: Splash,
+    ) : TaskThumbnailUiState()
 
-data class TaskThumbnail(val taskId: Int, val isRunning: Boolean)
+    data class Snapshot(
+        val bitmap: Bitmap,
+        @Surface.Rotation val thumbnailRotation: Int,
+        @ColorInt val backgroundColor: Int
+    )
+
+    data class Splash(
+        val icon: Drawable?,
+        val size: Point,
+    )
+}
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
index fcc2af3..41aee52 100644
--- a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
@@ -28,6 +28,7 @@
 import android.widget.ImageView
 import androidx.annotation.ColorInt
 import androidx.core.view.isVisible
+import androidx.core.view.updateLayoutParams
 import com.android.launcher3.R
 import com.android.launcher3.Utilities
 import com.android.launcher3.util.ViewPool
@@ -36,10 +37,12 @@
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.BackgroundOnly
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Snapshot
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.SnapshotSplash
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
 import com.android.quickstep.task.viewmodel.TaskThumbnailViewModel
 import com.android.quickstep.util.TaskCornerRadius
 import com.android.systemui.shared.system.QuickStepContract
+import kotlin.math.abs
 import kotlinx.coroutines.CoroutineName
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -50,6 +53,7 @@
 
 class TaskThumbnailView : FrameLayout, ViewPool.Reusable {
 
+    private val viewData: TaskThumbnailViewData by RecentsDependencies.inject(this)
     private val viewModel: TaskThumbnailViewModel by RecentsDependencies.inject(this)
 
     private lateinit var viewAttachedScope: CoroutineScope
@@ -57,6 +61,8 @@
     private val scrimView: View by lazy { findViewById(R.id.task_thumbnail_scrim) }
     private val liveTileView: LiveTileView by lazy { findViewById(R.id.task_thumbnail_live_tile) }
     private val thumbnailView: ImageView by lazy { findViewById(R.id.task_thumbnail) }
+    private val splashContainer: FrameLayout by lazy { findViewById(R.id.splash_container) }
+    private val splashIcon: ImageView by lazy { findViewById(R.id.splash_icon) }
 
     private var uiState: TaskThumbnailUiState = Uninitialized
     private var inheritedScale: Float = 1f
@@ -92,16 +98,16 @@
                 when (viewModelUiState) {
                     is Uninitialized -> {}
                     is LiveTile -> drawLiveWindow()
-                    is Snapshot -> drawSnapshot(viewModelUiState)
+                    is SnapshotSplash -> drawSnapshotSplash(viewModelUiState)
                     is BackgroundOnly -> drawBackground(viewModelUiState.backgroundColor)
                 }
             }
             .launchIn(viewAttachedScope)
         viewModel.dimProgress
-            .onEach { dimProgress ->
-                // TODO(b/348195366) Add fade in/out for scrim
-                scrimView.alpha = dimProgress * MAX_SCRIM_ALPHA
-            }
+            .onEach { dimProgress -> scrimView.alpha = dimProgress }
+            .launchIn(viewAttachedScope)
+        viewModel.splashAlpha
+            .onEach { splashAlpha -> splashContainer.alpha = splashAlpha }
             .launchIn(viewAttachedScope)
         viewModel.cornerRadiusProgress.onEach { invalidateOutline() }.launchIn(viewAttachedScope)
         viewModel.inheritedScale
@@ -129,13 +135,35 @@
         uiState = Uninitialized
     }
 
+    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
+        super.onLayout(changed, left, top, right, bottom)
+        if (changed) {
+            viewData.width.value = abs(right - left)
+            viewData.height.value = abs(bottom - top)
+        }
+    }
+
     override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
         super.onSizeChanged(w, h, oldw, oldh)
-        if (uiState is Snapshot) {
+        if (uiState is SnapshotSplash) {
             setImageMatrix()
         }
     }
 
+    override fun setScaleX(scaleX: Float) {
+        super.setScaleX(scaleX)
+        viewData.scaleX.value = scaleX
+        // Splash icon should ignore scale
+        splashIcon.scaleX = 1 / scaleX
+    }
+
+    override fun setScaleY(scaleY: Float) {
+        super.setScaleY(scaleY)
+        viewData.scaleY.value = scaleY
+        // Splash icon should ignore scale
+        splashIcon.scaleY = 1 / scaleY
+    }
+
     override fun onConfigurationChanged(newConfig: Configuration?) {
         super.onConfigurationChanged(newConfig)
 
@@ -147,6 +175,7 @@
     private fun resetViews() {
         liveTileView.isVisible = false
         thumbnailView.isVisible = false
+        splashContainer.alpha = 0f
         scrimView.alpha = 0f
         setBackgroundColor(Color.BLACK)
     }
@@ -159,6 +188,18 @@
         liveTileView.isVisible = true
     }
 
+    private fun drawSnapshotSplash(snapshotSplash: SnapshotSplash) {
+        drawSnapshot(snapshotSplash.snapshot)
+
+        splashContainer.isVisible = true
+        splashContainer.setBackgroundColor(snapshotSplash.snapshot.backgroundColor)
+        splashIcon.setImageDrawable(snapshotSplash.splash.icon)
+        splashIcon.updateLayoutParams<LayoutParams> {
+            width = snapshotSplash.splash.size.x
+            height = snapshotSplash.splash.size.y
+        }
+    }
+
     private fun drawSnapshot(snapshot: Snapshot) {
         drawBackground(snapshot.backgroundColor)
         thumbnailView.setImageBitmap(snapshot.bitmap)
@@ -176,8 +217,4 @@
             overviewCornerRadius,
             fullscreenCornerRadius
         ) / inheritedScale
-
-    private companion object {
-        const val MAX_SCRIM_ALPHA = 0.4f
-    }
 }
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewData.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewData.kt
new file mode 100644
index 0000000..1f8c0bc
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewData.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 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.task.thumbnail
+
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class TaskThumbnailViewData {
+    val width = MutableStateFlow(0)
+    val height = MutableStateFlow(0)
+    val scaleX = MutableStateFlow(1f)
+    val scaleY = MutableStateFlow(1f)
+}
diff --git a/quickstep/src/com/android/quickstep/task/viewmodel/TaskContainerData.kt b/quickstep/src/com/android/quickstep/task/viewmodel/TaskContainerData.kt
index 769424c..5f2de94 100644
--- a/quickstep/src/com/android/quickstep/task/viewmodel/TaskContainerData.kt
+++ b/quickstep/src/com/android/quickstep/task/viewmodel/TaskContainerData.kt
@@ -20,4 +20,6 @@
 
 class TaskContainerData {
     val taskMenuOpenProgress = MutableStateFlow(0f)
+
+    val thumbnailSplashProgress = MutableStateFlow(0f)
 }
diff --git a/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModel.kt b/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModel.kt
index 6465645..4e29840 100644
--- a/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModel.kt
+++ b/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModel.kt
@@ -10,26 +10,32 @@
  * 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
+ * See the License for the specific language goveryning permissions and
  * limitations under the License.
  */
 
 package com.android.quickstep.task.viewmodel
 
 import android.annotation.ColorInt
+import android.app.ActivityTaskManager.INVALID_TASK_ID
 import android.graphics.Matrix
+import android.graphics.Point
 import androidx.core.graphics.ColorUtils
 import com.android.quickstep.recents.data.RecentTasksRepository
 import com.android.quickstep.recents.usecase.GetThumbnailPositionUseCase
 import com.android.quickstep.recents.usecase.ThumbnailPositionState
 import com.android.quickstep.recents.viewmodel.RecentsViewData
-import com.android.quickstep.task.thumbnail.TaskThumbnail
+import com.android.quickstep.task.thumbnail.GetSplashSizeUseCase
+import com.android.quickstep.task.thumbnail.SplashAlphaUseCase
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.BackgroundOnly
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Snapshot
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.SnapshotSplash
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Splash
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
 import com.android.systemui.shared.recents.model.Task
+import kotlin.math.max
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -47,10 +53,13 @@
     taskViewData: TaskViewData,
     taskContainerData: TaskContainerData,
     private val tasksRepository: RecentTasksRepository,
-    private val getThumbnailPositionUseCase: GetThumbnailPositionUseCase
+    private val getThumbnailPositionUseCase: GetThumbnailPositionUseCase,
+    private val splashAlphaUseCase: SplashAlphaUseCase,
+    private val getSplashSizeUseCase: GetSplashSizeUseCase,
 ) {
     private val task = MutableStateFlow<Flow<Task?>>(flowOf(null))
-    private lateinit var taskThumbnail: TaskThumbnail
+    private val splashProgress = MutableStateFlow(flowOf(0f))
+    private var taskId: Int = INVALID_TASK_ID
 
     /**
      * Progress for changes in corner radius. progress: 0 = overview corner radius; 1 = fullscreen
@@ -59,40 +68,55 @@
     val cornerRadiusProgress =
         if (taskViewData.isOutlineFormedByThumbnailView) recentsViewData.fullscreenProgress
         else MutableStateFlow(1f).asStateFlow()
+
     val inheritedScale =
         combine(recentsViewData.scale, taskViewData.scale) { recentsScale, taskScale ->
             recentsScale * taskScale
         }
-    val dimProgress: Flow<Float> = taskContainerData.taskMenuOpenProgress
+
+    val dimProgress: Flow<Float> =
+        combine(taskContainerData.taskMenuOpenProgress, recentsViewData.tintAmount) {
+            taskMenuOpenProgress,
+            tintAmount ->
+            max(taskMenuOpenProgress * MAX_SCRIM_ALPHA, tintAmount)
+        }
+    val splashAlpha = splashProgress.flatMapLatest { it }
+
+    private val isLiveTile =
+        combine(
+                task.flatMapLatest { it }.map { it?.key?.id }.distinctUntilChanged(),
+                recentsViewData.runningTaskIds,
+                recentsViewData.runningTaskShowScreenshot
+            ) { taskId, runningTaskIds, runningTaskShowScreenshot ->
+                runningTaskIds.contains(taskId) && !runningTaskShowScreenshot
+            }
+            .distinctUntilChanged()
+
     val uiState: Flow<TaskThumbnailUiState> =
-        task
-            .flatMapLatest { taskFlow ->
-                taskFlow.map { taskVal ->
-                    when {
-                        taskVal == null -> Uninitialized
-                        taskThumbnail.isRunning -> LiveTile
-                        isBackgroundOnly(taskVal) ->
-                            BackgroundOnly(taskVal.colorBackground.removeAlpha())
-                        isSnapshotState(taskVal) -> {
-                            val bitmap = taskVal.thumbnail?.thumbnail!!
-                            Snapshot(bitmap, taskVal.colorBackground.removeAlpha())
-                        }
-                        else -> Uninitialized
-                    }
+        combine(task.flatMapLatest { it }, isLiveTile) { taskVal, isRunning ->
+                when {
+                    taskVal == null -> Uninitialized
+                    isRunning -> LiveTile
+                    isBackgroundOnly(taskVal) ->
+                        BackgroundOnly(taskVal.colorBackground.removeAlpha())
+                    isSnapshotSplashState(taskVal) ->
+                        SnapshotSplash(createSnapshotState(taskVal), createSplashState(taskVal))
+                    else -> Uninitialized
                 }
             }
             .distinctUntilChanged()
 
-    fun bind(taskThumbnail: TaskThumbnail) {
-        this.taskThumbnail = taskThumbnail
-        task.value = tasksRepository.getTaskDataById(taskThumbnail.taskId)
+    fun bind(taskId: Int) {
+        this.taskId = taskId
+        task.value = tasksRepository.getTaskDataById(taskId)
+        splashProgress.value = splashAlphaUseCase.execute(taskId)
     }
 
     fun getThumbnailPositionState(width: Int, height: Int, isRtl: Boolean): Matrix {
         return runBlocking {
             when (
                 val thumbnailPositionState =
-                    getThumbnailPositionUseCase.run(taskThumbnail.taskId, width, height, isRtl)
+                    getThumbnailPositionUseCase.run(taskId, width, height, isRtl)
             ) {
                 is ThumbnailPositionState.MatrixScaling -> thumbnailPositionState.matrix
                 is ThumbnailPositionState.MissingThumbnail -> Matrix.IDENTITY_MATRIX
@@ -102,12 +126,28 @@
 
     private fun isBackgroundOnly(task: Task): Boolean = task.isLocked || task.thumbnail == null
 
-    private fun isSnapshotState(task: Task): Boolean {
+    private fun isSnapshotSplashState(task: Task): Boolean {
         val thumbnailPresent = task.thumbnail?.thumbnail != null
         val taskLocked = task.isLocked
 
         return thumbnailPresent && !taskLocked
     }
 
+    private fun createSnapshotState(task: Task): Snapshot {
+        val thumbnailData = task.thumbnail
+        val bitmap = thumbnailData?.thumbnail!!
+        return Snapshot(bitmap, thumbnailData.rotation, task.colorBackground.removeAlpha())
+    }
+
+    private fun createSplashState(task: Task): Splash {
+        val taskIcon = task.icon
+        val size = if (taskIcon == null) Point() else getSplashSizeUseCase.execute(taskIcon)
+        return Splash(taskIcon, size)
+    }
+
     @ColorInt private fun Int.removeAlpha(): Int = ColorUtils.setAlphaComponent(this, 0xff)
+
+    private companion object {
+        const val MAX_SCRIM_ALPHA = 0.4f
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt b/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt
index 7a9ecf2..07dfc29 100644
--- a/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt
+++ b/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt
@@ -23,6 +23,8 @@
     // This is typically a View concern but it is used to invalidate rendering in other Views
     val scale = MutableStateFlow(1f)
 
+    val nonGridScale = MutableStateFlow(1f)
+
     // TODO(b/331753115): This property should not be in TaskViewData once TaskView is MVVM.
     /** Whether outline of TaskView is formed by outline thumbnail view(s). */
     val isOutlineFormedByThumbnailView: Boolean = taskViewType != TaskViewType.DESKTOP
diff --git a/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewModel.kt b/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewModel.kt
index ec75d59..30ee360 100644
--- a/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewModel.kt
+++ b/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewModel.kt
@@ -22,4 +22,8 @@
     fun updateScale(scale: Float) {
         taskViewData.scale.value = scale
     }
+
+    fun updateNonGridScale(nonGridScale: Float) {
+        taskViewData.nonGridScale.value = nonGridScale
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index b8bc828..15081da 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -66,6 +66,7 @@
     private Float mPreviousVelocity = null;
 
     private OnMotionPauseListener mOnMotionPauseListener;
+    private boolean mIsTrackpadGesture;
     private boolean mIsPaused;
     // Bias more for the first pause to make it feel extra responsive.
     private boolean mHasEverBeenPaused;
@@ -115,6 +116,10 @@
         mOnMotionPauseListener = listener;
     }
 
+    public void setIsTrackpadGesture(boolean isTrackpadGesture) {
+        mIsTrackpadGesture = isTrackpadGesture;
+    }
+
     /**
      * @param disallowPause If true, we will not detect any pauses until this is set to false again.
      */
@@ -179,7 +184,8 @@
                     // We want to be more aggressive about detecting the first pause to ensure it
                     // feels as responsive as possible; getting two very slow speeds back to back
                     // takes too long, so also check for a rapid deceleration.
-                    boolean isRapidDeceleration = speed < previousSpeed * RAPID_DECELERATION_FACTOR;
+                    boolean isRapidDeceleration =
+                            speed < previousSpeed * getRapidDecelerationFactor();
                     isPaused = isRapidDeceleration && speed < mSpeedSomewhatFast;
                     isPausedReason = new ActiveGestureLog.CompoundString(
                             "Didn't have back to back slow speeds, checking for rapid ")
@@ -253,6 +259,7 @@
         mVelocityProvider.clear();
         mPreviousVelocity = null;
         setOnMotionPauseListener(null);
+        mIsTrackpadGesture = false;
         mIsPaused = mHasEverBeenPaused = false;
         mSlowStartTime = 0;
         mForcePauseTimeout.cancelAlarm();
@@ -262,6 +269,12 @@
         return mIsPaused;
     }
 
+    private float getRapidDecelerationFactor() {
+        return mIsTrackpadGesture ? Float.parseFloat(
+                Utilities.getSystemProperty("trackpad_in_app_swipe_up_deceleration_factor",
+                        String.valueOf(RAPID_DECELERATION_FACTOR))) : RAPID_DECELERATION_FACTOR;
+    }
+
     public interface OnMotionPauseListener {
         /** Called only the first time motion pause is detected. */
         void onMotionPauseDetected();
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
index e31a828..0335fa1 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
@@ -187,7 +187,6 @@
     ) {
         val snapshot = taskContainer.snapshotView
         val iconView: View = taskContainer.iconView.asView()
-        // TODO(334826842): Switch to splash state in TaskThumbnailView
         if (!enableRefactorTaskThumbnail()) {
             val thumbnailViewDeprecated = taskContainer.thumbnailViewDeprecated
             builder.add(
@@ -198,6 +197,15 @@
                 )
             )
             thumbnailViewDeprecated.setShowSplashForSplitSelection(true)
+        } else {
+            builder.add(
+                ValueAnimator.ofFloat(0f, 1f).apply {
+                    addUpdateListener {
+                        taskContainer.taskContainerData.thumbnailSplashProgress.value =
+                            it.animatedFraction
+                    }
+                }
+            )
         }
         // With the new `IconAppChipView`, we always want to keep the chip pinned to the
         // top left of the task / thumbnail.
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index d906bb3..54f2dd3 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -16,7 +16,6 @@
 
 package com.android.quickstep.util;
 
-import static com.android.launcher3.Utilities.postAsyncCallback;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DESKTOP_MODE_SPLIT_LEFT_TOP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTED_SECOND_APP;
@@ -60,8 +59,6 @@
 import android.os.UserHandle;
 import android.util.Log;
 import android.util.Pair;
-import android.view.RemoteAnimationAdapter;
-import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
 import android.window.IRemoteTransitionFinishedCallback;
 import android.window.RemoteTransition;
@@ -94,13 +91,11 @@
 import com.android.quickstep.RecentsModel;
 import com.android.quickstep.SplitSelectionListener;
 import com.android.quickstep.SystemUiProxy;
-import com.android.quickstep.TaskAnimationManager;
 import com.android.quickstep.views.FloatingTaskView;
 import com.android.quickstep.views.GroupedTaskView;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.RecentsViewContainer;
 import com.android.quickstep.views.SplitInstructionsView;
-import com.android.systemui.animation.RemoteAnimationRunnerCompat;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
@@ -276,17 +271,15 @@
                     // Loop through tasks in reverse, since they are ordered with recent tasks last
                     for (int j = taskGroups.size() - 1; j >= 0; j--) {
                         GroupTask groupTask = taskGroups.get(j);
-                        Task task1 = groupTask.task1;
-                        // Don't add duplicate Tasks
-                        if (isInstanceOfComponent(task1, key)
-                                && !Arrays.asList(lastActiveTasks).contains(task1)) {
-                            lastActiveTask = task1;
-                            break;
+                        // Account for desktop cases where there can be N tasks in the group
+                        for (Task task : groupTask.getTasks()) {
+                            if (isInstanceOfComponent(task, key)
+                                    && !Arrays.asList(lastActiveTasks).contains(task)) {
+                                lastActiveTask = task;
+                                break;
+                            }
                         }
-                        Task task2 = groupTask.task2;
-                        if (isInstanceOfComponent(task2, key)
-                                && !Arrays.asList(lastActiveTasks).contains(task2)) {
-                            lastActiveTask = task2;
+                        if (lastActiveTask != null) {
                             break;
                         }
                     }
@@ -460,77 +453,41 @@
         Bundle optionsBundle = options1.toBundle();
         Bundle extrasBundle = new Bundle(1);
         extrasBundle.putParcelable(KEY_EXTRA_WIDGET_INTENT, widgetIntent);
-        if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
-            final RemoteTransition remoteTransition = getShellRemoteTransition(firstTaskId,
-                    secondTaskId, callback, "LaunchSplitPair");
-            switch (launchData.getSplitLaunchType()) {
-                case SPLIT_TASK_TASK ->
-                        mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId,
-                                null /* options2 */, initialStagePosition, snapPosition,
-                                remoteTransition, shellInstanceId);
+        final RemoteTransition remoteTransition = getRemoteTransition(firstTaskId,
+                secondTaskId, callback, "LaunchSplitPair");
+        switch (launchData.getSplitLaunchType()) {
+            case SPLIT_TASK_TASK ->
+                    mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId,
+                            null /* options2 */, initialStagePosition, snapPosition,
+                            remoteTransition, shellInstanceId);
 
-                case SPLIT_TASK_PENDINGINTENT ->
-                        mSystemUiProxy.startIntentAndTask(secondPI, secondUserId, optionsBundle,
-                                firstTaskId, extrasBundle, initialStagePosition, snapPosition,
-                                remoteTransition, shellInstanceId);
+            case SPLIT_TASK_PENDINGINTENT ->
+                    mSystemUiProxy.startIntentAndTask(secondPI, secondUserId, optionsBundle,
+                            firstTaskId, extrasBundle, initialStagePosition, snapPosition,
+                            remoteTransition, shellInstanceId);
 
-                case SPLIT_TASK_SHORTCUT ->
-                        mSystemUiProxy.startShortcutAndTask(secondShortcut, optionsBundle,
-                                firstTaskId, null /*options2*/, initialStagePosition, snapPosition,
-                                remoteTransition, shellInstanceId);
+            case SPLIT_TASK_SHORTCUT ->
+                    mSystemUiProxy.startShortcutAndTask(secondShortcut, optionsBundle,
+                            firstTaskId, null /*options2*/, initialStagePosition, snapPosition,
+                            remoteTransition, shellInstanceId);
 
-                case SPLIT_PENDINGINTENT_TASK ->
-                        mSystemUiProxy.startIntentAndTask(firstPI, firstUserId, optionsBundle,
-                                secondTaskId, null /*options2*/, initialStagePosition, snapPosition,
-                                remoteTransition, shellInstanceId);
+            case SPLIT_PENDINGINTENT_TASK ->
+                    mSystemUiProxy.startIntentAndTask(firstPI, firstUserId, optionsBundle,
+                            secondTaskId, null /*options2*/, initialStagePosition, snapPosition,
+                            remoteTransition, shellInstanceId);
 
-                case SPLIT_PENDINGINTENT_PENDINGINTENT ->
-                        mSystemUiProxy.startIntents(firstPI, firstUserId, firstShortcut,
-                                optionsBundle, secondPI, secondUserId, secondShortcut, extrasBundle,
-                                initialStagePosition, snapPosition, remoteTransition,
-                                shellInstanceId);
+            case SPLIT_PENDINGINTENT_PENDINGINTENT ->
+                    mSystemUiProxy.startIntents(firstPI, firstUserId, firstShortcut,
+                            optionsBundle, secondPI, secondUserId, secondShortcut, extrasBundle,
+                            initialStagePosition, snapPosition, remoteTransition,
+                            shellInstanceId);
 
-                case SPLIT_SHORTCUT_TASK ->
-                        mSystemUiProxy.startShortcutAndTask(firstShortcut, optionsBundle,
-                                secondTaskId, null /*options2*/, initialStagePosition, snapPosition,
-                                remoteTransition, shellInstanceId);
-            }
-        } else {
-            final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(firstTaskId, secondTaskId,
-                    callback);
-            switch (launchData.getSplitLaunchType()) {
-                case SPLIT_TASK_TASK ->
-                        mSystemUiProxy.startTasksWithLegacyTransition(firstTaskId, optionsBundle,
-                                secondTaskId, null /* options2 */, initialStagePosition,
-                                snapPosition, adapter, shellInstanceId);
-
-                case SPLIT_TASK_PENDINGINTENT ->
-                        mSystemUiProxy.startIntentAndTaskWithLegacyTransition(secondPI,
-                                secondUserId, optionsBundle, firstTaskId, null /*options2*/,
-                                initialStagePosition, snapPosition, adapter, shellInstanceId);
-
-                case SPLIT_TASK_SHORTCUT ->
-                        mSystemUiProxy.startShortcutAndTaskWithLegacyTransition(secondShortcut,
-                                optionsBundle, firstTaskId, null /*options2*/, initialStagePosition,
-                                snapPosition, adapter, shellInstanceId);
-
-                case SPLIT_PENDINGINTENT_TASK ->
-                        mSystemUiProxy.startIntentAndTaskWithLegacyTransition(firstPI, firstUserId,
-                                optionsBundle, secondTaskId, null /*options2*/,
-                                initialStagePosition, snapPosition, adapter, shellInstanceId);
-
-                case SPLIT_PENDINGINTENT_PENDINGINTENT ->
-                        mSystemUiProxy.startIntentsWithLegacyTransition(firstPI, firstUserId,
-                                firstShortcut, optionsBundle, secondPI, secondUserId,
-                                secondShortcut, null /*options2*/, initialStagePosition,
-                                snapPosition, adapter, shellInstanceId);
-
-                case SPLIT_SHORTCUT_TASK ->
-                        mSystemUiProxy.startShortcutAndTaskWithLegacyTransition(firstShortcut,
-                                optionsBundle, secondTaskId, null /*options2*/,
-                                initialStagePosition, snapPosition, adapter, shellInstanceId);
-            }
+            case SPLIT_SHORTCUT_TASK ->
+                    mSystemUiProxy.startShortcutAndTask(firstShortcut, optionsBundle,
+                            secondTaskId, null /*options2*/, initialStagePosition, snapPosition,
+                            remoteTransition, shellInstanceId);
         }
+
     }
 
     /**
@@ -576,20 +533,13 @@
         }
         Bundle optionsBundle = options1.toBundle();
 
-        if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
-            final RemoteTransition transition = remoteTransition == null
-                    ? getShellRemoteTransition(
-                            firstTaskId, secondTaskId, callback, "LaunchExistingPair")
-                    : remoteTransition;
-            mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId, null /* options2 */,
-                    stagePosition, snapPosition, transition, null /*shellInstanceId*/);
-        } else {
-            final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(firstTaskId,
-                    secondTaskId, callback);
-            mSystemUiProxy.startTasksWithLegacyTransition(firstTaskId, optionsBundle, secondTaskId,
-                    null /* options2 */, stagePosition, snapPosition, adapter,
-                    null /*shellInstanceId*/);
-        }
+        final RemoteTransition transition = remoteTransition == null
+                ? getRemoteTransition(
+                firstTaskId, secondTaskId, callback, "LaunchExistingPair")
+                : remoteTransition;
+        mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId, null /* options2 */,
+                stagePosition, snapPosition, transition, null /*shellInstanceId*/);
+
     }
 
     /**
@@ -615,34 +565,16 @@
                 ActivityThread.currentActivityThread().getApplicationThread(),
                 "LaunchAppFullscreen");
         InstanceId instanceId = mSessionInstanceIds.first;
-        if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
-            switch (launchData.getSplitLaunchType()) {
-                case SPLIT_SINGLE_TASK_FULLSCREEN -> mSystemUiProxy.startTasks(firstTaskId,
-                        optionsBundle, secondTaskId, null /* options2 */, initialStagePosition,
-                        SNAP_TO_50_50, remoteTransition, instanceId);
-                case SPLIT_SINGLE_INTENT_FULLSCREEN -> mSystemUiProxy.startIntentAndTask(firstPI,
-                        firstUserId, optionsBundle, secondTaskId, null /*options2*/,
-                        initialStagePosition, SNAP_TO_50_50, remoteTransition, instanceId);
-                case SPLIT_SINGLE_SHORTCUT_FULLSCREEN -> mSystemUiProxy.startShortcutAndTask(
-                        initialShortcut, optionsBundle, firstTaskId, null /* options2 */,
-                        initialStagePosition, SNAP_TO_50_50, remoteTransition, instanceId);
-            }
-        } else {
-            final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(firstTaskId,
-                    secondTaskId, callback);
-            switch (launchData.getSplitLaunchType()) {
-                case SPLIT_SINGLE_TASK_FULLSCREEN -> mSystemUiProxy.startTasksWithLegacyTransition(
-                        firstTaskId, optionsBundle, secondTaskId, null /* options2 */,
-                        initialStagePosition, SNAP_TO_50_50, adapter, instanceId);
-                case SPLIT_SINGLE_INTENT_FULLSCREEN ->
-                        mSystemUiProxy.startIntentAndTaskWithLegacyTransition(firstPI, firstUserId,
-                                optionsBundle, secondTaskId, null /*options2*/,
-                                initialStagePosition, SNAP_TO_50_50, adapter, instanceId);
-                case SPLIT_SINGLE_SHORTCUT_FULLSCREEN ->
-                        mSystemUiProxy.startShortcutAndTaskWithLegacyTransition(
-                                initialShortcut, optionsBundle, firstTaskId, null /* options2 */,
-                                initialStagePosition, SNAP_TO_50_50, adapter, instanceId);
-            }
+        switch (launchData.getSplitLaunchType()) {
+            case SPLIT_SINGLE_TASK_FULLSCREEN -> mSystemUiProxy.startTasks(firstTaskId,
+                    optionsBundle, secondTaskId, null /* options2 */, initialStagePosition,
+                    SNAP_TO_50_50, remoteTransition, instanceId);
+            case SPLIT_SINGLE_INTENT_FULLSCREEN -> mSystemUiProxy.startIntentAndTask(firstPI,
+                    firstUserId, optionsBundle, secondTaskId, null /*options2*/,
+                    initialStagePosition, SNAP_TO_50_50, remoteTransition, instanceId);
+            case SPLIT_SINGLE_SHORTCUT_FULLSCREEN -> mSystemUiProxy.startShortcutAndTask(
+                    initialShortcut, optionsBundle, firstTaskId, null /* options2 */,
+                    initialStagePosition, SNAP_TO_50_50, remoteTransition, instanceId);
         }
     }
 
@@ -660,7 +592,7 @@
         mSplitFromDesktopController = controller;
     }
 
-    private RemoteTransition getShellRemoteTransition(int firstTaskId, int secondTaskId,
+    private RemoteTransition getRemoteTransition(int firstTaskId, int secondTaskId,
             @Nullable Consumer<Boolean> callback, String transitionName) {
         final RemoteSplitLaunchTransitionRunner animationRunner =
                 new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
@@ -668,14 +600,6 @@
                 ActivityThread.currentActivityThread().getApplicationThread(), transitionName);
     }
 
-    private RemoteAnimationAdapter getLegacyRemoteAdapter(int firstTaskId, int secondTaskId,
-            @Nullable Consumer<Boolean> callback) {
-        final RemoteSplitLaunchAnimationRunner animationRunner =
-                new RemoteSplitLaunchAnimationRunner(firstTaskId, secondTaskId, callback);
-        return new RemoteAnimationAdapter(animationRunner, 300, 150,
-                ActivityThread.currentActivityThread().getApplicationThread());
-    }
-
     /**
      * Will initialize {@link #mSessionInstanceIds} if null and log the first split event from
      * {@link #mSplitSelectDataHolder}
@@ -807,55 +731,6 @@
     }
 
     /**
-     * LEGACY
-     * Remote animation runner for animation to launch an app.
-     */
-    private class RemoteSplitLaunchAnimationRunner extends RemoteAnimationRunnerCompat {
-
-        private final int mInitialTaskId;
-        private final int mSecondTaskId;
-        private final Consumer<Boolean> mSuccessCallback;
-
-        RemoteSplitLaunchAnimationRunner(int initialTaskId, int secondTaskId,
-                @Nullable Consumer<Boolean> successCallback) {
-            mInitialTaskId = initialTaskId;
-            mSecondTaskId = secondTaskId;
-            mSuccessCallback = successCallback;
-        }
-
-        @Override
-        public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
-                RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
-                Runnable finishedCallback) {
-            postAsyncCallback(mHandler,
-                    () -> mSplitAnimationController
-                            .playSplitLaunchAnimation(mLaunchingTaskView,
-                            mLaunchingIconView, mInitialTaskId, mSecondTaskId, apps, wallpapers,
-                            nonApps, mStateManager, mDepthController, null /* info */, null /* t */,
-                            () -> {
-                                finishedCallback.run();
-                                if (mSuccessCallback != null) {
-                                    mSuccessCallback.accept(true);
-                                }
-                                resetState();
-                            },
-                            QuickStepContract.getWindowCornerRadius(mContainer.asContext())));
-        }
-
-        @Override
-        public void onAnimationCancelled() {
-            postAsyncCallback(mHandler, () -> {
-                if (mSuccessCallback != null) {
-                    // Launching legacy tasks while recents animation is running will always cause
-                    // onAnimationCancelled to be called (should be fixed w/ shell transitions?)
-                    mSuccessCallback.accept(mRecentsAnimationRunning);
-                }
-                resetState();
-            });
-        }
-    }
-
-    /**
      * To be called whenever we exit split selection state. If
      * {@link FeatureFlags#enableSplitContextually()} is set, this should be the
      * central way split is getting reset, which should then go through the callbacks to reset
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index d63ac56..3702f93 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -193,7 +193,9 @@
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
 import com.android.quickstep.recents.data.RecentTasksRepository;
 import com.android.quickstep.recents.data.RecentsDeviceProfileRepository;
+import com.android.quickstep.recents.data.RecentsDeviceProfileRepositoryImpl;
 import com.android.quickstep.recents.data.RecentsRotationStateRepository;
+import com.android.quickstep.recents.data.RecentsRotationStateRepositoryImpl;
 import com.android.quickstep.recents.di.RecentsDependencies;
 import com.android.quickstep.recents.viewmodel.RecentsViewData;
 import com.android.quickstep.recents.viewmodel.RecentsViewModel;
@@ -231,6 +233,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -805,6 +808,7 @@
     private boolean mAnyTaskHasBeenDismissed;
 
     private final RecentsViewModel mRecentsViewModel;
+    private final RecentsViewHelper mHelper;
 
     public RecentsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
             BaseContainerInterface sizeStrategy) {
@@ -826,14 +830,16 @@
                     recentsDependencies.inject(RecentTasksRepository.class),
                     recentsDependencies.inject(RecentsViewData.class)
             );
+            mHelper = new RecentsViewHelper(mRecentsViewModel);
 
             recentsDependencies.provide(RecentsRotationStateRepository.class,
-                    () -> new RecentsRotationStateRepository(mOrientationState));
+                    () -> new RecentsRotationStateRepositoryImpl(mOrientationState));
 
             recentsDependencies.provide(RecentsDeviceProfileRepository.class,
-                    () -> new RecentsDeviceProfileRepository(mContainer));
+                    () -> new RecentsDeviceProfileRepositoryImpl(mContainer));
         } else {
             mRecentsViewModel = null;
+            mHelper = null;
         }
 
         mScrollHapticMinGapMillis = getResources()
@@ -1041,8 +1047,11 @@
     @Override
     @Nullable
     public Task onTaskThumbnailChanged(int taskId, ThumbnailData thumbnailData) {
+        if (enableRefactorTaskThumbnail()) {
+            // TODO(b/342560598): Listen in TaskRepository and reload
+            return null;
+        }
         if (mHandleTaskStackChanges) {
-            // TODO(b/342560598): Handle onTaskThumbnailChanged for new TTV.
             if (!enableRefactorTaskThumbnail()) {
                 TaskView taskView = getTaskViewByTaskId(taskId);
                 if (taskView != null) {
@@ -1061,6 +1070,7 @@
 
     @Override
     public void onTaskIconChanged(String pkg, UserHandle user) {
+        // TODO(b/342560598): Listen in TaskRepository and reload.
         for (int i = 0; i < getTaskViewCount(); i++) {
             TaskView tv = requireTaskViewAt(i);
             Task task = tv.getFirstTask();
@@ -1076,47 +1086,38 @@
 
     @Override
     public void onTaskIconChanged(int taskId) {
+        if (enableRefactorTaskThumbnail()) {
+            return;
+        }
         TaskView taskView = getTaskViewByTaskId(taskId);
         if (taskView != null) {
             taskView.refreshTaskThumbnailSplash();
         }
     }
 
-    /**
-     * Update the thumbnail(s) of the relevant TaskView.
-     *
-     * @param refreshNow Refresh immediately if it's true.
-     */
-    @Nullable
-    public TaskView updateThumbnail(
-            HashMap<Integer, ThumbnailData> thumbnailData, boolean refreshNow) {
+    /** Updates the thumbnail(s) of the relevant TaskView. */
+    public void updateThumbnail(Map<Integer, ThumbnailData> thumbnailData) {
         if (enableRefactorTaskThumbnail()) {
-            // TODO(b/342560598): Handle updateThumbnail for new TTV.
-            return null;
-        }
-        TaskView updatedTaskView = null;
-        for (Map.Entry<Integer, ThumbnailData> entry : thumbnailData.entrySet()) {
-            Integer id = entry.getKey();
-            ThumbnailData thumbnail = entry.getValue();
-            TaskView taskView = getTaskViewByTaskId(id);
-            if (taskView == null) {
-                continue;
+            mRecentsViewModel.addOrUpdateThumbnailOverride(thumbnailData);
+        } else {
+            for (Map.Entry<Integer, ThumbnailData> entry : thumbnailData.entrySet()) {
+                Integer id = entry.getKey();
+                ThumbnailData thumbnail = entry.getValue();
+                TaskView taskView = getTaskViewByTaskId(id);
+                if (taskView == null) {
+                    continue;
+                }
+                // taskView could be a GroupedTaskView, so select the relevant task by ID
+                TaskContainer taskContainer = taskView.getTaskContainerById(id);
+                if (taskContainer == null) {
+                    continue;
+                }
+                Task task = taskContainer.getTask();
+                TaskThumbnailViewDeprecated taskThumbnailViewDeprecated =
+                        taskContainer.getThumbnailViewDeprecated();
+                taskThumbnailViewDeprecated.setThumbnail(task, thumbnail, /*refreshNow=*/false);
             }
-            // taskView could be a GroupedTaskView, so select the relevant task by ID
-            TaskContainer taskAttributes = taskView.getTaskContainerById(id);
-            if (taskAttributes == null) {
-                continue;
-            }
-            Task task = taskAttributes.getTask();
-            TaskThumbnailViewDeprecated taskThumbnailViewDeprecated =
-                    taskAttributes.getThumbnailViewDeprecated();
-            taskThumbnailViewDeprecated.setThumbnail(task, thumbnail, refreshNow);
-            // thumbnailData can contain 1-2 ids, but they should correspond to the same
-            // TaskView, so overwriting is ok
-            updatedTaskView = taskView;
         }
-
-        return updatedTaskView;
     }
 
     @Override
@@ -1171,6 +1172,9 @@
         if (FeatureFlags.enableSplitContextually()) {
             mSplitSelectStateController.registerSplitListener(mSplitSelectionListener);
         }
+        if (enableRefactorTaskThumbnail()) {
+            mHelper.onAttachedToWindow();
+        }
     }
 
     @Override
@@ -1193,6 +1197,9 @@
             mSplitSelectStateController.unregisterSplitListener(mSplitSelectionListener);
         }
         reset();
+        if (enableRefactorTaskThumbnail()) {
+            mHelper.onDetachedFromWindow();
+        }
     }
 
     @Override
@@ -2428,10 +2435,6 @@
                 List<Task> tasksToUpdate = containers.stream()
                         .map(TaskContainer::getTask)
                         .collect(Collectors.toCollection(ArrayList::new));
-                if (enableRefactorTaskThumbnail()) {
-                    visibleTaskIds.addAll(
-                            tasksToUpdate.stream().map((task) -> task.key.id).toList());
-                }
                 if (mTmpRunningTasks != null) {
                     for (Task t : mTmpRunningTasks) {
                         // Skip loading if this is the task that we are animating into
@@ -2439,6 +2442,10 @@
                         tasksToUpdate.removeIf(task -> task == t);
                     }
                 }
+                if (enableRefactorTaskThumbnail()) {
+                    visibleTaskIds.addAll(
+                            tasksToUpdate.stream().map((task) -> task.key.id).toList());
+                }
                 if (tasksToUpdate.isEmpty()) {
                     continue;
                 }
@@ -2495,6 +2502,11 @@
             mModel.preloadCacheIfNeeded();
         }
 
+        if (enableRefactorTaskThumbnail()) {
+            // TODO(b/342560598): Listen in TaskRepository and reload.
+            return;
+        }
+
         // Whenever the high res loading state changes, poke each of the visible tasks to see if
         // they want to updated their thumbnail state
         for (int i = 0; i < mHasVisibleTaskData.size(); i++) {
@@ -2563,14 +2575,19 @@
 
         // These are relatively expensive and don't need to be done this frame (RecentsView isn't
         // visible anyway), so defer by a frame to get off the critical path, e.g. app to home.
-        post(() -> {
-            unloadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
-            setCurrentPage(0);
-            LayoutUtils.setViewEnabled(mActionsView, true);
-            if (mOrientationState.setGestureActive(false)) {
-                updateOrientationHandler(/* forceRecreateDragLayerControllers = */ false);
-            }
-        });
+        post(this::onReset);
+    }
+
+    private void onReset() {
+        if (enableRefactorTaskThumbnail()) {
+            mRecentsViewModel.onReset();
+        }
+        unloadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
+        setCurrentPage(0);
+        LayoutUtils.setViewEnabled(mActionsView, true);
+        if (mOrientationState.setGestureActive(false)) {
+            updateOrientationHandler(/* forceRecreateDragLayerControllers = */ false);
+        }
     }
 
     public int getRunningTaskViewId() {
@@ -2946,18 +2963,13 @@
     }
 
     private void setRunningTaskViewId(int runningTaskViewId) {
-        int prevRunningTaskViewId = mRunningTaskViewId;
         mRunningTaskViewId = runningTaskViewId;
 
         if (enableRefactorTaskThumbnail()) {
-            TaskView previousRunningTaskView = getTaskViewFromTaskViewId(prevRunningTaskViewId);
-            if (previousRunningTaskView != null) {
-                previousRunningTaskView.notifyIsRunningTaskUpdated();
-            }
-            TaskView newRunningTaskView = getTaskViewFromTaskViewId(runningTaskViewId);
-            if (newRunningTaskView != null) {
-                newRunningTaskView.notifyIsRunningTaskUpdated();
-            }
+            TaskView runningTaskView = getTaskViewFromTaskViewId(runningTaskViewId);
+            mRecentsViewModel.updateRunningTask(
+                    runningTaskView != null ? runningTaskView.getTaskIdSet()
+                            : Collections.emptySet());
         }
     }
 
@@ -2987,6 +2999,9 @@
         if (runningTaskView != null) {
             runningTaskView.setShouldShowScreenshot(mRunningTaskShowScreenshot);
         }
+        if (enableRefactorTaskThumbnail()) {
+            mRecentsViewModel.setRunningTaskShowScreenshot(showScreenshot);
+        }
     }
 
     public void setTaskIconScaledDown(boolean isScaledDown) {
@@ -3297,6 +3312,10 @@
     }
 
     private void setTaskThumbnailSplashAlpha(float taskThumbnailSplashAlpha) {
+        if (enableRefactorTaskThumbnail()) {
+            mRecentsViewModel.updateThumbnailSplashProgress(taskThumbnailSplashAlpha);
+            return;
+        }
         int taskCount = getTaskViewCount();
         if (taskCount == 0) {
             return;
@@ -4894,7 +4913,6 @@
                             mSplitHiddenTaskView.getWidth(), mSplitHiddenTaskView.getHeight(),
                             primaryTaskSelected);
             builder.addOnFrameCallback(() -> {
-                // TODO(b/334826842): Handle splash icon for new TTV.
                 if (!enableRefactorTaskThumbnail()) {
                     taskContainer.getThumbnailViewDeprecated().refreshSplashView();
                 }
@@ -6019,38 +6037,28 @@
             return;
         }
 
-        switchToScreenshotInternal(onFinishRunnable);
-    }
-
-    private void switchToScreenshotInternal(Runnable onFinishRunnable) {
-        // TODO(b/342560598): Handle switchToScreenshot for new TTV.
-        if (enableRefactorTaskThumbnail()) {
-            onFinishRunnable.run();
-            return;
-        }
-
         TaskView taskView = getRunningTaskView();
         if (taskView == null) {
             onFinishRunnable.run();
             return;
         }
 
-        setRunningTaskViewShowScreenshot(true);
-        for (TaskContainer container : taskView.getTaskContainers()) {
-            if (container == null) {
-                continue;
+        if (enableRefactorTaskThumbnail()) {
+            mHelper.switchToScreenshot(taskView, mRecentsAnimationController, onFinishRunnable);
+        } else {
+            setRunningTaskViewShowScreenshot(true);
+            for (TaskContainer container : taskView.getTaskContainers()) {
+                ThumbnailData thumbnailData =
+                        mRecentsAnimationController.screenshotTask(container.getTask().key.id);
+                TaskThumbnailViewDeprecated thumbnailView = container.getThumbnailViewDeprecated();
+                if (thumbnailData != null) {
+                    thumbnailView.setThumbnail(container.getTask(), thumbnailData);
+                } else {
+                    thumbnailView.refresh();
+                }
             }
-
-            ThumbnailData td =
-                    mRecentsAnimationController.screenshotTask(container.getTask().key.id);
-            TaskThumbnailViewDeprecated thumbnailView = container.getThumbnailViewDeprecated();
-            if (td != null) {
-                thumbnailView.setThumbnail(container.getTask(), td);
-            } else {
-                thumbnailView.refresh();
-            }
+            ViewUtils.postFrameDrawn(taskView, onFinishRunnable);
         }
-        ViewUtils.postFrameDrawn(taskView, onFinishRunnable);
     }
 
     /**
@@ -6064,9 +6072,13 @@
             Runnable onFinishRunnable) {
         final TaskView taskView = getRunningTaskView();
         if (taskView != null) {
-            taskView.setShouldShowScreenshot(true);
-            taskView.refreshThumbnails(thumbnailDatas);
-            ViewUtils.postFrameDrawn(taskView, onFinishRunnable);
+            if (enableRefactorTaskThumbnail()) {
+                mHelper.switchToScreenshot(taskView, thumbnailDatas, onFinishRunnable);
+            } else {
+                taskView.setShouldShowScreenshot(true);
+                taskView.refreshThumbnails(thumbnailDatas);
+                ViewUtils.postFrameDrawn(taskView, onFinishRunnable);
+            }
         } else {
             onFinishRunnable.run();
         }
@@ -6116,7 +6128,6 @@
      * tasks to be dimmed while other elements in the recents view are left alone.
      */
     public void showForegroundScrim(boolean show) {
-        // TODO(b/349601769) Add scrim response into new TTV - this is called from overlay
         if (!show && mColorTint == 0) {
             if (mTintingAnimator != null) {
                 mTintingAnimator.cancel();
@@ -6135,6 +6146,10 @@
     private void setColorTint(float tintAmount) {
         mColorTint = tintAmount;
 
+        if (enableRefactorTaskThumbnail()) {
+            mRecentsViewModel.setTintAmount(tintAmount);
+        }
+
         for (int i = 0; i < getTaskViewCount(); i++) {
             requireTaskViewAt(i).setColorTint(mColorTint, mTintingColor);
         }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewHelper.kt b/quickstep/src/com/android/quickstep/views/RecentsViewHelper.kt
new file mode 100644
index 0000000..a63ccec
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/RecentsViewHelper.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2024 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.views
+
+import com.android.quickstep.RecentsAnimationController
+import com.android.quickstep.ViewUtils
+import com.android.quickstep.recents.viewmodel.RecentsViewModel
+import com.android.systemui.shared.recents.model.ThumbnailData
+import kotlinx.coroutines.CoroutineName
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.launch
+
+/** Helper for [RecentsView] to interact with coroutine. */
+class RecentsViewHelper(private val recentsViewModel: RecentsViewModel) {
+    private lateinit var viewAttachedScope: CoroutineScope
+
+    fun onAttachedToWindow() {
+        viewAttachedScope =
+            CoroutineScope(SupervisorJob() + Dispatchers.Main + CoroutineName("RecentsView"))
+    }
+
+    fun onDetachedFromWindow() {
+        viewAttachedScope.cancel("RecentsView detaching from window")
+    }
+
+    fun switchToScreenshot(
+        taskView: TaskView,
+        recentsAnimationController: RecentsAnimationController,
+        onFinishRunnable: Runnable
+    ) {
+        val updatedThumbnails =
+            taskView.taskContainers.associate {
+                it.task.key.id to recentsAnimationController.screenshotTask(it.task.key.id)
+            }
+        switchToScreenshot(taskView, updatedThumbnails, onFinishRunnable)
+    }
+
+    fun switchToScreenshot(
+        taskView: TaskView,
+        updatedThumbnails: Map<Int, ThumbnailData>?,
+        onFinishRunnable: Runnable
+    ) {
+        // Update recentsViewModel and apply the thumbnailOverride ASAP, before waiting inside
+        // viewAttachedScope.
+        recentsViewModel.setRunningTaskShowScreenshot(true)
+        if (updatedThumbnails != null) {
+            recentsViewModel.addOrUpdateThumbnailOverride(updatedThumbnails)
+        }
+        viewAttachedScope.launch {
+            recentsViewModel.waitForRunningTaskShowScreenshotToUpdate()
+            if (updatedThumbnails != null) {
+                recentsViewModel.waitForThumbnailsToUpdate(updatedThumbnails)
+            }
+            ViewUtils.postFrameDrawn(taskView, onFinishRunnable)
+        }
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/views/TaskContainer.kt b/quickstep/src/com/android/quickstep/views/TaskContainer.kt
index e7a8720..af32ba2 100644
--- a/quickstep/src/com/android/quickstep/views/TaskContainer.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskContainer.kt
@@ -34,7 +34,6 @@
 import com.android.quickstep.recents.di.getScope
 import com.android.quickstep.recents.di.inject
 import com.android.quickstep.recents.viewmodel.TaskContainerViewModel
-import com.android.quickstep.task.thumbnail.TaskThumbnail
 import com.android.quickstep.task.thumbnail.TaskThumbnailView
 import com.android.quickstep.task.viewmodel.TaskContainerData
 import com.android.quickstep.task.viewmodel.TaskThumbnailViewModel
@@ -69,7 +68,8 @@
     private val taskContainerViewModel: TaskContainerViewModel by lazy {
         TaskContainerViewModel(
             sysUiStatusNavFlagsUseCase = RecentsDependencies.get(),
-            getThumbnailUseCase = RecentsDependencies.get()
+            getThumbnailUseCase = RecentsDependencies.get(),
+            splashAlphaUseCase = RecentsDependencies.get(),
         )
     }
 
@@ -81,7 +81,7 @@
                 val taskViewScope = RecentsDependencies.getScope(taskView)
                 linkTo(taskViewScope)
 
-                val taskContainerScope = RecentsDependencies.getScope(this)
+                val taskContainerScope = RecentsDependencies.getScope(this@TaskContainer)
                 linkTo(taskContainerScope)
             }
         } else {
@@ -112,10 +112,10 @@
     // TODO(b/334826842): Support shouldShowSplashView for new TTV.
     val shouldShowSplashView: Boolean
         get() =
-            if (enableRefactorTaskThumbnail()) false
+            if (enableRefactorTaskThumbnail())
+                taskContainerViewModel.shouldShowThumbnailSplash(task.key.id)
             else thumbnailViewDeprecated.shouldShowSplashView()
 
-    // TODO(b/350743460) Support sysUiStatusNavFlags for new TTV.
     val sysUiStatusNavFlags: Int
         get() =
             if (enableRefactorTaskThumbnail())
@@ -163,9 +163,7 @@
     }
 
     fun bindThumbnailView() {
-        // TODO(b/343364498): Existing view has shouldShowScreenshot as an override as well but
-        //  this should be decided inside TaskThumbnailViewModel.
-        taskThumbnailViewModel.bind(TaskThumbnail(task.key.id, taskView.isRunningTask))
+        taskThumbnailViewModel.bind(task.key.id)
     }
 
     fun setOverlayEnabled(enabled: Boolean) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt
index f2f036a..e189d14 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskView.kt
@@ -123,6 +123,10 @@
         /** Returns a copy of integer array containing taskIds of all tasks in the TaskView. */
         get() = taskContainers.map { it.task.key.id }.toIntArray()
 
+    val taskIdSet: Set<Int>
+        /** Returns a copy of integer array containing taskIds of all tasks in the TaskView. */
+        get() = taskContainers.map { it.task.key.id }.toSet()
+
     val snapshotViews: Array<View>
         get() = taskContainers.map { it.snapshotView }.toTypedArray()
 
@@ -285,6 +289,9 @@
         set(value) {
             field = value
             applyScale()
+            if (enableRefactorTaskThumbnail()) {
+                taskViewModel.updateNonGridScale(value)
+            }
         }
 
     private var dismissScale = 1f
@@ -566,9 +573,7 @@
         resetPersistentViewTransforms()
         // Clear any references to the thumbnail (it will be re-read either from the cache or the
         // system on next bind)
-        if (enableRefactorTaskThumbnail()) {
-            notifyIsRunningTaskUpdated()
-        } else {
+        if (!enableRefactorTaskThumbnail()) {
             taskContainers.forEach { it.thumbnailViewDeprecated.setThumbnail(it.task, null) }
         }
         setOverlayEnabled(false)
@@ -918,9 +923,8 @@
         iconView.setText(text)
     }
 
-    open fun refreshThumbnails(thumbnailDatas: HashMap<Int, ThumbnailData?>?) {
+    open fun refreshThumbnails(thumbnailDatas: Map<Int, ThumbnailData?>?) {
         if (enableRefactorTaskThumbnail()) {
-            // TODO(b/342560598) add thumbnail logic
             return
         }
 
@@ -1051,11 +1055,9 @@
                     if (isQuickSwitch) {
                         setFreezeRecentTasksReordering()
                     }
-                    // TODO(b/334826842) add splash functionality to new TTV
-                    if (!enableRefactorTaskThumbnail()) {
-                        disableStartingWindow =
-                            firstContainer.thumbnailViewDeprecated.shouldShowSplashView()
-                    }
+                    // TODO(b/334826842) no work required - add splash functionality to new TTV -
+                    // cold start e.g. restart device. Small splash moving to bigger splash
+                    disableStartingWindow = firstContainer.shouldShowSplashView
                 }
         Executors.UI_HELPER_EXECUTOR.execute {
             if (
@@ -1396,7 +1398,6 @@
 
     protected open fun refreshTaskThumbnailSplash() {
         if (!enableRefactorTaskThumbnail()) {
-            // TODO(b/334826842) add splash functionality to new TTV
             taskContainers.forEach { it.thumbnailViewDeprecated.refreshSplashView() }
         }
     }
@@ -1420,7 +1421,6 @@
 
     protected open fun applyThumbnailSplashAlpha() {
         if (!enableRefactorTaskThumbnail()) {
-            // TODO(b/334826842) add splash functionality to new TTV
             taskContainers.forEach {
                 it.thumbnailViewDeprecated.setSplashAlpha(taskThumbnailSplashAlpha)
             }
@@ -1490,11 +1490,6 @@
         }
     }
 
-    /** Updates [TaskThumbnailView] to reflect the latest [Task] state (i.e., task isRunning). */
-    fun notifyIsRunningTaskUpdated() {
-        taskContainers.forEach { it.bindThumbnailView() }
-    }
-
     fun resetPersistentViewTransforms() {
         nonGridTranslationX = 0f
         gridTranslationX = 0f
diff --git a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleViewScreenshotTest.kt b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleViewScreenshotTest.kt
new file mode 100644
index 0000000..3e0d6b5
--- /dev/null
+++ b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleViewScreenshotTest.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar.bubbles
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.util.PathParser
+import android.view.LayoutInflater
+import androidx.test.core.app.ApplicationProvider
+import com.android.launcher3.R
+import com.android.wm.shell.common.bubbles.BubbleInfo
+import com.google.android.apps.nexuslauncher.imagecomparison.goldenpathmanager.ViewScreenshotGoldenPathManager
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
+import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.Displays
+import platform.test.screenshot.ViewScreenshotTestRule
+import platform.test.screenshot.getEmulatedDevicePathConfig
+
+/** Screenshot tests for [BubbleView]. */
+@RunWith(ParameterizedAndroidJunit4::class)
+class BubbleViewScreenshotTest(emulationSpec: DeviceEmulationSpec) {
+
+    private val context = ApplicationProvider.getApplicationContext<Context>()
+
+    companion object {
+        @Parameters(name = "{0}")
+        @JvmStatic
+        fun getTestSpecs() =
+            DeviceEmulationSpec.forDisplays(
+                Displays.Phone,
+                isDarkTheme = false,
+                isLandscape = false
+            )
+    }
+
+    @get:Rule
+    val screenshotRule =
+        ViewScreenshotTestRule(
+            emulationSpec,
+            ViewScreenshotGoldenPathManager(getEmulatedDevicePathConfig(emulationSpec))
+        )
+
+    @Test
+    fun bubbleView_hasUnseenContent() {
+        screenshotRule.screenshotTest("bubbleView_hasUnseenContent") { activity ->
+            activity.actionBar?.hide()
+            setupBubbleView()
+        }
+    }
+
+    @Test
+    fun bubbleView_seen() {
+        screenshotRule.screenshotTest("bubbleView_seen") { activity ->
+            activity.actionBar?.hide()
+            setupBubbleView().apply { markSeen() }
+        }
+    }
+
+    @Test
+    fun bubbleView_badgeHidden() {
+        screenshotRule.screenshotTest("bubbleView_badgeHidden") { activity ->
+            activity.actionBar?.hide()
+            setupBubbleView().apply { setBadgeScale(0f) }
+        }
+    }
+
+    private fun setupBubbleView(): BubbleView {
+        val inflater = LayoutInflater.from(context)
+
+        val iconSize = 100
+        // BubbleView uses launcher's badge to icon ratio and expects the badge image to already
+        // have the right size
+        val badgeToIconRatio = 0.444f
+        val badgeRadius = iconSize * badgeToIconRatio / 2
+        val icon = createCircleBitmap(radius = iconSize / 2, color = Color.LTGRAY)
+        val badge = createCircleBitmap(radius = badgeRadius.toInt(), color = Color.RED)
+
+        val bubbleInfo = BubbleInfo("key", 0, null, null, 0, context.packageName, null, null, false)
+        val bubbleView = inflater.inflate(R.layout.bubblebar_item_view, null) as BubbleView
+        val dotPath =
+            PathParser.createPathFromPathData(
+                context.resources.getString(com.android.internal.R.string.config_icon_mask)
+            )
+        val bubble =
+            BubbleBarBubble(bubbleInfo, bubbleView, badge, icon, Color.BLUE, dotPath, "test app")
+        bubbleView.setBubble(bubble)
+        bubbleView.showDotIfNeeded(1f)
+        return bubbleView
+    }
+
+    private fun createCircleBitmap(radius: Int, color: Int): Bitmap {
+        val bitmap = Bitmap.createBitmap(radius * 2, radius * 2, Bitmap.Config.ARGB_8888)
+        val canvas = Canvas(bitmap)
+        canvas.drawARGB(0, 0, 0, 0)
+        val paint = Paint()
+        paint.color = color
+        canvas.drawCircle(radius.toFloat(), radius.toFloat(), radius.toFloat(), paint)
+        return bitmap
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarControllerTestUtil.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarControllerTestUtil.kt
new file mode 100644
index 0000000..a57fb70
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarControllerTestUtil.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar
+
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+
+object TaskbarControllerTestUtil {
+    inline fun runOnMainSync(crossinline runTest: () -> Unit) {
+        getInstrumentation().runOnMainSync { runTest() }
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarEduTooltipControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarEduTooltipControllerTest.kt
new file mode 100644
index 0000000..e583f63
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarEduTooltipControllerTest.kt
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar
+
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.Utilities
+import com.android.launcher3.taskbar.TaskbarControllerTestUtil.runOnMainSync
+import com.android.launcher3.taskbar.rules.TaskbarModeRule
+import com.android.launcher3.taskbar.rules.TaskbarModeRule.Mode.PINNED
+import com.android.launcher3.taskbar.rules.TaskbarModeRule.Mode.THREE_BUTTONS
+import com.android.launcher3.taskbar.rules.TaskbarModeRule.Mode.TRANSIENT
+import com.android.launcher3.taskbar.rules.TaskbarModeRule.TaskbarMode
+import com.android.launcher3.taskbar.rules.TaskbarPinningPreferenceRule
+import com.android.launcher3.taskbar.rules.TaskbarPreferenceRule
+import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule
+import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule.InjectController
+import com.android.launcher3.taskbar.rules.TaskbarWindowSandboxContext
+import com.android.launcher3.util.LauncherMultivalentJUnit
+import com.android.launcher3.util.LauncherMultivalentJUnit.EmulatedDevices
+import com.android.launcher3.util.OnboardingPrefs
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(LauncherMultivalentJUnit::class)
+@EmulatedDevices(["pixelFoldable2023", "pixelTablet2023"])
+class TaskbarEduTooltipControllerTest {
+
+    private val context =
+        TaskbarWindowSandboxContext.create(
+            InstrumentationRegistry.getInstrumentation().targetContext
+        )
+
+    @get:Rule
+    val tooltipStepPreferenceRule =
+        TaskbarPreferenceRule(
+            context,
+            OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP.prefItem,
+        )
+
+    @get:Rule
+    val searchEduPreferenceRule =
+        TaskbarPreferenceRule(
+            context,
+            OnboardingPrefs.TASKBAR_SEARCH_EDU_SEEN,
+        )
+
+    @get:Rule val taskbarPinningPreferenceRule = TaskbarPinningPreferenceRule(context)
+
+    @get:Rule val taskbarModeRule = TaskbarModeRule(context)
+
+    @get:Rule val taskbarUnitTestRule = TaskbarUnitTestRule(this, context)
+
+    @InjectController lateinit var taskbarEduTooltipController: TaskbarEduTooltipController
+
+    private val taskbarContext: TaskbarActivityContext
+        get() = taskbarUnitTestRule.activityContext
+
+    private val wasInTestHarness = Utilities.isRunningInTestHarness()
+
+    @Before
+    fun setUp() {
+        Utilities.disableRunningInTestHarnessForTests()
+    }
+
+    @After
+    fun tearDown() {
+        if (wasInTestHarness) {
+            Utilities.enableRunningInTestHarnessForTests()
+        }
+    }
+
+    @Test
+    @TaskbarMode(THREE_BUTTONS)
+    fun testMaybeShowSwipeEdu_whenTaskbarIsInThreeButtonMode_doesNotShowSwipeEdu() {
+        tooltipStepPreferenceRule.value = TOOLTIP_STEP_SWIPE
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_SWIPE)
+        runOnMainSync { taskbarEduTooltipController.maybeShowSwipeEdu() }
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_SWIPE)
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isFalse()
+    }
+
+    @Test
+    @TaskbarMode(TRANSIENT)
+    fun testMaybeShowSwipeEdu_whenSwipeEduAlreadyShown_doesNotShowSwipeEdu() {
+        tooltipStepPreferenceRule.value = TOOLTIP_STEP_FEATURES
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_FEATURES)
+        runOnMainSync { taskbarEduTooltipController.maybeShowSwipeEdu() }
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_FEATURES)
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isFalse()
+    }
+
+    @Test
+    @TaskbarMode(TRANSIENT)
+    fun testMaybeShowSwipeEdu_whenUserHasNotSeen_doesShowSwipeEdu() {
+        tooltipStepPreferenceRule.value = TOOLTIP_STEP_SWIPE
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_SWIPE)
+        runOnMainSync { taskbarEduTooltipController.maybeShowSwipeEdu() }
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_FEATURES)
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isTrue()
+    }
+
+    @Test
+    @TaskbarMode(TRANSIENT)
+    fun testMaybeShowFeaturesEdu_whenFeatureEduAlreadyShown_doesNotShowFeatureEdu() {
+        tooltipStepPreferenceRule.value = TOOLTIP_STEP_NONE
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_NONE)
+        runOnMainSync { taskbarEduTooltipController.maybeShowFeaturesEdu() }
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_NONE)
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isFalse()
+    }
+
+    @Test
+    @TaskbarMode(TRANSIENT)
+    fun testMaybeShowFeaturesEdu_whenUserHasNotSeen_doesShowFeatureEdu() {
+        tooltipStepPreferenceRule.value = TOOLTIP_STEP_FEATURES
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_FEATURES)
+        runOnMainSync { taskbarEduTooltipController.maybeShowFeaturesEdu() }
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_NONE)
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isTrue()
+    }
+
+    @Test
+    @TaskbarMode(THREE_BUTTONS)
+    fun testMaybeShowPinningEdu_whenTaskbarIsInThreeButtonMode_doesNotShowPinningEdu() {
+        tooltipStepPreferenceRule.value = TOOLTIP_STEP_PINNING
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_PINNING)
+        runOnMainSync { taskbarEduTooltipController.maybeShowFeaturesEdu() }
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_PINNING)
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isFalse()
+    }
+
+    @Test
+    @TaskbarMode(TRANSIENT)
+    fun testMaybeShowPinningEdu_whenUserHasNotSeen_doesShowPinningEdu() {
+        // Test standalone pinning edu, where user has seen taskbar edu before, but not pinning edu.
+        tooltipStepPreferenceRule.value = TOOLTIP_STEP_PINNING
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_PINNING)
+        runOnMainSync { taskbarEduTooltipController.maybeShowFeaturesEdu() }
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_NONE)
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isTrue()
+    }
+
+    @Test
+    @TaskbarMode(TRANSIENT)
+    fun testIsBeforeTooltipFeaturesStep_whenUserHasNotSeenFeatureEdu_shouldReturnTrue() {
+        tooltipStepPreferenceRule.value = TOOLTIP_STEP_SWIPE
+        assertThat(taskbarEduTooltipController.isBeforeTooltipFeaturesStep).isTrue()
+    }
+
+    @Test
+    @TaskbarMode(TRANSIENT)
+    fun testIsBeforeTooltipFeaturesStep_whenUserHasSeenFeatureEdu_shouldReturnFalse() {
+        tooltipStepPreferenceRule.value = TOOLTIP_STEP_NONE
+        assertThat(taskbarEduTooltipController.isBeforeTooltipFeaturesStep).isFalse()
+    }
+
+    @Test
+    @TaskbarMode(TRANSIENT)
+    fun testHide_whenTooltipIsOpen_shouldCloseTooltip() {
+        tooltipStepPreferenceRule.value = TOOLTIP_STEP_SWIPE
+        assertThat(taskbarEduTooltipController.tooltipStep).isEqualTo(TOOLTIP_STEP_SWIPE)
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isFalse()
+        runOnMainSync { taskbarEduTooltipController.maybeShowSwipeEdu() }
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isTrue()
+        runOnMainSync { taskbarEduTooltipController.hide() }
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isFalse()
+    }
+
+    @Test
+    @TaskbarMode(TRANSIENT)
+    fun testMaybeShowSearchEdu_whenTaskbarIsTransient_shouldNotShowSearchEdu() {
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isFalse()
+        runOnMainSync { taskbarEduTooltipController.init(taskbarContext.controllers) }
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isFalse()
+    }
+
+    @Test
+    @TaskbarMode(PINNED)
+    fun testMaybeShowSearchEdu_whenTaskbarIsPinnedAndUserHasSeenSearchEdu_shouldNotShowSearchEdu() {
+        searchEduPreferenceRule.value = true
+        assertThat(taskbarEduTooltipController.userHasSeenSearchEdu).isTrue()
+        runOnMainSync { taskbarEduTooltipController.hide() }
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isFalse()
+        runOnMainSync { taskbarEduTooltipController.init(taskbarContext.controllers) }
+        assertThat(taskbarEduTooltipController.isTooltipOpen).isFalse()
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsControllerTest.kt
index 2f0b446..43d924a 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsControllerTest.kt
@@ -26,6 +26,7 @@
 import com.android.launcher3.model.data.AppInfo
 import com.android.launcher3.model.data.WorkspaceItemInfo
 import com.android.launcher3.notification.NotificationKeyData
+import com.android.launcher3.taskbar.TaskbarControllerTestUtil.runOnMainSync
 import com.android.launcher3.taskbar.overlay.TaskbarOverlayController
 import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule
 import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule.InjectController
@@ -56,13 +57,13 @@
 
     @Test
     fun testToggle_once_showsAllApps() {
-        getInstrumentation().runOnMainSync { allAppsController.toggle() }
+        runOnMainSync { allAppsController.toggle() }
         assertThat(allAppsController.isOpen).isTrue()
     }
 
     @Test
     fun testToggle_twice_closesAllApps() {
-        getInstrumentation().runOnMainSync {
+        runOnMainSync {
             allAppsController.toggle()
             allAppsController.toggle()
         }
@@ -71,7 +72,7 @@
 
     @Test
     fun testToggle_taskbarRecreated_allAppsReopened() {
-        getInstrumentation().runOnMainSync { allAppsController.toggle() }
+        runOnMainSync { allAppsController.toggle() }
         taskbarUnitTestRule.recreateTaskbar()
         assertThat(allAppsController.isOpen).isTrue()
     }
@@ -138,7 +139,7 @@
 
     @Test
     fun testUpdateNotificationDots_appInfo_hasDot() {
-        getInstrumentation().runOnMainSync {
+        runOnMainSync {
             allAppsController.setApps(TEST_APPS, 0, emptyMap())
             allAppsController.toggle()
             taskbarUnitTestRule.activityContext.popupDataProvider.onNotificationPosted(
@@ -162,7 +163,7 @@
 
     @Test
     fun testUpdateNotificationDots_predictedApp_hasDot() {
-        getInstrumentation().runOnMainSync {
+        runOnMainSync {
             allAppsController.setPredictedApps(TEST_PREDICTED_APPS)
             allAppsController.toggle()
             taskbarUnitTestRule.activityContext.popupDataProvider.onNotificationPosted(
@@ -185,12 +186,12 @@
 
     @Test
     fun testToggleSearch_searchEditTextFocused() {
-        getInstrumentation().runOnMainSync { allAppsController.toggleSearch() }
-        getInstrumentation().runOnMainSync {
+        runOnMainSync { allAppsController.toggleSearch() }
+        runOnMainSync {
             // All Apps is now attached to window. Open animation is posted but not started.
         }
 
-        getInstrumentation().runOnMainSync {
+        runOnMainSync {
             // Animation has started. Advance to end of animation.
             animatorTestRule.advanceTimeBy(overlayController.openDuration.toLong())
         }
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
index e9c0dd6..619ce1c 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
@@ -35,8 +35,8 @@
 import com.android.launcher3.taskbar.bubbles.BubbleBarBubble
 import com.android.launcher3.taskbar.bubbles.BubbleBarOverflow
 import com.android.launcher3.taskbar.bubbles.BubbleBarView
-import com.android.launcher3.taskbar.bubbles.BubbleStashController
 import com.android.launcher3.taskbar.bubbles.BubbleView
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController
 import com.android.wm.shell.common.bubbles.BubbleInfo
 import com.android.wm.shell.shared.animation.PhysicsAnimator
 import com.android.wm.shell.shared.animation.PhysicsAnimatorTestUtils
@@ -78,7 +78,7 @@
 
         val handle = View(context)
         val handleAnimator = PhysicsAnimator.getInstance(handle)
-        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+        whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
         val animator =
             BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
@@ -122,7 +122,7 @@
 
         val handle = View(context)
         val handleAnimator = PhysicsAnimator.getInstance(handle)
-        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+        whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
         val animator =
             BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
@@ -165,7 +165,7 @@
 
         val handle = View(context)
         val handleAnimator = PhysicsAnimator.getInstance(handle)
-        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+        whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
         val animator =
             BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
@@ -205,7 +205,7 @@
 
         val handle = View(context)
         val handleAnimator = PhysicsAnimator.getInstance(handle)
-        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+        whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
         val animator =
             BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
@@ -246,7 +246,7 @@
 
         val handle = View(context)
         val handleAnimator = PhysicsAnimator.getInstance(handle)
-        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+        whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
         val animator =
             BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
@@ -278,7 +278,7 @@
 
         val handle = View(context)
         val handleAnimator = PhysicsAnimator.getInstance(handle)
-        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+        whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
         val barAnimator = PhysicsAnimator.getInstance(bubbleBarView)
 
@@ -321,7 +321,7 @@
 
         val handle = View(context)
         val handleAnimator = PhysicsAnimator.getInstance(handle)
-        whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+        whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator)
 
         val barAnimator = PhysicsAnimator.getInstance(bubbleBarView)
 
@@ -451,9 +451,9 @@
     private fun setUpBubbleStashController() {
         bubbleStashController = mock<BubbleStashController>()
         whenever(bubbleStashController.isStashed).thenReturn(true)
-        whenever(bubbleStashController.diffBetweenHandleAndBarCenters)
+        whenever(bubbleStashController.getDiffBetweenHandleAndBarCenters())
             .thenReturn(DIFF_BETWEEN_HANDLE_AND_BAR_CENTERS)
-        whenever(bubbleStashController.stashedHandleTranslationForNewBubbleAnimation)
+        whenever(bubbleStashController.getStashedHandleTranslationForNewBubbleAnimation())
             .thenReturn(HANDLE_TRANSLATION)
         whenever(bubbleStashController.bubbleBarTranslationYForTaskbar)
             .thenReturn(BAR_TRANSLATION_Y_FOR_TASKBAR)
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentTaskbarStashControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashControllerTest.kt
similarity index 97%
rename from quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentTaskbarStashControllerTest.kt
rename to quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashControllerTest.kt
index c46c08d..c0a5dfa 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentTaskbarStashControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashControllerTest.kt
@@ -40,10 +40,10 @@
 import org.mockito.kotlin.verify
 import org.mockito.kotlin.whenever
 
-/** Unit tests for [PersistentTaskbarStashController]. */
+/** Unit tests for [PersistentBubbleStashController]. */
 @SmallTest
 @RunWith(AndroidJUnit4::class)
-class PersistentTaskbarStashControllerTest {
+class PersistentBubbleStashControllerTest {
 
     companion object {
         const val BUBBLE_BAR_HEIGHT = 100f
@@ -52,15 +52,17 @@
     }
 
     @get:Rule val animatorTestRule: AnimatorTestRule = AnimatorTestRule(this)
+
     @get:Rule val rule: MockitoRule = MockitoJUnit.rule()
 
     private val context = ApplicationProvider.getApplicationContext<Context>()
     private lateinit var bubbleBarView: BubbleBarView
 
     @Mock lateinit var bubbleBarViewController: BubbleBarViewController
+
     @Mock lateinit var taskbarInsetsController: TaskbarInsetsController
 
-    private lateinit var persistentTaskBarStashController: PersistentTaskbarStashController
+    private lateinit var persistentTaskBarStashController: PersistentBubbleStashController
     private lateinit var translationY: AnimatedFloat
     private lateinit var scale: AnimatedFloat
     private lateinit var alpha: MultiValueAlpha
@@ -68,7 +70,7 @@
     @Before
     fun setUp() {
         persistentTaskBarStashController =
-            PersistentTaskbarStashController(DefaultDimensionsProvider())
+            PersistentBubbleStashController(DefaultDimensionsProvider())
         setUpBubbleBarView()
         setUpBubbleBarController()
         persistentTaskBarStashController.init(
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/StashingTestUtils.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/StashingTestUtils.kt
index 5dc9440..0f8a2c3 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/StashingTestUtils.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/StashingTestUtils.kt
@@ -17,17 +17,22 @@
 package com.android.launcher3.taskbar.bubbles.stashing
 
 class ImmediateAction : BubbleStashController.ControllersAfterInitAction {
-    override fun runAfterInit(action: () -> Unit) = action.invoke()
+    override fun runAfterInit(action: Runnable) = action.run()
 }
 
-class DefaultDimensionsProvider : BubbleStashController.TaskbarHotseatDimensionsProvider {
-    override fun getTaskbarBottomSpace(): Int = TASKBAR_BOTTOM_SPACE
+class DefaultDimensionsProvider(
+    private val taskBarBottomSpace: Int = TASKBAR_BOTTOM_SPACE,
+    private val taskBarHeight: Int = TASKBAR_HEIGHT,
+    private val hotseatBottomSpace: Int = HOTSEAT_BOTTOM_SPACE,
+    private val hotseatHeight: Int = HOTSEAT_HEIGHT
+) : BubbleStashController.TaskbarHotseatDimensionsProvider {
+    override fun getTaskbarBottomSpace(): Int = taskBarBottomSpace
 
-    override fun getTaskbarHeight(): Int = TASKBAR_HEIGHT
+    override fun getTaskbarHeight(): Int = taskBarHeight
 
-    override fun getHotseatBottomSpace(): Int = HOTSEAT_BOTTOM_SPACE
+    override fun getHotseatBottomSpace(): Int = hotseatBottomSpace
 
-    override fun getHotseatHeight(): Int = HOTSEAT_HEIGHT
+    override fun getHotseatHeight(): Int = hotseatHeight
 
     companion object {
         const val TASKBAR_BOTTOM_SPACE = 0
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashControllerTest.kt
new file mode 100644
index 0000000..b5809c2
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashControllerTest.kt
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.bubbles.stashing
+
+import android.animation.AnimatorTestRule
+import android.content.Context
+import android.view.View
+import android.widget.FrameLayout
+import androidx.dynamicanimation.animation.DynamicAnimation
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import com.android.launcher3.anim.AnimatedFloat
+import com.android.launcher3.taskbar.StashedHandleView
+import com.android.launcher3.taskbar.TaskbarInsetsController
+import com.android.launcher3.taskbar.bubbles.BubbleBarView
+import com.android.launcher3.taskbar.bubbles.BubbleBarViewController
+import com.android.launcher3.taskbar.bubbles.BubbleStashedHandleViewController
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController.Companion.STASHED_BAR_SCALE
+import com.android.launcher3.util.MultiValueAlpha
+import com.android.wm.shell.shared.animation.PhysicsAnimator
+import com.android.wm.shell.shared.animation.PhysicsAnimatorTestUtils
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.kotlin.any
+import org.mockito.kotlin.atLeastOnce
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+/** Unit tests for [TransientBubbleStashController]. */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class TransientBubbleStashControllerTest {
+
+    companion object {
+        const val TASKBAR_BOTTOM_SPACE = 5
+        const val BUBBLE_BAR_HEIGHT = 100f
+        const val HOTSEAT_TRANSLATION_Y = -45f
+        const val TASK_BAR_TRANSLATION_Y = -TASKBAR_BOTTOM_SPACE
+        const val HANDLE_VIEW_HEIGHT = 4
+        const val BUBBLE_BAR_STASHED_TRANSLATION_Y = 48
+    }
+
+    @get:Rule val animatorTestRule: AnimatorTestRule = AnimatorTestRule(this)
+
+    @get:Rule val rule: MockitoRule = MockitoJUnit.rule()
+
+    @Mock lateinit var bubbleStashedHandleViewController: BubbleStashedHandleViewController
+
+    @Mock lateinit var bubbleBarViewController: BubbleBarViewController
+
+    @Mock lateinit var taskbarInsetsController: TaskbarInsetsController
+
+    private val context = ApplicationProvider.getApplicationContext<Context>()
+    private lateinit var bubbleBarView: BubbleBarView
+    private lateinit var stashedHandleView: StashedHandleView
+    private lateinit var barTranslationY: AnimatedFloat
+    private lateinit var barScale: AnimatedFloat
+    private lateinit var barAlpha: MultiValueAlpha
+    private lateinit var stashedHandleAlpha: MultiValueAlpha
+    private lateinit var stashedHandleScale: AnimatedFloat
+    private lateinit var stashedHandleTranslationY: AnimatedFloat
+    private lateinit var stashPhysicsAnimator: PhysicsAnimator<View>
+
+    private lateinit var mTransientBubbleStashController: TransientBubbleStashController
+
+    @Before
+    fun setUp() {
+        val taskbarHotseatDimensionsProvider =
+            DefaultDimensionsProvider(taskBarBottomSpace = TASKBAR_BOTTOM_SPACE)
+        mTransientBubbleStashController =
+            TransientBubbleStashController(taskbarHotseatDimensionsProvider, context.resources)
+        setUpBubbleBarView()
+        setUpBubbleBarController()
+        setUpStashedHandleView()
+        setUpBubbleStashedHandleViewController()
+        PhysicsAnimatorTestUtils.prepareForTest()
+        mTransientBubbleStashController.init(
+            taskbarInsetsController,
+            bubbleBarViewController,
+            bubbleStashedHandleViewController,
+            ImmediateAction()
+        )
+    }
+
+    @Test
+    fun setBubblesShowingOnHomeUpdatedToTrue_barPositionYUpdated_controllersNotified() {
+        // Given bubble bar is on home and has bubbles
+        whenever(bubbleBarViewController.hasBubbles()).thenReturn(true)
+
+        // When switch out of the home screen
+        getInstrumentation().runOnMainSync {
+            mTransientBubbleStashController.isBubblesShowingOnHome = true
+        }
+
+        // Then BubbleBarView is animating, BubbleBarViewController controller is notified
+        assertThat(barTranslationY.isAnimating).isTrue()
+        verify(bubbleBarViewController).onBubbleBarConfigurationChanged(/* animate= */ true)
+
+        // Wait until animation ends
+        advanceTimeBy(BubbleStashController.BAR_TRANSLATION_DURATION)
+        PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+        // Then translation Y is correct and the insets controller is notified
+        assertThat(barTranslationY.isAnimating).isFalse()
+        verify(taskbarInsetsController).onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
+        assertThat(bubbleBarView.translationY).isEqualTo(HOTSEAT_TRANSLATION_Y)
+    }
+
+    @Test
+    fun setBubblesShowingOnOverviewUpdatedToTrue_barPositionYUpdated_controllersNotified() {
+        // Given bubble bar is on home and has bubbles
+        whenever(bubbleBarViewController.hasBubbles()).thenReturn(true)
+
+        // When switch out of the home screen
+        getInstrumentation().runOnMainSync {
+            mTransientBubbleStashController.isBubblesShowingOnOverview = true
+        }
+
+        // Then BubbleBarView is animating, BubbleBarViewController controller is notified
+        assertThat(barTranslationY.isAnimating).isTrue()
+        verify(bubbleBarViewController).onBubbleBarConfigurationChanged(/* animate= */ true)
+
+        // Wait until animation ends
+        advanceTimeBy(BubbleStashController.BAR_TRANSLATION_DURATION)
+        PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+        // Then translation Y is correct and the insets controller is notified
+        assertThat(barTranslationY.isAnimating).isFalse()
+        verify(taskbarInsetsController).onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
+        assertThat(bubbleBarView.translationY).isEqualTo(TASK_BAR_TRANSLATION_Y)
+    }
+
+    @Test
+    fun updateStashedAndExpandedState_stashAndCollapse_bubbleBarHidden_stashedHandleShown() {
+        // Given bubble bar has bubbles and not stashed
+        mTransientBubbleStashController.isStashed = false
+        whenever(bubbleBarViewController.isHiddenForNoBubbles).thenReturn(false)
+
+        // When stash
+        getInstrumentation().runOnMainSync {
+            mTransientBubbleStashController.updateStashedAndExpandedState(
+                stash = true,
+                expand = false
+            )
+        }
+
+        // Wait until animations ends
+        advanceTimeBy(BubbleStashController.BAR_STASH_DURATION)
+        PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+
+        // Then check BubbleBarController is notified
+        verify(bubbleBarViewController).onStashStateChanging()
+        // Bubble bar is stashed
+        assertThat(mTransientBubbleStashController.isStashed).isTrue()
+        assertThat(bubbleBarView.translationY).isEqualTo(BUBBLE_BAR_STASHED_TRANSLATION_Y)
+        assertThat(bubbleBarView.alpha).isEqualTo(0f)
+        assertThat(bubbleBarView.scaleX).isEqualTo(STASHED_BAR_SCALE)
+        assertThat(bubbleBarView.scaleY).isEqualTo(STASHED_BAR_SCALE)
+        // Handle view is visible
+        assertThat(stashedHandleView.translationY).isEqualTo(0)
+        assertThat(stashedHandleView.alpha).isEqualTo(1)
+    }
+
+    @Test
+    fun isSysuiLockedSwitchedToFalseForOverview_unlockAnimationIsShown() {
+        // Given screen is locked and bubble bar has bubbles
+        getInstrumentation().runOnMainSync {
+            mTransientBubbleStashController.isSysuiLocked = true
+            mTransientBubbleStashController.isBubblesShowingOnOverview = true
+            whenever(bubbleBarViewController.hasBubbles()).thenReturn(true)
+        }
+        advanceTimeBy(BubbleStashController.BAR_TRANSLATION_DURATION)
+
+        // When switch to the overview screen
+        getInstrumentation().runOnMainSync { mTransientBubbleStashController.isSysuiLocked = false }
+
+        // Then
+        assertThat(barTranslationY.isAnimating).isTrue()
+        assertThat(barScale.isAnimating).isTrue()
+        // Wait until animation ends
+        advanceTimeBy(BubbleStashController.BAR_STASH_DURATION)
+
+        // Then bubble bar is fully visible at the correct location
+        assertThat(bubbleBarView.scaleX).isEqualTo(1f)
+        assertThat(bubbleBarView.scaleY).isEqualTo(1f)
+        assertThat(bubbleBarView.translationY)
+            .isEqualTo(PersistentBubbleStashControllerTest.TASK_BAR_TRANSLATION_Y)
+        assertThat(bubbleBarView.alpha).isEqualTo(1f)
+        // Insets controller is notified
+        verify(taskbarInsetsController, atLeastOnce())
+            .onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
+    }
+
+    @Test
+    fun showBubbleBarImmediateToY() {
+        // Given bubble bar is fully transparent and scaled to 0 at 0 y position
+        val targetY = 341f
+        bubbleBarView.alpha = 0f
+        bubbleBarView.scaleX = 0f
+        bubbleBarView.scaleY = 0f
+        bubbleBarView.translationY = 0f
+        stashedHandleView.translationY = targetY
+
+        // When
+        mTransientBubbleStashController.showBubbleBarImmediate(targetY)
+
+        // Then all property values are updated
+        assertThat(bubbleBarView.translationY).isEqualTo(targetY)
+        assertThat(bubbleBarView.alpha).isEqualTo(1f)
+        assertThat(bubbleBarView.scaleX).isEqualTo(1f)
+        assertThat(bubbleBarView.scaleY).isEqualTo(1f)
+        // Handle is transparent
+        assertThat(stashedHandleView.alpha).isEqualTo(0)
+        // Insets controller is notified
+        verify(taskbarInsetsController).onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
+    }
+
+    @Test
+    fun stashBubbleBarImmediate() {
+        // When
+        mTransientBubbleStashController.stashBubbleBarImmediate()
+
+        // Then all property values are updated
+        assertThat(bubbleBarView.translationY).isEqualTo(BUBBLE_BAR_STASHED_TRANSLATION_Y)
+        assertThat(bubbleBarView.alpha).isEqualTo(0)
+        assertThat(bubbleBarView.scaleX).isEqualTo(STASHED_BAR_SCALE)
+        assertThat(bubbleBarView.scaleY).isEqualTo(STASHED_BAR_SCALE)
+        // Handle is visible at correct Y position
+        assertThat(stashedHandleView.alpha).isEqualTo(1)
+        assertThat(stashedHandleView.translationY).isEqualTo(0)
+        // Insets controller is notified
+        verify(taskbarInsetsController).onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
+    }
+
+    @Test
+    fun getTouchableHeight_stashed_stashHeightReturned() {
+        // When
+        mTransientBubbleStashController.isStashed = true
+        val height = mTransientBubbleStashController.getTouchableHeight()
+
+        // Then
+        assertThat(height).isEqualTo(HANDLE_VIEW_HEIGHT)
+    }
+
+    @Test
+    fun getTouchableHeight_unstashed_barHeightReturned() {
+        // When BubbleBar is not stashed
+        mTransientBubbleStashController.isStashed = false
+        val height = mTransientBubbleStashController.getTouchableHeight()
+
+        // Then bubble bar height is returned
+        assertThat(height).isEqualTo(BUBBLE_BAR_HEIGHT.toInt())
+    }
+
+    private fun advanceTimeBy(advanceMs: Long) {
+        // Advance animator for on-device tests
+        getInstrumentation().runOnMainSync { animatorTestRule.advanceTimeBy(advanceMs) }
+    }
+
+    private fun setUpBubbleBarView() {
+        getInstrumentation().runOnMainSync {
+            bubbleBarView = BubbleBarView(context)
+            bubbleBarView.layoutParams = FrameLayout.LayoutParams(0, 0)
+        }
+    }
+
+    private fun setUpStashedHandleView() {
+        getInstrumentation().runOnMainSync {
+            stashedHandleView = StashedHandleView(context)
+            stashedHandleView.layoutParams = FrameLayout.LayoutParams(0, 0)
+        }
+    }
+
+    private fun setUpBubbleBarController() {
+        barTranslationY =
+            AnimatedFloat(Runnable { bubbleBarView.translationY = barTranslationY.value })
+        barScale =
+            AnimatedFloat(
+                Runnable {
+                    val scale: Float = barScale.value
+                    bubbleBarView.scaleX = scale
+                    bubbleBarView.scaleY = scale
+                }
+            )
+        barAlpha = MultiValueAlpha(bubbleBarView, 1 /* num alpha channels */)
+
+        whenever(bubbleBarViewController.hasBubbles()).thenReturn(true)
+        whenever(bubbleBarViewController.bubbleBarTranslationY).thenReturn(barTranslationY)
+        whenever(bubbleBarViewController.bubbleBarScale).thenReturn(barScale)
+        whenever(bubbleBarViewController.bubbleBarAlpha).thenReturn(barAlpha)
+        whenever(bubbleBarViewController.bubbleBarCollapsedHeight).thenReturn(BUBBLE_BAR_HEIGHT)
+    }
+
+    private fun setUpBubbleStashedHandleViewController() {
+        stashedHandleTranslationY =
+            AnimatedFloat(Runnable { stashedHandleView.translationY = barTranslationY.value })
+        stashedHandleScale =
+            AnimatedFloat(
+                Runnable {
+                    val scale: Float = barScale.value
+                    bubbleBarView.scaleX = scale
+                    bubbleBarView.scaleY = scale
+                }
+            )
+        stashedHandleAlpha = MultiValueAlpha(stashedHandleView, 1 /* num alpha channels */)
+        stashPhysicsAnimator = PhysicsAnimator.getInstance(stashedHandleView)
+        whenever(bubbleStashedHandleViewController.stashedHandleAlpha)
+            .thenReturn(stashedHandleAlpha)
+        whenever(bubbleStashedHandleViewController.physicsAnimator).thenReturn(stashPhysicsAnimator)
+        whenever(bubbleStashedHandleViewController.stashedHeight).thenReturn(HANDLE_VIEW_HEIGHT)
+        whenever(bubbleStashedHandleViewController.setTranslationYForSwipe(any())).thenAnswer {
+            invocation ->
+            (invocation.arguments[0] as Float).also { stashedHandleView.translationY = it }
+        }
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayControllerTest.kt
index f946d4d..4fa821d 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayControllerTest.kt
@@ -25,6 +25,7 @@
 import com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_OVERLAY_PROXY
 import com.android.launcher3.AbstractFloatingView.hasOpenView
 import com.android.launcher3.taskbar.TaskbarActivityContext
+import com.android.launcher3.taskbar.TaskbarControllerTestUtil.runOnMainSync
 import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule
 import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule.InjectController
 import com.android.launcher3.taskbar.rules.TaskbarWindowSandboxContext
@@ -64,7 +65,7 @@
     @Test
     fun testRequestWindow_afterHidingExistingWindow_createsNewWindow() {
         val context1 = getOnUiThread { overlayController.requestWindow() }
-        getInstrumentation().runOnMainSync { overlayController.hideWindow() }
+        runOnMainSync { overlayController.hideWindow() }
 
         val context2 = getOnUiThread { overlayController.requestWindow() }
         assertThat(context1).isNotSameInstanceAs(context2)
@@ -73,7 +74,7 @@
     @Test
     fun testRequestWindow_afterHidingOverlay_createsNewWindow() {
         val context1 = getOnUiThread { overlayController.requestWindow() }
-        getInstrumentation().runOnMainSync {
+        runOnMainSync {
             TestOverlayView.show(context1)
             overlayController.hideWindow()
         }
@@ -84,16 +85,14 @@
 
     @Test
     fun testRequestWindow_addsProxyView() {
-        getInstrumentation().runOnMainSync {
-            TestOverlayView.show(overlayController.requestWindow())
-        }
+        runOnMainSync { TestOverlayView.show(overlayController.requestWindow()) }
         assertThat(hasOpenView(taskbarContext, TYPE_TASKBAR_OVERLAY_PROXY)).isTrue()
     }
 
     @Test
     fun testRequestWindow_closeProxyView_closesOverlay() {
         val overlay = getOnUiThread { TestOverlayView.show(overlayController.requestWindow()) }
-        getInstrumentation().runOnMainSync {
+        runOnMainSync {
             AbstractFloatingView.closeOpenContainer(taskbarContext, TYPE_TASKBAR_OVERLAY_PROXY)
         }
         assertThat(overlay.isOpen).isFalse()
@@ -103,13 +102,13 @@
     fun testRequestWindow_attachesDragLayer() {
         val dragLayer = getOnUiThread { overlayController.requestWindow().dragLayer }
         // Allow drag layer to attach before checking.
-        getInstrumentation().runOnMainSync { assertThat(dragLayer.isAttachedToWindow).isTrue() }
+        runOnMainSync { assertThat(dragLayer.isAttachedToWindow).isTrue() }
     }
 
     @Test
     fun testHideWindow_closesOverlay() {
         val overlay = getOnUiThread { TestOverlayView.show(overlayController.requestWindow()) }
-        getInstrumentation().runOnMainSync { overlayController.hideWindow() }
+        runOnMainSync { overlayController.hideWindow() }
         assertThat(overlay.isOpen).isFalse()
     }
 
@@ -118,7 +117,7 @@
         val dragLayer = getOnUiThread { overlayController.requestWindow().dragLayer }
 
         // Wait for drag layer to be attached to window before hiding.
-        getInstrumentation().runOnMainSync {
+        runOnMainSync {
             overlayController.hideWindow()
             assertThat(dragLayer.isAttachedToWindow).isFalse()
         }
@@ -132,7 +131,7 @@
                 Pair(TestOverlayView.show(context), TestOverlayView.show(context))
             }
 
-        getInstrumentation().runOnMainSync { overlay1.close(false) }
+        runOnMainSync { overlay1.close(false) }
         assertThat(overlay2.isOpen).isTrue()
         assertThat(hasOpenView(taskbarContext, TYPE_TASKBAR_OVERLAY_PROXY)).isTrue()
     }
@@ -145,7 +144,7 @@
                 Pair(TestOverlayView.show(context), TestOverlayView.show(context))
             }
 
-        getInstrumentation().runOnMainSync {
+        runOnMainSync {
             overlay1.close(false)
             overlay2.close(false)
         }
@@ -154,9 +153,7 @@
 
     @Test
     fun testRecreateTaskbar_closesWindow() {
-        getInstrumentation().runOnMainSync {
-            TestOverlayView.show(overlayController.requestWindow())
-        }
+        runOnMainSync { TestOverlayView.show(overlayController.requestWindow()) }
         taskbarUnitTestRule.recreateTaskbar()
         assertThat(hasOpenView(taskbarContext, TYPE_TASKBAR_OVERLAY_PROXY)).isFalse()
     }
@@ -166,29 +163,25 @@
         val overlay = getOnUiThread { TestOverlayView.show(overlayController.requestWindow()) }
         TaskStackChangeListeners.getInstance().listenerImpl.onTaskMovedToFront(RunningTaskInfo())
         // Make sure TaskStackChangeListeners' Handler posts the callback before checking state.
-        getInstrumentation().runOnMainSync { assertThat(overlay.isOpen).isFalse() }
+        runOnMainSync { assertThat(overlay.isOpen).isFalse() }
     }
 
     @Test
     fun testTaskStackChanged_allAppsClosed_overlayStaysOpen() {
         val overlay = getOnUiThread { TestOverlayView.show(overlayController.requestWindow()) }
-        getInstrumentation().runOnMainSync {
-            taskbarContext.controllers.sharedState?.allAppsVisible = false
-        }
+        runOnMainSync { taskbarContext.controllers.sharedState?.allAppsVisible = false }
 
         TaskStackChangeListeners.getInstance().listenerImpl.onTaskStackChanged()
-        getInstrumentation().runOnMainSync { assertThat(overlay.isOpen).isTrue() }
+        runOnMainSync { assertThat(overlay.isOpen).isTrue() }
     }
 
     @Test
     fun testTaskStackChanged_allAppsOpen_closesOverlay() {
         val overlay = getOnUiThread { TestOverlayView.show(overlayController.requestWindow()) }
-        getInstrumentation().runOnMainSync {
-            taskbarContext.controllers.sharedState?.allAppsVisible = true
-        }
+        runOnMainSync { taskbarContext.controllers.sharedState?.allAppsVisible = true }
 
         TaskStackChangeListeners.getInstance().listenerImpl.onTaskStackChanged()
-        getInstrumentation().runOnMainSync { assertThat(overlay.isOpen).isFalse() }
+        runOnMainSync { assertThat(overlay.isOpen).isFalse() }
     }
 
     @Test
@@ -198,7 +191,7 @@
             TestOverlayView.show(context).apply { type = TYPE_OPTIONS_POPUP }
         }
 
-        getInstrumentation().runOnMainSync {
+        runOnMainSync {
             overlayController.updateLauncherDeviceProfile(
                 overlayController.launcherDeviceProfile
                     .toBuilder(context)
@@ -217,7 +210,7 @@
             TestOverlayView.show(context).apply { type = TYPE_TASKBAR_ALL_APPS }
         }
 
-        getInstrumentation().runOnMainSync {
+        runOnMainSync {
             overlayController.updateLauncherDeviceProfile(
                 overlayController.launcherDeviceProfile
                     .toBuilder(context)
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/MultiStateCallbackTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/MultiStateCallbackTest.java
new file mode 100644
index 0000000..0ff142a
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/MultiStateCallbackTest.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.launcher3.util.LauncherMultivalentJUnit;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.function.Consumer;
+
+@SmallTest
+@RunWith(LauncherMultivalentJUnit.class)
+public class MultiStateCallbackTest {
+
+    private int mFlagCount = 0;
+    private int getNextStateFlag() {
+        int index = 1 << mFlagCount;
+        mFlagCount++;
+        return index;
+    }
+
+    private final MultiStateCallback mMultiStateCallback = new MultiStateCallback(new String[0]);
+    private final Runnable mCallback = spy(new Runnable() {
+        @Override
+        public void run() {}
+    });
+    private final Consumer<Boolean> mListener = spy(new Consumer<Boolean>() {
+        @Override
+        public void accept(Boolean isOn) {}
+    });
+
+    @Test
+    public void testSetState_trackedProperly() {
+        int watchedAnime = getNextStateFlag();
+
+        assertThat(mMultiStateCallback.getState()).isEqualTo(0);
+        assertThat(mMultiStateCallback.hasStates(watchedAnime)).isFalse();
+
+        mMultiStateCallback.setState(watchedAnime);
+
+        assertThat(mMultiStateCallback.getState()).isEqualTo(watchedAnime);
+        assertThat(mMultiStateCallback.hasStates(watchedAnime)).isTrue();
+    }
+
+    @Test
+    public void testSetState_withMultipleStates_trackedProperly() {
+        int watchedAnime = getNextStateFlag();
+        int sharedMemes = getNextStateFlag();
+
+        mMultiStateCallback.setState(watchedAnime);
+        mMultiStateCallback.setState(sharedMemes);
+
+        assertThat(mMultiStateCallback.getState()).isEqualTo(watchedAnime | sharedMemes);
+        assertThat(mMultiStateCallback.hasStates(watchedAnime)).isTrue();
+        assertThat(mMultiStateCallback.hasStates(sharedMemes)).isTrue();
+        assertThat(mMultiStateCallback.hasStates(watchedAnime | sharedMemes)).isTrue();
+    }
+
+    @Test
+    public void testClearState_trackedProperly() {
+        int lovedAnime = getNextStateFlag();
+
+        mMultiStateCallback.setState(lovedAnime);
+        mMultiStateCallback.clearState(lovedAnime);
+
+        assertThat(mMultiStateCallback.getState()).isEqualTo(0);
+        assertThat(mMultiStateCallback.hasStates(lovedAnime)).isFalse();
+    }
+
+    @Test
+    public void testClearState_withMultipleState_trackedProperly() {
+        int lovedAnime = getNextStateFlag();
+        int talkedAboutAnime = getNextStateFlag();
+
+        mMultiStateCallback.setState(lovedAnime);
+        mMultiStateCallback.setState(talkedAboutAnime);
+        mMultiStateCallback.clearState(talkedAboutAnime);
+
+        assertThat(mMultiStateCallback.getState()).isEqualTo(lovedAnime);
+        assertThat(mMultiStateCallback.hasStates(lovedAnime)).isTrue();
+        assertThat(mMultiStateCallback.hasStates(talkedAboutAnime)).isFalse();
+        assertThat(mMultiStateCallback.hasStates(lovedAnime | talkedAboutAnime)).isFalse();
+    }
+
+    @Test
+    public void testCallbackDoesNotRun_withoutState() {
+        int watchedOnePiece = getNextStateFlag();
+
+        mMultiStateCallback.runOnceAtState(watchedOnePiece, mCallback);
+
+        verify(mCallback, never()).run();
+    }
+
+    @Test
+    public void testCallbackDoesNotRun_whenNotTracked() {
+        int watchedJujutsuKaisen = getNextStateFlag();
+
+        mMultiStateCallback.setState(watchedJujutsuKaisen);
+
+        verify(mCallback, never()).run();
+    }
+
+    @Test
+    public void testCallbackRuns_afterTrackedAndStateSet() {
+        int watchedHunterXHunter = getNextStateFlag();
+
+        mMultiStateCallback.runOnceAtState(watchedHunterXHunter, mCallback);
+        mMultiStateCallback.setState(watchedHunterXHunter);
+
+        verify(mCallback, times(1)).run();
+    }
+
+    @Test
+    public void testCallbackRuns_onUiThread() {
+        int watchedHunterXHunter = getNextStateFlag();
+
+        mMultiStateCallback.runOnceAtState(watchedHunterXHunter, mCallback);
+        mMultiStateCallback.setStateOnUiThread(watchedHunterXHunter);
+
+        runOnMainSync(() -> verify(mCallback, times(1)).run());
+    }
+
+    @Test
+    public void testCallbackRuns_agnosticallyToCallOrder() {
+        int watchedFullMetalAlchemist = getNextStateFlag();
+
+        mMultiStateCallback.setState(watchedFullMetalAlchemist);
+        mMultiStateCallback.runOnceAtState(watchedFullMetalAlchemist, mCallback);
+
+        verify(mCallback, times(1)).run();
+    }
+
+    @Test
+    public void testCallbackRuns_onlyOnceAfterStateSet() {
+        int watchedBleach = getNextStateFlag();
+
+        mMultiStateCallback.runOnceAtState(watchedBleach, mCallback);
+        mMultiStateCallback.setState(watchedBleach);
+        mMultiStateCallback.setState(watchedBleach);
+
+        verify(mCallback, times(1)).run();
+    }
+
+    @Test
+    public void testCallbackRuns_onlyOnceAfterClearState() {
+        int rememberedGreatShow = getNextStateFlag();
+
+        mMultiStateCallback.runOnceAtState(rememberedGreatShow, mCallback);
+        mMultiStateCallback.setState(rememberedGreatShow);
+        mMultiStateCallback.clearState(rememberedGreatShow);
+        mMultiStateCallback.setState(rememberedGreatShow);
+
+        verify(mCallback, times(1)).run();
+    }
+
+    @Test
+    public void testCallbackDoesNotRun_withoutFullStateSet() {
+        int watchedMobPsycho = getNextStateFlag();
+        int watchedVinlandSaga = getNextStateFlag();
+
+        mMultiStateCallback.runOnceAtState(watchedMobPsycho | watchedVinlandSaga, mCallback);
+        mMultiStateCallback.setState(watchedMobPsycho);
+
+        verify(mCallback, times(0)).run();
+    }
+
+    @Test
+    public void testCallbackRuns_withFullStateSet_agnosticallyToCallOrder() {
+        int watchedReZero = getNextStateFlag();
+        int watchedJojosBizareAdventure = getNextStateFlag();
+
+        mMultiStateCallback.setState(watchedJojosBizareAdventure);
+        mMultiStateCallback.runOnceAtState(watchedReZero | watchedJojosBizareAdventure, mCallback);
+        mMultiStateCallback.setState(watchedReZero);
+
+        verify(mCallback, times(1)).run();
+    }
+
+    @Test
+    public void testCallbackRuns_withFullStateSet_asIntegerMask() {
+        int watchedPokemon = getNextStateFlag();
+        int watchedDigimon = getNextStateFlag();
+
+        mMultiStateCallback.runOnceAtState(watchedPokemon | watchedDigimon, mCallback);
+        mMultiStateCallback.setState(watchedPokemon | watchedDigimon);
+
+        verify(mCallback, times(1)).run();
+    }
+
+    @Test
+    public void testCallbackDoesNotRun_afterClearState() {
+        int watchedMonster = getNextStateFlag();
+        int watchedPingPong = getNextStateFlag();
+
+        mMultiStateCallback.runOnceAtState(watchedMonster | watchedPingPong, mCallback);
+        mMultiStateCallback.setState(watchedMonster);
+        mMultiStateCallback.clearState(watchedMonster);
+        mMultiStateCallback.setState(watchedPingPong);
+
+        verify(mCallback, times(0)).run();
+    }
+
+    @Test
+    public void testlistenerRuns_multipleTimes() {
+        int watchedSteinsGate = getNextStateFlag();
+
+        mMultiStateCallback.addChangeListener(watchedSteinsGate, mListener);
+        mMultiStateCallback.setState(watchedSteinsGate);
+
+        // Called exactly one
+        verify(mListener, times(1)).accept(anyBoolean());
+        // Called exactly once with isOn = true
+        verify(mListener, times(1)).accept(eq(true));
+        // Never called with isOn = false
+        verify(mListener, times(0)).accept(eq(false));
+
+        mMultiStateCallback.clearState(watchedSteinsGate);
+
+        // Called exactly twice
+        verify(mListener, times(2)).accept(anyBoolean());
+        // Called exactly once with isOn = true
+        verify(mListener, times(1)).accept(eq(true));
+        // Called exactly once with isOn = false
+        verify(mListener, times(1)).accept(eq(false));
+    }
+
+    @Test
+    public void testlistenerDoesNotRun_forUnchangedState() {
+        int watchedSteinsGate = getNextStateFlag();
+
+        mMultiStateCallback.addChangeListener(watchedSteinsGate, mListener);
+        mMultiStateCallback.setState(watchedSteinsGate);
+        mMultiStateCallback.setState(watchedSteinsGate);
+
+        // State remained unchanged
+        verify(mListener, times(1)).accept(anyBoolean());
+        // Called exactly once with isOn = true
+        verify(mListener, times(1)).accept(eq(true));
+    }
+
+    private static void runOnMainSync(Runnable runnable) {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(runnable);
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java
index 679a208..80b9489 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java
@@ -24,6 +24,8 @@
 
 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
 
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertFalse;
@@ -45,13 +47,16 @@
 
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
+import com.android.quickstep.DeviceConfigWrapper;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.InputConsumer;
 import com.android.quickstep.NavHandle;
 import com.android.quickstep.RecentsAnimationDeviceState;
 import com.android.quickstep.TopTaskTracker;
+import com.android.quickstep.util.TestExtensions;
 import com.android.systemui.shared.system.InputMonitorCompat;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -68,7 +73,9 @@
     private static final float SQUARED_TOUCH_SLOP = 100;
 
     private final AtomicBoolean mLongPressTriggered = new AtomicBoolean();
+    private final Runnable mLongPressRunnable = () -> mLongPressTriggered.set(true);
     private NavHandleLongPressInputConsumer mUnderTest;
+    private SandboxContext mContext;
     private float mScreenWidth;
     @Mock InputConsumer mDelegate;
     @Mock InputMonitorCompat mInputMonitor;
@@ -85,15 +92,15 @@
         when(mTopTaskTracker.getCachedTopTask(anyBoolean())).thenReturn(mTaskInfo);
         when(mDeviceState.getSquaredTouchSlop()).thenReturn(SQUARED_TOUCH_SLOP);
         when(mDelegate.allowInterceptByParent()).thenReturn(true);
+        MAIN_EXECUTOR.getHandler().removeCallbacks(mLongPressRunnable);
         mLongPressTriggered.set(false);
-        when(mNavHandleLongPressHandler.getLongPressRunnable(any())).thenReturn(
-                () -> mLongPressTriggered.set(true));
-        SandboxContext context = new SandboxContext(getApplicationContext());
-        context.putObject(TopTaskTracker.INSTANCE, mTopTaskTracker);
-        mScreenWidth = DisplayController.INSTANCE.get(context).getInfo().currentSize.x;
-        mUnderTest = new NavHandleLongPressInputConsumer(context, mDelegate, mInputMonitor,
-                mDeviceState, mNavHandle, mGestureState);
-        mUnderTest.setNavHandleLongPressHandler(mNavHandleLongPressHandler);
+        when(mNavHandleLongPressHandler.getLongPressRunnable(any())).thenReturn(mLongPressRunnable);
+        initializeObjectUnderTest();
+    }
+
+    @After
+    public void tearDown() {
+        mContext.onDestroy();
     }
 
     @Test
@@ -173,6 +180,60 @@
     }
 
     @Test
+    public void testLongPressTriggeredWithExtendedTwoStageDuration() {
+        try (AutoCloseable flag = overrideTwoStageFlag(true)) {
+            // Reinitialize to pick up updated flag state.
+            initializeObjectUnderTest();
+
+            mUnderTest.onMotionEvent(generateCenteredMotionEvent(ACTION_DOWN));
+            mUnderTest.onMotionEvent(generateMotionEvent(ACTION_MOVE,
+                    mScreenWidth / 2f - (TOUCH_SLOP - 1), 0));
+            // We have entered the second stage, so the normal timeout shouldn't trigger.
+            SystemClock.sleep(ViewConfiguration.getLongPressTimeout());
+            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+            assertThat(mUnderTest.mState).isEqualTo(DelegateInputConsumer.STATE_INACTIVE);
+            assertFalse(mLongPressTriggered.get());
+            verify(mNavHandleLongPressHandler, times(1)).onTouchStarted(any());
+            verify(mNavHandleLongPressHandler, never()).onTouchFinished(any(), any());
+
+            // After an extended time, the long press should trigger.
+            float extendedDurationMultiplier =
+                    (DeviceConfigWrapper.get().getTwoStageDurationPercentage() / 100f);
+            SystemClock.sleep((long) (ViewConfiguration.getLongPressTimeout()
+                    * (extendedDurationMultiplier - 1)));  // -1 because we already waited 1x
+            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+            assertThat(mUnderTest.mState).isEqualTo(DelegateInputConsumer.STATE_ACTIVE);
+            assertTrue(mLongPressTriggered.get());
+            verify(mNavHandleLongPressHandler, times(1)).onTouchStarted(any());
+            verify(mNavHandleLongPressHandler, never()).onTouchFinished(any(), any());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
+    public void testLongPressTriggeredWithNormalDurationInFirstStage() {
+        try (AutoCloseable flag = overrideTwoStageFlag(true)) {
+            // Reinitialize to pick up updated flag state.
+            initializeObjectUnderTest();
+
+            mUnderTest.onMotionEvent(generateCenteredMotionEvent(ACTION_DOWN));
+            // We have not entered the second stage, so the normal timeout should trigger.
+            SystemClock.sleep(ViewConfiguration.getLongPressTimeout());
+            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+            assertThat(mUnderTest.mState).isEqualTo(DelegateInputConsumer.STATE_ACTIVE);
+            assertTrue(mLongPressTriggered.get());
+            verify(mNavHandleLongPressHandler, times(1)).onTouchStarted(any());
+            verify(mNavHandleLongPressHandler, never()).onTouchFinished(any(), any());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
     public void testLongPressAbortedByTouchUp() {
         mUnderTest.onMotionEvent(generateCenteredMotionEvent(ACTION_DOWN));
         SystemClock.sleep(ViewConfiguration.getLongPressTimeout() - 10);
@@ -255,6 +316,80 @@
     }
 
     @Test
+    public void testLongPressAbortedByTouchSlopPassedVertically_twoStageEnabled() {
+        try (AutoCloseable flag = overrideTwoStageFlag(true)) {
+            // Reinitialize to pick up updated flag state.
+            initializeObjectUnderTest();
+
+            mUnderTest.onMotionEvent(generateCenteredMotionEvent(ACTION_DOWN));
+            // Enter the second stage.
+            mUnderTest.onMotionEvent(generateCenteredMotionEventWithYOffset(ACTION_MOVE,
+                    -(TOUCH_SLOP - 1)));
+            // Normal duration shouldn't trigger.
+            SystemClock.sleep(ViewConfiguration.getLongPressTimeout());
+            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+            assertThat(mUnderTest.mState).isEqualTo(DelegateInputConsumer.STATE_INACTIVE);
+            assertFalse(mLongPressTriggered.get());
+
+            // Move out of the second stage.
+            mUnderTest.onMotionEvent(generateCenteredMotionEventWithYOffset(ACTION_MOVE,
+                    -(TOUCH_SLOP + 1)));
+            // Wait past the extended long press timeout, to be sure it wouldn't have triggered.
+            float extendedDurationMultiplier =
+                    (DeviceConfigWrapper.get().getTwoStageDurationPercentage() / 100f);
+            SystemClock.sleep((long) (ViewConfiguration.getLongPressTimeout()
+                    * (extendedDurationMultiplier - 1)));  // -1 because we already waited 1x
+            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+            assertThat(mUnderTest.mState).isEqualTo(DelegateInputConsumer.STATE_INACTIVE);
+            assertFalse(mLongPressTriggered.get());
+            verify(mNavHandleLongPressHandler, times(1)).onTouchStarted(any());
+            // Touch cancelled.
+            verify(mNavHandleLongPressHandler, times(1)).onTouchFinished(any(), any());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
+    public void testLongPressAbortedByTouchSlopPassedHorizontally_twoStageEnabled() {
+        try (AutoCloseable flag = overrideTwoStageFlag(true)) {
+            // Reinitialize to pick up updated flag state.
+            initializeObjectUnderTest();
+
+            mUnderTest.onMotionEvent(generateCenteredMotionEvent(ACTION_DOWN));
+            // Enter the second stage.
+            mUnderTest.onMotionEvent(generateMotionEvent(ACTION_MOVE,
+                    mScreenWidth / 2f - (TOUCH_SLOP - 1), 0));
+            // Normal duration shouldn't trigger.
+            SystemClock.sleep(ViewConfiguration.getLongPressTimeout());
+            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+            assertThat(mUnderTest.mState).isEqualTo(DelegateInputConsumer.STATE_INACTIVE);
+            assertFalse(mLongPressTriggered.get());
+
+            // Move out of the second stage.
+            mUnderTest.onMotionEvent(generateMotionEvent(ACTION_MOVE,
+                    mScreenWidth / 2f - (TOUCH_SLOP + 1), 0));
+            // Wait past the extended long press timeout, to be sure it wouldn't have triggered.
+            float extendedDurationMultiplier =
+                    (DeviceConfigWrapper.get().getTwoStageDurationPercentage() / 100f);
+            SystemClock.sleep((long) (ViewConfiguration.getLongPressTimeout()
+                    * (extendedDurationMultiplier - 1)));  // -1 because we already waited 1x
+            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+            assertThat(mUnderTest.mState).isEqualTo(DelegateInputConsumer.STATE_INACTIVE);
+            assertFalse(mLongPressTriggered.get());
+            verify(mNavHandleLongPressHandler, times(1)).onTouchStarted(any());
+            // Touch cancelled.
+            verify(mNavHandleLongPressHandler, times(1)).onTouchFinished(any(), any());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
     public void testTouchOutsideNavHandleIgnored() {
         // Touch the far left side of the screen. (y=0 is top of navbar region, picked arbitrarily)
         mUnderTest.onMotionEvent(generateMotionEvent(ACTION_DOWN, 0, 0));
@@ -282,6 +417,18 @@
         verify(mDelegate, times(2)).onHoverEvent(any());
     }
 
+    private void initializeObjectUnderTest() {
+        if (mContext != null) {
+            mContext.onDestroy();
+        }
+        mContext = new SandboxContext(getApplicationContext());
+        mContext.putObject(TopTaskTracker.INSTANCE, mTopTaskTracker);
+        mScreenWidth = DisplayController.INSTANCE.get(mContext).getInfo().currentSize.x;
+        mUnderTest = new NavHandleLongPressInputConsumer(mContext, mDelegate, mInputMonitor,
+                mDeviceState, mNavHandle, mGestureState);
+        mUnderTest.setNavHandleLongPressHandler(mNavHandleLongPressHandler);
+    }
+
     /** Generate a motion event centered horizontally in the screen. */
     private MotionEvent generateCenteredMotionEvent(int motionAction) {
         return generateCenteredMotionEventWithYOffset(motionAction, 0);
@@ -295,4 +442,11 @@
     private static MotionEvent generateMotionEvent(int motionAction, float x, float y) {
         return MotionEvent.obtain(0, 0, motionAction, x, y, 0);
     }
+
+    private static AutoCloseable overrideTwoStageFlag(boolean value) {
+        return TestExtensions.overrideNavConfigFlag(
+                "ENABLE_LPNH_TWO_STAGES",
+                value,
+                () -> DeviceConfigWrapper.get().getEnableLpnhTwoStages());
+    }
 }
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeRecentsDeviceProfileRepository.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeRecentsDeviceProfileRepository.kt
new file mode 100644
index 0000000..cdfbd16
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeRecentsDeviceProfileRepository.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 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.recents.data
+
+class FakeRecentsDeviceProfileRepository : RecentsDeviceProfileRepository {
+    private var recentsDeviceProfile =
+        RecentsDeviceProfile(
+            isLargeScreen = false,
+            widthPx = 1080,
+            heightPx = 1920,
+        )
+
+    override fun getRecentsDeviceProfile() = recentsDeviceProfile
+
+    fun setRecentsDeviceProfile(newValue: RecentsDeviceProfile) {
+        recentsDeviceProfile = newValue
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeRecentsRotationStateRepository.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeRecentsRotationStateRepository.kt
new file mode 100644
index 0000000..c328672
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeRecentsRotationStateRepository.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 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.recents.data
+
+import android.view.Surface
+
+class FakeRecentsRotationStateRepository : RecentsRotationStateRepository {
+    private var recentsRotationState =
+        RecentsRotationState(
+            activityRotation = Surface.ROTATION_0,
+            orientationHandlerRotation = Surface.ROTATION_0
+        )
+
+    override fun getRecentsRotationState() = recentsRotationState
+
+    fun setRecentsRotationState(newValue: RecentsRotationState) {
+        recentsRotationState = newValue
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTaskIconDataSource.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTaskIconDataSource.kt
index 242bc73..fee4979 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTaskIconDataSource.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTaskIconDataSource.kt
@@ -23,10 +23,12 @@
 import com.android.systemui.shared.recents.model.Task
 import com.google.common.truth.Truth.assertThat
 import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
 
 class FakeTaskIconDataSource : TaskIconDataSource {
 
-    val taskIdToDrawable: Map<Int, Drawable> = (0..10).associateWith { mock() }
+    val taskIdToDrawable: Map<Int, Drawable> = (0..10).associateWith { mockCopyableDrawable() }
+
     val taskIdToUpdatingTask: MutableMap<Int, () -> Unit> = mutableMapOf()
     var shouldLoadSynchronously: Boolean = true
 
@@ -49,6 +51,17 @@
         }
         return null
     }
+
+    private fun mockCopyableDrawable(): Drawable {
+        val mutableDrawable = mock<Drawable>()
+        val immutableDrawable =
+            mock<Drawable>().apply { whenever(mutate()).thenReturn(mutableDrawable) }
+        val constantState =
+            mock<Drawable.ConstantState>().apply {
+                whenever(newDrawable()).thenReturn(immutableDrawable)
+            }
+        return mutableDrawable.apply { whenever(this.constantState).thenReturn(constantState) }
+    }
 }
 
 fun Task.assertHasIconDataFromSource(fakeTaskIconDataSource: FakeTaskIconDataSource) {
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTasksRepository.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTasksRepository.kt
index 19990a8..d94a351 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTasksRepository.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTasksRepository.kt
@@ -20,24 +20,58 @@
 import com.android.systemui.shared.recents.model.ThumbnailData
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.map
 
 class FakeTasksRepository : RecentTasksRepository {
     private var thumbnailDataMap: Map<Int, ThumbnailData> = emptyMap()
+    private var taskIconDataMap: Map<Int, TaskIconQueryResponse> = emptyMap()
     private var tasks: MutableStateFlow<List<Task>> = MutableStateFlow(emptyList())
     private var visibleTasks: MutableStateFlow<List<Int>> = MutableStateFlow(emptyList())
+    private var thumbnailOverrideMap: Map<Int, ThumbnailData> = emptyMap()
 
     override fun getAllTaskData(forceRefresh: Boolean): Flow<List<Task>> = tasks
 
     override fun getTaskDataById(taskId: Int): Flow<Task?> =
-        getAllTaskData().map { taskList -> taskList.firstOrNull { it.key.id == taskId } }
+        combine(getAllTaskData(), visibleTasks) { taskList, visibleTasks ->
+                taskList.filter { visibleTasks.contains(it.key.id) }
+            }
+            .map { taskList ->
+                val task = taskList.firstOrNull { it.key.id == taskId } ?: return@map null
+                Task(task).apply {
+                    thumbnail = thumbnailOverrideMap[taskId] ?: task.thumbnail
+                    icon = task.icon
+                    titleDescription = task.titleDescription
+                    title = task.title
+                }
+            }
 
     override fun getThumbnailById(taskId: Int): Flow<ThumbnailData?> =
         getTaskDataById(taskId).map { it?.thumbnail }
 
     override fun setVisibleTasks(visibleTaskIdList: List<Int>) {
         visibleTasks.value = visibleTaskIdList
-        tasks.value = tasks.value.map { it.apply { thumbnail = thumbnailDataMap[it.key.id] } }
+        tasks.value =
+            tasks.value.map {
+                it.apply {
+                    thumbnail = thumbnailDataMap[it.key.id]
+                    taskIconDataMap[it.key.id].let { taskIconData ->
+                        icon = taskIconData?.icon
+                        titleDescription = taskIconData?.contentDescription
+                        title = taskIconData?.title
+                    }
+                }
+            }
+        setThumbnailOverrideInternal(thumbnailOverrideMap)
+    }
+
+    override fun addOrUpdateThumbnailOverride(thumbnailOverride: Map<Int, ThumbnailData>) {
+        setThumbnailOverrideInternal(thumbnailOverride)
+    }
+
+    private fun setThumbnailOverrideInternal(thumbnailOverride: Map<Int, ThumbnailData>) {
+        thumbnailOverrideMap =
+            thumbnailOverride.filterKeys(this.visibleTasks.value::contains).toMap()
     }
 
     fun seedTasks(tasks: List<Task>) {
@@ -47,4 +81,8 @@
     fun seedThumbnailData(thumbnailDataMap: Map<Int, ThumbnailData>) {
         this.thumbnailDataMap = thumbnailDataMap
     }
+
+    fun seedIconData(iconDataMap: Map<Int, TaskIconQueryResponse>) {
+        this.taskIconDataMap = iconDataMap
+    }
 }
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/RecentsDeviceProfileRepositoryTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/RecentsDeviceProfileRepositoryImplTest.kt
similarity index 84%
rename from quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/RecentsDeviceProfileRepositoryTest.kt
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/RecentsDeviceProfileRepositoryImplTest.kt
index eff926d..e74fe4b 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/RecentsDeviceProfileRepositoryTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/RecentsDeviceProfileRepositoryImplTest.kt
@@ -25,12 +25,12 @@
 import org.mockito.kotlin.mock
 import org.mockito.kotlin.whenever
 
-/** Test for [RecentsDeviceProfileRepository] */
+/** Test for [RecentsDeviceProfileRepositoryImpl] */
 @RunWith(AndroidJUnit4::class)
-class RecentsDeviceProfileRepositoryTest : FakeInvariantDeviceProfileTest() {
+class RecentsDeviceProfileRepositoryImplTest : FakeInvariantDeviceProfileTest() {
     private val recentsViewContainer = mock<RecentsViewContainer>()
 
-    private val systemUnderTest = RecentsDeviceProfileRepository(recentsViewContainer)
+    private val systemUnderTest = RecentsDeviceProfileRepositoryImpl(recentsViewContainer)
 
     @Test
     fun deviceProfileMappedCorrectly() {
@@ -39,6 +39,6 @@
         whenever(recentsViewContainer.deviceProfile).thenReturn(tabletDeviceProfile)
 
         assertThat(systemUnderTest.getRecentsDeviceProfile())
-            .isEqualTo(RecentsDeviceProfileRepository.RecentsDeviceProfile(isLargeScreen = true))
+            .isEqualTo(RecentsDeviceProfile(isLargeScreen = true, widthPx = 1600, heightPx = 2560))
     }
 }
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/RecentsRotationStateRepositoryTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/RecentsRotationStateRepositoryImplTest.kt
similarity index 71%
rename from quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/RecentsRotationStateRepositoryTest.kt
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/RecentsRotationStateRepositoryImplTest.kt
index 1f4da26..017f037 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/RecentsRotationStateRepositoryTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/RecentsRotationStateRepositoryImplTest.kt
@@ -16,26 +16,32 @@
 
 package com.android.quickstep.recents.data
 
+import android.view.Surface.ROTATION_270
 import android.view.Surface.ROTATION_90
+import com.android.quickstep.orientation.SeascapePagedViewHandler
 import com.android.quickstep.util.RecentsOrientedState
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.mockito.kotlin.mock
 import org.mockito.kotlin.whenever
 
-/** Test for [RecentsRotationStateRepository] */
-class RecentsRotationStateRepositoryTest {
+/** Test for [RecentsRotationStateRepositoryImpl] */
+class RecentsRotationStateRepositoryImplTest {
     private val recentsOrientedState = mock<RecentsOrientedState>()
 
-    private val systemUnderTest = RecentsRotationStateRepository(recentsOrientedState)
+    private val systemUnderTest = RecentsRotationStateRepositoryImpl(recentsOrientedState)
 
     @Test
     fun orientedStateMappedCorrectly() {
         whenever(recentsOrientedState.recentsActivityRotation).thenReturn(ROTATION_90)
+        whenever(recentsOrientedState.orientationHandler).thenReturn(SeascapePagedViewHandler())
 
         assertThat(systemUnderTest.getRecentsRotationState())
             .isEqualTo(
-                RecentsRotationStateRepository.RecentsRotationState(activityRotation = ROTATION_90)
+                RecentsRotationState(
+                    activityRotation = ROTATION_90,
+                    orientationHandlerRotation = ROTATION_270
+                )
             )
     }
 }
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/TasksRepositoryTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/TasksRepositoryTest.kt
index 88fa190..b34e156 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/TasksRepositoryTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/TasksRepositoryTest.kt
@@ -18,9 +18,13 @@
 
 import android.content.ComponentName
 import android.content.Intent
+import android.graphics.Bitmap
+import android.view.Surface
+import com.android.quickstep.task.thumbnail.TaskThumbnailViewModelTest
 import com.android.quickstep.util.DesktopTask
 import com.android.quickstep.util.GroupTask
 import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.ThumbnailData
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.drop
@@ -30,6 +34,8 @@
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
 
 @OptIn(ExperimentalCoroutinesApi::class)
 class TasksRepositoryTest {
@@ -186,6 +192,90 @@
         assertThat(taskFlowValuesList[1]!!.thumbnail!!.thumbnail).isEqualTo(bitmap2)
     }
 
+    @Test
+    fun addThumbnailOverrideOverrideThumbnails() = runTest {
+        recentsModel.seedTasks(defaultTaskList)
+        val bitmap1 = taskThumbnailDataSource.taskIdToBitmap[1]
+        val thumbnailOverride2 = createThumbnailData()
+        systemUnderTest.getAllTaskData(forceRefresh = true)
+
+        systemUnderTest.setVisibleTasks(listOf(1, 2))
+        systemUnderTest.addOrUpdateThumbnailOverride(mapOf(2 to thumbnailOverride2))
+
+        // .drop(1) to ignore initial null content before from thumbnail was loaded.
+        assertThat(systemUnderTest.getThumbnailById(1).drop(1).first()!!.thumbnail)
+            .isEqualTo(bitmap1)
+        assertThat(systemUnderTest.getThumbnailById(2).first()!!.thumbnail)
+            .isEqualTo(thumbnailOverride2.thumbnail)
+    }
+
+    @Test
+    fun addThumbnailOverrideMultipleOverrides() = runTest {
+        recentsModel.seedTasks(defaultTaskList)
+        val thumbnailOverride1 = createThumbnailData()
+        val thumbnailOverride2 = createThumbnailData()
+        val thumbnailOverride3 = createThumbnailData()
+        systemUnderTest.getAllTaskData(forceRefresh = true)
+
+        systemUnderTest.setVisibleTasks(listOf(1, 2))
+        systemUnderTest.addOrUpdateThumbnailOverride(mapOf(1 to thumbnailOverride1))
+        systemUnderTest.addOrUpdateThumbnailOverride(mapOf(2 to thumbnailOverride2))
+        systemUnderTest.addOrUpdateThumbnailOverride(mapOf(2 to thumbnailOverride3))
+
+        assertThat(systemUnderTest.getThumbnailById(1).first()!!.thumbnail)
+            .isEqualTo(thumbnailOverride1.thumbnail)
+        assertThat(systemUnderTest.getThumbnailById(2).first()!!.thumbnail)
+            .isEqualTo(thumbnailOverride3.thumbnail)
+    }
+
+    @Test
+    fun addThumbnailOverrideClearedWhenTaskBecomeInvisible() = runTest {
+        recentsModel.seedTasks(defaultTaskList)
+        val bitmap2 = taskThumbnailDataSource.taskIdToBitmap[2]
+        val thumbnailOverride1 = createThumbnailData()
+        val thumbnailOverride2 = createThumbnailData()
+        systemUnderTest.getAllTaskData(forceRefresh = true)
+
+        systemUnderTest.setVisibleTasks(listOf(1, 2))
+        systemUnderTest.addOrUpdateThumbnailOverride(mapOf(1 to thumbnailOverride1))
+        systemUnderTest.addOrUpdateThumbnailOverride(mapOf(2 to thumbnailOverride2))
+        // Making task 2 invisible and visible again should clear the override
+        systemUnderTest.setVisibleTasks(listOf(1))
+        systemUnderTest.setVisibleTasks(listOf(1, 2))
+
+        // .drop(1) to ignore initial null content before from thumbnail was loaded.
+        assertThat(systemUnderTest.getThumbnailById(1).first()!!.thumbnail)
+            .isEqualTo(thumbnailOverride1.thumbnail)
+        assertThat(systemUnderTest.getThumbnailById(2).drop(1).first()!!.thumbnail)
+            .isEqualTo(bitmap2)
+    }
+
+    @Test
+    fun addThumbnailOverrideDoesNotOverrideInvisibleTasks() = runTest {
+        recentsModel.seedTasks(defaultTaskList)
+        val bitmap1 = taskThumbnailDataSource.taskIdToBitmap[1]
+        val bitmap2 = taskThumbnailDataSource.taskIdToBitmap[2]
+        val thumbnailOverride = createThumbnailData()
+        systemUnderTest.getAllTaskData(forceRefresh = true)
+
+        systemUnderTest.setVisibleTasks(listOf(1))
+        systemUnderTest.addOrUpdateThumbnailOverride(mapOf(2 to thumbnailOverride))
+        systemUnderTest.setVisibleTasks(listOf(1, 2))
+
+        // .drop(1) to ignore initial null content before from thumbnail was loaded.
+        assertThat(systemUnderTest.getThumbnailById(1).drop(1).first()!!.thumbnail)
+            .isEqualTo(bitmap1)
+        assertThat(systemUnderTest.getThumbnailById(2).first()!!.thumbnail).isEqualTo(bitmap2)
+    }
+
     private fun createTaskWithId(taskId: Int) =
         Task(Task.TaskKey(taskId, 0, Intent(), ComponentName("", ""), 0, 2000))
+
+    private fun createThumbnailData(rotation: Int = Surface.ROTATION_0): ThumbnailData {
+        val bitmap = mock<Bitmap>()
+        whenever(bitmap.width).thenReturn(TaskThumbnailViewModelTest.THUMBNAIL_WIDTH)
+        whenever(bitmap.height).thenReturn(TaskThumbnailViewModelTest.THUMBNAIL_HEIGHT)
+
+        return ThumbnailData(thumbnail = bitmap, rotation = rotation)
+    }
 }
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/usecase/GetThumbnailPositionUseCaseTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/usecase/GetThumbnailPositionUseCaseTest.kt
index e657d59..02f1d11 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/usecase/GetThumbnailPositionUseCaseTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/usecase/GetThumbnailPositionUseCaseTest.kt
@@ -24,9 +24,9 @@
 import android.graphics.Rect
 import android.view.Surface.ROTATION_90
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.quickstep.recents.data.FakeRecentsDeviceProfileRepository
+import com.android.quickstep.recents.data.FakeRecentsRotationStateRepository
 import com.android.quickstep.recents.data.FakeTasksRepository
-import com.android.quickstep.recents.data.RecentsDeviceProfileRepository
-import com.android.quickstep.recents.data.RecentsRotationStateRepository
 import com.android.quickstep.recents.usecase.ThumbnailPositionState.MatrixScaling
 import com.android.quickstep.recents.usecase.ThumbnailPositionState.MissingThumbnail
 import com.android.systemui.shared.recents.model.Task
@@ -56,8 +56,8 @@
                 }
         )
 
-    private val deviceProfileRepository = mock<RecentsDeviceProfileRepository>()
-    private val rotationStateRepository = mock<RecentsRotationStateRepository>()
+    private val deviceProfileRepository = FakeRecentsDeviceProfileRepository()
+    private val rotationStateRepository = FakeRecentsRotationStateRepository()
     private val tasksRepository = FakeTasksRepository()
     private val previewPositionHelper = mock<PreviewPositionHelper>()
 
@@ -93,15 +93,18 @@
         tasksRepository.setVisibleTasks(listOf(TASK_ID))
 
         val isLargeScreen = true
+        deviceProfileRepository.setRecentsDeviceProfile(
+            deviceProfileRepository.getRecentsDeviceProfile().copy(isLargeScreen = isLargeScreen)
+        )
         val activityRotation = ROTATION_90
+        rotationStateRepository.setRecentsRotationState(
+            rotationStateRepository
+                .getRecentsRotationState()
+                .copy(activityRotation = activityRotation)
+        )
         val isRtl = true
         val isRotated = true
 
-        whenever(deviceProfileRepository.getRecentsDeviceProfile())
-            .thenReturn(RecentsDeviceProfileRepository.RecentsDeviceProfile(isLargeScreen))
-        whenever(rotationStateRepository.getRecentsRotationState())
-            .thenReturn(RecentsRotationStateRepository.RecentsRotationState(activityRotation))
-
         whenever(previewPositionHelper.matrix).thenReturn(MATRIX)
         whenever(previewPositionHelper.isOrientationChanged).thenReturn(isRotated)
 
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/viewmodel/RecentsViewModelTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/viewmodel/RecentsViewModelTest.kt
new file mode 100644
index 0000000..b3caf2d
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/viewmodel/RecentsViewModelTest.kt
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2024 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.recents.viewmodel
+
+import android.content.ComponentName
+import android.content.Intent
+import android.graphics.Bitmap
+import android.graphics.Color
+import android.view.Surface
+import com.android.quickstep.recents.data.FakeTasksRepository
+import com.android.quickstep.task.thumbnail.TaskThumbnailViewModelTest
+import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.ThumbnailData
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+
+class RecentsViewModelTest {
+    private val tasksRepository = FakeTasksRepository()
+    private val recentsViewData = RecentsViewData()
+    private val systemUnderTest = RecentsViewModel(tasksRepository, recentsViewData)
+
+    private val tasks = (0..5).map(::createTaskWithId)
+
+    @Test
+    fun taskVisibilityControlThumbnailsAvailability() = runTest {
+        val thumbnailData1 = createThumbnailData()
+        val thumbnailData2 = createThumbnailData()
+        tasksRepository.seedTasks(tasks)
+        tasksRepository.seedThumbnailData(mapOf(1 to thumbnailData1, 2 to thumbnailData2))
+
+        val thumbnailDataFlow1 = tasksRepository.getThumbnailById(1)
+        val thumbnailDataFlow2 = tasksRepository.getThumbnailById(2)
+
+        systemUnderTest.refreshAllTaskData()
+
+        assertThat(thumbnailDataFlow1.first()).isNull()
+        assertThat(thumbnailDataFlow2.first()).isNull()
+
+        systemUnderTest.updateVisibleTasks(listOf(1, 2))
+
+        assertThat(thumbnailDataFlow1.first()).isEqualTo(thumbnailData1)
+        assertThat(thumbnailDataFlow2.first()).isEqualTo(thumbnailData2)
+
+        systemUnderTest.updateVisibleTasks(listOf(1))
+
+        assertThat(thumbnailDataFlow1.first()).isEqualTo(thumbnailData1)
+        assertThat(thumbnailDataFlow2.first()).isNull()
+
+        systemUnderTest.onReset()
+
+        assertThat(thumbnailDataFlow1.first()).isNull()
+        assertThat(thumbnailDataFlow2.first()).isNull()
+    }
+
+    @Test
+    fun thumbnailOverrideWaitAndReset() = runTest {
+        val thumbnailData1 = createThumbnailData()
+        val thumbnailData2 = createThumbnailData()
+        val thumbnailDataOverride = createThumbnailData()
+        tasksRepository.seedTasks(tasks)
+        tasksRepository.seedThumbnailData(mapOf(1 to thumbnailData1, 2 to thumbnailData2))
+
+        val thumbnailDataFlow1 = tasksRepository.getThumbnailById(1)
+        val thumbnailDataFlow2 = tasksRepository.getThumbnailById(2)
+
+        systemUnderTest.refreshAllTaskData()
+        systemUnderTest.updateVisibleTasks(listOf(1, 2))
+
+        assertThat(thumbnailDataFlow1.first()).isEqualTo(thumbnailData1)
+        assertThat(thumbnailDataFlow2.first()).isEqualTo(thumbnailData2)
+
+        val thumbnailUpdate = mapOf(2 to thumbnailDataOverride)
+        systemUnderTest.setRunningTaskShowScreenshot(true)
+        systemUnderTest.addOrUpdateThumbnailOverride(thumbnailUpdate)
+
+        systemUnderTest.waitForRunningTaskShowScreenshotToUpdate()
+        systemUnderTest.waitForThumbnailsToUpdate(thumbnailUpdate)
+
+        assertThat(thumbnailDataFlow1.first()).isEqualTo(thumbnailData1)
+        assertThat(thumbnailDataFlow2.first()).isEqualTo(thumbnailDataOverride)
+
+        systemUnderTest.onReset()
+
+        assertThat(thumbnailDataFlow1.first()).isNull()
+        assertThat(thumbnailDataFlow2.first()).isNull()
+
+        systemUnderTest.updateVisibleTasks(listOf(1, 2))
+
+        assertThat(thumbnailDataFlow1.first()).isEqualTo(thumbnailData1)
+        assertThat(thumbnailDataFlow2.first()).isEqualTo(thumbnailData2)
+    }
+
+    private fun createTaskWithId(taskId: Int) =
+        Task(Task.TaskKey(taskId, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
+            colorBackground = Color.argb(taskId, taskId, taskId, taskId)
+        }
+
+    private fun createThumbnailData(rotation: Int = Surface.ROTATION_0): ThumbnailData {
+        val bitmap = mock<Bitmap>()
+        whenever(bitmap.width).thenReturn(TaskThumbnailViewModelTest.THUMBNAIL_WIDTH)
+        whenever(bitmap.height).thenReturn(TaskThumbnailViewModelTest.THUMBNAIL_HEIGHT)
+
+        return ThumbnailData(thumbnail = bitmap, rotation = rotation)
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/GetSplashSizeUseCaseTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/GetSplashSizeUseCaseTest.kt
new file mode 100644
index 0000000..13e8b09
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/GetSplashSizeUseCaseTest.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 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.task.thumbnail
+
+import android.graphics.Point
+import android.graphics.drawable.Drawable
+import com.android.quickstep.recents.data.FakeRecentsDeviceProfileRepository
+import com.android.quickstep.task.viewmodel.TaskViewData
+import com.android.quickstep.views.TaskViewType
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+
+class GetSplashSizeUseCaseTest {
+    private val taskThumbnailViewData = TaskThumbnailViewData()
+    private val taskViewData = TaskViewData(TaskViewType.SINGLE)
+    private val recentsDeviceProfileRepository = FakeRecentsDeviceProfileRepository()
+    private val systemUnderTest =
+        GetSplashSizeUseCase(taskThumbnailViewData, taskViewData, recentsDeviceProfileRepository)
+
+    @Test
+    fun execute_whenNoScaleRequired_returnsIntrinsicSize() {
+        taskThumbnailViewData.width.value =
+            recentsDeviceProfileRepository.getRecentsDeviceProfile().widthPx
+        taskThumbnailViewData.height.value =
+            recentsDeviceProfileRepository.getRecentsDeviceProfile().heightPx
+
+        assertThat(systemUnderTest.execute(createIcon(100, 100))).isEqualTo(Point(100, 100))
+    }
+
+    @Test
+    fun execute_whenThumbnailViewIsSmallerThanScreen_returnsScaledSize() {
+        taskThumbnailViewData.width.value =
+            recentsDeviceProfileRepository.getRecentsDeviceProfile().widthPx / 2
+        taskThumbnailViewData.height.value =
+            recentsDeviceProfileRepository.getRecentsDeviceProfile().heightPx / 2
+
+        assertThat(systemUnderTest.execute(createIcon(100, 100))).isEqualTo(Point(50, 50))
+    }
+
+    @Test
+    fun execute_whenThumbnailViewIsSmallerThanScreen_withNonGridScale_returnsScaledSize() {
+        taskThumbnailViewData.width.value =
+            recentsDeviceProfileRepository.getRecentsDeviceProfile().widthPx / 2
+        taskThumbnailViewData.height.value =
+            recentsDeviceProfileRepository.getRecentsDeviceProfile().heightPx / 2
+        taskViewData.nonGridScale.value = 2f
+
+        assertThat(systemUnderTest.execute(createIcon(100, 100))).isEqualTo(Point(25, 25))
+    }
+
+    @Test
+    fun execute_whenThumbnailViewIsSmallerThanScreen_withThumbnailViewScale_returnsScaledSize() {
+        taskThumbnailViewData.width.value =
+            recentsDeviceProfileRepository.getRecentsDeviceProfile().widthPx / 2
+        taskThumbnailViewData.height.value =
+            recentsDeviceProfileRepository.getRecentsDeviceProfile().heightPx / 2
+        taskThumbnailViewData.scaleX.value = 2f
+        taskThumbnailViewData.scaleY.value = 2f
+
+        assertThat(systemUnderTest.execute(createIcon(100, 100))).isEqualTo(Point(25, 25))
+    }
+
+    private fun createIcon(width: Int, height: Int): Drawable =
+        mock<Drawable>().apply {
+            whenever(intrinsicWidth).thenReturn(width)
+            whenever(intrinsicHeight).thenReturn(height)
+        }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/SplashAlphaUseCaseTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/SplashAlphaUseCaseTest.kt
new file mode 100644
index 0000000..a584d71
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/SplashAlphaUseCaseTest.kt
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2024 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.task.thumbnail
+
+import android.content.ComponentName
+import android.content.Intent
+import android.graphics.Bitmap
+import android.graphics.Color
+import android.graphics.drawable.Drawable
+import android.view.Surface
+import android.view.Surface.ROTATION_90
+import com.android.quickstep.recents.data.FakeRecentsRotationStateRepository
+import com.android.quickstep.recents.data.FakeTasksRepository
+import com.android.quickstep.recents.data.TaskIconQueryResponse
+import com.android.quickstep.recents.viewmodel.RecentsViewData
+import com.android.quickstep.task.viewmodel.TaskContainerData
+import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.ThumbnailData
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+
+class SplashAlphaUseCaseTest {
+    private val recentsViewData = RecentsViewData()
+    private val taskContainerData = TaskContainerData()
+    private val taskThumbnailViewData = TaskThumbnailViewData()
+    private val recentTasksRepository = FakeTasksRepository()
+    private val recentsRotationStateRepository = FakeRecentsRotationStateRepository()
+    private val systemUnderTest =
+        SplashAlphaUseCase(
+            recentsViewData,
+            taskContainerData,
+            taskThumbnailViewData,
+            recentTasksRepository,
+            recentsRotationStateRepository
+        )
+
+    @Test
+    fun execute_withNullThumbnail_showsSplash() = runTest {
+        assertThat(systemUnderTest.execute(0).first()).isEqualTo(SPLASH_HIDDEN)
+    }
+
+    @Test
+    fun execute_withTaskSpecificSplashAlpha_showsSplash() = runTest {
+        setupTask(2)
+        taskContainerData.thumbnailSplashProgress.value = 0.7f
+
+        assertThat(systemUnderTest.execute(2).first()).isEqualTo(0.7f)
+    }
+
+    @Test
+    fun execute_withNoGlobalSplashEnabled_doesntShowSplash() = runTest {
+        setupTask(2)
+
+        assertThat(systemUnderTest.execute(2).first()).isEqualTo(SPLASH_HIDDEN)
+    }
+
+    @Test
+    fun execute_withSameAspectRatioAndRotation_withGlobalSplashEnabled_doesntShowSplash() =
+        runTest {
+            setupTask(2)
+            recentsViewData.thumbnailSplashProgress.value = 0.5f
+            taskThumbnailViewData.width.value = THUMBNAIL_WIDTH * 2
+            taskThumbnailViewData.height.value = THUMBNAIL_HEIGHT * 2
+
+            assertThat(systemUnderTest.execute(2).first()).isEqualTo(SPLASH_HIDDEN)
+        }
+
+    @Test
+    fun execute_withDifferentAspectRatioAndSameRotation_showsSplash() = runTest {
+        setupTask(2)
+        recentsViewData.thumbnailSplashProgress.value = 0.5f
+        taskThumbnailViewData.width.value = THUMBNAIL_WIDTH
+        taskThumbnailViewData.height.value = THUMBNAIL_HEIGHT * 2
+
+        assertThat(systemUnderTest.execute(2).first()).isEqualTo(0.5f)
+    }
+
+    @Test
+    fun execute_withSameAspectRatioAndDifferentRotation_showsSplash() = runTest {
+        setupTask(2, createThumbnailData(rotation = ROTATION_90))
+        recentsViewData.thumbnailSplashProgress.value = 0.5f
+        taskThumbnailViewData.width.value = THUMBNAIL_WIDTH * 2
+        taskThumbnailViewData.height.value = THUMBNAIL_HEIGHT * 2
+
+        assertThat(systemUnderTest.execute(2).first()).isEqualTo(0.5f)
+    }
+
+    @Test
+    fun execute_withDifferentAspectRatioAndRotation_showsSplash() = runTest {
+        setupTask(2, createThumbnailData(rotation = ROTATION_90))
+        recentsViewData.thumbnailSplashProgress.value = 0.5f
+        taskThumbnailViewData.width.value = THUMBNAIL_WIDTH
+        taskThumbnailViewData.height.value = THUMBNAIL_HEIGHT * 2
+
+        assertThat(systemUnderTest.execute(2).first()).isEqualTo(0.5f)
+    }
+
+    private val tasks = (0..5).map(::createTaskWithId)
+
+    private fun setupTask(taskId: Int, thumbnailData: ThumbnailData = createThumbnailData()) {
+        recentTasksRepository.seedThumbnailData(mapOf(taskId to thumbnailData))
+        val expectedIconData = createIconData("Task $taskId")
+        recentTasksRepository.seedIconData(mapOf(taskId to expectedIconData))
+        recentTasksRepository.seedTasks(tasks)
+        recentTasksRepository.setVisibleTasks(listOf(taskId))
+    }
+
+    private fun createThumbnailData(
+        rotation: Int = Surface.ROTATION_0,
+        width: Int = THUMBNAIL_WIDTH,
+        height: Int = THUMBNAIL_HEIGHT
+    ): ThumbnailData {
+        val bitmap = mock<Bitmap>()
+        whenever(bitmap.width).thenReturn(width)
+        whenever(bitmap.height).thenReturn(height)
+
+        return ThumbnailData(thumbnail = bitmap, rotation = rotation)
+    }
+
+    private fun createIconData(title: String) = TaskIconQueryResponse(mock<Drawable>(), "", title)
+
+    private fun createTaskWithId(taskId: Int) =
+        Task(Task.TaskKey(taskId, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
+            colorBackground = Color.argb(taskId, taskId, taskId, taskId)
+        }
+
+    companion object {
+        const val THUMBNAIL_WIDTH = 100
+        const val THUMBNAIL_HEIGHT = 200
+
+        const val SPLASH_HIDDEN = 0f
+        const val SPLASH_SHOWN = 1f
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
index 754c9d1..fe7d37a 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
@@ -21,8 +21,12 @@
 import android.graphics.Bitmap
 import android.graphics.Color
 import android.graphics.Matrix
+import android.graphics.Point
+import android.graphics.drawable.Drawable
+import android.view.Surface
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.quickstep.recents.data.FakeTasksRepository
+import com.android.quickstep.recents.data.TaskIconQueryResponse
 import com.android.quickstep.recents.usecase.GetThumbnailPositionUseCase
 import com.android.quickstep.recents.usecase.ThumbnailPositionState.MatrixScaling
 import com.android.quickstep.recents.usecase.ThumbnailPositionState.MissingThumbnail
@@ -30,6 +34,8 @@
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.BackgroundOnly
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Snapshot
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.SnapshotSplash
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Splash
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
 import com.android.quickstep.task.viewmodel.TaskContainerData
 import com.android.quickstep.task.viewmodel.TaskThumbnailViewModel
@@ -40,11 +46,14 @@
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.test.runTest
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.kotlin.any
 import org.mockito.kotlin.mock
 import org.mockito.kotlin.whenever
 
+/** Test for [TaskThumbnailView] */
 @RunWith(AndroidJUnit4::class)
 class TaskThumbnailViewModelTest {
     private var taskViewType = TaskViewType.SINGLE
@@ -53,18 +62,27 @@
     private val taskContainerData = TaskContainerData()
     private val tasksRepository = FakeTasksRepository()
     private val mGetThumbnailPositionUseCase = mock<GetThumbnailPositionUseCase>()
+    private val splashAlphaUseCase: SplashAlphaUseCase = mock()
+    private val getSplashSizeUseCase: GetSplashSizeUseCase = mock()
     private val systemUnderTest by lazy {
         TaskThumbnailViewModel(
             recentsViewData,
             taskViewData,
             taskContainerData,
             tasksRepository,
-            mGetThumbnailPositionUseCase
+            mGetThumbnailPositionUseCase,
+            splashAlphaUseCase,
+            getSplashSizeUseCase,
         )
     }
 
     private val tasks = (0..5).map(::createTaskWithId)
 
+    @Before
+    fun setUp() {
+        whenever(getSplashSizeUseCase.execute(any())).thenReturn(Point())
+    }
+
     @Test
     fun initialStateIsUninitialized() = runTest {
         assertThat(systemUnderTest.uiState.first()).isEqualTo(Uninitialized)
@@ -72,14 +90,42 @@
 
     @Test
     fun bindRunningTask_thenStateIs_LiveTile() = runTest {
+        val taskId = 1
         tasksRepository.seedTasks(tasks)
-        val taskThumbnail = TaskThumbnail(taskId = 1, isRunning = true)
-        systemUnderTest.bind(taskThumbnail)
+        tasksRepository.setVisibleTasks(listOf(taskId))
+        recentsViewData.runningTaskIds.value = setOf(taskId)
+        systemUnderTest.bind(taskId)
 
         assertThat(systemUnderTest.uiState.first()).isEqualTo(LiveTile)
     }
 
     @Test
+    fun bindRunningTaskShouldShowScreenshot_thenStateIs_SnapshotSplash() = runTest {
+        val taskId = 1
+        val expectedThumbnailData = createThumbnailData()
+        tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
+        val expectedIconData = createIconData("Task 1")
+        tasksRepository.seedIconData(mapOf(taskId to expectedIconData))
+        tasksRepository.seedTasks(tasks)
+        tasksRepository.setVisibleTasks(listOf(taskId))
+        recentsViewData.runningTaskIds.value = setOf(taskId)
+        recentsViewData.runningTaskShowScreenshot.value = true
+        systemUnderTest.bind(taskId)
+
+        assertThat(systemUnderTest.uiState.first())
+            .isEqualTo(
+                SnapshotSplash(
+                    Snapshot(
+                        backgroundColor = Color.rgb(1, 1, 1),
+                        bitmap = expectedThumbnailData.thumbnail!!,
+                        thumbnailRotation = Surface.ROTATION_0,
+                    ),
+                    Splash(expectedIconData.icon, Point())
+                )
+            )
+    }
+
+    @Test
     fun setRecentsFullscreenProgress_thenCornerRadiusProgressIsPassedThrough() = runTest {
         recentsViewData.fullscreenProgress.value = 0.5f
 
@@ -113,87 +159,119 @@
     @Test
     fun bindRunningTaskThenStoppedTaskWithoutThumbnail_thenStateChangesToBackgroundOnly() =
         runTest {
+            val runningTaskId = 1
+            val stoppedTaskId = 2
             tasksRepository.seedTasks(tasks)
-            val runningTask = TaskThumbnail(taskId = 1, isRunning = true)
-            val stoppedTask = TaskThumbnail(taskId = 2, isRunning = false)
-            systemUnderTest.bind(runningTask)
+            tasksRepository.setVisibleTasks(listOf(runningTaskId, stoppedTaskId))
+            recentsViewData.runningTaskIds.value = setOf(runningTaskId)
+            systemUnderTest.bind(runningTaskId)
             assertThat(systemUnderTest.uiState.first()).isEqualTo(LiveTile)
 
-            systemUnderTest.bind(stoppedTask)
+            systemUnderTest.bind(stoppedTaskId)
             assertThat(systemUnderTest.uiState.first())
                 .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
         }
 
     @Test
     fun bindStoppedTaskWithoutThumbnail_thenStateIs_BackgroundOnly_withAlphaRemoved() = runTest {
+        val stoppedTaskId = 2
         tasksRepository.seedTasks(tasks)
-        val stoppedTask = TaskThumbnail(taskId = 2, isRunning = false)
+        tasksRepository.setVisibleTasks(listOf(stoppedTaskId))
 
-        systemUnderTest.bind(stoppedTask)
+        systemUnderTest.bind(stoppedTaskId)
         assertThat(systemUnderTest.uiState.first())
             .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
     }
 
     @Test
     fun bindLockedTaskWithThumbnail_thenStateIs_BackgroundOnly() = runTest {
-        tasksRepository.seedThumbnailData(mapOf(2 to createThumbnailData()))
-        tasks[2].isLocked = true
+        val taskId = 2
+        tasksRepository.seedThumbnailData(mapOf(taskId to createThumbnailData()))
+        tasks[taskId].isLocked = true
         tasksRepository.seedTasks(tasks)
-        val recentTask = TaskThumbnail(taskId = 2, isRunning = false)
+        tasksRepository.setVisibleTasks(listOf(taskId))
 
-        systemUnderTest.bind(recentTask)
+        systemUnderTest.bind(taskId)
         assertThat(systemUnderTest.uiState.first())
             .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
     }
 
     @Test
-    fun bindStoppedTaskWithThumbnail_thenStateIs_Snapshot_withAlphaRemoved() = runTest {
-        val expectedThumbnailData = createThumbnailData()
-        tasksRepository.seedThumbnailData(mapOf(2 to expectedThumbnailData))
+    fun bindStoppedTaskWithThumbnail_thenStateIs_SnapshotSplash_withAlphaRemoved() = runTest {
+        val taskId = 2
+        val expectedThumbnailData = createThumbnailData(rotation = Surface.ROTATION_270)
+        tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
+        val expectedIconData = createIconData("Task 2")
+        tasksRepository.seedIconData(mapOf(taskId to expectedIconData))
         tasksRepository.seedTasks(tasks)
-        tasksRepository.setVisibleTasks(listOf(2))
-        val recentTask = TaskThumbnail(taskId = 2, isRunning = false)
+        tasksRepository.setVisibleTasks(listOf(taskId))
 
-        systemUnderTest.bind(recentTask)
+        systemUnderTest.bind(taskId)
         assertThat(systemUnderTest.uiState.first())
             .isEqualTo(
-                Snapshot(
-                    backgroundColor = Color.rgb(2, 2, 2),
-                    bitmap = expectedThumbnailData.thumbnail!!,
+                SnapshotSplash(
+                    Snapshot(
+                        backgroundColor = Color.rgb(2, 2, 2),
+                        bitmap = expectedThumbnailData.thumbnail!!,
+                        thumbnailRotation = Surface.ROTATION_270,
+                    ),
+                    Splash(expectedIconData.icon, Point())
                 )
             )
     }
 
     @Test
-    fun bindNonVisibleStoppedTask_whenMadeVisible_thenStateIsSnapshot() = runTest {
+    fun bindNonVisibleStoppedTask_whenMadeVisible_thenStateIsSnapshotSplash() = runTest {
+        val taskId = 2
         val expectedThumbnailData = createThumbnailData()
-        tasksRepository.seedThumbnailData(mapOf(2 to expectedThumbnailData))
+        tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
+        val expectedIconData = createIconData("Task 2")
+        tasksRepository.seedIconData(mapOf(taskId to expectedIconData))
         tasksRepository.seedTasks(tasks)
-        val recentTask = TaskThumbnail(taskId = 2, isRunning = false)
 
-        systemUnderTest.bind(recentTask)
-        assertThat(systemUnderTest.uiState.first())
-            .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
-        tasksRepository.setVisibleTasks(listOf(2))
+        systemUnderTest.bind(taskId)
+        assertThat(systemUnderTest.uiState.first()).isEqualTo(Uninitialized)
+
+        tasksRepository.setVisibleTasks(listOf(taskId))
         assertThat(systemUnderTest.uiState.first())
             .isEqualTo(
-                Snapshot(
-                    backgroundColor = Color.rgb(2, 2, 2),
-                    bitmap = expectedThumbnailData.thumbnail!!,
+                SnapshotSplash(
+                    Snapshot(
+                        backgroundColor = Color.rgb(2, 2, 2),
+                        bitmap = expectedThumbnailData.thumbnail!!,
+                        thumbnailRotation = Surface.ROTATION_0,
+                    ),
+                    Splash(expectedIconData.icon, Point())
                 )
             )
     }
 
     @Test
+    fun bindStoppedTask_thenStateContainsSplashSizeFromUseCase() = runTest {
+        val taskId = 2
+        val expectedSplashSize = Point(100, 150)
+        whenever(getSplashSizeUseCase.execute(any())).thenReturn(expectedSplashSize)
+        val expectedThumbnailData = createThumbnailData(rotation = Surface.ROTATION_270)
+        tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
+        val expectedIconData = createIconData("Task 2")
+        tasksRepository.seedIconData(mapOf(taskId to expectedIconData))
+        tasksRepository.seedTasks(tasks)
+        tasksRepository.setVisibleTasks(listOf(taskId))
+
+        systemUnderTest.bind(taskId)
+        val uiState = systemUnderTest.uiState.first() as SnapshotSplash
+        assertThat(uiState.splash.size).isEqualTo(expectedSplashSize)
+    }
+
+    @Test
     fun getSnapshotMatrix_MissingThumbnail() = runTest {
         val taskId = 2
-        val recentTask = TaskThumbnail(taskId = taskId, isRunning = false)
         val isRtl = true
 
         whenever(mGetThumbnailPositionUseCase.run(taskId, CANVAS_WIDTH, CANVAS_HEIGHT, isRtl))
             .thenReturn(MissingThumbnail)
 
-        systemUnderTest.bind(recentTask)
+        systemUnderTest.bind(taskId)
         assertThat(systemUnderTest.getThumbnailPositionState(CANVAS_WIDTH, CANVAS_HEIGHT, isRtl))
             .isEqualTo(Matrix.IDENTITY_MATRIX)
     }
@@ -201,30 +279,52 @@
     @Test
     fun getSnapshotMatrix_MatrixScaling() = runTest {
         val taskId = 2
-        val recentTask = TaskThumbnail(taskId = taskId, isRunning = false)
         val isRtl = true
 
         whenever(mGetThumbnailPositionUseCase.run(taskId, CANVAS_WIDTH, CANVAS_HEIGHT, isRtl))
             .thenReturn(MatrixScaling(MATRIX, isRotated = false))
 
-        systemUnderTest.bind(recentTask)
+        systemUnderTest.bind(taskId)
         assertThat(systemUnderTest.getThumbnailPositionState(CANVAS_WIDTH, CANVAS_HEIGHT, isRtl))
             .isEqualTo(MATRIX)
     }
 
+    @Test
+    fun getForegroundScrimDimProgress_returnsForegroundMaxScrim() = runTest {
+        recentsViewData.tintAmount.value = 0.32f
+        taskContainerData.taskMenuOpenProgress.value = 0f
+        assertThat(systemUnderTest.dimProgress.first()).isEqualTo(0.32f)
+    }
+
+    @Test
+    fun getTaskMenuScrimDimProgress_returnsTaskMenuScrim() = runTest {
+        recentsViewData.tintAmount.value = 0f
+        taskContainerData.taskMenuOpenProgress.value = 1f
+        assertThat(systemUnderTest.dimProgress.first()).isEqualTo(0.4f)
+    }
+
+    @Test
+    fun getForegroundScrimDimProgress_returnsNoScrim() = runTest {
+        recentsViewData.tintAmount.value = 0f
+        taskContainerData.taskMenuOpenProgress.value = 0f
+        assertThat(systemUnderTest.dimProgress.first()).isEqualTo(0f)
+    }
+
     private fun createTaskWithId(taskId: Int) =
         Task(Task.TaskKey(taskId, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
             colorBackground = Color.argb(taskId, taskId, taskId, taskId)
         }
 
-    private fun createThumbnailData(): ThumbnailData {
+    private fun createThumbnailData(rotation: Int = Surface.ROTATION_0): ThumbnailData {
         val bitmap = mock<Bitmap>()
         whenever(bitmap.width).thenReturn(THUMBNAIL_WIDTH)
         whenever(bitmap.height).thenReturn(THUMBNAIL_HEIGHT)
 
-        return ThumbnailData(thumbnail = bitmap)
+        return ThumbnailData(thumbnail = bitmap, rotation = rotation)
     }
 
+    private fun createIconData(title: String) = TaskIconQueryResponse(mock<Drawable>(), "", title)
+
     companion object {
         const val THUMBNAIL_WIDTH = 100
         const val THUMBNAIL_HEIGHT = 200
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/TestExtensions.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/TestExtensions.kt
new file mode 100644
index 0000000..6c526a4
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/TestExtensions.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.util
+
+import com.android.launcher3.BuildConfig
+import com.android.launcher3.util.SafeCloseable
+import com.android.quickstep.DeviceConfigWrapper.Companion.configHelper
+import com.android.quickstep.util.DeviceConfigHelper.Companion.prefs
+import java.util.concurrent.CountDownLatch
+import java.util.function.BooleanSupplier
+import org.junit.Assert
+import org.junit.Assume
+
+/** Helper methods for testing */
+object TestExtensions {
+
+    @JvmStatic
+    fun overrideNavConfigFlag(
+        key: String,
+        value: Boolean,
+        targetValue: BooleanSupplier
+    ): AutoCloseable {
+        Assume.assumeTrue(BuildConfig.IS_DEBUG_DEVICE)
+        if (targetValue.asBoolean == value) {
+            return AutoCloseable {}
+        }
+
+        navConfigEditWatcher().let {
+            prefs.edit().putBoolean(key, value).commit()
+            it.close()
+        }
+        Assert.assertEquals(value, targetValue.asBoolean)
+
+        val watcher = navConfigEditWatcher()
+        return AutoCloseable {
+            prefs.edit().remove(key).commit()
+            watcher.close()
+        }
+    }
+
+    private fun navConfigEditWatcher(): SafeCloseable {
+        val wait = CountDownLatch(1)
+        val listener = Runnable { wait.countDown() }
+        configHelper.addChangeListener(listener)
+
+        return SafeCloseable {
+            wait.await()
+            configHelper.removeChangeListener(listener)
+        }
+    }
+}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
index c0ff189..88ffeea 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
@@ -20,10 +20,12 @@
 import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
+import android.content.res.Resources
 import android.os.Process
 import android.os.UserHandle
 import android.platform.test.rule.TestWatcher
 import android.testing.AndroidTestingRunner
+import com.android.internal.R
 import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT
 import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION
 import com.android.launcher3.model.data.AppInfo
@@ -73,6 +75,7 @@
     @Mock private lateinit var mockIconCache: TaskIconCache
     @Mock private lateinit var mockRecentsModel: RecentsModel
     @Mock private lateinit var mockContext: Context
+    @Mock private lateinit var mockResources: Resources
     @Mock private lateinit var mockDesktopVisibilityController: DesktopVisibilityController
 
     private var taskListChangeId: Int = 1
@@ -88,6 +91,10 @@
         super.setup()
         userHandle = Process.myUserHandle()
 
+        // Set desktop mode supported
+        whenever(mockContext.getResources()).thenReturn(mockResources)
+        whenever(mockResources.getBoolean(R.bool.config_isDesktopModeSupported)).thenReturn(true)
+
         whenever(mockRecentsModel.iconCache).thenReturn(mockIconCache)
         whenever(mockRecentsModel.unregisterRecentTasksChangedListener()).then {
             recentTasksChangedListener = null
diff --git a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
index c213dbb..cbc8441 100644
--- a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
+++ b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
@@ -30,9 +30,11 @@
 import android.app.ActivityManager;
 import android.app.KeyguardManager;
 import android.content.Context;
+import android.content.res.Resources;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.R;
 import com.android.launcher3.util.LooperExecutor;
 import com.android.quickstep.util.GroupTask;
 import com.android.quickstep.views.TaskViewType;
@@ -57,6 +59,8 @@
     @Mock
     private Context mContext;
     @Mock
+    private Resources mResources;
+    @Mock
     private SystemUiProxy mSystemUiProxy;
     @Mock
     private TopTaskTracker mTopTaskTracker;
@@ -69,6 +73,11 @@
         MockitoAnnotations.initMocks(this);
         LooperExecutor mockMainThreadExecutor = mock(LooperExecutor.class);
         KeyguardManager mockKeyguardManager = mock(KeyguardManager.class);
+
+        // Set desktop mode supported
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mResources.getBoolean(R.bool.config_isDesktopModeSupported)).thenReturn(true);
+
         mRecentTasksList = new RecentTasksList(mContext, mockMainThreadExecutor,
                 mockKeyguardManager, mSystemUiProxy, mTopTaskTracker);
     }
diff --git a/quickstep/tests/src/com/android/quickstep/TaskAnimationManagerTest.java b/quickstep/tests/src/com/android/quickstep/TaskAnimationManagerTest.java
index 2d79623..3a83ae3 100644
--- a/quickstep/tests/src/com/android/quickstep/TaskAnimationManagerTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaskAnimationManagerTest.java
@@ -16,7 +16,7 @@
 
 package com.android.quickstep;
 
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
@@ -71,7 +71,7 @@
         final ArgumentCaptor<ActivityOptions> optionsCaptor =
                 ArgumentCaptor.forClass(ActivityOptions.class);
         verify(mSystemUiProxy).startRecentsActivity(any(), optionsCaptor.capture(), any());
-        assertTrue(optionsCaptor.getValue()
-                .isPendingIntentBackgroundActivityLaunchAllowedByPermission());
+        assertEquals(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS,
+                optionsCaptor.getValue().getPendingIntentBackgroundActivityStartMode());
     }
 }
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 0ef1f47..dca7cab 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Apppaar is nie beskikbaar nie"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Meer opsies"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Wys alle legstukke"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d breed by %2$d hoog"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-legstuk"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 63cace9..3e0eaf7 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"የመተግበሪያ ጥምረት አይገኝም"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ምግብርን ለማንቀሳቀስ ይንኩ እና ይያዙ።"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ምግብርን ለማንቀሳቀስ ወይም ብጁ እርምጃዎችን ለመጠቀም ሁለቴ መታ ያድርጉ እና ይያዙ።"</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"ተጨማሪ አማራጮች"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"ሁሉንም ምግብሮች አሳይ"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ስፋት በ%2$d ከፍታ"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"የ<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ምግብር"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index d62400e..794c249 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"ميزة \"استخدام تطبيقين في الوقت نفسه\" غير متوفّرة"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"انقر مع الاستمرار لنقل أداة."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"انقر مرتين مع تثبيت إصبعك لنقل أداة أو استخدام الإجراءات المخصّصة."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"خيارات إضافية"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"عرض كل التطبيقات المصغّرة"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"‏العرض %1$d الطول %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"أداة <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index a3c0bc0..55a80b4 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"এপ্‌ পেয়াৰ কৰাৰ সুবিধাটো উপলব্ধ নহয়"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ৱিজেট স্থানান্তৰ কৰিবলৈ টিপি ধৰি ৰাখক।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"কোনো ৱিজেট স্থানান্তৰ কৰিবলৈ দুবাৰ টিপি ধৰি ৰাখক অথবা কাষ্টম কাৰ্য ব্যৱহাৰ কৰক।"</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"অধিক বিকল্প"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"আটাইবোৰ ৱিজেট দেখুৱাওক"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d বহল x %2$d ওখ"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ৱিজেট"</string>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index cfdcbe0..7713e89 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Tətbiq cütü əlçatan deyil"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Digər seçimlər"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Bütün vidcetləri göstərin"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%2$d hündürlük %1$d enində"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidceti"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 322a613..71bd34c 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Par aplikacija nije dostupan"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Još opcija"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Prikaži sve vidžete"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"širina od %1$d i visina od %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidžet"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 6f423aa..edb9a35 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Спалучэнне праграм недаступнае"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Націсніце і ўтрымлівайце віджэт для перамяшчэння."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Дакраніцеся двойчы і ўтрымлівайце, каб перамясціць віджэт або выкарыстоўваць спецыяльныя дзеянні."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Дадатковыя параметры"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Паказваць усе віджэты"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Шырына: %1$d, вышыня: %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Віджэт \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\""</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 2230012..3d39828 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Двойката приложения не е налице"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Докоснете и задръжте за преместване на приспособление"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Докоснете двукратно и задръжте за преместване на приспособление или използвайте персонал. действия."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Още опции"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Показв. на всички присп."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Ширина %1$d и височина %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> приспособление"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index e6dffb2..346a7ea 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Par aplikacija nije dostupan"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Više opcija"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Prikazuj sve vidžete"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Širina %1$d, visina %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Vidžet <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 014e481..9da16bb 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"La parella d\'aplicacions no està disponible"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Més opcions"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Mostra tots els widgets"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d d\'amplada per %2$d d\'alçada"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget de <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 456b4da..63858d3 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Dvojice aplikací není k dispozici"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Další možnosti"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Zobrazit všechny widgety"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"šířka %1$d, výška %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index b202828..99b1bf2 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Appsammenknytning er ikke tilgængelig"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Flere valgmuligheder"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Vis alle widgets"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d i bredden og %2$d i højden"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widgetten <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 3e984cd..d052fba 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"App-Paar nicht verfügbar"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Zum Verschieben des Widgets gedrückt 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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Weitere Optionen"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Alle Widgets anzeigen"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d breit und %2$d hoch"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget „<xliff:g id="WIDGET_NAME">%1$s</xliff:g>“"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index cda7670..5a178a4 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Το ζεύγος εφαρμογών δεν είναι διαθέσιμο"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Πατήστε παρατετ. για μετακίνηση γραφ. στοιχείου."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Πατήστε δύο φορές παρατεταμένα για μετακίνηση γραφικού στοιχείου ή χρήση προσαρμοσμένων ενεργειών."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Περισσότερες επιλογές"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Εμφ. συνόλου γραφ. στοιχ."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Πλάτος %1$d επί ύψος %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Γραφικό στοιχείο <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 80957b2..c9579a5 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"App pair isn\'t available"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"More options"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Show all widgets"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d wide by %2$d high"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 80957b2..c9579a5 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"App pair isn\'t available"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"More options"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Show all widgets"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d wide by %2$d high"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 80957b2..c9579a5 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"App pair isn\'t available"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"More options"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Show all widgets"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d wide by %2$d high"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index dc3e779..f5b4d8a 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"La vinculación de apps no está disponible"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Más opciones"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Mostrar todos los widgets"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de ancho por %2$d de alto"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 0f716dc..92e4a2d0 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"La aplicación emparejada no está disponible"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Más opciones"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Mostrar todos los widgets"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de ancho por %2$d de alto"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget de <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index e7e9c98..c2be8cd 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Rakendusepaar ei ole saadaval"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Rohkem valikuid"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Kuva kõik vidinad"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d lai ja %2$d kõrge"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Vidin <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 9868cca..4a9ae90 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Aplikazio parea ez dago erabilgarri"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Aukera gehiago"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Erakutsi widget guztiak"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d zabal eta %2$d luze"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widgeta"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 19689d3..0047f8d 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"جفت برنامه دردسترس نیست"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"برای جابه‌جا کردن ابزارک، لمس کنید و نگه دارید."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"برای جابه‌جا کردن ابزارک یا استفاده از کنش‌های سفارشی، دو تک‌ضرب بزنید و نگه دارید."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"گزینه‌های بیشتر"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"نمایش همه ابزاره‌ها"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"‏%1$d عرض در %2$d طول"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"ابزارک <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 6bb0faf..9eaaeb6 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Sovelluspari ei ole saatavilla"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Lisäasetukset"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Näytä kaikki widgetit"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Leveys: %1$d, korkeus: %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 6bf5d63..5490ee3 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"La Paire d\'applis n\'est pas offerte"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Autres options"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Afficher tous les widgets"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largeur sur %2$d de hauteur"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index c128343..6e04abd 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"La paire d\'applications n\'est pas disponible"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Autres options"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Afficher tous les widgets"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largeur et %2$d de hauteur"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index c5e00ef..92d52a7 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"ઍપની જોડી ઉપલબ્ધ નથી"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"વિજેટ ખસેડવા ટચ કરીને થોડી વાર દબાવી રાખો."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"વિજેટ ખસેડવા બે વાર ટૅપ કરીને દબાવી રાખો અથવા કસ્ટમ ક્રિયાઓનો ઉપયોગ કરો."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"વધુ વિકલ્પો"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"બધા વિજેટ બતાવો"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d પહોળાઈ X %2$d ઊંચાઈ"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> વિજેટ"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 6c86d88..eaf1b55 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Par aplikacija nije dostupan"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Više opcija"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Prikaži sve widgete"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d širine i %2$d visine"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 2378a52..c33cb5a 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Az alkalmazáspár nem áll rendelkezésre"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"További lehetőségek"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Minden modul mutatása"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d széles és %2$d magas"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> modul"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 67cc1d5..f06ff83 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Հավելվածների զույգը հասանելի չէ"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Հպեք և պահեք՝ վիջեթ տեղափոխելու համար։"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Կրկնակի հպեք և պահեք՝ վիջեթ տեղափոխելու համար, կամ օգտվեք հատուկ գործողություններից։"</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Այլ ընտրանքներ"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Ցույց տալ բոլոր վիջեթները"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Լայնությունը՝ %1$d, բարձրությունը՝ %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> վիջեթ"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index f112064..8487e62 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Pasangan aplikasi tidak tersedia"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Opsi lainnya"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Tampilkan semua widget"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"lebar %1$d x tinggi %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 558af15..ab343e5 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Forritapar er ekki í boði"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Fleiri valkostir"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Sýna allar græjur"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d á breidd og %2$d á hæð"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Græjan <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index fb05034..378d1e9 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"La coppia di app non è disponibile"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Altre opzioni"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Mostra tutti i widget"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d di larghezza per %2$d di altezza"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 09a876a..2e8cacb 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"צמד האפליקציות לא זמין"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"להעברת ווידג\'ט למקום אחר לוחצים עליו לחיצה ארוכה."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"כדי להעביר ווידג\'ט למקום אחר או להשתמש בפעולות מותאמות אישית, יש ללחוץ פעמיים ולא להרפות."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"אפשרויות נוספות"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"הצגת כל הווידג\'טים"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"‏רוחב %1$d על גובה %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"ווידג\'ט <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 369aa22..1d674cb 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"აპთა წყვილი მიუწვდომელია"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"შეხებით აირჩიეთ და გეჭიროთ ვიჯეტის გადასაადგილებლად."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ორმაგი შეხებით აირჩიეთ და გეჭიროთ ვიჯეტის გადასაადგილებლად ან მორგებული მოქმედებების გამოსაყენებლად."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"სხვა ვარიანტები"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"ყველა ვიჯეტის ჩვენება"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"სიგრძე: %1$d, სიგანე: %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ვიჯეტი"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 8d4efa7..363fc2f 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Қолданбаларды жұптау функциясы қолжетімді емес."</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Виджетті жылжыту үшін басып тұрыңыз."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетті жылжыту үшін екі рет түртіңіз де, ұстап тұрыңыз немесе арнаулы әрекеттерді пайдаланыңыз."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Басқа опциялар"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Барлық виджетті көрсету"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Ені: %1$d, биіктігі: %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджеті"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index caa92bd..ab5decf 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"មិនអាចប្រើគូកម្មវិធីបានទេ"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ចុចឱ្យជាប់​ដើម្បីផ្លាស់ទី​ធាតុក្រាហ្វិក​។"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ចុចពីរដង រួចសង្កត់ឱ្យជាប់ ដើម្បីផ្លាស់ទី​ធាតុក្រាហ្វិក ឬប្រើ​សកម្មភាព​តាមបំណង​។"</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"ជម្រើស​ច្រើនទៀត"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"បង្ហាញគ្រប់ធាតុ​ក្រាហ្វិក"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"ទទឺង %1$d គុណនឹងកម្ពស់ %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"ធាតុ​ក្រាហ្វិក <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 152745a..7aa9e03 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"앱 페어링을 사용할 수 없습니다."</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"길게 터치하여 위젯을 이동하세요."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"두 번 탭한 다음 길게 터치하여 위젯을 이동하거나 맞춤 작업을 사용하세요."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"옵션 더보기"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"모든 위젯 표시"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"너비 %1$d, 높이 %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"위젯 <xliff:g id="WIDGET_NAME">%1$s</xliff:g>개"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 6a9b4df..d0079d0 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Эки колдонмону бир маалда пайдаланууга болбойт"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Виджетти кое бербей басып туруп жылдырыңыз."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетти жылдыруу үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Дагы параметрлер"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Бардык виджет-ди көрсөтүү"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Туурасы: %1$d, бийиктиги: %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджети"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 6fd8345..426fdc0 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Lietotņu pāris nav pieejams"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Citas iespējas"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Rādīt visus logrīkus"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d plats un %2$d augsts"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Logrīks <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 5440af6..c84f232 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Парот апликации не е достапен"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Допрете и задржете за да преместите виџет."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Допрете двапати и задржете за да преместите виџет или користете приспособени дејства."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Повеќе опции"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Прикажи ги сите виџети"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d широк на %2$d висок"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Виџет <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 8a860bf..ff06bcf 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"ആപ്പ് ജോടി ലഭ്യമല്ല"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"വിജറ്റ് നീക്കാൻ സ്‌പർശിച്ച് പിടിക്കുക."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"വിജറ്റ് നീക്കാൻ ഡബിൾ ടാപ്പ് ചെയ്യൂ, ഹോൾഡ് ചെയ്യൂ അല്ലെങ്കിൽ ഇഷ്‌ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കൂ."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"കൂടുതൽ ഓപ്ഷനുകൾ"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"എല്ലാ വിജറ്റുകളും കാണിക്കൂ"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d വീതിയും %2$d ഉയരവും"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> വിജറ്റ്"</string>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index e85a33c..d9b220c 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Апп хослуулалт боломжгүй байна"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Виджетийг зөөх бол хүрээд, удаан дарна уу."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетийг зөөх эсвэл захиалгат үйлдлийг ашиглахын тулд хоёр товшоод, удаан дарна уу."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Бусад сонголт"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Бүх виджетийг харуулах"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d өргөн %2$d өндөр"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> жижиг хэрэгсэл"</string>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index a6b8500..946d8df 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"အက်ပ်တွဲချိတ်ခြင်းကို မရနိုင်ပါ"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ဝိဂျက်ကို ရွှေ့ရန် တို့ပြီး ဖိထားပါ။"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ဝိဂျက်ကို ရွှေ့ရန် (သို့) စိတ်ကြိုက်လုပ်ဆောင်ချက်များကို သုံးရန် နှစ်ချက်တို့ပြီး ဖိထားပါ။"</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"နောက်ထပ် ရွေးစရာများ"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"ဝိဂျက်အားလုံး ပြပါ"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"အလျား %1$d နှင့် အမြင့် %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ဝိဂျက်"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index bc688aa..5c0158c 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Apptilkoblingen er ikke tilgjengelig"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Flere alternativer"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Vis alle moduler"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d bredde x %2$d høyde"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-modul"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 000ab13..74001c7 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"ଆପ ପେୟାର ଉପଲବ୍ଧ ନାହିଁ"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ଦୁଇଥର-ଟାପ୍ କରି ଧରି ରଖନ୍ତୁ କିମ୍ବା କଷ୍ଟମ୍ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"ଅଧିକ ବିକଳ୍ପ"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"ସମସ୍ତ ୱିଜେଟ ଦେଖାନ୍ତୁ"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ଓସାର ଓ %2$d ଉଚ୍ଚ"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ୱିଜେଟ୍"</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 6e558c3..e72d1f3 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"ਐਪ ਜੋੜਾਬੱਧ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ਕਿਸੇ ਵਿਜੇਟ ਨੂੰ ਲਿਜਾਉਣ ਲਈ ਸਪਰਸ਼ ਕਰਕੇ ਰੱਖੋ।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ਵਿਜੇਟ ਲਿਜਾਉਣ ਲਈ ਜਾਂ ਵਿਉਂਂਤੀਆਂ ਕਾਰਵਾਈਆਂ ਵਰਤਣ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰਕੇ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"ਹੋਰ ਵਿਕਲਪ"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"ਸਭ ਵਿਜੇਟ ਦਿਖਾਓ"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ਚੌੜਾਈ ਅਤੇ %2$d ਲੰਬਾਈ"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ਵਿਜੇਟ"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index c2aaf69..76ddbdc 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Para aplikacji jest niedostępna"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Więcej opcji"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Pokaż wszystkie widżety"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Szerokość %1$d, wysokość %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widżet <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 10cf03f..20edc93 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"O Par de apps não está disponível"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Toque e pressione para mover um widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toque duas vezes e mantenha a tela pressionada para mover um widget ou usar ações personalizadas."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Mais opções"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Mostrar todos os widgets"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largura por %2$d de altura"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 510f671..ec8e558 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Perechea de aplicații nu este disponibilă"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Mai multe opțiuni"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Afișează toate widgeturile"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d lățime și %2$d înălțime"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widgetul <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 3add9fa..c941cba 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Одновременное использование двух приложений недоступно"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Чтобы переместить виджет, нажмите на него и удерживайте"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Чтобы использовать специальные действия или перенести виджет, нажмите на него дважды и удерживайте."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Другие параметры"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Показать все виджеты"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Ширина %1$d, высота %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Виджет \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\""</string>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 2adccc3..298a078 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"යෙදුම් යුගලයක් නොමැත"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"විජට් එකක් ගෙන යාමට ස්පර්ශ කර අල්ලා ගෙන සිටින්න."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"විජට් එකක් ගෙන යාමට හෝ අභිරුචි ක්‍රියා භාවිත කිරීමට දෙවරක් තට්ටු කර අල්ලා ගෙන සිටින්න."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"තවත් විකල්ප"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"සියලු ම විජට් පෙන්වන්න"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"පළල %1$d උස %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> විජට්ටුව"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 2a44faf..94d109c 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Pár aplikácií nie je k dispozícii"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Ďalšie možnosti"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Zobrazovať všetky miniap."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"šírka %1$d, výška %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Miniaplikácia <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 638f9e4..6ee5e07 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Par aplikacij ni na voljo"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Več možnosti"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Pokaži vse pripomočke"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Širina %1$d, višina %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Pripomoček <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 72e4f04..f106fab 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Çifti i aplikacioneve nuk ofrohet"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Opsione të tjera"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Shfaq të gjitha miniapl."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d i gjerë me %2$d i lartë"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> miniaplikacion"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 0252765..a9c4e24 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Пар апликација није доступан"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Додирните и задржите ради померања виџета."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Двапут додирните и задржите да бисте померали виџет или користите прилагођене радње."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Још опција"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Прикажи све виџете"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"ширина од %1$d и висина од %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виџет"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 6c03884..5806d1e 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"App-paret är inte tillgängligt"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Fler alternativ"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Visa alla widgetar"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d bred gånger %2$d hög"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget för <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index cb93952..5d69573 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Kipengele cha jozi ya programu hakipatikani"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Chaguo zaidi"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Onyesha wijeti zote"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Upana wa %1$d na kimo cha %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Wijeti ya <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index ef3635c..559843a 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"ஆப்ஸ் ஜோடி கிடைக்கவில்லை"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"விட்ஜெட்டை நகர்த்தத் தொட்டுப் பிடிக்கவும்."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"விட்ஜெட்டை நகர்த்த இருமுறை தட்டிப் பிடிக்கவும் அல்லது பிரத்தியேகச் செயல்களைப் பயன்படுத்தவும்."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"கூடுதல் விருப்பங்கள்"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"விட்ஜெட்டுகளைக் காட்டு"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d அகலத்திற்கு %2$d உயரம்"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> விட்ஜெட்"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 12dfb60..cf18156 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"యాప్ పెయిర్ అందుబాటులో లేదు"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"విడ్జెట్‌ను తరలించడానికి తాకి &amp; నొక్కి ఉంచండి."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"విడ్జెట్‌ను తరలించడానికి లేదా అనుకూల చర్యలను ఉపయోగించడానికి రెండుసార్లు నొక్కండి &amp; హోల్డ్ చేయి."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"మరిన్ని ఆప్షన్‌లు"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"అన్ని విడ్జెట్‌లను చూడండి"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d వెడల్పు X %2$d ఎత్తు"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> విడ్జెట్"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 9522e572..706c4f4 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"การจับคู่อุปกรณ์ไม่พร้อมให้บริการ"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"แตะค้างไว้เพื่อย้ายวิดเจ็ต"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"แตะสองครั้งค้างไว้เพื่อย้ายวิดเจ็ตหรือใช้การดำเนินการที่กำหนดเอง"</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"ตัวเลือกเพิ่มเติม"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"แสดงวิดเจ็ตทั้งหมด"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"กว้าง %1$d x สูง %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"วิดเจ็ต <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 6c27385..d99ffdc 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Hindi available ang pares ng app"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Higit pang opsyon"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Ipakita lahat ng widget"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ang lapad at %2$d ang taas"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index fe4d538..09939b3 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Uygulama çifti kullanılamıyor"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Diğer seçenekler"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Tüm widget\'ları göster"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"genişlik: %1$d, yükseklik: %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget\'ı"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index cdb943e..0c9ee22 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Одночасне використання двох додатків недоступне"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Натисніть і втримуйте, щоб перемістити віджет."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Двічі натисніть і втримуйте віджет, щоб перемістити його або виконати інші дії."</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Інші опції"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Показати всі віджети"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Ширина – %1$d, висота – %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Віджет <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index a12e8f9..8312ece 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"ایپ کا جوڑا دستیاب نہیں ہے"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ویجیٹ منتقل کرنے کے لیے ٹچ کریں اور پکڑ کر رکھیں۔"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ویجیٹ کو منتقل کرنے یا حسب ضرورت کارروائیاں استعمال کرنے کے لیے دوبار تھپتھپائیں اور پکڑ کر رکھیں۔"</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"مزید اختیارات"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"سبھی ویجیٹس دکھائیں"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"‏%1$d چوڑا اور ‎%2$d اونچا"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ویجیٹ"</string>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index ad5137e..8f41d49 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Ikkita ilovadan bir vaqtda foydalanish mumkin emas"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Yana"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Barcha vidjetlar"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Eni %1$d, bo‘yi %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ta vidjet"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index bcb4b98..af4a773 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Hiện không có cặp ứng dụng này"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Lựa chọn khác"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Hiện tất cả tiện ích"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Rộng %1$d x cao %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Tiện ích <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index b36f7d6..3435eb0 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"应用对不可用"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"轻触并按住即可移动微件。"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"点按两次并按住微件即可移动该微件或使用自定义操作。"</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"更多选项"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"显示所有微件"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"宽 %1$d,高 %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"“<xliff:g id="WIDGET_NAME">%1$s</xliff:g>”微件"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index d3de49c..950d54b 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"應用程式配對無法使用"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"輕觸並按住即可移動小工具。"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"㩒兩下之後㩒住,就可以郁小工具或者用自訂操作。"</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"更多選項"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"顯示所有小工具"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d 闊,%2$d 高"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"「<xliff:g id="WIDGET_NAME">%1$s</xliff:g>」小工具"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 5b65c35..331071d 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"這個應用程式配對無法使用"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"按住即可移動小工具。"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"輕觸兩下並按住即可移動小工具或使用自訂操作。"</string>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"更多選項"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"顯示所有小工具"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"寬度為 %1$d,高度為 %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"「<xliff:g id="WIDGET_NAME">%1$s</xliff:g>」小工具"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index fb6d8f2..d167f14 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -38,10 +38,8 @@
     <string name="app_pair_not_available" msgid="3556767440808032031">"Ukubhangqwa kwe-app akutholakali"</string>
     <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>
-    <!-- no translation found for widget_picker_widget_options_button_description (4770099264476852363) -->
-    <skip />
-    <!-- no translation found for widget_picker_show_all_widgets_menu_item_title (9023638224586908119) -->
-    <skip />
+    <string name="widget_picker_widget_options_button_description" msgid="4770099264476852363">"Okungakhethwa kukho okuningi"</string>
+    <string name="widget_picker_show_all_widgets_menu_item_title" msgid="9023638224586908119">"Bonisa wonke amawijethi"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ububanzi ngokungu-%2$d ukuya phezulu"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Iwijethi elingu-<xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 00db3a3..1a5f4b9 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -993,7 +993,6 @@
         return mHotseatColumnSpan;
     }
 
-    @VisibleForTesting
     public int getHotseatWidthPx() {
         return mHotseatWidthPx;
     }
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index f775673..0d4ebe0 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -162,14 +162,14 @@
                 animatorSet.play(ObjectAnimator.ofFloat(child, VIEW_TRANSLATE_X, tx));
             }
         }
-        if (mQsb instanceof HorizontalInsettableView) {
-            HorizontalInsettableView horizontalInsettableQsb = (HorizontalInsettableView) mQsb;
-            ValueAnimator qsbAnimator = ValueAnimator.ofFloat(0f, 1f);
+        if (mQsb instanceof HorizontalInsettableView horizontalInsettableQsb) {
+            final float currentInsetFraction = horizontalInsettableQsb.getHorizontalInsets();
+            final float targetInsetFraction =
+                    isBubbleBarVisible ? (float) dp.iconSizePx / dp.hotseatQsbWidth : 0;
+            ValueAnimator qsbAnimator =
+                    ValueAnimator.ofFloat(currentInsetFraction, targetInsetFraction);
             qsbAnimator.addUpdateListener(animation -> {
-                float fraction = qsbAnimator.getAnimatedFraction();
-                float insetFraction = isBubbleBarVisible
-                        ? (float) dp.iconSizePx * fraction / dp.hotseatQsbWidth
-                        : (float) dp.iconSizePx * (1 - fraction) / dp.hotseatQsbWidth;
+                float insetFraction = (float) animation.getAnimatedValue();
                 horizontalInsettableQsb.setHorizontalInsets(insetFraction);
             });
             animatorSet.play(qsbAnimator);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 5949732..6c706be 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -266,6 +266,7 @@
 import com.android.launcher3.widget.custom.CustomWidgetManager;
 import com.android.launcher3.widget.model.WidgetsListBaseEntry;
 import com.android.launcher3.widget.picker.WidgetsFullSheet;
+import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider;
 import com.android.launcher3.widget.util.WidgetSizes;
 import com.android.systemui.plugins.LauncherOverlayPlugin;
 import com.android.systemui.plugins.PluginListener;
@@ -371,6 +372,7 @@
     private LauncherAccessibilityDelegate mAccessibilityDelegate;
 
     private PopupDataProvider mPopupDataProvider;
+    private WidgetPickerDataProvider mWidgetPickerDataProvider;
 
     // We only want to get the SharedPreferences once since it does an FS stat each time we get
     // it from the context.
@@ -532,6 +534,7 @@
                 mFocusHandler, new CellLayout(mWorkspace.getContext(), mWorkspace));
 
         mPopupDataProvider = new PopupDataProvider(this::updateNotificationDots);
+        mWidgetPickerDataProvider = new WidgetPickerDataProvider();
 
         boolean internalStateHandled = ACTIVITY_TRACKER.handleCreate(this);
         if (internalStateHandled) {
@@ -2702,6 +2705,7 @@
         mDragLayer.dump(prefix, writer);
         mStateManager.dump(prefix, writer);
         mPopupDataProvider.dump(prefix, writer);
+        mWidgetPickerDataProvider.dump(prefix, writer);
         mDeviceProfile.dump(this, prefix, writer);
         mAppsView.getAppsStore().dump(prefix, writer);
 
@@ -3011,6 +3015,12 @@
         return mPopupDataProvider;
     }
 
+    @NonNull
+    @Override
+    public WidgetPickerDataProvider getWidgetPickerDataProvider() {
+        return mWidgetPickerDataProvider;
+    }
+
     @Override
     public DotInfo getDotInfoForItem(ItemInfo info) {
         return mPopupDataProvider.getDotInfoForItem(info);
diff --git a/src/com/android/launcher3/ModelCallbacks.kt b/src/com/android/launcher3/ModelCallbacks.kt
index 83c34ce..d57f8a0 100644
--- a/src/com/android/launcher3/ModelCallbacks.kt
+++ b/src/com/android/launcher3/ModelCallbacks.kt
@@ -254,8 +254,8 @@
         PopupContainerWithArrow.dismissInvalidPopup(launcher)
     }
 
-    override fun bindAllWidgets(allWidgets: List<WidgetsListBaseEntry?>?) {
-        launcher.popupDataProvider.allWidgets = allWidgets
+    override fun bindAllWidgets(allWidgets: List<WidgetsListBaseEntry>) {
+        launcher.widgetPickerDataProvider.setWidgets(allWidgets, /* defaultWidgets= */ listOf())
     }
 
     /** Returns the ids of the workspaces to bind. */
@@ -304,7 +304,8 @@
         }
 
         val widgetsListBaseEntry: WidgetsListBaseEntry =
-            launcher.popupDataProvider.allWidgets.firstOrNull { item: WidgetsListBaseEntry ->
+            launcher.widgetPickerDataProvider.get().allWidgets.firstOrNull {
+                item: WidgetsListBaseEntry ->
                 item.mPkgItem.packageName == BuildConfig.APPLICATION_ID
             } ?: return
 
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 53fed20..fde7014 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -178,6 +178,11 @@
         sIsRunningInTestHarness = true;
     }
 
+    /** Disables running test in test harness mode */
+    public static void disableRunningInTestHarnessForTests() {
+        sIsRunningInTestHarness = false;
+    }
+
     public static boolean isPropertyEnabled(String propertyName) {
         return Log.isLoggable(propertyName, Log.VERBOSE);
     }
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 5d03a93..9271596 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.allapps;
 
+import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_BOTTOM_VIEW_TO_SCROLL_TO;
 import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_BOTTOM_LEFT;
 import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_BOTTOM_RIGHT;
 import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_NOTHING;
@@ -295,6 +296,14 @@
             if (Flags.enablePrivateSpace()) {
                 position = addPrivateSpaceItems(position);
             }
+            if (!mFastScrollerSections.isEmpty()) {
+                // After all the adapterItems are added, add a view to the bottom so that user can
+                // scroll all the way down.
+                mAdapterItems.add(new AdapterItem(VIEW_TYPE_BOTTOM_VIEW_TO_SCROLL_TO));
+                mFastScrollerSections.add(new FastScrollSectionInfo(
+                        mFastScrollerSections.get(mFastScrollerSections.size() - 1).sectionName,
+                        position++));
+            }
         }
         mAccessibilityResultsCount = (int) mAdapterItems.stream()
                 .filter(AdapterItem::isCountedForAccessibility).count();
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
index 4b38df8..60bf3ea 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
@@ -68,7 +68,8 @@
     public static final int VIEW_TYPE_WORK_DISABLED_CARD = 1 << 5;
     public static final int VIEW_TYPE_PRIVATE_SPACE_HEADER = 1 << 6;
     public static final int VIEW_TYPE_PRIVATE_SPACE_SYS_APPS_DIVIDER = 1 << 7;
-    public static final int NEXT_ID = 8;
+    public static final int VIEW_TYPE_BOTTOM_VIEW_TO_SCROLL_TO = 1 << 8;
+    public static final int NEXT_ID = 9;
 
     // Common view type masks
     public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
@@ -247,6 +248,8 @@
             case VIEW_TYPE_PRIVATE_SPACE_HEADER:
                 return new ViewHolder(mLayoutInflater.inflate(
                         R.layout.private_space_header, parent, false));
+            case VIEW_TYPE_BOTTOM_VIEW_TO_SCROLL_TO:
+                return new ViewHolder(new View(mActivityContext));
             default:
                 if (mAdapterProvider.isViewSupported(viewType)) {
                     return mAdapterProvider.onCreateViewHolder(mLayoutInflater, parent, viewType);
@@ -324,6 +327,7 @@
                         == STATE_DISABLED ? null : new SectionDecorationInfo(mActivityContext,
                         ROUND_NOTHING, true /* decorateTogether */);
                 break;
+            case VIEW_TYPE_BOTTOM_VIEW_TO_SCROLL_TO:
             case VIEW_TYPE_ALL_APPS_DIVIDER:
             case VIEW_TYPE_WORK_DISABLED_CARD:
                 // nothing to do
diff --git a/src/com/android/launcher3/allapps/FloatingMaskView.java b/src/com/android/launcher3/allapps/FloatingMaskView.java
index 606eb03..cee5e18 100644
--- a/src/com/android/launcher3/allapps/FloatingMaskView.java
+++ b/src/com/android/launcher3/allapps/FloatingMaskView.java
@@ -21,6 +21,7 @@
 import android.view.ViewGroup;
 import android.widget.ImageView;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.constraintlayout.widget.ConstraintLayout;
 
 import com.android.launcher3.R;
@@ -53,13 +54,21 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();
-        AllAppsRecyclerView allAppsContainerView =
-                mActivityContext.getAppsView().getActiveRecyclerView();
+        setParameters((ViewGroup.MarginLayoutParams) getLayoutParams(),
+                mActivityContext.getAppsView().getActiveRecyclerView());
+    }
+
+    @VisibleForTesting
+    void setParameters(ViewGroup.MarginLayoutParams lp, AllAppsRecyclerView recyclerView) {
         if (lp != null) {
-            lp.rightMargin = allAppsContainerView.getPaddingRight();
-            lp.leftMargin = allAppsContainerView.getPaddingLeft();
-            mBottomBox.setMinimumHeight(allAppsContainerView.getPaddingBottom());
+            lp.rightMargin = recyclerView.getPaddingRight();
+            lp.leftMargin = recyclerView.getPaddingLeft();
+            getBottomBox().setMinimumHeight(recyclerView.getPaddingBottom());
         }
     }
+
+    @VisibleForTesting
+    ImageView getBottomBox() {
+        return mBottomBox;
+    }
 }
diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java
index c1264d6..e215cab 100644
--- a/src/com/android/launcher3/allapps/PrivateProfileManager.java
+++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java
@@ -403,6 +403,7 @@
                     mLockText.setHorizontallyScrolling(false);
                     mPrivateSpaceSettingsButton.setVisibility(
                             isPrivateSpaceSettingsAvailable() ? VISIBLE : GONE);
+                    mPrivateSpaceSettingsButton.setClickable(isPrivateSpaceSettingsAvailable());
                 }
                 lockPill.setVisibility(VISIBLE);
                 lockPill.setOnClickListener(view -> lockingAction(/* lock */ true));
@@ -425,6 +426,7 @@
                 lockPill.setContentDescription(mLockedStateContentDesc);
 
                 mPrivateSpaceSettingsButton.setVisibility(GONE);
+                mPrivateSpaceSettingsButton.setClickable(false);
                 transitionView.setVisibility(GONE);
             }
             case STATE_TRANSITION -> {
@@ -660,10 +662,7 @@
             return;
         }
         attachFloatingMaskView(expand);
-        PropertySetter headerSetter = new AnimatedPropertySetter();
-        headerSetter.add(updateSettingsGearAlpha(expand));
-        headerSetter.add(updateLockTextAlpha(expand));
-        AnimatorSet animatorSet = headerSetter.buildAnim();
+        AnimatorSet animatorSet = new AnimatedPropertySetter().buildAnim();
         animatorSet.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
@@ -708,12 +707,16 @@
             }
         }));
         if (expand) {
-            animatorSet.playTogether(animateAlphaOfIcons(true),
+            animatorSet.playTogether(updateSettingsGearAlpha(true),
+                    updateLockTextAlpha(true),
+                    animateAlphaOfIcons(true),
                     animatePillTransition(true),
                     translateFloatingMaskView(false));
         } else {
             AnimatorSet parallelSet = new AnimatorSet();
-            parallelSet.playTogether(animateAlphaOfIcons(false),
+            parallelSet.playTogether(updateSettingsGearAlpha(false),
+                    updateLockTextAlpha(false),
+                    animateAlphaOfIcons(false),
                     animatePillTransition(false));
             if (isPrivateSpaceHidden()) {
                 animatorSet.playSequentially(parallelSet,
@@ -794,6 +797,14 @@
             @Override
             public void onAnimationStart(Animator animator) {
                 mPrivateSpaceSettingsButton.setVisibility(VISIBLE);
+                mPrivateSpaceSettingsButton.setClickable(false);
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animator) {
+                if (expand) {
+                    mPrivateSpaceSettingsButton.setClickable(true);
+                }
             }
         });
         return settingsAlphaAnim;
diff --git a/src/com/android/launcher3/model/GridSizeMigrationUtil.java b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
index ad32fc2..f54fc57 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationUtil.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
@@ -213,9 +213,13 @@
         Collections.sort(hotseatToBeAdded);
         Collections.sort(workspaceToBeAdded);
 
+        List<Integer> idsInUse = dstWorkspaceItems.stream().map(entry -> entry.id).collect(
+                Collectors.toList());
+        idsInUse.addAll(dstHotseatItems.stream().map(entry -> entry.id).toList());
+
         // Migrate hotseat
         solveHotseatPlacement(helper, destHotseatSize,
-                srcReader, destReader, dstHotseatItems, hotseatToBeAdded);
+                srcReader, destReader, dstHotseatItems, hotseatToBeAdded, idsInUse);
 
         // Migrate workspace.
         // First we create a collection of the screens
@@ -230,7 +234,7 @@
                 Log.d(TAG, "Migrating " + screenId);
             }
             solveGridPlacement(helper, srcReader,
-                    destReader, screenId, trgX, trgY, workspaceToBeAdded);
+                    destReader, screenId, trgX, trgY, workspaceToBeAdded, idsInUse);
             if (workspaceToBeAdded.isEmpty()) {
                 break;
             }
@@ -241,7 +245,7 @@
         int screenId = destReader.mLastScreenId + 1;
         while (!workspaceToBeAdded.isEmpty()) {
             solveGridPlacement(helper, srcReader, destReader, screenId, trgX, trgY,
-                    workspaceToBeAdded);
+                    workspaceToBeAdded, srcWorkspaceItems.stream().map(entry -> entry.id).toList());
             screenId++;
         }
 
@@ -257,47 +261,57 @@
     private static void calcDiff(@NonNull final List<DbEntry> src,
             @NonNull final List<DbEntry> dest, @NonNull final List<DbEntry> toBeAdded,
             @NonNull final IntArray toBeRemoved) {
+        HashMap<DbEntry, Integer> entryCountDiff = new HashMap<>();
+        src.forEach(entry ->
+                entryCountDiff.put(entry, entryCountDiff.getOrDefault(entry, 0) + 1));
+        dest.forEach(entry ->
+                entryCountDiff.put(entry, entryCountDiff.getOrDefault(entry, 0) - 1));
+
         src.forEach(entry -> {
-            if (!dest.contains(entry)) {
+            if (entryCountDiff.get(entry) > 0) {
                 toBeAdded.add(entry);
+                entryCountDiff.put(entry, entryCountDiff.get(entry) - 1);
             }
         });
+
         dest.forEach(entry -> {
-            if (!src.contains(entry)) {
+            if (entryCountDiff.get(entry) < 0) {
                 toBeRemoved.add(entry.id);
                 if (entry.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
                     entry.mFolderItems.values().forEach(ids -> ids.forEach(toBeRemoved::add));
                 }
+                entryCountDiff.put(entry, entryCountDiff.get(entry) + 1);
             }
         });
     }
 
     private static void insertEntryInDb(DatabaseHelper helper, DbEntry entry,
-            String srcTableName, String destTableName) {
-        int id = copyEntryAndUpdate(helper, entry, srcTableName, destTableName);
-
+            String srcTableName, String destTableName, List<Integer> idsInUse) {
+        int id = copyEntryAndUpdate(helper, entry, srcTableName, destTableName, idsInUse);
         if (entry.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER
                 || entry.itemType == LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR) {
             for (Set<Integer> itemIds : entry.mFolderItems.values()) {
                 for (int itemId : itemIds) {
-                    copyEntryAndUpdate(helper, itemId, id, srcTableName, destTableName);
+                    copyEntryAndUpdate(helper, itemId, id, srcTableName, destTableName, idsInUse);
                 }
             }
         }
     }
 
     private static int copyEntryAndUpdate(DatabaseHelper helper,
-            DbEntry entry, String srcTableName, String destTableName) {
-        return copyEntryAndUpdate(helper, entry, -1, -1, srcTableName, destTableName);
+            DbEntry entry, String srcTableName, String destTableName, List<Integer> idsInUse) {
+        return copyEntryAndUpdate(
+                helper, entry, -1, -1, srcTableName, destTableName, idsInUse);
     }
 
-    private static int copyEntryAndUpdate(DatabaseHelper helper,
-            int id, int folderId, String srcTableName, String destTableName) {
-        return copyEntryAndUpdate(helper, null, id, folderId, srcTableName, destTableName);
+    private static int copyEntryAndUpdate(DatabaseHelper helper, int id,
+            int folderId, String srcTableName, String destTableName, List<Integer> idsInUse) {
+        return copyEntryAndUpdate(
+                helper, null, id, folderId, srcTableName, destTableName, idsInUse);
     }
 
-    private static int copyEntryAndUpdate(DatabaseHelper helper, DbEntry entry,
-            int id, int folderId, String srcTableName, String destTableName) {
+    private static int copyEntryAndUpdate(DatabaseHelper helper, DbEntry entry, int id,
+            int folderId, String srcTableName, String destTableName, List<Integer> idsInUse) {
         int newId = -1;
         Cursor c = helper.getWritableDatabase().query(srcTableName, null,
                 LauncherSettings.Favorites._ID + " = '" + (entry != null ? entry.id : id) + "'",
@@ -311,6 +325,9 @@
                 values.put(LauncherSettings.Favorites.CONTAINER, folderId);
             }
             newId = helper.generateNewItemId();
+            while (idsInUse.contains(newId)) {
+                newId = helper.generateNewItemId();
+            }
             values.put(LauncherSettings.Favorites._ID, newId);
             helper.getWritableDatabase().insert(destTableName, null, values);
         }
@@ -343,7 +360,7 @@
     private static void solveGridPlacement(@NonNull final DatabaseHelper helper,
             @NonNull final DbReader srcReader, @NonNull final DbReader destReader,
             final int screenId, final int trgX, final int trgY,
-            @NonNull final List<DbEntry> sortedItemsToPlace) {
+            @NonNull final List<DbEntry> sortedItemsToPlace, List<Integer> idsInUse) {
         final GridOccupancy occupied = new GridOccupancy(trgX, trgY);
         final Point trg = new Point(trgX, trgY);
         final Point next = new Point(0, screenId == 0
@@ -366,7 +383,8 @@
                 continue;
             }
             if (findPlacementForEntry(entry, next, trg, occupied, screenId)) {
-                insertEntryInDb(helper, entry, srcReader.mTableName, destReader.mTableName);
+                insertEntryInDb(
+                        helper, entry, srcReader.mTableName, destReader.mTableName, idsInUse);
                 iterator.remove();
             }
         }
@@ -407,7 +425,7 @@
             @NonNull final DatabaseHelper helper, final int hotseatSize,
             @NonNull final DbReader srcReader, @NonNull final DbReader destReader,
             @NonNull final  List<DbEntry> placedHotseatItems,
-            @NonNull final List<DbEntry> itemsToPlace) {
+            @NonNull final List<DbEntry> itemsToPlace, List<Integer> idsInUse) {
 
         final boolean[] occupied = new boolean[hotseatSize];
         for (DbEntry entry : placedHotseatItems) {
@@ -422,7 +440,8 @@
                 // to something other than -1.
                 entry.cellX = i;
                 entry.cellY = 0;
-                insertEntryInDb(helper, entry, srcReader.mTableName, destReader.mTableName);
+                insertEntryInDb(
+                        helper, entry, srcReader.mTableName, destReader.mTableName, idsInUse);
                 occupied[entry.screenId] = true;
             }
         }
@@ -564,12 +583,12 @@
                         }
                         case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: {
                             entry.mProvider = c.getString(indexAppWidgetProvider);
+                            entry.appWidgetId = c.getInt(indexAppWidgetId);
                             ComponentName cn = ComponentName.unflattenFromString(entry.mProvider);
                             verifyPackage(cn.getPackageName());
 
-                            int widgetId = c.getInt(indexAppWidgetId);
                             LauncherAppWidgetProviderInfo pInfo = widgetManagerHelper
-                                    .getLauncherAppWidgetInfo(widgetId, cn);
+                                    .getLauncherAppWidgetInfo(entry.appWidgetId, cn);
                             Point spans = null;
                             if (pInfo != null) {
                                 spans = pInfo.getMinSpans();
diff --git a/src/com/android/launcher3/model/ModelDbController.java b/src/com/android/launcher3/model/ModelDbController.java
index 7e1d40d..da1a221 100644
--- a/src/com/android/launcher3/model/ModelDbController.java
+++ b/src/com/android/launcher3/model/ModelDbController.java
@@ -83,6 +83,7 @@
 
 import org.xmlpull.v1.XmlPullParser;
 
+import java.io.File;
 import java.io.InputStream;
 import java.io.StringReader;
 
@@ -104,10 +105,30 @@
         mContext = context;
     }
 
+    private void printDBs(String prefix) {
+        try {
+            File directory = new File(
+                    mContext.getDatabasePath(InvariantDeviceProfile.INSTANCE.get(mContext).dbFile)
+                            .getParent()
+            );
+            if (directory.exists()) {
+                for (File file : directory.listFiles()) {
+                    Log.d("b/353505773", prefix + "Database file: " + file.getName());
+                }
+            } else {
+                Log.d("b/353505773", prefix + "No files found in the database directory");
+            }
+        } catch (Exception e) {
+            Log.e("b/353505773", prefix + e.getMessage());
+        }
+    }
+
     private synchronized void createDbIfNotExists() {
         if (mOpenHelper == null) {
             mOpenHelper = createDatabaseHelper(false /* forMigration */);
+            printDBs("before: ");
             RestoreDbTask.restoreIfNeeded(mContext, this);
+            printDBs("after: ");
         }
     }
 
diff --git a/src/com/android/launcher3/model/WidgetsModel.java b/src/com/android/launcher3/model/WidgetsModel.java
index 35064cf..c949ce6 100644
--- a/src/com/android/launcher3/model/WidgetsModel.java
+++ b/src/com/android/launcher3/model/WidgetsModel.java
@@ -89,7 +89,7 @@
         if (!WIDGETS_ENABLED) {
             return Collections.emptyMap();
         }
-        return mWidgetsByPackageItem;
+        return new HashMap<>(mWidgetsByPackageItem);
     }
 
     /**
diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java
index 7e139c3..8a5e388 100644
--- a/src/com/android/launcher3/popup/PopupDataProvider.java
+++ b/src/com/android/launcher3/popup/PopupDataProvider.java
@@ -24,28 +24,20 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.dot.DotInfo;
-import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.notification.NotificationKeyData;
 import com.android.launcher3.notification.NotificationListener;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.PackageUserKey;
 import com.android.launcher3.util.ShortcutUtil;
-import com.android.launcher3.widget.PendingAddWidgetInfo;
-import com.android.launcher3.widget.model.WidgetsListBaseEntry;
-import com.android.launcher3.widget.model.WidgetsListContentEntry;
-import com.android.launcher3.widget.picker.WidgetRecommendationCategory;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.function.Consumer;
-import java.util.function.Function;
 import java.util.function.Predicate;
-import java.util.stream.Collectors;
 
 /**
  * Provides data for the popup menu that appears after long-clicking on apps.
@@ -62,18 +54,6 @@
     /** Maps packages to their DotInfo's . */
     private Map<PackageUserKey, DotInfo> mPackageUserToDotInfos = new HashMap<>();
 
-    /** All installed widgets. */
-    private List<WidgetsListBaseEntry> mAllWidgets = List.of();
-    /**
-     * Selectively chosen installed widgets which may be preferred for default display over the list
-     * of all widgets.
-     */
-    private List<WidgetsListBaseEntry> mDefaultWidgets = List.of();
-    /** Widgets that can be recommended to the users. */
-    private List<ItemInfo> mRecommendedWidgets = List.of();
-
-    private PopupDataChangeListener mChangeListener = PopupDataChangeListener.INSTANCE;
-
     public PopupDataProvider(Consumer<Predicate<PackageUserKey>> notificationDotsChangeListener) {
         mNotificationDotsChangeListener = notificationDotsChangeListener;
     }
@@ -188,124 +168,8 @@
         })) ? dotInfo : null;
     }
 
-    /**
-     * Sets a list of recommended widgets ordered by their order of appearance in the widgets
-     * recommendation UI.
-     */
-    public void setRecommendedWidgets(List<ItemInfo> recommendedWidgets) {
-        mRecommendedWidgets = recommendedWidgets;
-        mChangeListener.onRecommendedWidgetsBound();
-    }
-
-    public void setAllWidgets(List<WidgetsListBaseEntry> allWidgets) {
-        mAllWidgets = allWidgets;
-        mDefaultWidgets = List.of();
-        mChangeListener.onWidgetsBound();
-    }
-
-    /**
-     * Sets the list of widgets to be displayed by default and a complete list that can be displayed
-     * when user chooses to show all widgets.
-     */
-    public void setAllWidgets(List<WidgetsListBaseEntry> allWidgets,
-            List<WidgetsListBaseEntry> defaultWidgets) {
-        mAllWidgets = allWidgets;
-        mDefaultWidgets = defaultWidgets;
-        mChangeListener.onWidgetsBound();
-    }
-
-    public void setChangeListener(PopupDataChangeListener listener) {
-        mChangeListener = listener == null ? PopupDataChangeListener.INSTANCE : listener;
-    }
-
-    public List<WidgetsListBaseEntry> getAllWidgets() {
-        return mAllWidgets;
-    }
-
-    /**
-     * Returns a "selectively" chosen list of widgets that may be preferred to be shown by default
-     * instead of a complete list.
-     */
-    public List<WidgetsListBaseEntry> getDefaultWidgets() {
-        return mDefaultWidgets;
-    }
-
-    /** Returns a list of recommended widgets. */
-    public List<WidgetItem> getRecommendedWidgets() {
-        HashMap<ComponentKey, WidgetItem> allWidgetItems = new HashMap<>();
-        mAllWidgets.stream()
-                .filter(entry -> entry instanceof WidgetsListContentEntry)
-                .forEach(entry -> ((WidgetsListContentEntry) entry).mWidgets
-                        .forEach(widget -> allWidgetItems.put(
-                                new ComponentKey(widget.componentName, widget.user), widget)));
-        return mRecommendedWidgets.stream()
-                .map(recommendedWidget -> allWidgetItems.get(
-                        new ComponentKey(recommendedWidget.getTargetComponent(),
-                                recommendedWidget.user)))
-                .filter(Objects::nonNull)
-                .collect(Collectors.toList());
-    }
-
-    /** Returns the recommended widgets mapped by their category. */
-    @NonNull
-    public Map<WidgetRecommendationCategory, List<WidgetItem>> getCategorizedRecommendedWidgets() {
-        Map<ComponentKey, WidgetItem> allWidgetItems = mAllWidgets.stream()
-                .filter(entry -> entry instanceof WidgetsListContentEntry)
-                .flatMap(entry -> entry.mWidgets.stream())
-                .distinct()
-                .collect(Collectors.toMap(
-                        widget -> new ComponentKey(widget.componentName, widget.user),
-                        Function.identity()
-                ));
-        return mRecommendedWidgets.stream()
-                .filter(itemInfo -> itemInfo instanceof PendingAddWidgetInfo
-                        && ((PendingAddWidgetInfo) itemInfo).recommendationCategory != null)
-                .collect(Collectors.groupingBy(
-                        it -> ((PendingAddWidgetInfo) it).recommendationCategory,
-                        Collectors.collectingAndThen(
-                                Collectors.toList(),
-                                list -> list.stream()
-                                        .map(it -> allWidgetItems.get(
-                                                new ComponentKey(it.getTargetComponent(),
-                                                        it.user)))
-                                        .filter(Objects::nonNull)
-                                        .collect(Collectors.toList())
-                        )
-                ));
-    }
-
-    public List<WidgetItem> getWidgetsForPackageUser(PackageUserKey packageUserKey) {
-        return mAllWidgets.stream()
-                .filter(row -> row instanceof WidgetsListContentEntry
-                        && row.mPkgItem.packageName.equals(packageUserKey.mPackageName))
-                .flatMap(row -> ((WidgetsListContentEntry) row).mWidgets.stream())
-                .filter(widget -> packageUserKey.mUser.equals(widget.user))
-                .collect(Collectors.toList());
-    }
-
-    /** Gets the WidgetsListContentEntry for the currently selected header. */
-    public WidgetsListContentEntry getSelectedAppWidgets(PackageUserKey packageUserKey,
-            boolean useDefault) {
-        List<WidgetsListBaseEntry> widgets = useDefault ? mDefaultWidgets : mAllWidgets;
-        return (WidgetsListContentEntry) widgets.stream()
-                .filter(row -> row instanceof WidgetsListContentEntry
-                        && PackageUserKey.fromPackageItemInfo(row.mPkgItem).equals(packageUserKey))
-                .findAny()
-                .orElse(null);
-    }
-
     public void dump(String prefix, PrintWriter writer) {
         writer.println(prefix + "PopupDataProvider:");
         writer.println(prefix + "\tmPackageUserToDotInfos:" + mPackageUserToDotInfos);
     }
-
-    public interface PopupDataChangeListener {
-
-        PopupDataChangeListener INSTANCE = new PopupDataChangeListener() { };
-
-        default void onWidgetsBound() { }
-
-        /** A callback to get notified when recommended widgets are bound. */
-        default void onRecommendedWidgetsBound() { }
-    }
 }
diff --git a/src/com/android/launcher3/popup/PopupLiveUpdateHandler.java b/src/com/android/launcher3/popup/PopupLiveUpdateHandler.java
index 4c94f94..1fd3557 100644
--- a/src/com/android/launcher3/popup/PopupLiveUpdateHandler.java
+++ b/src/com/android/launcher3/popup/PopupLiveUpdateHandler.java
@@ -19,6 +19,8 @@
 import android.view.View;
 
 import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider;
+import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider.WidgetPickerDataChangeListener;
 
 /**
  * Utility class to handle updates while the popup is visible (like widgets and
@@ -27,7 +29,7 @@
  * @param <T> The activity on which the popup shows
  */
 public abstract class PopupLiveUpdateHandler<T extends Context & ActivityContext> implements
-        PopupDataProvider.PopupDataChangeListener, View.OnAttachStateChangeListener {
+        WidgetPickerDataChangeListener, View.OnAttachStateChangeListener {
 
     protected final T mContext;
     protected final PopupContainerWithArrow<T> mPopupContainerWithArrow;
@@ -40,19 +42,25 @@
 
     @Override
     public void onViewAttachedToWindow(View view) {
-        PopupDataProvider popupDataProvider = mContext.getPopupDataProvider();
+        WidgetPickerDataProvider widgetsDataProvider = mContext.getWidgetPickerDataProvider();
 
-        if (popupDataProvider != null) {
-            popupDataProvider.setChangeListener(this);
+        if (widgetsDataProvider != null) {
+            widgetsDataProvider.setChangeListener(this);
         }
     }
 
     @Override
     public void onViewDetachedFromWindow(View view) {
-        PopupDataProvider popupDataProvider = mContext.getPopupDataProvider();
+        WidgetPickerDataProvider widgetsDataProvider = mContext.getWidgetPickerDataProvider();
 
-        if (popupDataProvider != null) {
-            popupDataProvider.setChangeListener(null);
+        if (widgetsDataProvider != null) {
+            widgetsDataProvider.setChangeListener(null);
         }
     }
+
+    @Override
+    public void onWidgetsBound() {} // NO_OP
+
+    @Override
+    public void onRecommendedWidgetsBound() {} // NO_OP
 }
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 83e9810..f7e1168 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -5,6 +5,7 @@
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_WIDGETS_TAP;
+import static com.android.launcher3.widget.picker.model.data.WidgetPickerDataUtils.findAllWidgetsForPackageUser;
 
 import android.app.ActivityOptions;
 import android.content.ComponentName;
@@ -28,7 +29,6 @@
 import com.android.launcher3.SecondaryDropTarget;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.PrivateProfileManager;
-import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.UserCache;
@@ -39,9 +39,9 @@
 import com.android.launcher3.util.PackageUserKey;
 import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.widget.WidgetsBottomSheet;
+import com.android.launcher3.widget.picker.model.data.WidgetPickerData;
 
 import java.util.Arrays;
-import java.util.List;
 
 /**
  * Represents a system shortcut for a given app. The shortcut should have a label and icon, and an
@@ -107,11 +107,12 @@
     }
 
     public static final Factory<ActivityContext> WIDGETS = (context, itemInfo, originalView) -> {
-        if (itemInfo.getTargetComponent() == null) return null;
-        final List<WidgetItem> widgets =
-                context.getPopupDataProvider().getWidgetsForPackageUser(new PackageUserKey(
-                        itemInfo.getTargetComponent().getPackageName(), itemInfo.user));
-        if (widgets.isEmpty()) {
+        final PackageUserKey packageUserKey = PackageUserKey.fromItemInfo(itemInfo);
+        if (packageUserKey == null) return null;
+
+        final WidgetPickerData data = context.getWidgetPickerDataProvider().get();
+        if (findAllWidgetsForPackageUser(data, packageUserKey).isEmpty()) {
+            // hides widget picker shortcut if there are no widgets for the package.
             return null;
         }
         return new Widgets(context, itemInfo, originalView);
diff --git a/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt b/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt
index f895b30..0a7beab 100644
--- a/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt
+++ b/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt
@@ -17,6 +17,7 @@
 package com.android.launcher3.recyclerview
 
 import android.content.Context
+import android.util.Log
 import android.view.ViewGroup
 import androidx.annotation.VisibleForTesting
 import androidx.annotation.VisibleForTesting.Companion.PROTECTED
@@ -24,6 +25,7 @@
 import androidx.recyclerview.widget.RecyclerView.RecycledViewPool
 import androidx.recyclerview.widget.RecyclerView.ViewHolder
 import com.android.launcher3.BubbleTextView
+import com.android.launcher3.BuildConfig
 import com.android.launcher3.allapps.BaseAllAppsAdapter
 import com.android.launcher3.config.FeatureFlags
 import com.android.launcher3.util.CancellableTask
@@ -32,6 +34,7 @@
 import com.android.launcher3.util.Themes
 import com.android.launcher3.views.ActivityContext
 import com.android.launcher3.views.ActivityContext.ActivityContextDelegate
+import java.lang.IllegalStateException
 
 const val PREINFLATE_ICONS_ROW_COUNT = 4
 const val EXTRA_ICONS_COUNT = 2
@@ -47,6 +50,12 @@
     @VisibleForTesting(otherwise = PROTECTED)
     var mCancellableTask: CancellableTask<List<ViewHolder>>? = null
 
+    companion object {
+        private const val TAG = "AllAppsRecyclerViewPool"
+        private const val NULL_LAYOUT_MANAGER_ERROR_STRING =
+            "activeRv's layoutManager should not be null"
+    }
+
     /**
      * Preinflate app icons. If all apps RV cannot be scrolled down, we don't need to preinflate.
      */
@@ -54,6 +63,15 @@
         val appsView = context.appsView ?: return
         val activeRv: RecyclerView = appsView.activeRecyclerView ?: return
 
+        if (activeRv.layoutManager == null) {
+            if (BuildConfig.IS_STUDIO_BUILD) {
+                throw IllegalStateException(NULL_LAYOUT_MANAGER_ERROR_STRING)
+            } else {
+                Log.e(TAG, NULL_LAYOUT_MANAGER_ERROR_STRING)
+            }
+            return
+        }
+
         // Create a separate context dedicated for all apps preinflation thread. The goal is to
         // create a separate AssetManager obj internally to avoid lock contention with
         // AssetManager obj that is associated with the launcher context on the main thread.
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
index 0299a23..9b3292d 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
@@ -59,6 +59,7 @@
 import com.android.launcher3.util.Preconditions;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.BaseDragLayer;
+import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -76,6 +77,7 @@
     private View mAppsButton;
 
     private PopupDataProvider mPopupDataProvider;
+    private WidgetPickerDataProvider mWidgetPickerDataProvider;
 
     private boolean mAppDrawerShown = false;
 
@@ -315,6 +317,11 @@
     }
 
     @Override
+    public WidgetPickerDataProvider getWidgetPickerDataProvider() {
+        return mWidgetPickerDataProvider;
+    }
+
+    @Override
     public OnClickListener getItemOnClickListener() {
         return this::onIconClicked;
     }
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index 52ce4e8..bd9298b 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -44,11 +44,13 @@
 import androidx.preference.PreferenceFragmentCompat;
 import androidx.preference.PreferenceFragmentCompat.OnPreferenceStartFragmentCallback;
 import androidx.preference.PreferenceFragmentCompat.OnPreferenceStartScreenCallback;
+import androidx.preference.PreferenceGroup;
 import androidx.preference.PreferenceGroup.PreferencePositionCallback;
 import androidx.preference.PreferenceScreen;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.launcher3.BuildConfig;
+import com.android.launcher3.Flags;
 import com.android.launcher3.LauncherFiles;
 import com.android.launcher3.R;
 import com.android.launcher3.states.RotationHelper;
@@ -165,6 +167,7 @@
         private boolean mRestartOnResume = false;
 
         private String mHighLightKey;
+
         private boolean mPreferenceHighlighted = false;
 
         @Override
@@ -198,11 +201,62 @@
                 }
             }
 
+            // If the target preference is not in the current preference screen, find the parent
+            // preference screen that contains the target preference and set it as the preference
+            // screen.
+            if (Flags.navigateToChildPreference()
+                    && mHighLightKey != null
+                    && !isKeyInPreferenceGroup(mHighLightKey, screen)) {
+                final PreferenceScreen parentPreferenceScreen =
+                        findParentPreference(screen, mHighLightKey);
+                if (parentPreferenceScreen != null && getActivity() != null) {
+                    if (!TextUtils.isEmpty(parentPreferenceScreen.getTitle())) {
+                        getActivity().setTitle(parentPreferenceScreen.getTitle());
+                    }
+                    setPreferenceScreen(parentPreferenceScreen);
+                    return;
+                }
+            }
+
             if (getActivity() != null && !TextUtils.isEmpty(getPreferenceScreen().getTitle())) {
                 getActivity().setTitle(getPreferenceScreen().getTitle());
             }
         }
 
+        private boolean isKeyInPreferenceGroup(String targetKey, PreferenceGroup parent) {
+            for (int i = 0; i < parent.getPreferenceCount(); i++) {
+                Preference pref = parent.getPreference(i);
+                if (pref.getKey() != null && pref.getKey().equals(targetKey)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /**
+         * Finds the parent preference screen for the given target key.
+         *
+         * @param parent the parent preference screen
+         * @param targetKey the key of the preference to find
+         * @return the parent preference screen that contains the target preference
+         */
+        @Nullable
+        private PreferenceScreen findParentPreference(PreferenceScreen parent, String targetKey) {
+            for (int i = 0; i < parent.getPreferenceCount(); i++) {
+                Preference pref = parent.getPreference(i);
+                if (pref instanceof PreferenceScreen) {
+                    PreferenceScreen foundKey = findParentPreference((PreferenceScreen) pref,
+                            targetKey);
+                    if (foundKey != null) {
+                        return foundKey;
+                    }
+                } else if (pref.getKey() != null && pref.getKey().equals(targetKey)) {
+                    return parent;
+                }
+            }
+            return null;
+        }
+
         @Override
         public void onViewCreated(View view, Bundle savedInstanceState) {
             super.onViewCreated(view, savedInstanceState);
diff --git a/src/com/android/launcher3/util/OnboardingPrefs.kt b/src/com/android/launcher3/util/OnboardingPrefs.kt
index ac6e97c..771594e 100644
--- a/src/com/android/launcher3/util/OnboardingPrefs.kt
+++ b/src/com/android/launcher3/util/OnboardingPrefs.kt
@@ -16,6 +16,7 @@
 package com.android.launcher3.util
 
 import android.content.Context
+import androidx.annotation.VisibleForTesting
 import com.android.launcher3.LauncherPrefs
 import com.android.launcher3.LauncherPrefs.Companion.backedUpItem
 
@@ -26,7 +27,7 @@
         val sharedPrefKey: String,
         val maxCount: Int,
     ) {
-        private val prefItem = backedUpItem(sharedPrefKey, 0)
+        @VisibleForTesting val prefItem = backedUpItem(sharedPrefKey, 0)
 
         /** @return The number of times we have seen the given event. */
         fun get(c: Context): Int {
diff --git a/src/com/android/launcher3/util/SplitConfigurationOptions.java b/src/com/android/launcher3/util/SplitConfigurationOptions.java
index 95624b1..837d7bc 100644
--- a/src/com/android/launcher3/util/SplitConfigurationOptions.java
+++ b/src/com/android/launcher3/util/SplitConfigurationOptions.java
@@ -186,12 +186,6 @@
         public int stagePosition = STAGE_POSITION_UNDEFINED;
         @StageType
         public int stageType = STAGE_TYPE_UNDEFINED;
-
-        @Override
-        public String toString() {
-            return "SplitStageInfo { taskId=" + taskId
-                    + ", stagePosition=" + stagePosition + ", stageType=" + stageType + " }";
-        }
     }
 
     public static StatsLogManager.EventEnum getLogEventForPosition(@StagePosition int position) {
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index cfac91a..d3160e0 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -81,6 +81,7 @@
 import com.android.launcher3.util.RunnableList;
 import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.ViewCache;
+import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider;
 
 import java.util.List;
 
@@ -266,6 +267,14 @@
         return null;
     }
 
+    /**
+     * Returns the {@link WidgetPickerDataProvider} that can be used to read widgets for display.
+     */
+    @Nullable
+    default WidgetPickerDataProvider getWidgetPickerDataProvider() {
+        return null;
+    }
+
     @Nullable
     default StringCache getStringCache() {
         return null;
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index c59e295..1c0d94c 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -45,13 +45,13 @@
 import com.android.launcher3.PendingAddItemInfo;
 import com.android.launcher3.R;
 import com.android.launcher3.model.WidgetItem;
-import com.android.launcher3.popup.PopupDataProvider;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
 import com.android.launcher3.util.SystemUiController;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.window.WindowManagerProxy;
 import com.android.launcher3.views.AbstractSlideInView;
+import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider.WidgetPickerDataChangeListener;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -60,7 +60,7 @@
  */
 public abstract class BaseWidgetSheet extends AbstractSlideInView<BaseActivity>
         implements OnClickListener, OnLongClickListener,
-        PopupDataProvider.PopupDataChangeListener, Insettable, OnDeviceProfileChangeListener {
+        WidgetPickerDataChangeListener, Insettable, OnDeviceProfileChangeListener {
     /** The default number of cells that can fit horizontally in a widget sheet. */
     public static final int DEFAULT_MAX_HORIZONTAL_SPANS = 4;
 
@@ -106,14 +106,14 @@
         WindowInsets windowInsets = WindowManagerProxy.INSTANCE.get(getContext())
                 .normalizeWindowInsets(getContext(), getRootWindowInsets(), new Rect());
         mNavBarScrimHeight = getNavBarScrimHeight(windowInsets);
-        mActivityContext.getPopupDataProvider().setChangeListener(this);
+        mActivityContext.getWidgetPickerDataProvider().setChangeListener(this);
         mActivityContext.addOnDeviceProfileChangeListener(this);
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        mActivityContext.getPopupDataProvider().setChangeListener(null);
+        mActivityContext.getWidgetPickerDataProvider().setChangeListener(null);
         mActivityContext.removeOnDeviceProfileChangeListener(this);
     }
 
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHost.java b/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
index 71d8503..91b899c 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
@@ -24,6 +24,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.util.Executors;
@@ -77,6 +78,11 @@
         mViewToRecycle = viewToRecycle;
     }
 
+    @VisibleForTesting
+    @Nullable ListenableHostView getViewToRecycle() {
+        return mViewToRecycle;
+    }
+
     @Override
     @NonNull
     public LauncherAppWidgetHostView onCreateView(Context context, int appWidgetId,
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 894099d..ddbd291 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -17,6 +17,7 @@
 package com.android.launcher3.widget;
 
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_BOTTOM_WIDGETS_TRAY;
+import static com.android.launcher3.widget.picker.model.data.WidgetPickerDataUtils.findAllWidgetsForPackageUser;
 
 import android.content.Context;
 import android.graphics.Rect;
@@ -40,6 +41,7 @@
 import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.widget.picker.model.data.WidgetPickerData;
 import com.android.launcher3.widget.util.WidgetsTableUtils;
 
 import java.util.List;
@@ -124,10 +126,10 @@
 
     @Override
     public void onWidgetsBound() {
-        List<WidgetItem> widgets = mActivityContext.getPopupDataProvider().getWidgetsForPackageUser(
-                new PackageUserKey(
-                        mOriginalItemInfo.getTargetComponent().getPackageName(),
-                        mOriginalItemInfo.user));
+        final WidgetPickerData data = mActivityContext.getWidgetPickerDataProvider().get();
+        final PackageUserKey packageUserKey = PackageUserKey.fromItemInfo(mOriginalItemInfo);
+        List<WidgetItem> widgets = packageUserKey != null ? findAllWidgetsForPackageUser(data,
+                packageUserKey) : List.of();
 
         TableLayout widgetsTable = findViewById(R.id.widgets_table);
         widgetsTable.removeAllViews();
@@ -247,4 +249,7 @@
             }
         }
     }
+
+    @Override
+    public void onRecommendedWidgetsBound() {} // no op
 }
diff --git a/src/com/android/launcher3/widget/picker/WidgetRecommendationCategory.java b/src/com/android/launcher3/widget/picker/WidgetRecommendationCategory.java
index 072d1d5..a68effd 100644
--- a/src/com/android/launcher3/widget/picker/WidgetRecommendationCategory.java
+++ b/src/com/android/launcher3/widget/picker/WidgetRecommendationCategory.java
@@ -19,6 +19,8 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 
+import com.android.launcher3.R;
+
 import java.util.Objects;
 
 /**
@@ -26,6 +28,10 @@
  * option in the pop-up opened on long press of launcher workspace).
  */
 public class WidgetRecommendationCategory implements Comparable<WidgetRecommendationCategory> {
+    public static WidgetRecommendationCategory DEFAULT_WIDGET_RECOMMENDATION_CATEGORY =
+            new WidgetRecommendationCategory(
+                    R.string.others_widget_recommendation_category_label, /*order=*/0);
+
     /** Resource id that holds the user friendly label for the category. */
     @StringRes
     public final int categoryTitleRes;
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 21b7be4..2af8e6f 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -74,6 +74,7 @@
 import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePageChangedListener;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -471,7 +472,7 @@
      * Returns all displayable widgets.
      */
     protected List<WidgetsListBaseEntry> getWidgetsToDisplay() {
-        return mActivityContext.getPopupDataProvider().getAllWidgets();
+        return mActivityContext.getWidgetPickerDataProvider().get().getAllWidgets();
     }
 
     @Override
@@ -572,12 +573,11 @@
         if (mIsInSearchMode) {
             return;
         }
-
         if (enableCategorizedWidgetSuggestions()) {
             // We avoid applying new recommendations when some are already displayed.
             if (mRecommendedWidgetsMap.isEmpty()) {
                 mRecommendedWidgetsMap =
-                        mActivityContext.getPopupDataProvider().getCategorizedRecommendedWidgets();
+                        mActivityContext.getWidgetPickerDataProvider().get().getRecommendations();
             }
             mRecommendedWidgetsCount = mWidgetRecommendationsView.setRecommendations(
                     mRecommendedWidgetsMap,
@@ -589,17 +589,20 @@
             );
         } else {
             if (mRecommendedWidgets.isEmpty()) {
-                mRecommendedWidgets =
-                        mActivityContext.getPopupDataProvider().getRecommendedWidgets();
+                mRecommendedWidgets = mActivityContext.getWidgetPickerDataProvider().get()
+                        .getRecommendations()
+                        .values().stream()
+                        .flatMap(Collection::stream).toList();
+                mRecommendedWidgetsCount = mWidgetRecommendationsView.setRecommendations(
+                        mRecommendedWidgets,
+                        mDeviceProfile,
+                        /* availableHeight= */ getMaxAvailableHeightForRecommendations(),
+                        /* availableWidth= */ mMaxSpanPerRow,
+                        /* cellPadding= */ mWidgetCellHorizontalPadding
+                );
             }
-            mRecommendedWidgetsCount = mWidgetRecommendationsView.setRecommendations(
-                    mRecommendedWidgets,
-                    mDeviceProfile,
-                    /* availableHeight= */ getMaxAvailableHeightForRecommendations(),
-                    /* availableWidth= */ mMaxSpanPerRow,
-                    /* cellPadding= */ mWidgetCellHorizontalPadding
-            );
         }
+
         mWidgetRecommendationsContainer.setVisibility(
                 mRecommendedWidgetsCount > 0 ? VISIBLE : GONE);
     }
diff --git a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
index c4c755a..c2cd903 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
@@ -22,6 +22,7 @@
 import static com.android.launcher3.UtilitiesKt.modifyAttributesOnViewTree;
 import static com.android.launcher3.UtilitiesKt.restoreAttributesOnViewTree;
 import static com.android.launcher3.widget.picker.WidgetsListItemAnimator.WIDGET_LIST_ITEM_APPEARANCE_DELAY;
+import static com.android.launcher3.widget.picker.model.data.WidgetPickerDataUtils.findContentEntryForPackageUser;
 
 import android.content.Context;
 import android.graphics.Rect;
@@ -287,9 +288,9 @@
     @Override
     protected List<WidgetsListBaseEntry> getWidgetsToDisplay() {
         List<WidgetsListBaseEntry> allWidgets =
-                mActivityContext.getPopupDataProvider().getAllWidgets();
+                mActivityContext.getWidgetPickerDataProvider().get().getAllWidgets();
         List<WidgetsListBaseEntry> defaultWidgets =
-                mActivityContext.getPopupDataProvider().getDefaultWidgets();
+                mActivityContext.getWidgetPickerDataProvider().get().getDefaultWidgets();
 
         if (allWidgets.isEmpty() || defaultWidgets.isEmpty()) {
             // no menu if there are no default widgets to show
@@ -359,7 +360,7 @@
         WidgetsListHeaderEntry widgetsListHeaderEntry = WidgetsListHeaderEntry.create(
                         packageItemInfo,
                         /*titleSectionName=*/ suggestionsHeaderTitle,
-                        /*items=*/ mActivityContext.getPopupDataProvider().getRecommendedWidgets(),
+                        /*items=*/ List.of(), // not necessary
                         /*visibleWidgetsCount=*/ 0)
                 .withWidgetListShown();
 
@@ -509,11 +510,11 @@
                 final boolean isUserClick = mSelectedHeader != null
                         && !getAccessibilityInitialFocusView().isAccessibilityFocused();
                 mSelectedHeader = selectedHeader;
-                WidgetsListContentEntry contentEntry =
-                        mActivityContext.getPopupDataProvider().getSelectedAppWidgets(
-                                selectedHeader, /*useDefault=*/
-                                (mWidgetOptionsMenuState != null
-                                        && !mWidgetOptionsMenuState.showAllWidgets));
+                final boolean showDefaultWidgets = mWidgetOptionsMenuState != null
+                        && !mWidgetOptionsMenuState.showAllWidgets;
+                WidgetsListContentEntry contentEntry = findContentEntryForPackageUser(
+                        mActivityContext.getWidgetPickerDataProvider().get(),
+                        selectedHeader, showDefaultWidgets);
 
                 if (contentEntry == null || mRightPane == null) {
                     return;
diff --git a/src/com/android/launcher3/widget/picker/model/WidgetPickerDataProvider.kt b/src/com/android/launcher3/widget/picker/model/WidgetPickerDataProvider.kt
new file mode 100644
index 0000000..46d3e7a
--- /dev/null
+++ b/src/com/android/launcher3/widget/picker/model/WidgetPickerDataProvider.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 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.widget.picker.model
+
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.widget.model.WidgetsListBaseEntry
+import com.android.launcher3.widget.picker.model.data.WidgetPickerData
+import com.android.launcher3.widget.picker.model.data.WidgetPickerDataUtils.withRecommendedWidgets
+import com.android.launcher3.widget.picker.model.data.WidgetPickerDataUtils.withWidgets
+import java.io.PrintWriter
+
+/**
+ * Provides [WidgetPickerData] to various views such as widget picker, app-specific widget picker,
+ * widgets shortcut.
+ */
+class WidgetPickerDataProvider {
+    /** All the widgets data provided for the views */
+    private var mWidgetPickerData: WidgetPickerData = WidgetPickerData()
+
+    private var changeListener: WidgetPickerDataChangeListener? = null
+
+    /** Sets a listener to be called back when widget data is updated. */
+    fun setChangeListener(changeListener: WidgetPickerDataChangeListener?) {
+        this.changeListener = changeListener
+    }
+
+    /** Returns the current snapshot of [WidgetPickerData]. */
+    fun get(): WidgetPickerData {
+        return mWidgetPickerData
+    }
+
+    /**
+     * Updates the widgets available to the widget picker.
+     *
+     * Generally called when the widgets model has new data.
+     */
+    @JvmOverloads
+    fun setWidgets(
+        allWidgets: List<WidgetsListBaseEntry>,
+        defaultWidgets: List<WidgetsListBaseEntry> = listOf()
+    ) {
+        mWidgetPickerData =
+            mWidgetPickerData.withWidgets(allWidgets = allWidgets, defaultWidgets = defaultWidgets)
+        changeListener?.onWidgetsBound()
+    }
+
+    /**
+     * Makes the widget recommendations available to the widget picker
+     *
+     * Generally called when new widget predictions are available.
+     */
+    fun setWidgetRecommendations(recommendations: List<ItemInfo>) {
+        mWidgetPickerData = mWidgetPickerData.withRecommendedWidgets(recommendations)
+        changeListener?.onRecommendedWidgetsBound()
+    }
+
+    /** Writes the current state to the provided writer. */
+    fun dump(prefix: String, writer: PrintWriter) {
+        writer.println(prefix + "WidgetPickerDataProvider:")
+        writer.println("$prefix\twidgetPickerData:$mWidgetPickerData")
+    }
+
+    interface WidgetPickerDataChangeListener {
+        /** A callback to get notified when widgets are bound. */
+        fun onWidgetsBound()
+
+        /** A callback to get notified when recommended widgets are bound. */
+        fun onRecommendedWidgetsBound()
+    }
+}
diff --git a/src/com/android/launcher3/widget/picker/model/data/WidgetPickerData.kt b/src/com/android/launcher3/widget/picker/model/data/WidgetPickerData.kt
new file mode 100644
index 0000000..3332ef0
--- /dev/null
+++ b/src/com/android/launcher3/widget/picker/model/data/WidgetPickerData.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2024 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.widget.picker.model.data
+
+import com.android.launcher3.model.WidgetItem
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.util.ComponentKey
+import com.android.launcher3.util.PackageUserKey
+import com.android.launcher3.widget.PendingAddWidgetInfo
+import com.android.launcher3.widget.model.WidgetsListBaseEntry
+import com.android.launcher3.widget.model.WidgetsListContentEntry
+import com.android.launcher3.widget.picker.WidgetRecommendationCategory
+import com.android.launcher3.widget.picker.WidgetRecommendationCategory.DEFAULT_WIDGET_RECOMMENDATION_CATEGORY
+
+// This file contains WidgetPickerData and utility functions to operate on it.
+
+/** Widget data for display in the widget picker. */
+data class WidgetPickerData(
+    val allWidgets: List<WidgetsListBaseEntry> = listOf(),
+    val defaultWidgets: List<WidgetsListBaseEntry> = listOf(),
+    val recommendations: Map<WidgetRecommendationCategory, List<WidgetItem>> = mapOf(),
+)
+
+/** Provides utility methods to work with a [WidgetPickerData] object. */
+object WidgetPickerDataUtils {
+    /**
+     * Returns a [WidgetPickerData] with the provided widgets.
+     *
+     * When [defaultWidgets] is not passed, defaults from previous object are not copied over.
+     * Defaults (if supported) should be updated when all widgets are updated.
+     */
+    fun WidgetPickerData.withWidgets(
+        allWidgets: List<WidgetsListBaseEntry>,
+        defaultWidgets: List<WidgetsListBaseEntry> = listOf()
+    ): WidgetPickerData {
+        return copy(allWidgets = allWidgets, defaultWidgets = defaultWidgets)
+    }
+
+    /** Returns a [WidgetPickerData] with the given recommendations set. */
+    fun WidgetPickerData.withRecommendedWidgets(recommendations: List<ItemInfo>): WidgetPickerData {
+        val allWidgetsMap: Map<ComponentKey, WidgetItem> =
+            allWidgets
+                .filterIsInstance<WidgetsListContentEntry>()
+                .flatMap { it.mWidgets }
+                .filterNotNull()
+                .distinct()
+                .associateBy { it } // as ComponentKey
+
+        val categoriesMap =
+            recommendations
+                .filterIsInstance<PendingAddWidgetInfo>()
+                .filter { allWidgetsMap.containsKey(ComponentKey(it.targetComponent, it.user)) }
+                .groupBy { it.recommendationCategory ?: DEFAULT_WIDGET_RECOMMENDATION_CATEGORY }
+                .mapValues { (_, pendingAddWidgetInfos) ->
+                    pendingAddWidgetInfos.map {
+                        allWidgetsMap[ComponentKey(it.targetComponent, it.user)] as WidgetItem
+                    }
+                }
+
+        return copy(recommendations = categoriesMap)
+    }
+
+    /** Finds all [WidgetItem]s available for the provided package user. */
+    @JvmStatic
+    fun findAllWidgetsForPackageUser(
+        widgetPickerData: WidgetPickerData,
+        packageUserKey: PackageUserKey
+    ): List<WidgetItem> {
+        return findContentEntryForPackageUser(widgetPickerData, packageUserKey)?.mWidgets
+            ?: emptyList()
+    }
+
+    /**
+     * Finds and returns the [WidgetsListContentEntry] for the given package user.
+     *
+     * Set [fromDefaultWidgets] to true to limit the content entry to default widgets.
+     */
+    @JvmOverloads
+    @JvmStatic
+    fun findContentEntryForPackageUser(
+        widgetPickerData: WidgetPickerData,
+        packageUserKey: PackageUserKey,
+        fromDefaultWidgets: Boolean = false
+    ): WidgetsListContentEntry? {
+        val widgetsListBaseEntries =
+            if (fromDefaultWidgets) {
+                widgetPickerData.defaultWidgets
+            } else {
+                widgetPickerData.allWidgets
+            }
+
+        return widgetsListBaseEntries.filterIsInstance<WidgetsListContentEntry>().firstOrNull {
+            PackageUserKey.fromPackageItemInfo(it.mPkgItem) == packageUserKey
+        }
+    }
+}
diff --git a/tests/multivalentTests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java b/tests/multivalentTests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java
index d2238ff..d938119 100644
--- a/tests/multivalentTests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java
@@ -65,6 +65,7 @@
     private static final int PRIVATE_SPACE_HEADER_ITEM_COUNT = 1;
     private static final int MAIN_USER_APP_COUNT = 2;
     private static final int PRIVATE_USER_APP_COUNT = 2;
+    private static final int VIEW_AT_END_OF_APP_LIST = 1;
     private static final int NUM_APP_COLS = 4;
     private static final int NUM_APP_ROWS = 3;
     private static final int PRIVATE_SPACE_SYS_APP_SEPARATOR_ITEM_COUNT = 1;
@@ -107,7 +108,8 @@
                 && info.user.equals(MAIN_HANDLE));
 
         assertEquals(MAIN_USER_APP_COUNT + PRIVATE_SPACE_HEADER_ITEM_COUNT
-                + PRIVATE_USER_APP_COUNT, mAlphabeticalAppsList.getAdapterItems().size());
+                + PRIVATE_USER_APP_COUNT + VIEW_AT_END_OF_APP_LIST,
+                mAlphabeticalAppsList.getAdapterItems().size());
         assertEquals(PRIVATE_SPACE_HEADER_ITEM_COUNT,
                 mAlphabeticalAppsList.getAdapterItems().stream().filter(item ->
                         item.viewType == VIEW_TYPE_PRIVATE_SPACE_HEADER).toList().size());
@@ -136,7 +138,7 @@
                 && info.user.equals(MAIN_HANDLE));
 
         assertEquals(MAIN_USER_APP_COUNT + PRIVATE_SPACE_HEADER_ITEM_COUNT
-                + PRIVATE_SPACE_SYS_APP_SEPARATOR_ITEM_COUNT
+                + PRIVATE_SPACE_SYS_APP_SEPARATOR_ITEM_COUNT + VIEW_AT_END_OF_APP_LIST
                 + PRIVATE_USER_APP_COUNT, mAlphabeticalAppsList.getAdapterItems().size());
         assertEquals(PRIVATE_SPACE_HEADER_ITEM_COUNT,
                 mAlphabeticalAppsList.getAdapterItems().stream().filter(item ->
@@ -166,7 +168,8 @@
         mAlphabeticalAppsList.updateItemFilter(info -> info != null
                 && info.user.equals(MAIN_HANDLE));
 
-        assertEquals(MAIN_USER_APP_COUNT + PRIVATE_SPACE_HEADER_ITEM_COUNT,
+        assertEquals(MAIN_USER_APP_COUNT + PRIVATE_SPACE_HEADER_ITEM_COUNT +
+                        VIEW_AT_END_OF_APP_LIST,
                 mAlphabeticalAppsList.getAdapterItems().size());
         assertEquals(PRIVATE_SPACE_HEADER_ITEM_COUNT, mAlphabeticalAppsList
                 .getAdapterItems().stream().filter(item ->
@@ -187,8 +190,8 @@
         mAlphabeticalAppsList.updateItemFilter(info -> info != null
                 && info.user.equals(MAIN_HANDLE));
 
-        assertEquals(MAIN_USER_APP_COUNT + PRIVATE_SPACE_HEADER_ITEM_COUNT,
-                mAlphabeticalAppsList.getAdapterItems().size());
+        assertEquals(MAIN_USER_APP_COUNT + PRIVATE_SPACE_HEADER_ITEM_COUNT +
+                        VIEW_AT_END_OF_APP_LIST, mAlphabeticalAppsList.getAdapterItems().size());
         assertEquals(PRIVATE_SPACE_HEADER_ITEM_COUNT, mAlphabeticalAppsList
                 .getAdapterItems().stream().filter(item ->
                         item.viewType == VIEW_TYPE_PRIVATE_SPACE_HEADER).toList().size());
@@ -206,7 +209,8 @@
         mAlphabeticalAppsList.updateItemFilter(info -> info != null
                 && info.user.equals(MAIN_HANDLE));
 
-        assertEquals(MAIN_USER_APP_COUNT, mAlphabeticalAppsList.getAdapterItems().size());
+        assertEquals(MAIN_USER_APP_COUNT + VIEW_AT_END_OF_APP_LIST,
+                mAlphabeticalAppsList.getAdapterItems().size());
         assertEquals(0, mAlphabeticalAppsList.getAdapterItems().stream().filter(item ->
                 item.viewType == VIEW_TYPE_PRIVATE_SPACE_HEADER).toList().size());
         assertEquals(0, mAlphabeticalAppsList.getAdapterItems().stream().filter(item ->
@@ -222,7 +226,8 @@
         mAlphabeticalAppsList.updateItemFilter(info -> info != null
                 && info.user.equals(MAIN_HANDLE));
 
-        assertEquals(2, mAlphabeticalAppsList.getAdapterItems().size());
+        assertEquals(MAIN_USER_APP_COUNT + VIEW_AT_END_OF_APP_LIST,
+                mAlphabeticalAppsList.getAdapterItems().size());
         assertEquals(0, mAlphabeticalAppsList.getAdapterItems().stream().filter(item ->
                         item.itemInfo != null
                                 && item.itemInfo.itemType == VIEW_TYPE_PRIVATE_SPACE_HEADER)
diff --git a/tests/multivalentTests/src/com/android/launcher3/model/WidgetsModelTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/WidgetsModelTest.kt
index 71f7d47..ff545fe 100644
--- a/tests/multivalentTests/src/com/android/launcher3/model/WidgetsModelTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/model/WidgetsModelTest.kt
@@ -186,6 +186,35 @@
         assertThat(underTest.widgetsByComponentKey).isEmpty()
     }
 
+    @Test
+    fun getWidgetsByPackageItem_returnsACopyOfMap() {
+        loadWidgets()
+
+        val latch = CountDownLatch(1)
+        Executors.MODEL_EXECUTOR.execute {
+            var update = true
+
+            // each "widgetsByPackageItem" read returns a different copy of the map held internally.
+            // Modifying one shouldn't impact another.
+            for ((_, _) in underTest.widgetsByPackageItem.entries) {
+                underTest.widgetsByPackageItem.clear()
+                if (update) { // trigger update
+                    update = false
+                    // Similarly, model could update its code independently while a client is
+                    // iterating on the list.
+                    underTest.update(app, /* packageUser= */ null)
+                }
+            }
+
+            latch.countDown()
+        }
+        if (!latch.await(LOAD_WIDGETS_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
+            fail("Timed out waiting for test")
+        }
+
+        // No exception
+    }
+
     private fun loadWidgets() {
         val latch = CountDownLatch(1)
         Executors.MODEL_EXECUTOR.execute {
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/TestSandboxModelContextWrapper.java b/tests/multivalentTests/src/com/android/launcher3/util/TestSandboxModelContextWrapper.java
index 3f37563..71637f1 100644
--- a/tests/multivalentTests/src/com/android/launcher3/util/TestSandboxModelContextWrapper.java
+++ b/tests/multivalentTests/src/com/android/launcher3/util/TestSandboxModelContextWrapper.java
@@ -32,6 +32,7 @@
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.popup.PopupDataProvider;
+import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider;
 
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
@@ -57,6 +58,8 @@
     protected ActivityAllAppsContainerView<ActivityContextWrapper> mAppsView;
 
     private final PopupDataProvider mPopupDataProvider = new PopupDataProvider(i -> {});
+    private final WidgetPickerDataProvider mWidgetPickerDataProvider =
+            new WidgetPickerDataProvider();
     protected final UserCache mUserCache;
 
     public TestSandboxModelContextWrapper(SandboxContext base) {
@@ -76,12 +79,19 @@
         mAppsList = mAppsView.getPersonalAppList();
         mAllAppsStore = mAppsView.getAppsStore();
     }
+
     @Nullable
     @Override
     public PopupDataProvider getPopupDataProvider() {
         return mPopupDataProvider;
     }
 
+    @Nullable
+    @Override
+    public WidgetPickerDataProvider getWidgetPickerDataProvider() {
+        return mWidgetPickerDataProvider;
+    }
+
     @Override
     public ActivityAllAppsContainerView<ActivityContextWrapper> getAppsView() {
         return mAppsView;
diff --git a/tests/multivalentTests/src/com/android/launcher3/widget/LauncherAppWidgetHostTest.kt b/tests/multivalentTests/src/com/android/launcher3/widget/LauncherAppWidgetHostTest.kt
new file mode 100644
index 0000000..79b493a
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/LauncherAppWidgetHostTest.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 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.widget
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import com.android.launcher3.util.ActivityContextWrapper
+import com.android.launcher3.util.Executors
+import java.util.function.IntConsumer
+import org.junit.Assert.assertNotSame
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertSame
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class LauncherAppWidgetHostTest {
+
+    @Mock private lateinit var onAppWidgetRemovedCallback: IntConsumer
+
+    private val context = ActivityContextWrapper(getInstrumentation().targetContext)
+    private lateinit var underTest: LauncherAppWidgetHost
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        underTest = LauncherAppWidgetHost(context, onAppWidgetRemovedCallback, emptyList())
+    }
+
+    @Test
+    fun `Host set view to recycle`() {
+        val mockRecycleView = mock(ListenableHostView::class.java)
+
+        assertNull(underTest.viewToRecycle)
+        underTest.recycleViewForNextCreation(mockRecycleView)
+
+        assertSame(mockRecycleView, underTest.viewToRecycle)
+    }
+
+    @Test
+    fun `Host create view`() {
+        val mockRecycleView = mock(ListenableHostView::class.java)
+
+        var resultView = underTest.onCreateView(context, WIDGET_ID, null)
+
+        assertNotSame(mockRecycleView, resultView)
+
+        underTest.recycleViewForNextCreation(mockRecycleView)
+        resultView = underTest.onCreateView(context, WIDGET_ID, null)
+
+        assertSame(mockRecycleView, resultView)
+    }
+
+    @Test
+    fun `Runnable called when app widget removed`() {
+        underTest.onAppWidgetRemoved(WIDGET_ID)
+
+        Executors.MODEL_EXECUTOR.submit {}.get()
+        getInstrumentation().waitForIdleSync()
+
+        verify(onAppWidgetRemovedCallback).accept(WIDGET_ID)
+    }
+
+    companion object {
+        const val WIDGET_ID = 10001
+    }
+}
diff --git a/tests/multivalentTests/src/com/android/launcher3/widget/picker/model/WidgetPickerDataProviderTest.kt b/tests/multivalentTests/src/com/android/launcher3/widget/picker/model/WidgetPickerDataProviderTest.kt
new file mode 100644
index 0000000..1822639
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/model/WidgetPickerDataProviderTest.kt
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2024 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.widget.picker.model
+
+import android.content.ComponentName
+import android.content.Context
+import android.os.UserHandle
+import android.platform.test.rule.AllowedDevices
+import android.platform.test.rule.DeviceProduct
+import android.platform.test.rule.LimitDevicesRule
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.launcher3.InvariantDeviceProfile
+import com.android.launcher3.LauncherAppState
+import com.android.launcher3.LauncherSettings
+import com.android.launcher3.icons.ComponentWithLabel
+import com.android.launcher3.icons.IconCache
+import com.android.launcher3.model.WidgetItem
+import com.android.launcher3.model.data.PackageItemInfo
+import com.android.launcher3.util.ActivityContextWrapper
+import com.android.launcher3.util.WidgetUtils
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo
+import com.android.launcher3.widget.PendingAddWidgetInfo
+import com.android.launcher3.widget.model.WidgetsListBaseEntry
+import com.android.launcher3.widget.model.WidgetsListContentEntry
+import com.android.launcher3.widget.model.WidgetsListHeaderEntry
+import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider.WidgetPickerDataChangeListener
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.invocation.InvocationOnMock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doAnswer
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.verifyNoMoreInteractions
+
+// Tests for the WidgetPickerDataProvider class
+
+@RunWith(AndroidJUnit4::class)
+@AllowedDevices(allowed = [DeviceProduct.ROBOLECTRIC])
+class WidgetPickerDataProviderTest {
+    @Rule @JvmField val limitDevicesRule = LimitDevicesRule()
+    @Rule @JvmField val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+    @Mock private lateinit var changeListener: WidgetPickerDataChangeListener
+
+    @Mock private lateinit var iconCache: IconCache
+
+    private lateinit var userHandle: UserHandle
+    private lateinit var context: Context
+    private lateinit var testInvariantProfile: InvariantDeviceProfile
+
+    private lateinit var appWidgetItem: WidgetItem
+
+    private var underTest = WidgetPickerDataProvider()
+
+    @Before
+    fun setUp() {
+        userHandle = UserHandle.CURRENT
+        context = ActivityContextWrapper(ApplicationProvider.getApplicationContext())
+        testInvariantProfile = LauncherAppState.getIDP(context)
+
+        doAnswer { invocation: InvocationOnMock ->
+                val componentWithLabel = invocation.getArgument<Any>(0) as ComponentWithLabel
+                componentWithLabel.getComponent().shortClassName
+            }
+            .`when`(iconCache)
+            .getTitleNoCache(any<ComponentWithLabel>())
+
+        appWidgetItem = createWidgetItem()
+    }
+
+    @Test
+    fun setWidgets_invokesTheListener_andUpdatedWidgetsAvailable() {
+        assertThat(underTest.get().allWidgets).isEmpty()
+
+        underTest.setChangeListener(changeListener)
+        val allWidgets = appWidgetListBaseEntries()
+        underTest.setWidgets(allWidgets = allWidgets)
+
+        assertThat(underTest.get().allWidgets).containsExactlyElementsIn(allWidgets)
+        verify(changeListener, times(1)).onWidgetsBound()
+        verifyNoMoreInteractions(changeListener)
+    }
+
+    @Test
+    fun setWidgetRecommendations_callsBackTheListener_andUpdatedRecommendationsAvailable() {
+        underTest.setWidgets(allWidgets = appWidgetListBaseEntries())
+        assertThat(underTest.get().recommendations).isEmpty()
+
+        underTest.setChangeListener(changeListener)
+        val recommendations =
+            listOf(
+                PendingAddWidgetInfo(
+                    appWidgetItem.widgetInfo,
+                    LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION
+                ),
+            )
+        underTest.setWidgetRecommendations(recommendations)
+
+        assertThat(underTest.get().recommendations).hasSize(1)
+        verify(changeListener, times(1)).onRecommendedWidgetsBound()
+        verifyNoMoreInteractions(changeListener)
+    }
+
+    @Test
+    fun setChangeListener_null_noCallback() {
+        underTest.setChangeListener(changeListener)
+        underTest.setChangeListener(null) // reset
+
+        underTest.setWidgets(allWidgets = appWidgetListBaseEntries())
+        val recommendations =
+            listOf(
+                PendingAddWidgetInfo(
+                    appWidgetItem.widgetInfo,
+                    LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION
+                ),
+            )
+        underTest.setWidgetRecommendations(recommendations)
+
+        verifyNoMoreInteractions(changeListener)
+    }
+
+    private fun createWidgetItem(): WidgetItem {
+        val providerInfo =
+            WidgetUtils.createAppWidgetProviderInfo(
+                ComponentName.createRelative(APP_PACKAGE_NAME, APP_PROVIDER_1_CLASS_NAME)
+            )
+        val widgetInfo = LauncherAppWidgetProviderInfo.fromProviderInfo(context, providerInfo)
+        return WidgetItem(widgetInfo, testInvariantProfile, iconCache, context)
+    }
+
+    private fun appWidgetListBaseEntries(): List<WidgetsListBaseEntry> {
+        val packageItemInfo = PackageItemInfo(APP_PACKAGE_NAME, userHandle)
+        packageItemInfo.title = APP_PACKAGE_TITLE
+        val widgets = listOf(appWidgetItem)
+
+        return buildList {
+            add(WidgetsListHeaderEntry.create(packageItemInfo, APP_SECTION_NAME, widgets))
+            add(WidgetsListContentEntry(packageItemInfo, APP_SECTION_NAME, widgets))
+        }
+    }
+
+    companion object {
+        const val APP_PACKAGE_NAME = "com.example.app"
+        const val APP_PACKAGE_TITLE = "SomeApp"
+        const val APP_SECTION_NAME = "S" // for fast popup
+        const val APP_PROVIDER_1_CLASS_NAME = "appProvider1"
+    }
+}
diff --git a/tests/multivalentTests/src/com/android/launcher3/widget/picker/model/data/WidgetPickerDataTest.kt b/tests/multivalentTests/src/com/android/launcher3/widget/picker/model/data/WidgetPickerDataTest.kt
new file mode 100644
index 0000000..e59e211
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/model/data/WidgetPickerDataTest.kt
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2024 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.widget.picker.model.data
+
+import android.content.ComponentName
+import android.content.Context
+import android.os.UserHandle
+import android.platform.test.rule.AllowedDevices
+import android.platform.test.rule.DeviceProduct
+import android.platform.test.rule.LimitDevicesRule
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.launcher3.InvariantDeviceProfile
+import com.android.launcher3.LauncherAppState
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION
+import com.android.launcher3.icons.ComponentWithLabel
+import com.android.launcher3.icons.IconCache
+import com.android.launcher3.model.WidgetItem
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.PackageItemInfo
+import com.android.launcher3.util.ActivityContextWrapper
+import com.android.launcher3.util.PackageUserKey
+import com.android.launcher3.util.WidgetUtils
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo
+import com.android.launcher3.widget.PendingAddWidgetInfo
+import com.android.launcher3.widget.model.WidgetsListBaseEntry
+import com.android.launcher3.widget.model.WidgetsListContentEntry
+import com.android.launcher3.widget.model.WidgetsListHeaderEntry
+import com.android.launcher3.widget.picker.WidgetRecommendationCategory
+import com.android.launcher3.widget.picker.WidgetRecommendationCategory.DEFAULT_WIDGET_RECOMMENDATION_CATEGORY
+import com.android.launcher3.widget.picker.model.data.WidgetPickerDataUtils.findAllWidgetsForPackageUser
+import com.android.launcher3.widget.picker.model.data.WidgetPickerDataUtils.findContentEntryForPackageUser
+import com.android.launcher3.widget.picker.model.data.WidgetPickerDataUtils.withRecommendedWidgets
+import com.android.launcher3.widget.picker.model.data.WidgetPickerDataUtils.withWidgets
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.invocation.InvocationOnMock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doAnswer
+
+// Tests for code / classes in WidgetPickerData file.
+
+@RunWith(AndroidJUnit4::class)
+@AllowedDevices(allowed = [DeviceProduct.ROBOLECTRIC])
+class WidgetPickerDataTest {
+    @Rule @JvmField val limitDevicesRule = LimitDevicesRule()
+    @Rule @JvmField val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+    @Mock private lateinit var iconCache: IconCache
+
+    private lateinit var userHandle: UserHandle
+    private lateinit var context: Context
+    private lateinit var testInvariantProfile: InvariantDeviceProfile
+
+    private lateinit var app1PackageItemInfo: PackageItemInfo
+    private lateinit var app2PackageItemInfo: PackageItemInfo
+
+    private lateinit var app1WidgetItem1: WidgetItem
+    private lateinit var app1WidgetItem2: WidgetItem
+    private lateinit var app2WidgetItem1: WidgetItem
+
+    @Before
+    fun setUp() {
+        userHandle = UserHandle.CURRENT
+        context = ActivityContextWrapper(ApplicationProvider.getApplicationContext())
+        testInvariantProfile = LauncherAppState.getIDP(context)
+
+        doAnswer { invocation: InvocationOnMock ->
+                val componentWithLabel = invocation.getArgument<Any>(0) as ComponentWithLabel
+                componentWithLabel.getComponent().shortClassName
+            }
+            .`when`(iconCache)
+            .getTitleNoCache(any<ComponentWithLabel>())
+
+        app1PackageItemInfo = packageItemInfoWithTitle(APP_1_PACKAGE_NAME, APP_1_PACKAGE_TITLE)
+        app2PackageItemInfo = packageItemInfoWithTitle(APP_2_PACKAGE_NAME, APP_2_PACKAGE_TITLE)
+
+        app1WidgetItem1 = createWidgetItem(APP_1_PACKAGE_NAME, APP_1_PROVIDER_1_CLASS_NAME)
+        app1WidgetItem2 = createWidgetItem(APP_1_PACKAGE_NAME, APP_1_PROVIDER_2_CLASS_NAME)
+        app2WidgetItem1 = createWidgetItem(APP_2_PACKAGE_NAME, APP_2_PROVIDER_1_CLASS_NAME)
+    }
+
+    @Test
+    fun withWidgets_returnsACopyWithProvidedWidgets() {
+        // only app two
+        val widgetPickerData = WidgetPickerData(allWidgets = appTwoWidgetsListBaseEntries())
+
+        // update: only app 1 and default list set
+        val newAllWidgets: List<WidgetsListBaseEntry> =
+            appOneWidgetsListBaseEntries(includeWidgetTwo = true)
+        val newDefaultWidgets: List<WidgetsListBaseEntry> =
+            appOneWidgetsListBaseEntries(includeWidgetTwo = false)
+
+        val newWidgetData = widgetPickerData.withWidgets(newAllWidgets, newDefaultWidgets)
+
+        assertThat(newWidgetData.allWidgets).containsExactlyElementsIn(newAllWidgets)
+        assertThat(newWidgetData.defaultWidgets).containsExactlyElementsIn(newDefaultWidgets)
+    }
+
+    @Test
+    fun withWidgets_noExplicitDefaults_unsetsOld() {
+        // only app two
+        val widgetPickerData =
+            WidgetPickerData(
+                allWidgets = appTwoWidgetsListBaseEntries(),
+                defaultWidgets = appTwoWidgetsListBaseEntries()
+            )
+
+        val newWidgetData =
+            widgetPickerData.withWidgets(allWidgets = appOneWidgetsListBaseEntries())
+
+        assertThat(newWidgetData.allWidgets)
+            .containsExactlyElementsIn(appOneWidgetsListBaseEntries())
+        assertThat(newWidgetData.defaultWidgets).isEmpty() // previous values cleared.
+    }
+
+    @Test
+    fun withRecommendedWidgets_returnsACopyWithProvidedRecommendedWidgets() {
+        val widgetPickerData =
+            WidgetPickerData(
+                allWidgets =
+                    buildList {
+                        addAll(appOneWidgetsListBaseEntries())
+                        addAll(appTwoWidgetsListBaseEntries())
+                    },
+                defaultWidgets = buildList { appTwoWidgetsListBaseEntries() }
+            )
+        val recommendations: List<ItemInfo> =
+            listOf(
+                PendingAddWidgetInfo(
+                    app1WidgetItem1.widgetInfo,
+                    CONTAINER_WIDGETS_PREDICTION,
+                    CATEGORY_1
+                ),
+                PendingAddWidgetInfo(
+                    app2WidgetItem1.widgetInfo,
+                    CONTAINER_WIDGETS_PREDICTION,
+                    CATEGORY_2
+                ),
+            )
+
+        val updatedData = widgetPickerData.withRecommendedWidgets(recommendations)
+
+        assertThat(updatedData.recommendations.keys).containsExactly(CATEGORY_1, CATEGORY_2)
+        assertThat(updatedData.recommendations[CATEGORY_1]).containsExactly(app1WidgetItem1)
+        assertThat(updatedData.recommendations[CATEGORY_2]).containsExactly(app2WidgetItem1)
+    }
+
+    @Test
+    fun withRecommendedWidgets_noCategory_usesDefault() {
+        val widgetPickerData =
+            WidgetPickerData(
+                allWidgets =
+                    buildList {
+                        addAll(appOneWidgetsListBaseEntries())
+                        addAll(appTwoWidgetsListBaseEntries())
+                    },
+                defaultWidgets = buildList { appTwoWidgetsListBaseEntries() }
+            )
+        val recommendations: List<ItemInfo> =
+            listOf(
+                PendingAddWidgetInfo(app1WidgetItem1.widgetInfo, CONTAINER_WIDGETS_PREDICTION),
+                PendingAddWidgetInfo(app2WidgetItem1.widgetInfo, CONTAINER_WIDGETS_PREDICTION),
+            )
+
+        val updatedData = widgetPickerData.withRecommendedWidgets(recommendations)
+
+        assertThat(updatedData.recommendations.keys)
+            .containsExactly(DEFAULT_WIDGET_RECOMMENDATION_CATEGORY)
+        assertThat(updatedData.recommendations[DEFAULT_WIDGET_RECOMMENDATION_CATEGORY])
+            .containsExactly(app1WidgetItem1, app2WidgetItem1)
+    }
+
+    @Test
+    fun withRecommendedWidgets_emptyRecommendations_clearsOld() {
+        val widgetPickerData =
+            WidgetPickerData(
+                allWidgets =
+                    buildList {
+                        addAll(appOneWidgetsListBaseEntries())
+                        addAll(appTwoWidgetsListBaseEntries())
+                    },
+                defaultWidgets = buildList { appTwoWidgetsListBaseEntries() },
+                recommendations = mapOf(CATEGORY_1 to listOf(app1WidgetItem1))
+            )
+
+        val updatedData = widgetPickerData.withRecommendedWidgets(listOf())
+
+        assertThat(updatedData.recommendations).isEmpty()
+    }
+
+    @Test
+    fun withRecommendedWidgets_widgetNotInAllWidgets_filteredOut() {
+        val widgetPickerData =
+            WidgetPickerData(
+                allWidgets =
+                    buildList {
+                        addAll(appOneWidgetsListBaseEntries(includeWidgetTwo = false))
+                        addAll(appTwoWidgetsListBaseEntries())
+                    },
+                defaultWidgets = buildList { appTwoWidgetsListBaseEntries() },
+            )
+
+        val recommendations: List<ItemInfo> =
+            listOf(
+                PendingAddWidgetInfo(app1WidgetItem2.widgetInfo, CONTAINER_WIDGETS_PREDICTION),
+                PendingAddWidgetInfo(app2WidgetItem1.widgetInfo, CONTAINER_WIDGETS_PREDICTION),
+            )
+        val updatedData = widgetPickerData.withRecommendedWidgets(recommendations)
+
+        assertThat(updatedData.recommendations).hasSize(1)
+        // no app1widget2
+        assertThat(updatedData.recommendations.values.first()).containsExactly(app2WidgetItem1)
+    }
+
+    @Test
+    fun findContentEntryForPackageUser_returnsCorrectEntry() {
+        val widgetPickerData =
+            WidgetPickerData(
+                allWidgets =
+                    buildList {
+                        addAll(appOneWidgetsListBaseEntries())
+                        addAll(appTwoWidgetsListBaseEntries())
+                    },
+                defaultWidgets = buildList { addAll(appTwoWidgetsListBaseEntries()) }
+            )
+        val app1PackageUserKey = PackageUserKey.fromPackageItemInfo(app1PackageItemInfo)
+
+        val contentEntry = findContentEntryForPackageUser(widgetPickerData, app1PackageUserKey)
+
+        assertThat(contentEntry).isNotNull()
+        assertThat(contentEntry?.mPkgItem).isEqualTo(app1PackageItemInfo)
+        assertThat(contentEntry?.mWidgets).hasSize(2)
+    }
+
+    @Test
+    fun findContentEntryForPackageUser_fromDefaults_returnsEntryFromDefaultWidgets() {
+        val widgetPickerData =
+            WidgetPickerData(
+                allWidgets =
+                    buildList {
+                        addAll(appOneWidgetsListBaseEntries())
+                        addAll(appTwoWidgetsListBaseEntries())
+                    },
+                defaultWidgets =
+                    buildList { addAll(appOneWidgetsListBaseEntries(includeWidgetTwo = false)) }
+            )
+        val app1PackageUserKey = PackageUserKey.fromPackageItemInfo(app1PackageItemInfo)
+
+        val contentEntry =
+            findContentEntryForPackageUser(
+                widgetPickerData = widgetPickerData,
+                packageUserKey = app1PackageUserKey,
+                fromDefaultWidgets = true
+            )
+
+        assertThat(contentEntry).isNotNull()
+        assertThat(contentEntry?.mPkgItem).isEqualTo(app1PackageItemInfo)
+        // only one widget (since default widgets had only one widget for app A
+        assertThat(contentEntry?.mWidgets).hasSize(1)
+    }
+
+    @Test
+    fun findContentEntryForPackageUser_noMatch_returnsNull() {
+        val app2PackageUserKey = PackageUserKey.fromPackageItemInfo(app2PackageItemInfo)
+        val widgetPickerData =
+            WidgetPickerData(allWidgets = buildList { addAll(appOneWidgetsListBaseEntries()) })
+
+        val contentEntry = findContentEntryForPackageUser(widgetPickerData, app2PackageUserKey)
+
+        assertThat(contentEntry).isNull()
+    }
+
+    @Test
+    fun findAllWidgetsForPackageUser_returnsListOfWidgets() {
+        val app1PackageUserKey = PackageUserKey.fromPackageItemInfo(app1PackageItemInfo)
+        val widgetPickerData =
+            WidgetPickerData(
+                allWidgets =
+                    buildList {
+                        addAll(appOneWidgetsListBaseEntries())
+                        addAll(appTwoWidgetsListBaseEntries())
+                    },
+                defaultWidgets =
+                    buildList { addAll(appOneWidgetsListBaseEntries(includeWidgetTwo = false)) }
+            )
+
+        val widgets = findAllWidgetsForPackageUser(widgetPickerData, app1PackageUserKey)
+
+        // both widgets returned irrespective of default widgets list
+        assertThat(widgets).hasSize(2)
+    }
+
+    @Test
+    fun findAllWidgetsForPackageUser_noMatch_returnsEmptyList() {
+        val widgetPickerData =
+            WidgetPickerData(
+                allWidgets = buildList { addAll(appTwoWidgetsListBaseEntries()) },
+            )
+        val app1PackageUserKey = PackageUserKey.fromPackageItemInfo(app1PackageItemInfo)
+
+        val widgets = findAllWidgetsForPackageUser(widgetPickerData, app1PackageUserKey)
+
+        assertThat(widgets).isEmpty()
+    }
+
+    private fun packageItemInfoWithTitle(packageName: String, title: String): PackageItemInfo {
+        val packageItemInfo = PackageItemInfo(packageName, userHandle)
+        packageItemInfo.title = title
+        return packageItemInfo
+    }
+
+    private fun createWidgetItem(packageName: String, widgetProviderName: String): WidgetItem {
+        val providerInfo =
+            WidgetUtils.createAppWidgetProviderInfo(
+                ComponentName.createRelative(packageName, widgetProviderName)
+            )
+        val widgetInfo = LauncherAppWidgetProviderInfo.fromProviderInfo(context, providerInfo)
+        return WidgetItem(widgetInfo, testInvariantProfile, iconCache, context)
+    }
+
+    private fun appTwoWidgetsListBaseEntries(): List<WidgetsListBaseEntry> = buildList {
+        val widgets = listOf(app2WidgetItem1)
+        add(WidgetsListHeaderEntry.create(app2PackageItemInfo, APP_2_SECTION_NAME, widgets))
+        add(WidgetsListContentEntry(app2PackageItemInfo, APP_2_SECTION_NAME, widgets))
+    }
+
+    private fun appOneWidgetsListBaseEntries(
+        includeWidgetTwo: Boolean = true
+    ): List<WidgetsListBaseEntry> = buildList {
+        val widgets =
+            if (includeWidgetTwo) {
+                listOf(app1WidgetItem1, app1WidgetItem2)
+            } else {
+                listOf(app1WidgetItem1)
+            }
+
+        add(WidgetsListHeaderEntry.create(app1PackageItemInfo, APP_1_SECTION_NAME, widgets))
+        add(WidgetsListContentEntry(app1PackageItemInfo, APP_1_SECTION_NAME, widgets))
+    }
+
+    companion object {
+        private const val APP_1_PACKAGE_NAME = "com.example.app1"
+        private const val APP_1_PACKAGE_TITLE = "App1"
+        private const val APP_1_SECTION_NAME = "A" // for fast popup
+        private const val APP_1_PROVIDER_1_CLASS_NAME = "app1Provider1"
+        private const val APP_1_PROVIDER_2_CLASS_NAME = "app1Provider2"
+
+        private const val APP_2_PACKAGE_NAME = "com.example.app2"
+        private const val APP_2_PACKAGE_TITLE = "SomeApp2"
+        private const val APP_2_SECTION_NAME = "S" // for fast popup
+        private const val APP_2_PROVIDER_1_CLASS_NAME = "app2Provider1"
+
+        private val CATEGORY_1 =
+            WidgetRecommendationCategory(/* categoryTitleRes= */ 0, /* order= */ 0)
+        private val CATEGORY_2 =
+            WidgetRecommendationCategory(/* categoryTitleRes= */ 1, /* order= */ 1)
+    }
+}
diff --git a/tests/src/com/android/launcher3/allapps/FloatingMaskViewTest.kt b/tests/src/com/android/launcher3/allapps/FloatingMaskViewTest.kt
new file mode 100644
index 0000000..cf03adc
--- /dev/null
+++ b/tests/src/com/android/launcher3/allapps/FloatingMaskViewTest.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps
+
+import android.content.Context
+import android.view.ViewGroup
+import android.view.ViewGroup.MarginLayoutParams
+import android.widget.ImageView
+import androidx.test.core.app.ApplicationProvider
+import com.android.launcher3.util.ActivityContextWrapper
+import com.google.common.truth.Truth
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.MockitoAnnotations
+
+class FloatingMaskViewTest {
+    @Mock
+    private val mockAllAppsRecyclerView: AllAppsRecyclerView? = null
+
+    @Mock
+    private val mockBottomBox: ImageView? = null
+    private var mVut: FloatingMaskView? = null
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        val context: Context = ActivityContextWrapper(ApplicationProvider.getApplicationContext())
+        mVut = FloatingMaskView(context)
+        mVut!!.layoutParams = MarginLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT)
+    }
+
+    @Test
+    fun setParameters_paramsMarginEqualRecyclerViewPadding() {
+        val floatingMaskView = Mockito.spy(mVut)
+        Mockito.`when`(mockAllAppsRecyclerView!!.paddingLeft).thenReturn(PADDING_PX)
+        Mockito.`when`(mockAllAppsRecyclerView.paddingRight).thenReturn(PADDING_PX)
+        Mockito.`when`(mockAllAppsRecyclerView.paddingBottom).thenReturn(PADDING_PX)
+        Mockito.`when`(floatingMaskView!!.bottomBox).thenReturn(mockBottomBox)
+        val lp = floatingMaskView.layoutParams as MarginLayoutParams
+
+        floatingMaskView.setParameters(lp, mockAllAppsRecyclerView)
+
+        Truth.assertThat(lp.leftMargin).isEqualTo(PADDING_PX)
+        Truth.assertThat(lp.rightMargin).isEqualTo(PADDING_PX)
+        Mockito.verify(mockBottomBox)?.minimumHeight = PADDING_PX
+    }
+
+    companion object {
+        private const val PADDING_PX = 15
+    }
+}
diff --git a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java
index de48432..398f9c5 100644
--- a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java
+++ b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java
@@ -86,6 +86,8 @@
     private static final String CAMERA_PACKAGE_NAME = "com.android.launcher3.tests.camera";
     private static final int CONTAINER_HEADER_ELEMENT_COUNT = 1;
     private static final int LOCK_UNLOCK_BUTTON_COUNT = 1;
+    private static final int MAIN_USER_APP_COUNT = 1;
+    private static final int VIEW_AT_END_OF_APP_LIST = 1;
     private static final int PS_SETTINGS_BUTTON_COUNT_VISIBLE = 1;
     private static final int PS_SETTINGS_BUTTON_COUNT_INVISIBLE = 0;
     private static final int PS_TRANSITION_IMAGE_COUNT = 1;
@@ -300,8 +302,8 @@
         int rows = (int) (ALL_APPS_HEIGHT - PS_HEADER_HEIGHT - HEADER_PROTECTION_HEIGHT);
         int position = rows * NUM_APP_COLS - (NUM_APP_COLS-1) + 1;
 
-        // The number of adapterItems should be the private space apps + one main app + header.
-        assertEquals(NUM_PRIVATE_SPACE_APPS + 1 + 1,
+        assertEquals(NUM_PRIVATE_SPACE_APPS + MAIN_USER_APP_COUNT
+                        + CONTAINER_HEADER_ELEMENT_COUNT + VIEW_AT_END_OF_APP_LIST,
                 mAlphabeticalAppsList.getAdapterItems().size());
         assertEquals(position,
                 privateProfileManager.scrollForHeaderToBeVisibleInContainer(
@@ -335,8 +337,8 @@
         int rows = (int) (ALL_APPS_HEIGHT - PS_HEADER_HEIGHT - HEADER_PROTECTION_HEIGHT) - 1;
         int position = rows * NUM_APP_COLS - (NUM_APP_COLS-1) + 1;
 
-        // The number of adapterItems should be the private space apps + one main app + header.
-        assertEquals(NUM_PRIVATE_SPACE_APPS + 1 + 1,
+        assertEquals(NUM_PRIVATE_SPACE_APPS + MAIN_USER_APP_COUNT
+                        + CONTAINER_HEADER_ELEMENT_COUNT + VIEW_AT_END_OF_APP_LIST,
                 mAlphabeticalAppsList.getAdapterItems().size());
         assertEquals(position,
                 privateProfileManager.scrollForHeaderToBeVisibleInContainer(
@@ -370,8 +372,8 @@
         int rows = (int) (ALL_APPS_HEIGHT - BIGGER_PS_HEADER_HEIGHT - HEADER_PROTECTION_HEIGHT);
         int position = rows * NUM_APP_COLS - (NUM_APP_COLS-1) + 1;
 
-        // The number of adapterItems should be the private space apps + one main app + header.
-        assertEquals(NUM_PRIVATE_SPACE_APPS + 1 + 1,
+        assertEquals(NUM_PRIVATE_SPACE_APPS + MAIN_USER_APP_COUNT
+                        + CONTAINER_HEADER_ELEMENT_COUNT + VIEW_AT_END_OF_APP_LIST,
                 mAlphabeticalAppsList.getAdapterItems().size());
         assertEquals(position,
                 privateProfileManager.scrollForHeaderToBeVisibleInContainer(
@@ -399,8 +401,7 @@
         mAlphabeticalAppsList.updateItemFilter(info -> info != null
                 && info.user.equals(MAIN_HANDLE));
 
-        // The number of adapterItems should be the private space apps + one main app.
-        assertEquals(NUM_PRIVATE_SPACE_APPS + 1,
+        assertEquals(NUM_PRIVATE_SPACE_APPS + MAIN_USER_APP_COUNT + VIEW_AT_END_OF_APP_LIST,
                 mAlphabeticalAppsList.getAdapterItems().size());
         assertEquals(SCROLL_NO_WHERE, privateProfileManager.scrollForHeaderToBeVisibleInContainer(
                 new AllAppsRecyclerView(mContext),
diff --git a/tests/src/com/android/launcher3/model/gridmigration/ValidGridMigrationUnitTest.kt b/tests/src/com/android/launcher3/model/gridmigration/ValidGridMigrationUnitTest.kt
index 58b915f..7182cf3 100644
--- a/tests/src/com/android/launcher3/model/gridmigration/ValidGridMigrationUnitTest.kt
+++ b/tests/src/com/android/launcher3/model/gridmigration/ValidGridMigrationUnitTest.kt
@@ -94,7 +94,13 @@
 
         val srcCountMap = itemsToMap(srcGrid.items)
         val resultCountMap = itemsToMap(resultItems)
-        val diff = resultCountMap - srcCountMap
+        val diff = resultCountMap.toMutableMap()
+        for ((srcKey, srcValue) in srcCountMap) {
+            val destValue = diff[srcKey]
+            if (destValue != null) {
+                diff[srcKey] = destValue - srcValue
+            }
+        }
 
         diff.forEach { (k, count) ->
             assert(count >= 0) { "Source item $k not present on the result" }
diff --git a/tests/src/com/android/launcher3/popup/SystemShortcutTest.java b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
index 98b6b4b..dcfcad5 100644
--- a/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
+++ b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
@@ -63,6 +63,8 @@
 import com.android.launcher3.util.TestSandboxModelContextWrapper;
 import com.android.launcher3.util.UserIconInfo;
 import com.android.launcher3.views.BaseDragLayer;
+import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider;
+import com.android.launcher3.widget.picker.model.data.WidgetPickerData;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -73,8 +75,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.ArrayList;
-
 @SmallTest
 @RunWith(LauncherMultivalentJUnit.class)
 public class SystemShortcutTest {
@@ -86,7 +86,7 @@
     private TestSandboxModelContextWrapper mTestContext;
     private final SandboxModelContext mSandboxContext = new SandboxModelContext();
     private PrivateProfileManager mPrivateProfileManager;
-    private PopupDataProvider mPopupDataProvider;
+    private WidgetPickerDataProvider mWidgetPickerDataProvider;
     private AppInfo mAppInfo;
     @Mock UserCache mUserCache;
     @Mock ApiWrapper mApiWrapper;
@@ -119,8 +119,8 @@
         spyOn(mPrivateProfileManager);
         when(mPrivateProfileManager.getProfileUser()).thenReturn(PRIVATE_HANDLE);
 
-        mPopupDataProvider = mTestContext.getPopupDataProvider();
-        spyOn(mPopupDataProvider);
+        mWidgetPickerDataProvider = mTestContext.getWidgetPickerDataProvider();
+        spyOn(mWidgetPickerDataProvider);
     }
 
     @After
@@ -141,7 +141,7 @@
         mAppInfo = new AppInfo();
         mAppInfo.componentName = new ComponentName(mTestContext, getClass());
         assertNotNull(mAppInfo.getTargetComponent());
-        doReturn(new ArrayList<>()).when(mPopupDataProvider).getWidgetsForPackageUser(any());
+        doReturn(new WidgetPickerData()).when(mWidgetPickerDataProvider).get();
         spyOn(mAppInfo);
         SystemShortcut systemShortcut = SystemShortcut.WIDGETS
                 .getShortcut(mTestContext, mAppInfo, mView);
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index c926ba9..1e2744c 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -22,7 +22,6 @@
 import static com.android.launcher3.testing.shared.TestProtocol.ICON_MISSING;
 import static com.android.launcher3.testing.shared.TestProtocol.WIDGET_CONFIG_NULL_EXTRA_INTENT;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -64,7 +63,6 @@
 import com.android.launcher3.tapl.TestHelpers;
 import com.android.launcher3.testcomponent.TestCommandReceiver;
 import com.android.launcher3.util.LooperExecutor;
-import com.android.launcher3.util.SimpleBroadcastReceiver;
 import com.android.launcher3.util.TestUtil;
 import com.android.launcher3.util.Wait;
 import com.android.launcher3.util.rule.ExtendedLongPressTimeoutRule;
@@ -237,16 +235,12 @@
     }
 
     protected void clearPackageData(String pkg) throws IOException, InterruptedException {
-        final CountDownLatch count = new CountDownLatch(2);
-        final SimpleBroadcastReceiver broadcastReceiver =
-                new SimpleBroadcastReceiver(UI_HELPER_EXECUTOR, i -> count.countDown());
-        // We OK to make binder calls on main thread in test.
-        broadcastReceiver.registerPkgActions(mTargetContext, pkg,
-                Intent.ACTION_PACKAGE_RESTARTED, Intent.ACTION_PACKAGE_DATA_CLEARED);
-
-        mDevice.executeShellCommand("pm clear " + pkg);
-        assertTrue(pkg + " didn't restart", count.await(20, TimeUnit.SECONDS));
-        mTargetContext.unregisterReceiver(broadcastReceiver);
+        assertTrue("pm clear command failed",
+                mDevice.executeShellCommand("pm clear " + pkg)
+                .contains("Success"));
+        assertTrue("pm wait-for-handler command failed",
+                mDevice.executeShellCommand("pm wait-for-handler")
+                .contains("Success"));
     }
 
     protected TestRule getRulesInsideActivityMonitor() {
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 27f6c16..567a8bd 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -45,6 +45,7 @@
  * Common overview panel for both Launcher and fallback recents
  */
 public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
+    private static final String TAG = "BaseOverview";
     protected static final String TASK_RES_ID = "task";
     private static final Pattern EVENT_ALT_ESC_UP = Pattern.compile(
             "Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
@@ -384,39 +385,32 @@
     }
 
     protected boolean isActionsViewVisible() {
-        boolean hasTasks = hasTasks();
-        if (!hasTasks || isClearAllVisible()) {
-            LauncherInstrumentation.log("Not expecting an actions bar:"
-                    + (!hasTasks ? "no recent tasks" : "clear all button is visible"));
+        if (!hasTasks() || isClearAllVisible()) {
+            Log.d(TAG, "Not expecting an actions bar: no tasks/'Clear all' is visible");
             return false;
         }
         boolean isTablet = mLauncher.isTablet();
         if (isTablet && mLauncher.isGridOnlyOverviewEnabled()) {
-            LauncherInstrumentation.log("Not expecting an actions bar: "
-                    + "device is tablet with grid-only Overview");
+            Log.d(TAG, "Not expecting an actions bar: device is tablet with grid-only Overview");
             return false;
         }
         OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask();
         if (task == null) {
-            LauncherInstrumentation.log("Not expecting an actions bar: no focused task");
+            Log.d(TAG, "Not expecting an actions bar: no current task");
             return false;
         }
-        float centerOffset = Math.abs(task.getExactCenterX() - mLauncher.getExactScreenCenterX());
         // In tablets, if focused task is not in center, overview actions aren't visible.
-        if (isTablet && centerOffset >= 1) {
-            LauncherInstrumentation.log("Not expecting an actions bar: "
-                    + "device is tablet and task is not centered; center offset by "
-                    + centerOffset + "px");
+        if (isTablet && Math.abs(task.getExactCenterX() - mLauncher.getExactScreenCenterX()) >= 1) {
+            Log.d(TAG, "Not expecting an actions bar: device is tablet and task is not centered");
             return false;
         }
         if (task.isTaskSplit() && (!mLauncher.isAppPairsEnabled() || !isTablet)) {
-            LauncherInstrumentation.log("Not expecting an actions bar: "
-                    + "device is phone and task is split");
+            Log.d(TAG, "Not expecting an actions bar: device is phone and task is split");
             // Overview actions aren't visible for split screen tasks, except for save app pair
             // button on tablets.
             return false;
         }
-        LauncherInstrumentation.log("Expecting an actions bar");
+        Log.d(TAG, "Expecting an actions bar");
         return true;
     }
 
@@ -499,18 +493,13 @@
             throw new IllegalStateException("Must be run on tablet device.");
         }
         final List<UiObject2> taskViews = getTasks();
-        if (!hasTasks()) {
-            LauncherInstrumentation.log("no recent tasks");
+        if (taskViews.size() == 0) {
             return null;
         }
         int focusedTaskHeight = mLauncher.getFocusedTaskHeightForTablet();
         for (UiObject2 task : taskViews) {
             OverviewTask overviewTask = new OverviewTask(mLauncher, task, this);
 
-            LauncherInstrumentation.log("checking task height ("
-                    + overviewTask.getVisibleHeight()
-                    + ") against defined focused task height ("
-                    + focusedTaskHeight + ")");
             if (overviewTask.getVisibleHeight() == focusedTaskHeight) {
                 return overviewTask;
             }
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index ad37f7b..75c1b24 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -1229,7 +1229,8 @@
     void pressBackImpl() {
         waitForLauncherInitialized();
         final boolean launcherVisible =
-                isTablet() ? isLauncherContainerVisible() : isLauncherVisible();
+                (isTablet() || isTaskbarNavbarUnificationEnabled()) ? isLauncherContainerVisible()
+                        : isLauncherVisible();
         boolean isThreeFingerTrackpadGesture =
                 mTrackpadGestureType == TrackpadGestureType.THREE_FINGER;
         if (getNavigationModel() == NavigationModel.ZERO_BUTTON